leonardoaguiar.com coder-leo
Language

coder-leo

A coding agent for the terminal that runs on local models. It reads, writes and edits code, runs commands, searches a project and keeps a task list, driven by a model that runs on your own machine through Ollama or any server with the OpenAI chat API (LM Studio, llama-server, vLLM, mlx). It works the way Claude Code does, and it is built for small context windows: it measures the window, keeps every tool result in budget, clears old results, summarises the conversation in parts when it must, and gives the model tools that find things without reading everything.

Install

macOS, with Homebrew, two commands, once:

brew tap leonardoaguiar/coder-leo https://leonardoaguiar.com/apps/coder-leo/tap.git
brew install leonardoaguiar/coder-leo/coder-leo

brew upgrade brings new versions, and so does coder-leo update.

Linux (any distribution, x86_64 or ARM), Android inside Termux, and Windows inside WSL:

curl -fsSL https://leonardoaguiar.com/apps/coder-leo/install.sh | sh

It picks the build for the machine, checks its published SHA-256 and installs the binary, the man page and the shell completions in /usr/local (asking for sudo when needed), ~/.local or Termux's own folder. Running it again updates; sh -s -- --uninstall removes it.

You also need a model server with a model that supports tools:

Start

Open a terminal in a project and run coder-leo. The first time, pick a model from the list; it is remembered. Type what you want; /help lists the commands.

coder-leo                         a session in this directory
coder-leo "add tests for parser"  a session with a first prompt
coder-leo -p "explain main.go"    one answer, then exit (also reads stdin)
coder-leo -c                      continue the latest session here
coder-leo --sessions              pick an earlier session
coder-leo --list                  the installed models

The welcome box shows the model, the context window, the permission mode and the directory. The line under the prompt shows the mode, the model, how full the context is and the git branch.

Working with it

Tools

The model works through these tools, named as in Claude Code (it also understands the names other agents use, like read_file or run_command):

ToolWhat it does
ReadA file, numbered, with offset and limit; images for vision models; PDFs through pdftotext; notebooks as cells. A big file read whole returns its outline and the start
Write, EditCreate a file; replace an exact snippet (tolerant of copied line numbers and of indentation differences)
LS, Glob, GrepList, find files by pattern, search contents with a regular expression (content, file names or counts, with context)
SearchThe files and lines most relevant to a plain-language question, ranked by the words of identifiers
Outline, RepoMapThe functions and types of a file; the map of the repository, ranked by how much the code refers to each file
Bash, BashOutput, KillShellRun a command with a timeout; long ones in the background
WebFetch, WebSearchA page as readable text; a web search
TodoWriteThe task list, shown as it changes
TaskA sub-agent with a fresh context window (explore, plan, general, review, or your own) that returns only its report
RecallSearch the whole conversation, including what was summarised away
AskUserQuestion, ExitPlanMode, SkillAsk you something; present a plan; load a skill
mcp__server__toolThe tools of your MCP servers

The context window

Local models have small windows (8k to 32k tokens is common on a 16 GB machine), and re-reading a long prompt costs seconds per turn. coder-leo keeps the window working:

Permissions

Four modes: default asks before editing and running commands; acceptEdits lets edits inside the project through and asks for commands; plan only reads, and the model presents a plan for approval; yolo runs everything without asking, the way the first versions did, and it is the default unless your settings say otherwise. Destructive commands (removing wide directories, discarding git work, force pushes, sudo, dropping tables) still ask in yolo mode; "guard": false in the settings turns that off.

Rules in the settings decide before the mode: "allow": ["Bash(git *)", "Read"], "deny": ["Bash(rm *)"], "ask": ["Write"]. Answering a permission prompt with a allows that tool for the session; answering with words sends them to the model as instructions instead.

Sessions

Every session is saved as it happens in ~/.config/coder-leo/sessions/<project>/. coder-leo -c continues the latest one, --resume <id> or /resume picks one, /rename names it, /export writes it as Markdown. Before every edit the file is checkpointed: /rewind (or Esc Esc) goes back to an earlier turn, restoring the files changed since and cutting the conversation there.

Instructions, commands, skills, agents

Settings

~/.config/coder-leo/settings.json, then .coder-leo/settings.json and .coder-leo/settings.local.json in the project, each overriding the one before; then the environment (CODER_MODEL, CODER_API, CODER_HOST or OLLAMA_HOST, CODER_API_KEY).

{
  "model": "qwen2.5-coder:14b",
  "api": "ollama",
  "numCtx": 16384,
  "think": "low",
  "permissions": { "mode": "default", "allow": ["Bash(git *)"], "guard": true },
  "compact": { "micro": 0.7, "full": 0.85, "keepRecent": 6 },
  "repoMap": { "enabled": true, "budget": 3000 },
  "tools": { "minimal": false, "disabled": ["WebSearch"] },
  "hooks": { "PreToolUse": [{ "matcher": "Bash", "hooks": [{ "type": "command", "command": "./check.sh" }] }] },
  "mcpServers": { "fs": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "."] } },
  "statusLine": { "command": "~/.config/coder-leo/status.sh" },
  "notify": "bell"
}

/config shows what is in effect and where it came from; /doctor checks the server, the model, the memory and the setup.

Headless

coder-leo -p "prompt" answers once: the reply on stdout, everything else on stderr. --output-format json prints one object with the result, the session id and the token counts; --output-format stream-json prints one JSON event per line as things happen. --max-turns, --allowedTools, --disallowedTools, --system-prompt, --append-system-prompt and --mode shape the run; -c or --resume continue a session.

Privacy

Everything runs on your machine: the model, the files, the conversation. The program reaches the network only when the model calls WebFetch or WebSearch for your task (a permission prompt, outside yolo mode), when you set up an MCP server that reaches out, and when you run coder-leo update. No accounts, no telemetry, nothing sent anywhere.

Updates

coder-leo update checks the site for a newer version and installs it (through Homebrew for a Homebrew copy); coder-leo update --check only tells. The program never checks on its own.

Help and bug reports

Problems and ideas: the support address at the end of the coder-leo page. Include the model, the server, coder-leo version and the output of /doctor.