Forge is a fully-featured, ACP-native AI coding assistant — built entirely by AI. 76,000+ lines of Rust across 27 crates, with a custom TUI rendering engine and 48 built-in tools. Supports Anthropic, OpenAI, Ollama, and OpenAI-compatible providers. Run it standalone in your terminal, or plug it into VS Code, Zed, or JetBrains via the ACP v1.2 protocol.
git clone https://github.com/andeya/forge
cd forge
cargo build --release
# Binary at target/release/forgeForge supports four provider protocols: anthropic, openai, openai-compat, and ollama. Configure them in ~/.forge/config.toml:
[agent]
provider = "my-anthropic" # references a key below
model = "claude-sonnet-4-6"
# Key names are arbitrary; the "protocol" field determines the implementation
[providers.my-anthropic]
protocol = "anthropic"
api_key = "sk-ant-..."
api_base = "https://api.anthropic.com"
[providers.my-openai]
protocol = "openai"
api_key = "sk-..."
api_base = "https://api.openai.com/v1"
[providers.my-gateway]
protocol = "openai-compat"
api_key = "your-token"
api_base = "https://llm.example.com/v1"
[providers.my-ollama]
protocol = "ollama"
api_base = "http://localhost:11434"
auto_discover = true
prefer_local = trueYou can also skip the config file entirely and rely on environment variables:
export ANTHROPIC_API_KEY="sk-ant-..." # auto-registers an anthropic provider
export OPENAI_API_KEY="sk-..." # auto-registers an openai provider
export DEEPSEEK_API_KEY="sk-ds-..." # auto-registers a deepseek provider (openai-compat)
# Ollama runs locally — no key needed; just make sure ollama serve is runningforge # Interactive TUI (recommended)
forge -p "explain this codebase" # Headless one-shot, output to stdout
forge acp # ACP JSON-RPC server (editor integration)| Key | Action |
|---|---|
/ |
Trigger command / Skill autocomplete |
? |
Show inline help |
↑ ↓ |
Browse input history |
^J |
New line inside the input box |
Esc |
Cancel the current turn |
^C |
Stop an in-flight response |
^e / Enter |
Send message |
| Command | Description |
|---|---|
/clear |
Clear and start a new session |
/help |
View full help |
/history |
Browse session history |
#text |
Prompt Actions (template input) |
!cmd |
Run a shell command directly in the terminal |
Forge handles the full development loop — understanding requirements, writing code, self-testing, and delivering results. Built-in tools cover file I/O, shell execution, web search, code search, and LSP integration. The agent autonomously plans tasks, chains tool calls, and streams progress live into the TUI.
Forge coding a Snake game, verifying functions and UI elements in real time (green ✅)
Key coding capabilities:
- File Operations — Read, Write, Edit, BatchEdit, ApplyPatch (precise string replacement or unified diff)
- Shell Execution — Full shell with pipes, chaining, redirection, and timeout
- Code Search — Grep (ripgrep) + Glob + Fd
- Web Access — WebSearch (auto-fallback between DDG / Brave / Bing) + WebFetch (HTML to plain text)
- LSP Integration — Go-to-definition, find references, hover docs, diagnostics
Forge's built-in Todo system breaks complex requirements into trackable subtasks. Check progress at any time, and get a structured summary when done.
Forge's task list and feature verification report after completing the Snake game
Type / in the input box to trigger autocomplete, then pick a built-in or custom Skill to run a predefined AI workflow:
/review [forge] Code review
/deploy [cursor] Deployment assistant
/test [builtin] Run test matrix
Skills are compatible with the SKILL.md open standard used by 32+ AI coding tools — Claude Code, Cursor, Codex CLI, Gemini CLI, and more. Reuse any existing skill library directly.
Control how much autonomy the agent has — from strict review to fully automatic CI:
| Mode | Behavior | Best For |
|---|---|---|
normal |
Prompt on dangerous operations (default) | Daily development |
readonly |
Read-only, no writes allowed | Code review / exploration |
auto-approve |
Fully automatic, no human confirmation | CI / batch processing |
plan |
Plan only, no execution | Requirements review |
The current mode is always shown in the status bar, and you can switch at any time.
- Sessions auto-persist to
~/.forge/— resume seamlessly after restart - Checkpoint system snapshots file state before every tool call
- Undo rolls back operations at the action level
Start the ACP JSON-RPC server with forge acp. Editors communicate with Forge over stdin/stdout — no plugins required:
forge acp # Start the editor integration serverForge wrote a particle-effects Tetris game via VS Code ACP integration and ran it in the browser
| Feature | Description |
|---|---|
| Protocol | ACP v1.2 |
| Transport | stdin/stdout newline-delimited JSON-RPC |
| Editors | VS Code, Zed, JetBrains |
| Internal channel | Zero-serialization — passes ACP wire types directly |
| Permissions | MVP: auto-approve; production needs editor-side UI |
Implemented RPC methods: initialize, session/new, session/prompt, session/cancel
Three-layer architecture with a binary entry point. Dependencies flow downward only — reverse dependencies are strictly forbidden.
graph TB
subgraph APP["forge-app — Binary entry"]
ENTRY["main()"]
end
subgraph EXT["Extension layer — Optional features"]
SDK["forge-sdk"]
SKILL["forge-skill"]
SUBAGENT["forge-subagent"]
HARNESS["forge-harness"]
MAP["forge-map"]
MCP["forge-mcp"]
SANDBOX["forge-sandbox"]
PLUGIN["forge-plugin"]
RULES["forge-rules"]
SCHEDULE["forge-schedule"]
SYNC["forge-sync"]
end
subgraph CORE["Core layer — Agent runtime"]
ENGINE["forge-engine"]
TUI["forge-tui"]
TOOLS["forge-tools"]
PROVIDER["forge-provider"]
COMMANDS["forge-commands"]
COMPACT["forge-compact"]
end
subgraph INFRA["Infrastructure layer — Shared foundations"]
ACP["forge-acp"]
PROTOCOL["forge-protocol"]
CONFIG["forge-config"]
SESSION["forge-session"]
AUDIT["forge-audit"]
HISTORY["forge-history"]
CHECKPOINT["forge-checkpoint"]
UNDO["forge-undo"]
LINT["forge-lint"]
end
ENTRY --> TUI & ENGINE & TOOLS & PROVIDER & COMMANDS
ENTRY --> MAP & SKILL & AUDIT & CONFIG & SESSION & HISTORY
SDK & SUBAGENT & HARNESS --> ENGINE
SUBAGENT --> TOOLS & PROVIDER & HARNESS
MAP & SKILL --> TOOLS
REVIEW --> MAP
TUI --> ENGINE & COMMANDS & PROVIDER & ACP & SESSION
ENGINE --> TOOLS & PROVIDER & ACP & AUDIT & CHECKPOINT & HISTORY & SESSION & COMPACT
COMPACT --> PROVIDER
SDK --> ACP & PROVIDER & AUDIT
ACP --> PROTOCOL
CONFIG --> PROTOCOL
SESSION --> CONFIG
AUDIT & CHECKPOINT & LINT --> CONFIG
HISTORY --> SESSION
UNDO --> CHECKPOINT
classDef core fill:#4A90D9,stroke:#2C5F8A,color:#fff
classDef infra fill:#7CB342,stroke:#558B2F,color:#fff
classDef ext fill:#FF8F00,stroke:#E65100,color:#fff
classDef bin fill:#AB47BC,stroke:#6A1B9A,color:#fff
class ENGINE,TUI,TOOLS,PROVIDER,COMMANDS,COMPACT core
class ACP,PROTOCOL,CONFIG,SESSION,AUDIT,HISTORY,CHECKPOINT,UNDO,LINT infra
class SDK,SKILL,SUBAGENT,HARNESS,MAP,REVIEW,MCP,SANDBOX,SCHEDULE,PLUGIN,SYNC,RULES ext
class ENTRY bin
| Rule | Description |
|---|---|
| Extension → Core ✅ | Extension crates may depend on Core and Infrastructure |
| Core → Infrastructure ✅ | Core crates may depend on Infrastructure |
| Core → Extension ❌ | Forbidden — Core must never reference Extension |
| Infrastructure → Core ❌ | Forbidden — no reverse dependencies |
Engine ↔ TUI communication goes through an mpsc channel using native ACP v1.2 types — fully decoupled. The internal channel passes standard ACP SessionUpdate structs with zero serialization; serialization only happens at the JSON-RPC boundary.
sequenceDiagram
participant User
participant TUI as forge-tui
participant Engine as forge-engine
participant Provider as forge-provider
participant Tools as forge-tools
User->>TUI: Type a message
TUI->>Engine: EngineCommand::Prompt
Engine->>Provider: Streaming SSE request
loop Streaming response
Provider-->>Engine: StreamEvent::TextDelta
Engine-->>TUI: SessionUpdate::AgentMessageChunk
TUI-->>User: Render in real time
end
Provider-->>Engine: StreamEvent::ToolUse
Engine-->>TUI: PermissionRpc (oneshot channel)
User->>TUI: Approve
TUI-->>Engine: PermissionDecision::AllowOnce
Engine->>Tools: execute_tool()
Tools-->>Engine: ToolOutput
Engine-->>TUI: SessionUpdate::ToolCallUpdate (status=Complete)
Engine-->>TUI: SessionUpdate (TurnComplete via _meta)
ACP-Native Design:
SessionUpdate: ACP v1.2 standard wire type, doubles as the internal Engine→UI channel typeEngineCommand: UI→Engine command enum (Prompt, Cancel, SetMode, ChangeModel, etc.)PermissionRpc/DiffRpc: Reverse RPC pattern — Engine usesoneshot::Senderto request a response from the UIClientExtension+ForgeAdapter: Extracts Forge-specific data (status updates, subagent lifecycle, diff previews) fromSessionUpdate._meta'sforge:*keys — no raw JSON parsing in the TUI
Forge ships 48 built-in tools covering file operations, code search, shell execution, web access, agent orchestration, task management, and more. All tools are dispatched through the ToolKind enum for zero-cost abstraction, with Custom(DynamicTool) for extensibility.
Tools aren't all dumped into the LLM's context at once. Each tool has a ToolExposure level. The Engine filters them dynamically based on session state:
| Exposure | Behavior | Examples |
|---|---|---|
Essential |
Always included in the system prompt | ToolSearch |
Discoverable |
Included by default, can be filtered per scenario | Read, Write, Bash (most tools) |
Hidden |
Not in the prompt; only called internally or by the model itself | StructuredOutput |
| Tool | Permission | Description |
|---|---|---|
| Read | ReadOnly | Read files with line numbers, pagination, images, PDFs, Jupyter notebooks |
| Write | Write | Atomic write / create files |
| Edit | Write | Precise string-replacement editing |
| ApplyPatch | Write | Apply unified diffs |
| BatchEdit | Write | Atomic multi-file batch editing |
| Move | Write | Move / rename files and directories |
| Delete | Write | Delete files or directories |
| MkDir | Write | Recursively create directories |
| Ls | ReadOnly | List directory contents with metadata |
| Fd | ReadOnly | Find files by type, extension, or size |
| Glob | ReadOnly | Glob pattern matching |
| Grep | ReadOnly | Regex search in file contents (ripgrep) |
| NotebookEdit | Write | Edit Jupyter notebook cells |
| Tool | Permission | Description |
|---|---|---|
| Bash | Execute | Run shell commands (pipes, chaining, redirection, timeout) |
| Jq | ReadOnly | Query JSON with jq syntax |
| Git | ReadOnly | Read-only Git operations (status, log, diff, blame) |
| Diff | ReadOnly | Compare text and output unified diffs |
| Tool | Permission | Description |
|---|---|---|
| WebFetch | ReadOnly | Fetch URL content (HTML → plain text) |
| WebSearch | ReadOnly | Search engine queries (auto-fallback DDG / Brave / Bing) |
| HttpRequest | ReadOnly | Full-control HTTP requests |
| Tool | Permission | Description |
|---|---|---|
| TodoWrite | Write | Create / update session todo items |
| TodoRead | ReadOnly | Read the session todo list |
| Tool | Permission | Description |
|---|---|---|
| Agent | Execute | Spawn a sub-agent for independent tasks |
| AskUserQuestion | ReadOnly | Ask the user a question and wait for an answer |
| EnterPlanMode | ReadOnly | Enter plan mode — explore code, design a solution |
| ExitPlanMode | Write | Exit plan mode and submit the plan for approval |
| VerifyPlanExecution | ReadOnly | Verify plan execution progress |
| EnterWorktree | Write | Create / enter an isolated Git worktree |
| ExitWorktree | Write | Exit a worktree (keep or discard) |
| Skill | Execute | Invoke a registered Skill workflow |
| LSP | Execute | Language Server operations (definition, references, hover, diagnostics) |
| Tool | Permission | Description |
|---|---|---|
| TaskCreate | Write | Create a new task |
| TaskList | ReadOnly | List all tasks and their statuses |
| TaskGet | ReadOnly | Get task details by ID |
| TaskUpdate | Write | Update task status, fields, or dependencies |
| TaskStop | Write | Stop a running task |
| TaskOutput | ReadOnly | Get task output |
| Tool | Permission | Description |
|---|---|---|
| CronCreate | Write | Create a scheduled / recurring task (5-field cron) |
| CronDelete | Write | Cancel a scheduled task |
| CronList | ReadOnly | List all scheduled tasks |
| Tool | Permission | Description |
|---|---|---|
| TeamCreate | Execute | Create an agent team |
| TeamDelete | Execute | Delete an agent team |
| SendMessage | Execute | Send a message to a team member |
| Tool | Permission | Description |
|---|---|---|
| McpAuth | Execute | MCP server authentication (login / logout / status) |
| ListMcpResources | ReadOnly | List available MCP server resources |
| ReadMcpResource | ReadOnly | Read a specific MCP resource |
| Tool | Permission | Exposure | Description |
|---|---|---|---|
| ToolSearch | ReadOnly | Essential | Search available tools by name / description |
| StructuredOutput | ReadOnly | Hidden | Force the model to output structured JSON |
The Engine has a three-layer guard system (ToolCallGuard) to prevent the agent from getting stuck in useless tool-call loops. Inspired by Claude Code's doom-loop detection.
┌─────────────────────┐
│ LLM requests tool │
└──────────┬──────────┘
│
┌──────────▼──────────┐
┌────┤ 1. Rate limit │ Same tool called >5 times in 60s?
│ NO └──────────┬──────────┘
│ YES │
│ ┌──────────▼──────────┐
│ │ ⛔ Runaway — block │
│ └─────────────────────┘
│
├────┐
│ ▼
│ ┌────────────────────────┐
│ │ 2. Doom-loop guard │ Last 4 calls = same tool + same args?
│ └──────────┬─────────────┘
│ YES │
│ ┌──────────▼──────────┐
│ │ ⛔ DoomLoop — block │
│ └─────────────────────┘
│ NO
├────────────────────────────► Execute tool
│ │
│ ┌──────────▼──────────┐
│ │ 3. Consecutive │ 3+ consecutive tool failures?
│ │ error guard │
│ └──────────┬──────────┘
│ YES │
│ ┌──────────▼──────────┐
│ │ ⚠️ Inject hint │
│ │ "Stop retrying, │
│ │ change strategy │
│ │ or ask the user" │
│ └─────────────────────┘
| Layer | Trigger | Action | Example |
|---|---|---|---|
| Rate limit | Same tool called >5 times in 60s | Block call, return error | Bash keeps trying different commands |
| Doom loop | Last 4 calls identical (tool name + args) | Block call, return error | WebFetch keeps hitting the same URL |
| Consecutive errors | 3+ consecutive tool failures | Inject hint into result | Reminds the LLM to change strategy |
Forge's forge-compact crate applies progressive context compression based on context window usage. It automatically selects the best strategy to free up space while preserving critical information.
Usage Strategy Behavior
─────────────────────────────────────────────
< 70% None No compression
70% ~ 80% Level 1 Snip Truncate large tool outputs (>200 tokens)
80% ~ 85% Level 2 Micro LLM-summarize large tool results, preserve structure
85% ~ 90% Level 3 Sum LLM-summarize old messages, keep last 2 rounds
90% ~ 95% Level 4 Hybrid Summarize old messages + keep last 3 rounds intact
≥ 95% Level 5 Trunc Budget truncation: sort by importance, keep errors + recent
Key features:
- Progressive escalation — compression ramps up smoothly, avoiding sudden context loss
- LLM summarization — Levels 2-4 use the same Provider for intelligent summarization, preserving key decisions, file paths, function names, and results
- Circuit breaker — After 3 consecutive LLM failures, falls back to pure memory strategies (Snip / Truncate) so the main loop never stalls
- Error preservation — All levels prioritize keeping tool-call errors so the agent doesn't repeat mistakes
- Size constraint — LLM summaries must be ≤50% of the original; exceeding this discards the summary and keeps the original
Forge has an extensible Skills system — type /skill-name to trigger predefined AI workflows. Compatible with the SKILL.md open standard used by 32+ AI coding tools (Claude Code, Cursor, Codex CLI, Gemini CLI, etc.).
On startup, Forge scans these directories (lower priority first; later files with the same name override earlier ones):
| Priority | Directory | Source |
|---|---|---|
| 1 | ~/.agents/skills/ |
Cross-tool shared (Linux Foundation standard) |
| 2 | ~/.cursor/skills/ |
Cursor |
| 3 | ~/.claude/skills/ |
Claude Code |
| 4 | ~/.forge/skills/ |
Forge |
| 5 | .agents/skills/ |
Project-level cross-tool shared |
| 6 | .cursor/skills/ |
Project-level Cursor |
| 7 | .claude/skills/ |
Project-level Claude Code |
| 8 | .forge/skills/ |
Project-level Forge |
SKILL.md (recommended) — Markdown + YAML frontmatter, compatible with 32+ tools:
---
name: review
description: Code review
model: claude-opus-4-8
allowed-tools: Read, Bash, Grep
max-turns: 10
---
Review code changes in the current working directory...TOML — Forge-native format:
name = "review"
description = "Code review"
prompt = "Review code changes in the current working directory..."
[constraints]
allowed_tools = ["Read", "Bash"]
max_turns = 10
model = "claude-opus-4-8".forge/skills/
├── review.md # Single-file skill
├── deploy.toml # TOML-format skill
├── complex-task/ # Directory-based skill
│ └── SKILL.md
└── _shared-rules.md # Underscore prefix → skipped (internal shared file)
Forge offers two plugin channels: directory plugins (forge-plugin) for distributable community plugins, and config hooks (forge-config HooksConfig) for quick project-level scripts.
Drop a directory with a plugin.json manifest into ~/.forge/plugins/ or .forge/plugins/:
{
"name": "my-linter",
"version": "1.0.0",
"description": "Pre-tool lint check",
"capabilities": ["read_files"],
"hooks": [
{
"event": "PreToolUse",
"matcher": "Bash",
"blocking": true,
"command": "scripts/check.sh"
}
]
}Declare shell commands directly in your project's .forge/settings.json:
{
"hooks": {
"PreToolUse": [
{ "command": "scripts/pre-check.sh", "matcher": "Bash", "blocking": true }
],
"PostToolUse": [
{ "command": "scripts/log-usage.sh" }
],
"SessionStart": [
{ "command": "scripts/setup-env.sh" }
]
}
}| Event | When | Blocking |
|---|---|---|
PreToolUse |
Before tool execution | Yes (blocking: true + exit 2 = deny) |
PostToolUse |
After tool execution | No |
PermissionRequest |
When a permission prompt is shown | No |
SessionStart |
When a session is created | No |
SessionEnd |
When a session ends | No |
Notification |
When a notification fires | No |
Exit code convention: 0 = allow, 2 = deny (blocking hook), anything else = log a warning and continue.
After any write tool (Write, Edit, BatchEdit, ApplyPatch), forge-lint automatically runs static analysis on modified files and appends diagnostics to the tool output.
| Language | Linter | Extensions |
|---|---|---|
| Rust | cargo check |
.rs |
| Python | ruff |
.py |
| JavaScript | eslint |
.js .jsx .mjs |
| TypeScript | eslint |
.ts .tsx |
| Go | go vet |
.go |
Silently skipped if the linter isn't installed — never blocks tool execution.
crates/
├── forge-app/ # Binary entry — wires everything together
│
├── forge-engine/ # Core — Agent loop, state machine, strategy traits
├── forge-tui/ # Core — Custom terminal UI rendering engine
├── forge-tools/ # Core — 48 tools, Tool trait
├── forge-provider/ # Core — LLM provider adapters
├── forge-commands/ # Core — CLI parsing
├── forge-compact/ # Core — 5-level progressive context compression
│
├── forge-protocol/ # Infrastructure — Domain types (minimal deps)
├── forge-acp/ # Infrastructure — ACP v1.2 native protocol
├── forge-config/ # Infrastructure — Five-layer config merging
├── forge-session/ # Infrastructure — Session management
├── forge-audit/ # Infrastructure — HMAC-signed audit logs
├── forge-history/ # Infrastructure — Collaboration records
├── forge-checkpoint/ # Infrastructure — Git file snapshots
├── forge-undo/ # Infrastructure — Operation rollback
├── forge-lint/ # Infrastructure — Post-write auto-lint
│
├── forge-subagent/ # Extension — Sub-agent system
├── forge-skill/ # Extension — Skills system
├── forge-mcp/ # Extension — MCP protocol
├── forge-map/ # Extension — Code symbol indexing
├── forge-plugin/ # Extension — Directory plugins + hook system
├── forge-rules/ # Extension — Rules system
├── forge-sandbox/ # Extension — Sandboxed execution
├── forge-sdk/ # Extension — Rust SDK
├── forge-schedule/ # Extension — Scheduled tasks
├── forge-sync/ # Extension — Cross-machine sync
└── forge-harness/ # Extension — Cost tracking, guard strategies, headless/interactive launch
cargo check --workspace # Compile check
cargo clippy --workspace --all-targets -- -D warnings # Lint
cargo fmt --all # Format
cargo test --workspace # Testmake build # Debug build (current platform)
make release # Release build (current platform)
make install # Install to ~/.cargo/binAll platform targets are built via cargo-zigbuild on any host — no Apple SDK or MSVC toolchain needed:
# Prerequisites (one-time)
pip install ziglang
cargo install cargo-zigbuild
rustup target add aarch64-apple-darwin x86_64-apple-darwin
rustup target add x86_64-unknown-linux-gnu x86_64-pc-windows-gnu
# Build
make mac # macOS ARM64 → dist/mac-aarch64/forge
make mac-intel # macOS x86_64 → dist/mac-x86_64/forge
make linux # Linux x86_64 → dist/linux-x86_64/forge
make win # Windows x64 → dist/win-x86_64/forge.exe
make package # Build all platforms and package (dist/*.tar.gz / *.zip)Pushing a v* tag triggers .github/workflows/release.yml, which uploads artifacts as a GitHub Release draft.
| Doc | Description |
|---|---|
| Technical Design | Early technical proposal (planning version) |
MIT