A local-first coding agent harness. It points a language model at a real repository and lets it answer questions, make a described change, or work through an open-ended task across multiple turns — while keeping every write on an isolated git branch, gated behind verification, and reversible.
RepoPilot is designed around models that don't have reliable native tool-calling (small local models served through Ollama), not just frontier APIs. Its retry/verification machinery exists specifically to make that work.
RepoPilot has three separate execution engines, each suited to a different kind of task:
| Engine | Entry point | Behavior |
|---|---|---|
| Chat | src/agents/orchestrator.py |
Read-only Q&A over a repo, grounded in retrieved context, with citations. No tool use. |
| Code task | src/agents/code_orchestrator.py + src/agents/graph_orchestrator.py |
A described change is planned into steps up front, then each step runs through an explore → generate → verify → self-correct pipeline. The harness drives execution, not the model. |
| Agent | src/agents/loop_orchestrator.py |
A persistent, model-driven tool-calling loop: the model picks its own next action, turn after turn, until it calls finish or hits a turn limit. |
Supporting infrastructure, all shared across the three engines above:
- Multi-language repository graph (
src/graph/) — tree-sitter-based call graph covering Python, JavaScript/TypeScript, Go, Java, and Rust. Deterministic, no LLM involved: definitions, imports, inheritance, and call resolution. - Git-based safety — every write happens on an isolated branch, never on
main/master. A separate git-shadow-repo snapshot store (src/snapshot/) takes a snapshot after every turn, independent of the real repo's own history, with restore/undo and fork support. - Checkpoint/resume (
src/agents/checkpoint.py) — a crashed or interrupted Agent run can resume from its last completed turn instead of restarting. - Permission model (
src/tools/bash_tool.py,src/tools/permission_store.py) — shell commands are classified deny/safe/confirm; a "confirm" decision can be persisted as an exact-match "always allow" rule, never a wildcard pattern. - Roles — the Agent loop can run as
build(full access),plan(research only, no writes), orexplore(read-only), enforced at the point each action is dispatched. - Hooks (
src/tools/hooks.py) — user-authored shell commands can run before/after an action, or at the end of a task. Configured only by a human editing a JSON file directly; the model itself can never write its own hooks. - MCP support — external tools (browser automation, documentation search, a persistent
terminal session, etc.) are reachable through the Model Context Protocol, configured in
data/mcp_servers.json.
- CLI —
python -m src.cli <subcommand> - TUI —
python -m src.tui.app(Textual-based terminal UI) - Web dashboard —
python -m src.web.app(Flask,http://127.0.0.1:5000)
All three call the same underlying engines; none of them have their own logic.
python -m venv venv
venv\Scripts\activate # or: source venv/bin/activate
pip install -r requirements.txt
By default RepoPilot talks to a local Ollama instance — see OLLAMA_SETUP.md. No API key is
required for that path.
To use a hosted provider instead, uncomment the matching package in requirements.txt
(openai, anthropic, or google-genai) and set the corresponding environment variables below.
Copy .env.example if present, or create .env in the repo root:
# Provider selection — one of: ollama (default), openai, anthropic, gemini, gemini-local
REPOPILOT_LLM_PROVIDER=ollama
# Required only for REPOPILOT_LLM_PROVIDER=openai (also covers OpenRouter and any other
# OpenAI-compatible endpoint via OPENAI_BASE_URL)
OPENAI_API_KEY=
OPENAI_BASE_URL=
OPENAI_MODEL=
# Required only for REPOPILOT_LLM_PROVIDER=anthropic
ANTHROPIC_API_KEY=
# Required only for REPOPILOT_LLM_PROVIDER=gemini
GEMINI_API_KEY=
.env is gitignored — never commit real keys.
MCP servers are configured in data/mcp_servers.json (empty list by default; opt-in). Hooks are
configured per-repo in data/hooks/<repo_name>.json (absent by default).
Onboard a repo first:
python -m src.cli ingest --repo-url https://github.com/owner/name
Ask questions about it:
python -m src.cli chat --repo-name name
Run one described change through the Planner → Coder → Verification pipeline:
python -m src.cli code --repo-name name --task "add input validation to the signup form"
Run the persistent Agent loop instead, for open-ended or exploratory tasks:
python -m src.cli agent --repo-name name --task "investigate why the login test is flaky and fix it" \
--allow-bash --confirm-writes --role build
Relevant agent flags: --max-turns (default 30), --role {build,plan,explore}, --resume
(continue a crashed run of the same repo+task), --plan-mode (require one approved plan before
any action dispatches), --delegate (split into isolated subtasks).
Build a new project from scratch, with no existing repo:
python -m src.cli scaffold --repo-name my-new-project --task "a FastAPI todo app with SQLite storage"
Query the repository graph directly:
python -m src.cli graph --repo-name name --callers-of some_function_id
python -m src.cli graph --repo-name name --dead-code
python -m src.cli graph --repo-name name --call-chain <source_id> <target_id>
Run python -m src.cli <subcommand> --help for the full flag list of any subcommand.
- Every turn of the Agent loop parses one JSON action out of the model's free-text response, rather than using a provider's native structured tool-calling — a deliberate trade-off for compatibility with models that don't support native tool-calling at all, not an oversight.
- Import resolution for JavaScript/TypeScript/Go/Java/Rust is a heuristic (path/name matching),
not a real module resolver for each language (no
go.mod/package.json/build-file parsing). - The Agent loop dispatches one action per turn, except for a narrow batch of read-only actions
(
read/grep/glob/webfetch) which can run concurrently in one turn; writes are never batched. - No production usage history. This has been exercised through targeted live testing during development, not by external users over time.