oml.shcoding agentbabashka
A minimal coding agent you change while it runs
oml is a coding agent in Clojure: its own agent loop in 1481 lines of babashka. Every step it takes is a named function, and you change any of them while it runs.
What it is
- Its own agent loop, small enough to read. Stream a Chat Completions call, run the tool calls, append the results, repeat. Built-in tools:
read,write,edit,bash. - Everything is a function. Each step of the loop, each tool and each slash command is a named function the core calls through its var. Redefine it with
defn, wrap it withadvise!, set a setting withsetq: from an init file, from/eval, or from an nREPL connected to the running agent. The next call uses it. - ACP is the UI. oml speaks the Agent Client Protocol over stdio, so Toad, Zed and Emacs agent-shell are its interface.
- Any OpenAI-compatible endpoint. A base URL, a key and a model id; responses stream over SSE.
Quick start
With nix (flakes enabled):
git clone https://github.com/sm-th/oh-my-lisp oml
cd oml
cp .env.example .env # set OPENAI_BASE_URL, OPENAI_API_KEY, OPENAI_MODEL
nix develop # or: direnv allow
oml-toad ~/some/project # Toad as the UI, oml as the agent
Then, in the session, try /tools, /doc oml.agent/run, or change the agent while it runs:
/eval (oml.custom/advise! #'oml.agent/system-prompt :pirate
(fn [system-prompt] (str (system-prompt) "\n\nAnswer like a pirate.")))
Read on
- Getting started: install, endpoint, Toad, Zed, Emacs, print mode, tests.
- Customising:
defn,advise!,setq; tools and commands as functions; init files; nREPL. - Primitives: the session, its transcript,
say,complete,call-tool,request!. - Recipes: project context, usage, search tools,
/model, permissions, a different loop. - Architecture: the namespaces, one turn from ACP to the model and back, limits.
- Chapters: what is done and what is planned.