by he-yufeng
Minimal AI coding agent (~1,000 lines of Python) inspired by Claude Code. Works with any LLM. Think NanoGPT for coding agents. Formerly NanoCoder.
# Add to your Claude Code skills
git clone https://github.com/he-yufeng/CoreCoderLast scanned: 5/9/2026
{
"issues": [],
"status": "PASSED",
"scannedAt": "2026-05-09T06:16:10.022Z",
"semgrepRan": false,
"npmAuditRan": true,
"pipAuditRan": true
}CoreCoder is an open-source ai agents skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by he-yufeng. Minimal AI coding agent (~1,000 lines of Python) inspired by Claude Code. Works with any LLM. Think NanoGPT for coding agents. Formerly NanoCoder. It has 1,455 GitHub stars.
Yes. CoreCoder passed SkillsLLM's automated security scan — a dependency vulnerability audit plus prompt-injection heuristics — with no high-severity issues. You can read the full report in the Security Report section on this page.
Clone the repository with "git clone https://github.com/he-yufeng/CoreCoder" and add it to your Claude Code skills directory (see the Installation section above).
CoreCoder is primarily written in Python. It is open-source under he-yufeng on GitHub, so you can review or fork the full source.
Yes. SkillsLLM lists many other AI Agents skills you can browse and compare side by side. Open the AI Agents category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh CoreCoder against similar tools.
No comments yet. Be the first to share your thoughts!
The nanoGPT of coding agents. 1,081 lines of pure Python — understand how a coding agent actually works, then fork your own.
learn from it · fork it · ship something better
中文 | English | Source-reading series · 8 bilingual essays
| CoreCoder | Claude Code | aider | nanoGPT | |
|---|---|---|---|---|
| Lines of code | ~1,081 engine / 1,714 total | hundreds of thousands (closed) | tens of thousands of Python | ~600 (two files) |
| Time to read it all | one afternoon | can't (closed) | a few days of slogging | one afternoon |
| Breakpoint, change, rerun? | yes, every line | no | yes, but there's a lot | yes |
| What it's for | understand one, then fork your own | production coding assistant | terminal pair-programming | minimal GPT for teaching |
The nanoGPT column is there as a reference point: minimal, readable, but it teaches you to train a GPT. CoreCoder is after the same thing, only the subject is an agent that actually edits code. Sitting it next to Claude Code and aider isn't about competing for their users. CoreCoder is the foundation you stand on while you learn from them and get going; it isn't in the same race.
I've always felt coding agents get talked about as if they were arcane. Strip a tool like Claude Code or Cursor all the way down and the core is a while loop wrapped around a large model, plus seven or eight tools that let it actually do things. The hard part was never the loop; it's everything the loop has to cope with once it meets the real world. CoreCoder is the minimal version that writes that core out honestly.
The engine (loop, model interface, context, tools, sessions) is 1,081 lines once you drop blank lines and comments. Counting the outer CLI, config and packaging too, the whole package is 18 files: 1,714 physical lines, 1,385 net, every one short enough to read in a single sitting.
And it really runs: reads and writes files, executes shell, spawns sub-agents, compacts context in three tiers, and tells you the tokens and dollars a run burned whenever you ask. 86 tests, all green. But the point of it running isn't to become your daily driver. It runs so the walkthrough can't lie: a reference that shows how an agent works has to actually work.
The code came out of a public teardown: open analyses have already exposed a lot of the load-bearing architecture inside production agents like Claude Code. I took the most essential layer and rewrote it honestly, in as little code as I could. So reading CoreCoder is roughly like reading a runnable, annotated take on how that kind of agent works, except it's only a minimal reimplementation, sitting right there on your machine for you to take apart and change.
This README follows the same arc: the first half helps you read it (the code map, the main loop, eight essays), the second half helps you fork it and points at a few directions worth pushing further.
Before you read the source, get it running on your machine once to build some intuition. It's a foundation meant for forking, so the recommended path is to clone it and install editable, reading and changing as you go:
git clone https://github.com/he-yufeng/CoreCoder
cd CoreCoder
pip install -e .
If you just want to get it running first, pip install corecoder works too.
Give it a model and a key and it goes. It speaks the OpenAI-compatible API by default, and switching providers is usually just two environment variables:
| Provider | Example env vars |
|---|---|
OpenAI (default gpt-5.5) |
OPENAI_API_KEY=sk-... |
| DeepSeek | OPENAI_API_KEY=sk-... OPENAI_BASE_URL=https://api.deepseek.com CORECODER_MODEL=deepseek-chat |
| Local Ollama | OPENAI_API_KEY=ollama OPENAI_BASE_URL=http://localhost:11434/v1 CORECODER_MODEL=qwen2.5-coder |
Kimi, Qwen and the like are the same two variables; for providers that don't even offer an OpenAI-compatible endpoint, the optional LiteLLM backend (pip install "corecoder[litellm]") routes to a hundred-plus of them. The third essay goes into this in detail. The key can be exported directly or dropped into a .env at the project root, which is loaded on startup. Then:
corecoder # interactive REPL
corecoder -p "add error handling to parse_config()" # one-shot mode, exits when done
Laid out flat, the whole project is this big. Skim it before you clone and you'll know where everything is. This is the most concrete difference from Claude Code's hundreds of thousands of lines: you can read it like the table of contents of a book. Start from the main loop in agent.py; that's the heart of the whole agent.
corecoder/
├── agent.py agent loop + parallel tool exec 150 lines ← start here
├── llm.py streaming client + retry + cost 336 lines
├── context.py three-tier context compaction 210 lines
├── session.py save / resume + path-traversal guard 97 lines
├── prompt.py system prompt 33 lines
├── cli.py REPL + slash commands + one-shot 270 lines
├── config.py env-var config 57 lines
└── tools/
├── bash.py shell + dangerous-command gate + cd 127 lines
├── edit.py unique-match search/replace + diff 92 lines
├── grep.py content search 79 lines
├── glob_tool.py filename matching 47 lines
├── read.py file read 53 lines
├── write.py file write 38 lines
├── agent.py sub-agent spawning 58 lines
└── base.py tool base class 27 lines
Seven tools: bash, read_file, write_file, edit_file, glob, grep, and agent (which spawns a sub-agent). Everything else is the CLI shell, config, and packaging wrapped around that engine core.
while loop is the whole agentThe whole of an agent fits in one sentence: hand the user's words to the model, run whatever tools it asks for, stuff the results back into the context, ask again, and keep going until it stops asking for tools and gives an answer. In code, that's about a dozen lines:
# corecoder/agent.py · the main loop (trimmed skeleton)
def chat(self, user_input):
self.messages.append(user_input)
for _ in range(self.max_rounds): # bounded, so it can't run away
reply = self.llm.chat(self.messages, self.tools) # ask the model what to do next
if not reply.tool_calls: # model wants no more tools
return reply.text # -> done, hand the answer back
results = run_parallel(reply.tool_calls) # tools requested -> run in parallel
self.messages += results # feed results back, loop again
return "(hit the round limit)"
That's the whole thing. The core skeleton is about twenty lines; counting parallel execution and the bookkeeping after a Ctrl+C interrupt, maybe forty. Almost everything else in CoreCoder's thousand-odd lines is there to clean up the mess the loop runs into once it meets the real world. llm.py ends up the biggest file in the project, not because calling a model is hard, but because a streamed response splinters each tool call's arguments into fragments you have to restitch in order, a provider will hand you half a JSON object or a null usage field, and 429s, timeouts, dropped connections and 5xx all need backoff-and-retry while the other 4xx should just raise. That unglamorous grunt work, not the loop, is where the real engineering of taking an agent from demo to delivery actually lives; the third essay follows it down to the line.
Three decisions are worth a closer look, because they're the kind of call you can only make after you've understood how others did it, and they're judgments you can lift straight into your own fork.
edit_file does search-and-replace on a unique match, not line numbers. Line numbers are a trap: the model only has to miscount by one and it quietly edits the wrong place. Anchor on a unique snippet of the original instead. If there's no