____ __ ____ _ _ _
/ ___ ___ __| | ___ | _ \ (_) | | | |
| | / _ \ / _ | / _ \ | |_) | | | | | | |
| |___ | (_) | | (_| | | __/ | _ < | | | | | |
\____ \___/ \__,_| \___| |_| \_\ |_| |_| |_|
A coding agent small enough to actually read.
Point it at a project, describe what you want, and it reads, writes, edits and runs code on its own. In standard mode, it asks before running tools that change files, run commands, or access the network.
Project website · English · 中文
The pitch
Coding agents are not scarce. Coding agents you can read are.
CodeRill is a few thousand lines of Python with focused tests. You can open
agent.py and follow a whole turn — build the request, stream
the reply, run the tools, loop — without crawling through five layers of
abstraction. Each subsystem is a handful of files, and each file is named after
the one thing it does.
That is the whole idea. Small is the feature, not the excuse.
you > there's a bug in utils.py — parse() crashes on empty input
allow edit_file? {"file_path": "utils.py", ...}
--- a/utils.py
+++ b/utils.py
- return json.loads(text)
+ return json.loads(text) if text else {}
[y]es / [n]o / [a]lways > y
→ edit_file (file_path="utils.py")
→ bash (command="python -m pytest tests/test_utils.py")
Fixed. parse() returns {} on empty input now instead of raising.
How it works
The agent is one loop. Each turn it streams a reply from the model; if the reply asks for tools, the agent runs them and feeds the results back, then loops. When the model answers without asking for a tool, the turn is over.
user message
|
v
+----------------------+
| compress + build the | <-- context.py, prompt.py, skills.py
| request (skills, plan,|
| todo, system prompt) |
+----------------------+
|
v
+----------------------+
| stream model reply | <-- llm.py (streaming + retry + deadlines)
+----------------------+
|
tool calls?
/ \
yes no --> done
|
v
+-------------------------------------------------+
| hooks -> consent -> run tools -> post hooks | <-- agent.py
| (read-only tools run in parallel) |
+-------------------------------------------------+
|
append results to the session log, loop
Decisions I'd defend in a code review
- File tools stay in the workspace. Their paths are resolved against the project root and rejected if they land outside — the check lives in one place, not in each tool. Shell commands are not sandboxed.
- Consent is code, not a prompt. Mutating calls go through a policy that classifies the action and either matches a saved grant or asks you, showing a diff for file writes. "Always" saves a scoped grant — a path, a command prefix, a host — never an open-ended yes.
- The session log is append-only. Compression writes a checkpoint and leaves the earlier events in place, so the audit trail survives and a session can be replayed, forked, or shared without touching the durable history.
- Tool failures are data, not crashes. A failed tool returns an error string the model can read and recover from, instead of unwinding the loop.
- Read-only tools run in parallel; writes do not. Concurrency where it is free, ordering where it matters.
What's in the box
| File | Responsibility |
|---|---|
coderill/agent.py |
The loop: turns, parallel tools, hooks, consent, sub-agents, plan reconciliation. |
coderill/llm.py |
Model client: streaming, tool-call reassembly, retry, deadlines, usage. |
coderill/tools/ |
The tools and the registry that dispatches them. |
coderill/permissions.py |
Consent: classification, modes, scoped persistent grants. |
coderill/review.py |
The trusted pre-write diff shown before a file changes. |
coderill/hooks.py |
User shell hooks around tool calls. |
coderill/skills.py |
File-based skills discovered and loaded on demand. |
coderill/taskplan.py |
The task plan, with revision-based concurrency. |
coderill/context.py |
Three-layer context compression. |
coderill/session.py |
Append-only JSONL event log, replay, fork and share. |
coderill/checkpoints.py |
Undo for the file-writing tools. |
coderill/mcp.py |
A distilled MCP stdio client. |
coderill/browser.py |
The optional Jev browser-task loop. |
coderill/cli.py |
The terminal interface. |
coderill/config.py |
Environment and settings. |
The tools
- read_file / write_file / edit_file — read with line numbers, write, and replace an exact unique string (returning a unified diff).
- bash — run a shell command from the workspace root (Git Bash on Windows).
- glob / grep — find files by pattern, search contents by regex.
- todo_write — the agent's lightweight checklist.
- task_list / task_create / task_update / task_revise — a real task plan with stable IDs and revisions.
- load_skill — pull a skill's instructions into the conversation.
- agent — delegate a self-contained sub-task to a fresh sub-agent.
- browser_task — hand a whole web task to the Jev model (optional).
Install
With Python, Git and pipx installed:
pipx install git+https://github.com/YeChenglin8888/CodeRill.git
coderill --version
This installs the current GitHub source. A versioned PyPI release is not available yet.
Set OPENAI_API_KEY in your environment or in a .env file in the project where
you run CodeRill before starting an agent session.
For development from a checkout:
git clone https://github.com/YeChenglin8888/CodeRill
cd CodeRill
pip install -e .
cp .env.example .env # then set OPENAI_API_KEY
Any OpenAI-compatible endpoint works — set OPENAI_BASE_URL for DeepSeek,
Moonshot, a local vLLM server, or whatever you use.
Use
coderill # interactive session
coderill "add type hints to llm.py" # one-shot
coderill --cwd ~/myproject # run against another directory
coderill --plan # start in plan mode (read-only)
coderill --auto-approve # no consent prompts
coderill --list # list saved sessions
coderill --resume 20260101-1200 # resume one
Inside the REPL: /help, /new, /list, /resume <id>, /where, /cost,
/undo, /share, /fork, /plan, /approve, /mode, /reasoning, /mcp,
/exit.
Skills
Drop a SKILL.md (or a <name>.md) into <project>/.agents/skills/,
<project>/skills/, ~/.agents/skills/ or ~/.coderill/skills/. The model sees
only each skill's name and one-line description; the body enters the conversation
only when it calls load_skill. Project skills override global ones of the same
name.
Sessions
A conversation is a JSONL event log under ~/.coderill/sessions/<id>.jsonl. The
message list is a projection replayed from that log, so you can resume it, /fork
it into a branch, or print a redacted /share transcript — none of which touch
the durable history. Task-plan updates are also logged, so resume and fork keep
the plan and its revision.
The Jev browser task (optional)
browser_task delegates a whole web task to TypeSafe's Jev model, a sub-second
"System 1" decision model that returns typed choices instead of text. CodeRill
drives a real browser with Playwright, asks Jev for the next operation, and
returns JSON page evidence plus a stop reason; model_done is Jev's claim, not
independent verification.
Its DOM reader (browser_snapshot.js) is adapted from browser-use/jev-ultrafast;
see coderill/browser_NOTICE.txt for the MIT notice
and reference commit. Install with pip install -e ".[browser]", then set
CODERILL_BROWSER_ENABLED=1 and the TYPESAFE_* variables.
Configuration
| Variable | Default | Meaning |
|---|---|---|
OPENAI_API_KEY |
— | Required. |
OPENAI_BASE_URL |
OpenAI | Any compatible endpoint. |
CODERILL_MODEL |
gpt-4o-mini |
Model name. |
CODERILL_MAX_TOKENS |
4096 |
Per-response cap. |
CODERILL_TEMPERATURE |
0 |
Sampling temperature. |
CODERILL_MAX_TURNS |
30 |
Tool rounds per user turn. |
CODERILL_MAX_CONTEXT |
128000 |
Context budget before compression. |
CODERILL_BROWSER_ENABLED |
0 |
Register the browser tool. |
CODERILL_BROWSER_CHANNEL |
msedge |
msedge or chrome. |
TYPESAFE_API_KEY |
— | Key for the Jev browser model. |
TYPESAFE_MODEL |
jev-latest |
Jev model name. |
State lives in ~/.coderill/: hooks.json, mcp.json, permissions.json,
skills/, sessions/.
Tests
pip install -e ".[dev]"
pytest tests/ -q # offline: no network, no API key
ruff check .
GitHub Actions runs these checks on Linux and Windows. The six real-browser integration tests are skipped unless explicitly enabled.
The loop, tools, permissions, hooks, skills, task-plan, context, review and
session tests use fakes, so the suite runs without a network. Browser tests run
against a fake browser and fake Jev responses; the real-browser checks are opt-in
via CODERILL_BROWSER_TEST=1.
What's next
- A provider layer with a first-class Anthropic adapter (today: any
OpenAI-compatible endpoint via
OPENAI_BASE_URL). - Sandboxed command execution and multimodal attachments.
- A Textual TUI as a client of the same runtime.
Acknowledgements
The Jev browser module adapts DOM-reading code from
browser-use/jev-ultrafast (MIT) —
the notice ships with the JS, in
coderill/browser_NOTICE.txt.
License
MIT — see LICENSE.
Metadata
Release files for coderill 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| coderill-0.1.0.tar.gz | 76.7 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| coderill-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 139.0 kB
Release files / coderill-0.1.0.tar.gz
| Download URL | coderill-0.1.0.tar.gz |
|---|---|
| Size | 76.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5164a146ec5161f905a6bc02aee7038eb4f21b189f1b3a6e21c51d754a8280f4
|
|
BLAKE2b-256 checksum How to use checksums |
a3296977bd378a43eddd1d96409c5dbe980626418db74c8c4f4e934e66e25de5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logRelease files / coderill-0.1.0-py3-none-any.whl
| Download URL | coderill-0.1.0-py3-none-any.whl |
|---|---|
| Size | 62.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
953c54acf8bbeadf9485a86ab891e32a277fccab42645a9fedd8bf7aaa913795
|
|
BLAKE2b-256 checksum How to use checksums |
b5146d12f30166d7d1f25565db76f400b953f00e503220099ed1f7021511d935
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logSecurity for coderill 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for coderill-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.