A coding agent built on LLM
Project description
llm-coding-agent
A coding agent built on LLM
Built by Fable 5
The first working alpha was built using the following prompts:
Write a spec.md for this project - it will depend on the latest “llm” alpha from PyPI and implement a Claude code style coding agent complete with tools for reading and editing files and executing commands
Then:
Commit the spec, then build it using red/green TDD in a series of sensible commits (each with passing tests and updated docs) - occasionally manually test it using the OpenAI API key in your environment
Installation
Install this library using pip (the --pre flag is needed while this depends on an LLM alpha release):
pip install --pre llm-coding-agent
Usage
See spec.md for the full design.
This package is an LLM plugin: installing it adds an llm code command that starts an interactive coding agent session in the current directory, using any tool-capable model LLM knows about:
llm code # interactive session, default model
llm code "add type hints to utils.py" # start with an initial task
llm code -m gpt-4.1 -d ~/dev/myproject # pick a model and directory
llm code --yolo # auto-approve every tool call
llm code --allow "pytest*" --allow "git diff*" # pre-approve some commands
The model can read, search and edit files under the session directory and run shell commands there. Read-only tools run freely; file writes, edits and shell commands show you what the model wants to do and ask for approval - y approves once, a approves similar actions for the rest of the session, anything else declines (the model is told, and can try another approach). Inside a session !quit exits, !yolo toggles auto-approval, !model MODEL switches models mid-conversation and !tokens reports token usage.
Sessions are logged to LLM's SQLite database just like llm chat, so llm logs shows full transcripts including every tool call, and conversations can be resumed:
llm code -c # continue the most recent conversation
llm code --cid 01ab... # continue a specific conversation ID
llm logs --short # review what the agent did
The plugin also registers the toolbox with LLM itself, so the same tools work with llm chat or llm prompt:
llm chat --tool CodingTools --chain-limit 20
CodingAgent
CodingAgent runs the full agent loop against any LLM model that supports tools:
from llm_coding_agent import CodingAgent
agent = CodingAgent(
model="gpt-4.1-mini", # any llm model ID, or a model instance
root="/path/to/project",
approve=True, # approve every tool call
)
result = agent.run("Fix the failing test in tests/test_parser.py")
print(result.text) # the model's final answer
for tool_call, tool_result in result.tool_calls:
print(tool_call.name, tool_call.arguments)
agent.run("Now add a changelog entry") # the conversation continues
The approve= parameter controls what happens when the model wants to run a mutating tool (write_file, edit_file, execute_command - read-only tools never ask):
approve=Trueapproves everythingapprove=callable- a(tool, tool_call) -> boolfunction; returningFalsecancels that call and the model is told it was declinedapprove=None(the default) pauses the run:result.pausedis true,result.pending_tool_callslists what the model wants to do, and callingagent.resume()approves those calls and continues the loop - useful for approval flows in applications with no terminal attached
A chain_limit= (default 25) bounds how many tool-execution rounds a single run() can use; if it is hit, result.hit_limit is true.
CodingTools
The tools themselves live on CodingTools, an llm.Toolbox confined to a root directory, usable directly with model.chain():
from llm_coding_agent import CodingTools
tools = CodingTools("/path/to/project")
print(tools.read_file("README.md")) # numbered lines, like cat -n
print(tools.read_file("big.log", offset=100, limit=50))
tools.write_file("notes/todo.md", "- ship it\n") # creates parent dirs
print(tools.edit_file("app.py", "DEBUG = True", "DEBUG = False"))
edit_file performs exact string replacement: old_string must appear exactly once in the file (pass replace_all=True to replace every occurrence) and the tool returns a unified diff of the change so the model can verify what it did.
For exploring a project there are two search tools:
print(tools.list_files("**/*.py")) # newest first, respects .gitignore
print(tools.search_files("TODO", glob="*.py")) # path:line:content matches
search_files uses ripgrep when it is installed and falls back to a pure-Python scan (with identical output format) when it is not.
Shell commands run in the session root, with stdout and stderr interleaved and the exit code reported at the end:
print(tools.execute_command("pytest -x", timeout=300))
On timeout (default 120s, capped at 600s) the entire process tree is killed and any partial output is returned.
All file access is confined to the root directory - relative paths resolve against it, and any path that escapes it (via .., absolute paths or symlinks) returns an Error: string instead of file content, so a model using these tools can see and correct its mistake.
Development
To contribute to this library, first checkout the code. Then create a new virtual environment:
cd llm-coding-agent
python -m venv venv
source venv/bin/activate
Now install the dependencies and test dependencies:
python -m pip install -e '.[test]'
To run the tests:
python -m pytest
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file llm_coding_agent-0.1a0.tar.gz.
File metadata
- Download URL: llm_coding_agent-0.1a0.tar.gz
- Upload date:
- Size: 25.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
900c7001849ef1013da6dad95e2efc7405b7a0fd7a17b854b483357813b20da7
|
|
| MD5 |
c1fa1cdd3b81de9e12884985d7f328d0
|
|
| BLAKE2b-256 |
48c4ab5eb9eb787df526d6ba64123830aa65dbc79aa76445063d9986765d33c8
|
Provenance
The following attestation bundles were made for llm_coding_agent-0.1a0.tar.gz:
Publisher:
publish.yml on simonw/llm-coding-agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
llm_coding_agent-0.1a0.tar.gz -
Subject digest:
900c7001849ef1013da6dad95e2efc7405b7a0fd7a17b854b483357813b20da7 - Sigstore transparency entry: 2048550719
- Sigstore integration time:
-
Permalink:
simonw/llm-coding-agent@01dbde5897fcfe2841ecf7882203d8cf6e099b59 -
Branch / Tag:
refs/tags/0.1a0 - Owner: https://github.com/simonw
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@01dbde5897fcfe2841ecf7882203d8cf6e099b59 -
Trigger Event:
release
-
Statement type:
File details
Details for the file llm_coding_agent-0.1a0-py3-none-any.whl.
File metadata
- Download URL: llm_coding_agent-0.1a0-py3-none-any.whl
- Upload date:
- Size: 19.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3e9ad2081d880c2fd16713548fc7fe165b8159aed621562b7e6173e56ed4ed67
|
|
| MD5 |
5ae1c34d3b653bc8c28e2bf36c106039
|
|
| BLAKE2b-256 |
14710229f11023fb92cd581f2778fe9ada9935cac4e37e3fedef9be2fc31bc79
|
Provenance
The following attestation bundles were made for llm_coding_agent-0.1a0-py3-none-any.whl:
Publisher:
publish.yml on simonw/llm-coding-agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
llm_coding_agent-0.1a0-py3-none-any.whl -
Subject digest:
3e9ad2081d880c2fd16713548fc7fe165b8159aed621562b7e6173e56ed4ed67 - Sigstore transparency entry: 2048550728
- Sigstore integration time:
-
Permalink:
simonw/llm-coding-agent@01dbde5897fcfe2841ecf7882203d8cf6e099b59 -
Branch / Tag:
refs/tags/0.1a0 - Owner: https://github.com/simonw
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@01dbde5897fcfe2841ecf7882203d8cf6e099b59 -
Trigger Event:
release
-
Statement type: