Skip to main content

clikernel

clikernel is a tiny stdin/stdout worker around execnb.shell.CaptureShell. It keeps one IPython-compatible Python process alive and returns concise text for each request.

The Key Idea

The idea of clikernel is to be a persistent python process that LLMs can use as their primary tool.

A persistent Python process is a good default tool for an LLM agent. The agent can import a module, inspect it, keep helper functions around, cache results, patch objects, and then continue from that state on the next request.

This is especially useful with pyskills. The agent can discover skills, read their docs, import the ones it needs, and keep using them in the same session. That makes Python a universal workbench for repo inspection, API checks, file edits, data transforms, and experiments.

clikernel gives an agent the part of a notebook kernel it usually needs: send code, wait for the result, read concise text, and keep the Python state.

Protocol

On startup, clikernel prints loading status, a short <stream-protocol> framing recipe (with the live delimiter, indented so line-based readers don't mistake it for the real one), and finally the random session delimiter:

please wait, loading...
<stream-protocol>
...
</stream-protocol>
loading complete. session delimiter:
--aB3x9

That delimiter stays the same until the worker exits.

Send one line to execute it immediately:

1+1

Each complete request is acknowledged with . before execution starts. Send exit() or quit() to receive an acknowledgement, a final delimiter, and stop the worker.

For multiline code, send -- on its own line, then the code, then the session delimiter exactly:

--
def f(x):
    return x + 1

f(2)
--aB3x9

After execution, clikernel prints the acknowledgement, the rendered output, and the session delimiter:

.
3
--aB3x9

Outputs are rendered with fastcore.nbio.render_text. A single non-empty output is printed directly. Multiple outputs use raw XML-ish tags, for example <stdout>, <display_data mime="text/markdown">, and <execute_result>.

Notebook magics

clikernel registers a %nbrun line magic wrapping execnb's nbrun, for running cells from a notebook by cell id prefix:

%nbrun ab12
%nbrun ab12 --above
%nbrun --all --exported
%nbrun ab12 --fname other.ipynb

%nbrun defaults to the current notebook (set with llmsurgery.dlgskill's set_dlg) when llmsurgery is installed; --fname overrides for one call. It runs the cell whose id starts with the given prefix; --above/--below also run the cells before/after it, --all runs every code cell, --exported filters to cells with an nbdev #| export/#| exports directive, and --skip_noeval skips #| eval: false and nbdev_export cells. The run stops at the first cell that errors, unless --continue_on_error is passed. The notebook is re-read from disk on each call, and each executed cell's rendered output is printed under a --- {cell id} --- header.

clikernel sets quiet defaults for IPYTHONDIR, MPLCONFIGDIR, and MPLBACKEND=Agg before creating the shell. Existing IPYTHONDIR and MPLCONFIGDIR values are left alone. Loading messages and any startup warnings are printed before the session delimiter. Set CLIKERNEL_STATE_DIR to choose the default parent directory.

Startup file

On startup, after creating the shell and before the session delimiter, clikernel runs $XDG_CONFIG_HOME/clikernel/startup.py (usually ~/.config/clikernel/startup.py) if it exists. It runs via IPython's %run -i, so __file__ is the startup path and any imports, variables, and helpers it defines remain available to every later request. The loading banner then carries a <startup file=...> element with a <source> child holding the file's whole source and, when the file prints anything, an <output> child holding its captured stdout; the clikernel-mcp server forwards this (after its own instructions) as the MCP instructions field. A broken startup.py is reported on stderr but does not stop the kernel starting.

Inspectors

clikernel can check each cell before it runs, to warn about or forbid certain code. On startup it loads inspectors from $XDG_CONFIG_HOME/clikernel/inspectors.py (usually ~/.config/clikernel/inspectors.py). If that file is absent, nothing changes.

Each cell is transformed first (so IPython magics and ! shell escapes parse), and its AST is passed to every inspector before the cell executes. An inspector returns a string to prepend a note to the cell's output, raises clikernel.base.RuleBlock to block the cell (it does not run, and the message is reported), or returns None to do nothing. Any other exception from an inspector is treated as an inspector bug: a warning is prepended and the cell still runs. Define a function inspect(tree) and/or a list inspectors of such functions in the file. A broken inspectors.py is reported on stderr and skipped, so it cannot stop the kernel starting.

See examples/inspectors.py for one that blocks subprocess, os.system/os.popen, and ! escapes, steering the agent to the permission-checked Bash tool instead. llmdojo builds its live session rules on this hook.

Why The Protocol Is Odd

clikernel is built for a client that reads stdout as tokens. Local echo is disabled when stdin is a TTY. The client already knows the code it sent, so echoing it back only makes the LLM read slow, expensive tokens that add no information.

Each complete request prints . on its own line before execution starts. That gives the client a cheap early byte to read, which is useful when the request will run for a while. Each response ends with the same delimiter on its own line. The client can read until that line appears instead of parsing prompts or waiting and guessing. The delimiter is random per process, so it is unlikely to appear in generated code, copied logs, examples, or earlier transcript text. Keeping it fixed for the session means a client does not get stuck just because it missed a rotated delimiter.

Startup messages appear before the session delimiter first prints. After that, the stream follows the request-response protocol. Outputs are rendered as concise text, using unescaped XML if required when there's multiple outputs.

IPython history is disabled. IPYTHONDIR and MPLCONFIGDIR get quiet defaults when the environment has not already set them, and MPLBACKEND defaults to Agg.

Development

pip install -e .[dev]

Versioning

Version lives in clikernel/__init__.py as __version__.

Release

  1. Ensure your GitHub issues are labeled (bug, enhancement, breaking).
  2. Run:
ship-gh
ship-pypi
ship-bump  # dev release always later than prod release

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

clikernel-0.1.7.tar.gz (30.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

clikernel-0.1.7-py3-none-any.whl (21.5 kB view details)

Uploaded Python 3

File details

Details for the file clikernel-0.1.7.tar.gz.

File metadata

  • Download URL: clikernel-0.1.7.tar.gz
  • Upload date:
  • Size: 30.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for clikernel-0.1.7.tar.gz
Algorithm Hash digest
SHA256 3f32c6f81d0a4015b54e3e3567df352fd089f9416e224d448f4792c9c8f62656
MD5 cc3190937d188fc042ed0bb2b3ade757
BLAKE2b-256 c0b36d8bb6591b6adda757c36934aba29450fd5655dd06ac3ecff6dc240a6e81

See more details on using hashes here.

File details

Details for the file clikernel-0.1.7-py3-none-any.whl.

File metadata

  • Download URL: clikernel-0.1.7-py3-none-any.whl
  • Upload date:
  • Size: 21.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for clikernel-0.1.7-py3-none-any.whl
Algorithm Hash digest
SHA256 77f4fe1a0055c03a29ba5226d3cbdaa2d560adec8e2a6156c9856c2fa9137c44
MD5 0f8e681f5528a5ea0f842e6c54de3291
BLAKE2b-256 b28ecf1d0a3a1d1d65937a8d1aed4e3ad2c25509563b3594cb4ccce2e8919057

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page