cd /news/ai-agents/autocode-one-file-one-tool-and-permi… · home topics ai-agents article
[ARTICLE · art-126852] src=empero.org ↗ pub= topic=ai-agents verified=true sentiment=· neutral

autocode — one file, one tool, and permission to rewrite itself

Empero-org released autocode, a coding agent contained in a single Python file of about 640 lines that ships with exactly one tool, bash, and is permitted to rewrite its own source code while working. The runner copies runner.py into each project, checks between steps whether the file changed, keeps the previous version in .autocode/runner.prev.py, and re-execs itself if the new version compiles, while any file in .autocode/tools/ defining a SCHEMA and run() function is picked up on the next step. The agent compacts context when it passes 80% of the window, and the release notes a pre-release bug in which some OpenAI-compatible servers ignored tool_choice: "none" and let a one-line preamble become the entire new context.

read5 min views2 publishedSep 11, 2026

autocode is out — a coding agent that fits in a single Python file, ships with exactly one tool, and is allowed to edit its own source while it works. No dependencies, no framework: the least an agent needs, if it gets to build the rest.

Agent frameworks have a habit of growing. Every release adds a tool, every tool

adds a schema, every schema adds a paragraph to the system prompt, and before long

the model spends its first few thousand tokens reading instructions about

instructions. Abacus sits deliberately at the full-featured end of that: plans,

approvals, subagents. autocode is the experiment at the other end — what is the least an agent needs, if it is allowed to build the rest itself?

The answer we shipped: one Python file, one tool, the standard library, and

permission to rewrite itself.

autocode on GitHub: empero-org/autocode

One file, and it's yours #

Install once, then run autocode in a project. The first run copies runner.py

into that directory and starts it. That file is the whole agent — the loop, the

streaming client, sessions, compaction, the REPL — in about 640 lines, with no

imports outside the standard library.

It is copied, not imported, on purpose. The agent is told where its own source

lives and that it may improve it. Between steps the runner checks whetherrunner.py changed; if the new version compiles, it saves the session, keeps the

previous version in .autocode/runner.prev.py, re-execs itself and carries on

with the same task. If it doesn't compile, the model is told about the syntax

error and the working version keeps running.

So every project ends up with its own agent, shaped by the work done there.autocode --diff shows how far it has drifted from the one we shipped.autocode --reset puts it back.

One tool #

The model gets bash. Nothing else. Commands run exactly as written — no

wrappers, no rewriting, no parser second-guessing the model. The runner only does

what a shell can't do for itself: a timeout that kills the whole process group, a

closed stdin so nothing waits for a human, a working directory that persists

between calls, and long output cut to its head and tail with the full text saved

to a file the agent can page through.

Search, edit, test, git — everything a model reaches for is already a command

away.

Tools it writes itself #

When a shell isn't enough, the agent writes a tool. Any file in.autocode/tools/ that defines a SCHEMA and a run() function is picked up on

the next step. A tool that fails to import doesn't disappear: it shows up to the

model marked BROKEN, with the error attached, so the agent can fix what it

wrote. The tools are plain Python in your repository — worth committing, if they

turn out to be good.

A system prompt you can read in ten seconds #

Three lines. Who it is and where; work until the task is done and verify as you

go; your own source is editable; here is how to add a tool. Plus the project'sAGENTS.md, if there is one. That's the whole prompt. Everything else the model

knows about your project, it found out with the shell.

Long sessions, honestly #

A small agent still runs long sessions, so compaction had to be right. When the

context passes 80% of the window, the model summarizes the conversation and the

summary replaces it — except your newest message and the latest step, the last

model message with its tool results, which stay word for word. The summary

request reuses the exact prefix of a normal request, so providers with prompt

caching reuse the cache.

We found a bug in it before release, and it's worth telling. The first version

asked for the summary with tool_choice: "none". Some OpenAI-compatible servers

ignore that field, so a model can answer "summarize this" with a tool call and a

one-line preamble — and that preamble became the entire new context. Against a

scripted fake server, a session's request and its failing test output were

replaced by "Let me look at the test file first."

Now a reply that isn't a summary is rejected and retried as a plain transcript

with no tools to call, a failed compaction never blocks the session, and the full

transcript is archived before anything is replaced. There's a test for exactly

that case. Not a feature. A fix we'd rather tell you about than have you find.

Any endpoint #

The first run opens a short setup. It marks the backends it can already use — a

key in your environment, a local server that's running — lists the server's

models, runs a one-line test call and saves the config. OpenAI, OpenRouter,

DeepSeek, Groq, a Qwythos on Ollama or llama.cpp: if it speaks/chat/completions, autocode runs on it.

Thinking is read from whichever field your server uses - reasoning_content, reasoning, OpenRouter's reasoning_details, or <think> tags left in the

answer and shown in the terminal next to the reply, with markdown, highlighted

code and LaTeX drawn as Unicode. The renderer is standard library too.

What it doesn't do #

autocode gives a model a shell and no approval step. That is the point of it, and

it is also the reason to run it somewhere you can afford to be surprised: a

container, a VM, a repository you can reset. It needs bash, so Linux and macOS.

And an agent that rewrites itself can rewrite itself badly — that's whatrunner.prev.py and --reset are for. If you want every change shown as a diff

before it lands, that's Abacus.

We built autocode to answer a narrow question: how little an agent can start with

and still do real work. It turned out to be one file, one tool, and a model that

is allowed to make the rest.

pip install empero-autocode
cd your-project
autocode

Get it on GitHub: empero-org/autocode ·

PyPI: empero-autocode

*autocode is open source, Apache-2.0. Point it at a Qwythos on your own machine

and see what it turns itself into.*

── more in #ai-agents 4 stories · sorted by recency
── more on @autocode 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/autocode-one-file-on…] indexed:0 read:5min 2026-09-11 ·