Getting Started
Zap is a single Rust binary — no Python venv, no Node, no Docker. Install it and run it from any directory.
Download & install
Pre-built binary, installed to ~/.local/bin. Works on both Apple Silicon and Intel Macs.
Set your API key
Or configure Gemini, OpenAI, or a local model — see Configuration.
Run
Type /init on first use to build the code index and generate a project summary.
Download & install
Pre-built binary, installed to ~/.local/bin. Supports x86_64 and arm64.
Set your API key
Run
One-line install (PowerShell)
Pre-built binary, installed automatically.
Set your API key
Run
/init after installing.
This builds the code graph and generates a project summary. It takes 10–30 seconds and runs once per project. With the index active, the model knows every symbol, every call site, every import, and which files are load-bearing — typically 3–5 fewer tool calls per task and no guesswork on impact analysis.
After big refactors, run /index to rebuild. See Code Graph ↓ for the analogy, the schema, and five real examples that show what changes.
Configuration
All settings live in ~/.agent.toml. Create the file if it doesn't exist — zap reads it on every startup.
mode = "auto" to let zap run tools without asking for confirmation each time. Useful for trusted projects.
| Key | Default | Description |
|---|---|---|
model |
"claude-sonnet-4-6" |
Model to use for all LLM calls. Any provider model string is accepted. |
mode |
"ask" |
ask — prompt before each tool call. auto — run tools without confirmation. Switch per project via /mode. |
skill_paths |
[] |
Directories scanned for skill files (.md). Skills found here are available for keyword-triggered injection. |
disabled_tools |
[] |
Tool names to exclude from every session. The LLM will not see or be able to call excluded tools.
Use /tools inside zap to list all available names.
Example: disabled_tools = ["shell", "web_fetch"]
|
disabled_skills |
[] |
Skill names to exclude from automatic injection. Skills matching this list are never triggered,
even if the user's message matches their keywords.
Example: disabled_skills = ["deploy", "ship"]
|
[model_routes] |
none |
Map task types to specific model slugs. Supported keys: coding, review,
explain, search. When a matching message is detected, zap shows an
approval prompt before routing to the configured model. The current session model is unchanged
after the turn. Example:
[model_routes] coding = "codex/gpt-5.5" review = "claude-opus-4-8" |
Project Init
Run /init once in a new project and zap goes from blank-slate to fully context-aware in about 30 seconds. It builds the code index, reads your source files, and writes persistent knowledge files the agent loads on every future session.
Detects your stack
Identifies language and framework from manifests (Cargo.toml, package.json, pom.xml) and fires the right skill automatically.
Builds the code graph
Runs tree-sitter across your repo and writes symbols, call sites, imports, and PageRank-ranked files to .zap/code.db. The model queries the graph before writing anything new.
Writes project knowledge
Asks the LLM to read your source and fill in ZAP.md — build commands, architecture, key files, do-not-touch list.
| File | What it contains | Loaded when |
|---|---|---|
ZAP.md | Project overview, build/test commands, architecture, do-not-touch list | Every session |
.zap/understanding.md | Navigation map (module layout, entry points, constraints) + business-domain map (added by /understand) | Every session |
.zap/context.md | Last session: goal, files touched, what's next (auto-updated on exit) | Session start |
.zap/session_log.md | History of all past sessions indexed by date | On request |
Domain Map /understand
Run /understand after /init to extract a structured business-domain map — which modules own auth, billing, storage, and so on. One LLM call, pure code_map output, no source-file reads needed.
Business Domains table
Each distinct concern — auth, billing, queuing, etc. — mapped to the files and key function names that implement it. Navigate straight to the right module, no guessing.
Cross-Cutting Concerns
Infrastructure every domain touches: error handling, logging, config, DB, serialization. Helps the agent know what to check before changing something low-level.
Dependency direction
One-line layering rule (e.g. tools → session → agent_core; nothing imports upward) so the agent never suggests a circular import.
Two code_map calls, zero source-file reads, one edit_file write. Total: ~80 seconds including LLM round-trip.
Zap records how many source modules existed when /understand last ran. If the count drifts more than 10% (new modules added, old ones removed), the system prompt shows a nudge — "project structure has changed — run /understand to update the domain map" — so the map stays accurate without any manual bookkeeping.
/init → /understand → done. The domain map is injected into every future session automatically alongside the navigation map.
Skill-First Context
Skills are plain markdown files that zap injects into the context window before the model sees your message. The key insight: only relevant skills fire. A greeting costs 31 tokens. A Rust question gets the Rust skill injected automatically.
| Type | When it fires | Example |
|---|---|---|
| Core | Every message, always injected | CLAUDE.md, project context |
| Trigger | When your message matches a keyword trigger | Rust, React, Python, testing skills |
Skills are markdown files with an optional YAML frontmatter block. Files without frontmatter are always-on Core skills.
Project skills
Drop .md files in .zap/skills/ inside your project. Checked in with your repo — shared with your team.
Global skills
Put skills in ~/.zap/skills/ or configure skill_paths in ~/.agent.toml to point at any directory.
Skills created for Claude Code or Gemini work in zap. Point skill_paths at ~/.claude/skills to share them automatically. This means you can keep the prompts and workflows you like while gaining Zap's code index, memory, context controls, and multi-provider runtime.
/skills in a session to see which skills are loaded and which triggered on the last message.
Code Graph
Most AI agents grep their way around your codebase. zap builds a structural map — what exists, what calls what, what imports what, and which files everything depends on — so the model answers questions in one query instead of guessing across ten.
Think of your project as a building.
A file = a room
Each source file is a room in the building. config.rs is one room, cli.rs is another.
A function = furniture
Each function, struct, or class is a piece of furniture in a room — with a known name and position.
An AST = the room blueprint
Every wall, outlet, and door in one room. Tree-sitter produces this for each file as it parses.
A symbol = floor plan summary
Just the labels for the key furniture and where it sits — name + line number + signature. The B-tier of code indexing.
A graph = doorways & corridors
The hallways connecting rooms. "This function in room A calls that one in room C." "Room B imports furniture from room D."
PageRank = foot traffic
Which rooms get used most — the lobby, the cafeteria, the main staircase. The load-bearing files.
Running /init (and every file change after) walks your source with tree-sitter and writes four kinds of facts to .zap/code.db:
| Table | What it records | Real example from zap's own codebase |
|---|---|---|
symbols |
Where every function, struct, class is defined | find_references is a function at src/code_index/index_impl.rs:395 |
call_sites |
Every place one function calls another | mod.rs:205 calls index_file from inside fn global_reindex_file |
imports |
Every use / import / using statement |
config.rs imports HashMap from std::collections |
file_rank |
PageRank score per file — its structural centrality | tools/todo.rs ranks 0.0208 — the orchestrator everything depends on |
Indexes the zap codebase in under 5 seconds: 264 files, 4,294 symbols, 20,272 call sites, 2,064 imports.
Every example below is a task you'd give an AI agent. The left column is what happens without a graph (most agents). The right column is what zap does in one query.
UserStore used?"register_provider, what breaks?"The hard kind of task — there's no symbol literally named "retry." The logic is scattered across handlers, configs, and helpers.
You don't have to think about any of this. The agent picks the right tool for each question automatically:
| Tool | What it does | When the agent reaches for it |
|---|---|---|
find_references |
Every call site for a symbol, ranked by file importance | Impact analysis, refactor planning |
who_calls |
Same as above, narrowed by qualifier (e.g. only Bar::foo) |
Disambiguation when many symbols share a name |
file_imports |
List every use / import in a file |
Understanding scope before editing |
where_imported |
Every file that imports a given name or module | Blast-radius check before a rename |
pack_context |
Curated context bundle within a token budget (signatures + provenance) | Loading the right code for a multi-file task |
ripple_analysis |
BFS walk of the call graph — direct callers, callers of callers, full transitive blast radius | Before renaming a function, changing a signature, or deleting a symbol |
get_diagnostics |
Live compiler errors and warnings via language server — no full compile needed | After editing a file, to confirm it's correct before moving on |
lsp_definition |
Type-resolved go-to-definition for cross-crate symbols (std, deps, generics, trait impls) | When AST index says "not found" — usually an external symbol |
lsp_type_at |
Exact inferred type of any expression — the editor tooltip, in the agent | When the type of an expression isn't obvious from reading the code |
| Language | Symbols | Call graph | Import graph |
|---|---|---|---|
| Rust | ✅ | ✅ | ✅ |
| Python | ✅ | ✅ | ✅ |
| JavaScript / TypeScript / TSX | ✅ | ✅ | ✅ |
| Go | ✅ | ✅ | ✅ |
| Java | ✅ | ✅ | ✅ |
| C# | ✅ | ✅ | ✅ |
The database is plain SQLite. If you want to poke at it directly:
zap resolves names, not types. That means foo.bar() matches any bar with that name — not the one a full type-checker would resolve to. The win: queries finish in microseconds, in-process, with zero external dependencies. The cost: when several symbols share a name, the agent gets all matches and disambiguates with a qualifier filter (who_calls). In practice this is rarely the bottleneck — agents read the file anyway to confirm.
For queries that need full type resolution — cross-crate symbols, generic instantiations, trait impls — zap now ships three LSP tools that query a running language server: get_diagnostics (instant compiler errors), lsp_definition (type-resolved go-to-definition), and lsp_type_at (inferred type of any expression). AST tools answer structural questions in microseconds; LSP tools answer semantic questions when precision matters. Both layers work together.
Context Visibility
Zap shows you exactly what's in the context window — token counts per message, which skills fired, and total usage. You can inspect, manage, and trim the context without starting a new session.
| Command | What it does |
|---|---|
/context |
List all messages with their index and token count |
/context drop 3 |
Remove message at index 3 (keeps the rest) |
/context drop 3-7 |
Remove messages 3 through 7 |
/context clear |
Wipe the entire context — keeps skills and system prompt |
Casual Messages
Not every message is a coding task. When you greet zap or ask something unrelated to your project, it skips skill injection entirely — saving the tokens for when they count.
The classifier runs locally and adds zero latency — it's a keyword heuristic, not a model call. It errs on the side of injecting skills when uncertain.
Dynamic MCP Loading
Zap supports the Model Context Protocol. MCP servers start pending — their tool schemas don't enter the context until explicitly needed. No 10,000-token schema dump on every turn.
Zap reads MCP config from ~/.zap/mcp.json (global) and .mcp.json (project-local). Both use the same Claude Code-compatible format.
Other agents
Dump all MCP tool schemas into every context window at startup — even tools you never call.
Zap
Servers start idle. Schemas enter context only when the model decides to call that tool — keeping baseline cost near zero.
~/.claude/mcp.json or a Claude Code MCP config, zap reads the same format. No migration needed.
Multi-Provider
Zap works with every major AI provider — and local models. Switch mid-session without restarting. The important part is that the surrounding agent stays the same: memory, tooling, indexing, permissions, and workflows do not disappear just because you changed models.
Not locked to Gemini CLI or OpenCode
If you like Gemini models but want stronger repo navigation, memory, and context control, you can use Gemini inside Zap instead of adopting a separate tool stack.
Keep one workflow across models
Teams can standardize on one set of slash commands, skills, and review habits even when different developers prefer Claude, Gemini, OpenAI, or local models.
Power without extra friction
Switching providers does not require reinstalling a new agent or relearning how it edits files, asks permission, searches code, or resumes past work.
Security Boundary
Zap is explicit about what it touches. Every shell command and file write is shown before it runs. You confirm — or deny — each action.
Zero telemetry
No usage data, no crash reports, no analytics. Your code and queries stay between you and your chosen model provider.
Keys stay local
API keys live in ~/.agent.toml or environment variables. Never logged, never sent anywhere other than the provider API.
Ask mode default
Tool calls (file edits, shell commands) require confirmation by default. Switch to auto only for trusted projects.
Zap is open source under the MIT License. Read the code, fork it, audit it. The binary you run is built from the public source.
Session Memory
Zap keeps a running log of what was worked on and which files were touched. When you start a new session, the model has context from previous ones — without bloating the live context window.
.zap/context.md
Last session's work, files touched, and what's next. Updated by zap at the end of each session.
.zap/session_log.md
A brief history of past sessions — goal and files per session. Grows incrementally, never overwrites.
You can also create a CLAUDE.md (or .zap/PROJECT.md) with permanent project-level context that fires on every message as a Core skill.
CLAUDE.md concise. It fires on every message — every token in it is spent whether the model needs it or not. Put language-specific context in trigger skills instead.
Autonomous Mode
/goal <condition> runs turns automatically until the model signals it's done or a turn limit is reached. Use it for multi-step tasks you'd otherwise have to shepherd turn-by-turn.
The model runs tool calls autonomously each turn. When it's finished it ends its response with ✓ DONE and the loop stops. The sidebar shows the goal condition, current turn, and elapsed time while it runs. Ctrl+C cancels at any point.
Good for
Multi-file refactors, adding full feature layers (controller + service + tests), fixing all lints, running a test suite and fixing failures.
Permission mode
Goal mode respects your current permission mode. Use /mode auto before /goal to let it run without confirmation prompts on every tool call.
Scheduler
Zap can run recurring goals on a schedule inside the TUI. Use it for background maintenance tasks like dependency checks, inbox triage, changelog drafting, or periodic repo health scans. It's one of the clearest examples of Zap being powerful in day-to-day use, not just in one-shot prompts.
Natural intervals
Create jobs with compact intervals like 30m, 1h, or a clock time such as 17:30.
TUI slash commands
Manage jobs with /schedule <interval> <goal>, inspect them with /schedule list, and stop them with /unschedule <name>.
Status visibility
The TUI status bar shows active job count, so you can see scheduled automation without leaving your current session.
Safe by default
Scheduled jobs still run through the same model, tool, and permission boundaries as normal Zap turns.
/help there.
Commands Reference
Type any command at the zap prompt. Tab-completion is available for all slash commands.
| Command | Description |
|---|---|
/init | Build the code index and write project knowledge files (ZAP.md, understanding.md) |
/understand | Extract a business-domain map from the code index — one LLM call, no file reads |
/index | Rebuild the code index after large refactors |
/skills | List loaded skills and which triggered last |
/context | Show context window with token counts per message |
/context drop N | Drop message at index N |
/context drop N-M | Drop messages from index N through M |
/context clear | Clear all messages (keeps skills and system prompt) |
/model <name> | Switch model for the current session |
/provider <name> | Switch AI provider mid-session |
/mode ask | Require confirmation for every tool call |
/mode auto | Run tools without confirmation prompts |
/schedule <interval> <goal> | Schedule a recurring goal in the TUI (examples: 30m, 1h, 17:30) |
/schedule list | Show active scheduled jobs in the current TUI session |
/unschedule <name> | Cancel a scheduled job by name |
/help | Show all available commands |
/exit | End the session (Ctrl+C also works) |