Autolith: a programming agent with a live runtime
Autolith runs in a terminal and works directly in your repository. It can read and edit files, search the workspace, run commands and tests, keep project context, and use Common Lisp without leaving the conversation.
- Repository work. Filesystem, shell, and search tools with visible results.
- Oversized context. Recursive inference over corpora larger than the model window.
- Continuity. Portable conversations, memories, agendas, checkpoints, and recovery.
- Live Lisp. An SBCL runtime it can inspect, test, and extend.
- Unattended. A single-job boundary with a structured-output contract, drivable from scripts and CI.
For developers who want an agent they can inspect, extend, and recover.
Install Autolith
Runs on Linux, macOS, FreeBSD, NetBSD, and OpenBSD. The binary carries its own SBCL, Lisp dependencies, and native helpers, and installed releases check for newer tags and ask before updating.
Sign-in methods and models are covered in the docs.
Yes, piping a URL into a shell is evil. Read the installer before running it. Nix is the better installation path.
Autolith executes model-generated code with your user privileges. Its process boundaries protect reliability, not against hostile code. Use it as a development agent, not as a security sandbox.
After the binary installer
$ autolith
Recommended · Nix
$ nix run github:lambda-symbolics/autolith
Build from the repository
$ git clone https://github.com/lambda-symbolics/autolith
$ cd autolith
$ ./script/bootstrap
$ ./script/check
$ ./bin/autolith
Examples
- Prompt
- Use rlm.complete over autolith-source.txt in the workspace root. It is the concatenation of this repository's 121 src/*.lisp files with ';;;; FILE:' headers, about 3.1 MB, larger than your context window. Task: list every condition class defined in the source, grouped by subsystem, with the defining file for each. Use a budget of 32 calls, 400000 tokens, depth 2. Do not read or search the file directly; if the budget exhausts, stop and report.
- Provider
- ChatGPT Codex subscription · gpt-5.6-terra (effort high)
- Wall time
- 3 min 15 s for the answer; 4 min 36 s for the whole session
- Tokens
- 59.6K in the root conversation (58.7K input + 915 output); the corpus itself never enters a prompt
- Artifact
- All 83 condition classes, grouped by 14 subsystems, each with its defining file
- Trace
inference:s2Wb1o2, the complete frame conversation, readable in-session with resource.read- Reproduce
find src -name '*.lisp' | sort | while read f; do printf ';;;; FILE: %s\n' "$f"; cat "$f"; done > autolith-source.txt && autolith, then the prompt above
- Prompt
- Show the source of terminal-ui--duration-text in your running image, then redefine it live so durations of 24 hours and more render as Dd H:MM:SS, for example 1d 2:00:00. Exercise the change with assertions for 59 seconds, 61 minutes, and 26 hours, then commit the mutation with a short message. Then deliberately break the function with a redefinition that signals an error, demonstrate the failure with self.eval, and recover by discarding the broken mutation. Verify with self.eval that the committed version is active again.
- Provider
- ChatGPT Codex subscription · gpt-5.6-terra (effort high)
- Wall time
- About 6 minutes, including the crash and the recovery boot
- Tokens
- 289.0K total (286.1K input + 3.0K output), most of it the bounded crash context of the diagnosis turn
- Artifact
- Private image commit "Format long activity durations". The broken
formatter is used by the live status row, so the deliberate break
killed the active process outright: Autolith wrote crash capsule
efa6aa16, booted the pristine recovery image, restarted from clean committed source with the private commit selected, restored the conversation, and opened a read-only diagnosis turn that asked before repairing anything. The committed mutation survived its own author. - Trace
- Append-only mutation journal, the crash capsule, and the private commit's replay script
- Reproduce
autolithin any workspace, then the prompt above
- Prompt
- Define autolith-demo-parse-fraction in the autolith package: parse a string like "3/4" into a rational. Exercise it, then persist it as a private image commit. Then add an agenda entry: handle zero denominators in autolith-demo-parse-fraction. After (quit) and autolith resume: Where were we? Check the agenda, confirm autolith-demo-parse-fraction is still defined in this fresh image by evaluating (autolith-demo-parse-fraction "3/4"), then finish the agenda item: signal a clear error for a zero denominator, exercise both paths, and mark the agenda entry done.
- Provider
- ChatGPT Codex subscription · gpt-5.6-terra (effort high)
- Wall time
- 10 min 11 s across two processes; each persist runs the full validation suite before anything is retained
- Tokens
- 601.1K total for the resumed conversation (598.5K input + 2.6K output)
- Artifact
- Private image commits 4048480f and 9eee3ae4. The function defined before (quit) answers (autolith-demo-parse-fraction "3/4") = 3/4 in the next process without any reloading; the agenda entry written in the first session is found, finished, and marked done in the second.
- Trace
- Append-only conversation store, the two commits' replay scripts, and the workspace agenda
- Reproduce
autolith, the first prompt,(quit), thenautolith resumeand the second prompt
The agent and its tools run in one process
Autolith is a terminal programming agent, not a wrapper around another agent process. Its Common Lisp image contains the provider client, terminal interface, tool registry, MCP connections, conversation state, persistent memories, workspace agenda, and the code that decides what happens next.
Context larger than the window is an environment, not a prompt.
rlm.complete interns the corpus as a
content-addressed object; the model receives only its label, size,
and digest, and drives a heap-isolated Lisp environment through
bounded slices, searches, and sub-inferences under an explicit
call and token budget. Every run leaves a readable inference
trace.
The conversation is not the only entry point. A
run-job boundary runs one
non-interactive job with a bounded data-only S-expression
envelope and a structured-output contract, reports trace and
usage, and installs the result atomically.
Fast search, optional immutable mode
Workspace search runs in-process through fff, a fast Rust search library. Autolith keeps the index warm instead of starting a new search process for every query.
If you want inspection without active-image changes, start it with
--immutable. The mode retains read-only inspection and
recovery information while withholding evaluation, mutation,
persistence, checkpoint, and rollback tools.
Update the running agent without restarting it
Autolith can inspect and replace complete functions, methods, classes, macros, conditions, and global settings in its running image. An exploratory change takes effect immediately and is recorded in an append-only mutation journal. It can be exercised, discarded, or retained as a private image commit.
A useful change can then become a private image commit. The commit contains a manifest and a complete executable Lisp replay script, retained in a separate private Git history. It changes the active agent without quietly patching the tracked source repository.
And when a signal interrupts the work, the live restart debugger offers Ask Autolith why this failed: an independent diagnosis beside the still-live restarts, with up to three validated recovery proposals.
→ lisp.source TERMINAL-UI--DURATION-TEXT target self
← complete tracked DEFUN
→ self.redefine
(defun terminal-ui--duration-text ...)
← compiled and installed in the active image
→ self.exercise
(assert (string= "1d 2:00:00" ...))
← journaled assertion passed
→ self.diff
← one reconstructible live mutation
→ self.commit "Show days in long durations"
← private image commit commit-id
complete reconstruct.lisp retained in private Git
Different kinds of state stay separate
Source, conversations, useful facts, live mutations, exact heaps, and disposable experiments have different lifetimes. Autolith keeps them separate instead of pretending that one database or one saved core is everything. Shared state transactions are serialized across processes, so concurrent agents can share one workspace.
| Conversations | Append-only portable S-expressions with exact resume commands, crash-tail repair, and read-only replay navigation. |
|---|---|
| Memories | Workspace or global facts, preferences, and decisions with bounded prompt recall. |
| Agendas | Short workspace tasks and notes, available in full on every request. |
| Private image commits | Complete replay scripts for durable user-specific definitions and settings, retained in private Git. |
| Generations | A saved active core, exact tracked source commit, reconstruction script, manifest, and journal position. |
| Worker images | Immutable experimental SBCL cores with parentage and durable notes, never selected as the active agent. |
| Recovery | A separately built pristine image that can inspect a crash and select a known-working generation without loading the damaged core. |