little-coder: a pi-based agent harness tuned for small local models
A harness optimized to smaller LLMs
At a glance
- What is it?
- little-coder wraps pi with roughly thirty extensions, thirty skill markdown files and a Python benchmark harness, aimed at people running 9B to 35B models on their own hardware. The design bet is scaffold-model fit, and the cost of that bet is a closed extension set at launch.
- Who is it for?
- Adopt little-coder if you already serve a local model through llama.cpp, Ollama or LM Studio and want a terminal agent whose scaffold is tuned for that model class rather than a frontier API. Skip it if you need your globally installed pi extensions to load by default, or if you expect Deep Research to read the repository you are sitting in; it will not.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 17 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem little-coder targets: a scaffold that matches a small model
Most coding agents are written for frontier models reached over an API. Their prompts, tool descriptions and recovery paths assume a large context window and a model that can hold a long instruction set without drifting. little-coder starts from the opposite end. The README describes it as a coding agent tuned for small local models, and the research post it links to is framed around why scaffold-model fit matters, with a claim that a 9.7B Qwen beat frontier entries on Aider Polyglot under this harness. That claim lives in the author's write-up, not in anything you can verify from the repository alone. The audience is narrow and identifiable: someone with a GPU or a laptop that can serve a Qwen-class model locally, who wants an agent loop rather than a chat window, and who is willing to accept a fixed tool set in exchange for predictable behaviour. If you are paying per token for a frontier model, the premise of the project does not apply to you.
What sits on top of pi, and what stays in pi
little-coder does not fork pi and does not shadow its CLI. According to the README, pi is a plain dependency in package.json, and everything project-specific lives under .pi/extensions/, skills/ and benchmarks/. pi itself supplies the substrate: the agent loop, a multi-provider API, the TUI, a session tree, compaction, and an extension model, with four built-in tools (read, write, edit, bash) and a system prompt of roughly 1000 tokens. The little-coder layer is about thirty extensions, about thirty skill markdown files, and a Python benchmark harness. That split matters when you debug something. If the agent loop misbehaves, the bug is probably in pi. If the tool selection is odd, or a skill card is being injected when you did not want it, that is the little-coder layer. The repository layout tells you which file to open.
The launcher, --no-extensions, and the 7k cold start
The launcher runs pi with --no-extensions and wires in exactly the bundled set. The README gives the reason: it keeps cold-start context around 7k tokens and makes behaviour predictable, because the set that loads is the set that ships and nothing in your working directory changes it mid-task. This is the most consequential design decision in the project, and it has a direct cost. A package installed globally with pi install registers into pi's settings, and --no-extensions skips those settings, so it will not load inside little-coder by default. That surprises people who installed a pi extension globally and then wonder why it is absent. There are three opt-in routes, none of which change the default: put your own extensions in ~/.config/little-coder/extensions/, point LITTLE_CODER_EXTRA_EXTENSIONS at files anywhere, or relaunch with --with-pi-extensions to let pi discover its own. The /extensions command shows what is loaded. Themes are unaffected, since pi themes have always loaded. I would call the default defensible rather than obviously right: a fixed tool set is what makes a small model's behaviour repeatable, but it also means the harness is a walled garden you have to climb out of deliberately.
Install and first run, with the commands as documented
Node.js 22.19 or later is required. The one-line install is curl -fsSL https://raw.githubusercontent.com/itayinbarr/little-coder/main/install.sh | bash. You can also use npm install -g little-coder or bun add -g little-coder. The README states there is no clone, no workspace npm install, and no PATH fiddling; the binary lands on your PATH and works from any directory. There is a caveat for bun users that is easy to miss: bin/little-coder.mjs carries a #!/usr/bin/env node shebang, so Node 22.19 or later still has to be on your PATH even when bun did the install. The README suggests replacing the shebang in $(bun pm bin -g)/little-coder with #!/usr/bin/env bun if you want a node-less setup. Running it means cd into your project and then little-coder, or little-coder --model llamacpp/qwen3.6-35b-a3b to name a model explicitly. Bare little-coder launches the default declared in models.json, which ships as "default": "llamacpp/qwen3.6-35b-a3b", and prints the friendly name at startup. That default only applies on a first run; once you pick a model in-session the choice sticks and the default stops overriding it. You change it with a default key in the user override file. Cloud and other local providers are named the same way: anthropic/claude-haiku-4-5, openai/gpt-4o-mini, ollama/qwen3.5, lmstudio/local-model. little-coder --list-models shows everything pi knows about. The working directory is the one you launched from, so read, write, edit and bash operate on your project rather than on the install path.
Plan Mode and /implement: splitting research from editing
Plan Mode toggles with ctrl+q (a PLAN MODE indicator appears below the input) or starts enabled with --plan-mode, which also reads LITTLE_CODER_PLAN_MODE=1. In that mode, a request is researched with sub-coders, you get one to three clarifying questions each with suggested answers and a free-text option, and the output is a plan written in chat rather than an edit. Approving the plan saves it to .pi/approved-plan.md and stops. The /implement command is what switches to the action model, opens a fresh session seeded with the plan, and starts work. The stated reason is context economy: the research and question-and-answer that produced the plan do not consume the context the implementation needs. That is a real constraint for small models, where a long transcript degrades tool use well before the window is full. Esc cancels a plan mid-run, and shift+tab remains pi's thinking-level cycle. The two-step flow is more ceremony than a single prompt, and if your task is a one-line fix the questions will feel like overhead. For anything that spans several files on a 9B model, the split is the point.
Skill cards, sub-coders, and where Deep Research does not apply
little-coder injects a short usage card for the tools a turn is likely to need, selected by error-recovery first, then recency, then intent. The /skills command lists what is loaded and what each costs, /skills <tool> pins one when the selector keeps choosing a different card, and /skills off returns to automatic selection. That pinning escape hatch is worth knowing about, because an automatic selector driven partly by recency can lock onto the wrong card after a run of similar turns. Sub-coders, invoked as dispatch, spawn isolated child sessions that can read the repository and browse online in read-only mode and report back concisely, with a live panel above the input tracking them. Deep Research is a separate feature bound to f2 or /deep-research <topic>: it scopes a topic into a brief, fans out read-only research sub-coders, and returns one cited markdown report saved next to your working directory. The README is explicit that the research children run in an ephemeral scratch directory rather than your project, so f2 is for external and online research and not for exploring the code you are sitting in. Use a normal session or dispatch for that. This is the kind of boundary that costs an hour if you learn it by trying. Other keys: ctrl+h opens a panel of useful shortcuts, /hotkeys is the full reference, ctrl+o expands tool output, ctrl+t toggles thinking blocks, ctrl+p cycles models. Prompt history persists across sessions, recalled with the up and down arrows from an empty input.
Where little-coder is the wrong tool
The fixed extension set is the first failure mode. If your workflow depends on a globally installed pi extension, little-coder will not load it until you take one of the three opt-in routes, and nothing in your working directory can change that mid-task. The second is the model assumption. The canonical setup is a local llama.cpp server hosting Qwen3.6-35B-A3B, and the extensions and skill cards are tuned for that class of model; pointing little-coder at a frontier API works, since the README shows the same flag with anthropic and openai model names, but you would be paying for a scaffold built to compensate for weaknesses your model does not have. The third is Deep Research, which by design cannot see your repository. The fourth is bun on a machine without Node: the launcher is a Node script, so the install succeeds and the binary fails until you edit the shebang. None of these are bugs exactly. They are the visible edge of a harness that chose predictability over openness, and you should decide whether that trade suits you before installing rather than after.
Alternatives and the difference in approach
The honest comparison is pi on its own. pi is the minimal substrate: agent loop, multi-provider API, TUI, session tree, compaction, extension model, four tools, a roughly 1000-token system prompt. Using pi directly gives you an open extension surface, since pi install registers into pi's settings and those settings are honoured, and it gives you no opinion about which model you run. little-coder is pi plus roughly thirty extensions, roughly thirty skill markdown files and a Python benchmark harness, launched with --no-extensions so that only the bundled set loads. The difference is not capability but constraint: pi asks you to assemble a scaffold, little-coder hands you one that is already fitted to small local models and then makes you opt out of the default to change it. If you are running a frontier model and want to pick your own tools, pi is the shorter path. If you are running a Qwen-class model locally and want the tool selection, skill cards and plan flow already tuned, little-coder saves you the assembly work at the cost of the closed default.
Maintenance, releases and the Apache-2.0 terms
The release cadence visible in the repository is weekly: v1.19.0 on 2026-08-29, v1.18.0 on 2026-08-22, v1.17.0 on 2026-08-15. That is frequent enough that pinning a version is worth considering if you depend on specific extension behaviour, since a weekly minor bump can change what loads at launch. little-coder ships no npm install scripts, and the README states the launcher does everything at launch time, so an upgrade is a package update plus whatever the new bundled set does on start. The project is licensed Apache-2.0, which permits commercial use and modification and includes an explicit patent grant; it also requires that you preserve copyright and licence notices and state significant changes. That is a summary of the licence text, not legal advice, and if you plan to redistribute a modified little-coder you should read the Apache-2.0 terms yourself. The dependency on pi is a plain package dependency, so pi's own release cycle is part of your upgrade surface too.
Editorial conclusion
Adopt little-coder if you already serve a local model through llama.cpp, Ollama or LM Studio and want a terminal agent whose scaffold is tuned for that model class rather than a frontier API. Skip it if you need your globally installed pi extensions to load by default, or if you expect Deep Research to read the repository you are sitting in; it will not. Before committing, run little-coder --list-models against your provider, confirm the default key in models.json points at a model you actually serve, and run /extensions to see exactly which of the bundled set loaded.
Community notes