clikernel gives an LLM agent a persistent Python workbench built from two processes. A gateway (rustygate) runs all the time and hosts real Jupyter kernels (ipymini by default); kernels live there and persist until explicitly stopped. clikernel itself starts and stops with each conversation: a small translator the MCP host launches, speaking MCP to the model and the Jupyter kernels API to the gateway. Outputs come back as concise text — a bare 42 for a single result, tagged sections for several, tracebacks ANSI-stripped and capped.
Because kernels outlive conversations, an agent can connect back to yesterday’s kernel (or the user’s live solveit kernel) and find its state intact. Kernels created or attached explicitly are never stopped implicitly: only stop_kernel ends them. The one exception is the auto kernel: an execute with nothing connected creates a kernel scoped to the conversation, stopped again when the conversation ends or the agent connects elsewhere. Creating a kernel runs the user’s startup.py and installs their inspectors.py cell-checking rules, delivered as source so remote kernels get the same setup as local ones.
pip install clikernelPlus the resident side: rustygate and a kernel (ipymini by default). Start the gateway (and keep it running, e.g. via launchd/systemd):
rustygate --port 8787Register the stdio server with your MCP host, e.g. for Claude Code:
claude mcp add clikernel -- clikernel-mcpThe tools mirror the gateway’s kernel API plus one composite: connect (create a fresh kernel — running startup.py and installing inspectors — or attach to an existing one by id), execute (run code, get concise text), list_kernels, stop_kernel, restart, and interrupt. An execute with no kernel connected auto-creates one, scoped to the conversation: it stops at conversation end, or when connect moves elsewhere. Kernels made or attached with an explicit connect are stopped only by stop_kernel — a later conversation reattaches by id and continues where the last one stopped. $CLIKERNEL_HOST overrides the default gateway (http://127.0.0.1:8787).
Three optional files in $XDG_CONFIG_HOME/clikernel/ (usually ~/.config/clikernel/):
startup.py— run in every kernel clikernel creates, with__file__bound to its path; its output returns as part of theconnectreply.inspectors.py— cell inspectors installed after startup. The file may defineinspectand/or a listinspectors; each is called once per cell before it runs (1-arg: the cell’s AST; 2-arg: AST and raw source). Return a string to print a note before the cell’s output, raiseRuleBlock(provided in the namespace) to block the cell; any other exception warns and the cell runs. Seeexamples/inspectors.py.gateways.toml— named remote gateways, so tokens never appear in tool arguments:
[gateways.solveit]
url = "https://solveit.example.com/gate"
token_env = "SOLVEIT_TOKEN"
verify = false # optional: accept a self-signed certificateRun clikernel as a plain CLI process and the same client speaks a delimiter-framed stdin/stdout protocol for token-reading clients: no echo, a cheap . acknowledgement per request, responses ended by a per-process random delimiter, multiline cells framed by -- and the delimiter. The full recipe is announced in the process’s own startup banner. Run bare it creates a kernel and stops it on exit; --kernel <id> attaches to an existing kernel and leaves it as found.