Metadata-Version: 2.4
Name: clikernel
Version: 0.2.9
Summary: Serve persistent Jupyter kernels to LLMs as concise text, over MCP or a plain stream protocol
Author: clikernel contributors
License: Apache-2.0
Project-URL: Repository, https://github.com/AnswerDotAI/clikernel
Project-URL: Documentation, https://AnswerDotAI.github.io/clikernel/
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastcore>=2.2.2
Requires-Dist: jupyasyncclient>=0.2.10
Requires-Dist: jupywire>=0.1.9
Requires-Dist: mcpmini>=0.0.4
Requires-Dist: rustygate>=0.1.7
Requires-Dist: httpx
Provides-Extra: dev
Requires-Dist: fastship; extra == "dev"
Dynamic: license-file

# clikernel


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

`clikernel` gives an LLM agent a persistent Python workbench built from two processes. A gateway ([rustygate](https://github.com/AnswerDotAI/rustygate)) hosts real Jupyter kernels ([ipymini](https://github.com/AnswerDotAI/ipymini) by default) and serves the MCP tool surface itself; kernels live there and persist until explicitly stopped. `clikernel` starts and stops with each conversation: a router the MCP host launches, speaking stdio MCP to the model and forwarding to gateways over HTTP. It adds what a single fixed endpoint cannot: gateway naming from `gateways.toml` (a `host` argument on the kernel-selection tools reaches any machine you’ve named), delivery of your `startup.py` and `inspectors.py` into every kernel a conversation creates, and a local gateway that always exists — found running, or started as a child that lives exactly as long as the conversation.

Kernel scope is the gateway’s rule, one rule everywhere: a session’s end stops the kernels it created with autoclose (the bare-`py` auto kernel, and `create`’s default) and nothing else. A kernel created with `autoclose=false` on a persistent gateway outlives the conversation, and a later conversation reattaches with `use_kernel` and finds its state intact — including the user’s live solveit kernel.

## Install

``` sh
pip install clikernel
```

This brings [rustygate](https://github.com/AnswerDotAI/rustygate) and a kernel ([ipymini](https://github.com/AnswerDotAI/ipymini)) with it, and no service setup is needed: a conversation that finds no gateway starts its own. Run a resident gateway when kernels should outlive conversations (e.g. via launchd/systemd):

``` sh
rustygate --port 8787
```

## Use with an MCP host

Register the stdio server with your MCP host, e.g. for Claude Code:

``` sh
claude mcp add clikernel -- clikernel-mcp
```

The tools are rustygate’s, forwarded: `py` (the normal tool — it auto-starts a kernel when none is current, and magics like a `%%bash` first line run as written), `list_kernels`, `create`, `use_kernel`, `delete_kernel`, `restart`, and `interrupt`. The router adds one thing to them: `list_kernels`, `use_kernel`, and `create` take a `host` naming a gateway from `gateways.toml`, so one MCP entry reaches every machine you’ve named. Replies carry text and image blocks exactly as the gateway rendered them.

A conversation cleans up after itself: its end stops the auto kernel and every `create` it made, unless `autoclose=false` asked for a keeper. Kernels reached with `use_kernel` are never touched. `$CLIKERNEL_HOST` overrides the default gateway (`http://127.0.0.1:8787`), and when nothing answers there, the conversation runs on a private child gateway that ends with it.

Pass `--quiet` (`clikernel-mcp --quiet`) for a host whose sessions should not see banner noise: startup still runs, but its output stays out of every reply.

## Configuration

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 in the reply that announces the kernel.
- `inspectors.py` — cell inspectors installed after startup. The file may define `inspect` and/or a list `inspectors`; 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, raise `RuleBlock` (provided in the namespace) to block the cell; any other exception warns and the cell runs. See `examples/inspectors.py`.
- `gateways.toml` — named remote gateways, so tokens never appear in tool arguments:

``` toml
[gateways.solveit]
url = "https://solveit.example.com/gate"
token_env = "SOLVEIT_TOKEN"
verify = false   # optional: accept a self-signed certificate
```

## The stream protocol

Run `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.
