{"slug": "an-extensible-coding-agent-for-the-modern-lisp-hacker", "title": "An extensible coding agent for the modern Lisp hacker", "summary": "Kleisli.io released kli, an extensible coding agent that runs inside its own live SBCL image, featuring a small boot kernel that installs, switches, and rolls back protocols, with all model providers, tools, the agent loop, and the TUI as extensions. It supports hot-patching and retraction of any contribution from the REPL without dropping the session, and is available via a curl installer, Nix, or building from source.", "body_md": "\n\n```\ncurl -fsSL https://kli.kleisli.io | sh\n```\n\nkli is a coding agent that runs inside its own live SBCL image. The boot kernel is\nsmall. It knows only how to install, switch, and roll back protocols, and nothing\nabout what an extension is. The extension system itself, the manifests, the\ncontribution kinds, the capabilities and the tools, is a protocol installed on that\nkernel through those same verbs. Every model provider, every tool, the agent loop,\nand the whole TUI is an extension on a protocol. Every contribution carries a\nretractor, so retraction drains exactly what it added and nothing else, and you can\ninstall, retract, swap, or hot patch any of it from the REPL without dropping the\nsession. Extensions all the way down. If that makes you want to open\n`src/kernel.lisp`\n\n, kli is for you.\n\n**Specialize the running program.** A`:method`\n\ncontribution adds a method to any generic in the live image, and retraction is`remove-method`\n\n. You change the program's own behavior and roll it back.**Rewrite without restarting, keep the state.** Behavior lives in CLOS cells over pandoric closures. A hot patch swaps the code and keeps the closed-over state, so the editor keeps its buffer and the transcript its scrollback. It runs behind a condition-system fault barrier, so a hot-patched function that throws degrades instead of killing the session.**Switch the whole world, safely.** A protocol switch validates, smoke-tests, swaps, and rolls back on any error.\n\nTwo dispatch axes are split on purpose. CLOS specialization handles image-global, per-class behavior, and capability providers, which are closure tables, handle per-protocol-instance variation. The agent loop itself is built this way, with the message handler, the skill expander, the retry count, and the compaction threshold all pandoric closures you can open and hot patch while a turn is in flight.\n\nInstall the prebuilt binary, use Nix, or build from source.\n\n```\ncurl -fsSL https://kli.kleisli.io | sh\n```\n\nIt installs under `~/.local`\n\n, overridable with `KLI_INSTALL_DIR`\n\nand pinnable with\n`KLI_VERSION`\n\n, and puts a `kli`\n\nwrapper on your `PATH`\n\n. Then run `kli`\n\n.\n\nRun it without installing, or add it to your profile.\n\n```\nnix run github:kleisli-io/kli\nnix profile install github:kleisli-io/kli\n```\n\nThe flake ships `overlays.default`\n\nand `packages.<system>.default`\n\n, plus\n`homeManagerModules.default`\n\nand `nixosModules.default`\n\n, both exposing\n`programs.kli`\n\n. Add the NixOS module to a flake.\n\n```\n{\n  inputs.nixpkgs.url = \"github:NixOS/nixpkgs/nixos-unstable\";\n  inputs.kli.url = \"github:kleisli-io/kli\";\n\n  outputs = { nixpkgs, kli, ... }: {\n    nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {\n      system = \"x86_64-linux\";\n      modules = [\n        kli.nixosModules.default\n        ({ pkgs, ... }: {\n          programs.kli = {\n            enable = true;\n            extensions = [ ];\n            blessedNativeLibs = [ pkgs.sqlite ];\n            settings.theme = \"dark\";\n          };\n        })\n      ];\n    };\n  };\n}\n```\n\nHome Manager is identical through `kli.homeManagerModules.default`\n\n, configuring the\nsame `programs.kli`\n\n.\n\nFor a project-local image without touching your system, configure one in `shell.nix`\n\n.\n\n``` js\nlet\n  kli = builtins.getFlake \"github:kleisli-io/kli\";\n  system = builtins.currentSystem;\n  pkgs = import <nixpkgs> { inherit system; };\nin\npkgs.mkShell {\n  packages = [\n    (kli.lib.${system}.mkConfiguredKli {\n      extensions = [ ];\n      blessedNativeLibs = [ pkgs.sqlite ];\n      dataDir = \"$PWD/.kli-data\";   # null resolves the data dir from the environment\n      settings.theme = \"dark\";\n    })\n  ];\n}\n```\n\nEach extension is a derivation exposing `passthru.name`\n\nand\n`passthru.manifestSymbol`\n\n, and baked settings sit below your own as defaults.\n\nSBCL and [qlot](https://github.com/fukamachi/qlot), with external systems pinned in\n`qlfile`\n\n.\n\n```\nqlot install\nqlot exec sbcl --script build.lisp\n./bin/kli\n```\n\nModel providers (OpenAI, Codex, OpenAI-compatible endpoints) are themselves extensions on a provider registry, wired with OAuth and credential auth. Tools cover bash, eval, and a file surface of read, write, edit, find, and search over hashline anchors. Reads emit line and content-hash anchors, edits are anchor-validated patches that reject stale anchors instead of clobbering drifted files, and search results arm the same anchor cache so a match is editable without a separate read. The TUI, sessions with compacting logs, slash commands, themes, keybindings, and status widgets are all extensions too.\n\nkli enforces authority, which capabilities an agent may exercise, not containment. By\ndefault nothing kli runs is isolated from the host, so a granted shell command, file\nwrite, or `eval`\n\nacts with the full privileges of the kli process. For autonomous or\nuntrusted use, run kli inside your own confinement, bwrap, a container, or a VM.\n\nRun `kli --print-authority`\n\nto print the exact capabilities a session will hold, so\nyou can size that confinement. The configured-image producer also takes a `sandbox`\n\noption that wraps the entrypoint in bwrap. See [Security model and\nsandboxing](https://docs.kleisli.io/kli/concepts/security-model-and-sandboxing) for\nthe boundary in full and bwrap, container, and systemd recipes.\n\n```\nnix flake check\n```\n\nFiveAM suites under `t/`\n\n.\n\nkli is released under the [MIT License](/kleisli-io/kli/blob/main/LICENSE).", "url": "https://wpnews.pro/news/an-extensible-coding-agent-for-the-modern-lisp-hacker", "canonical_source": "https://github.com/kleisli-io/kli", "published_at": "2026-08-29 10:22:10+00:00", "updated_at": "2026-08-29 10:48:46.862191+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents", "ai-tools"], "entities": ["Kleisli.io", "kli", "SBCL", "Nix", "OpenAI", "Codex"], "alternates": {"html": "https://wpnews.pro/news/an-extensible-coding-agent-for-the-modern-lisp-hacker", "markdown": "https://wpnews.pro/news/an-extensible-coding-agent-for-the-modern-lisp-hacker.md", "text": "https://wpnews.pro/news/an-extensible-coding-agent-for-the-modern-lisp-hacker.txt", "jsonld": "https://wpnews.pro/news/an-extensible-coding-agent-for-the-modern-lisp-hacker.jsonld"}}