Skip to content

Repository files navigation

Forge — Terminal AI Coding Agent

Version License Platform Rust Edition

Forge TUI Welcome Screen

Forge ACP Interface

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.


Installation

Build from Source

git clone https://github.com/andeya/forge
cd forge
cargo build --release
# Binary at target/release/forge

Configure a Provider

Forge 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 = true

You 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 running

Quick Start

Three Run Modes

forge                              # Interactive TUI (recommended)
forge -p "explain this codebase"   # Headless one-shot, output to stdout
forge acp                          # ACP JSON-RPC server (editor integration)

TUI Keyboard Shortcuts

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

Common Slash Commands

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

Highlights

End-to-End AI Coding

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.

TUI Tool Calls

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

Structured Task Execution

Forge's built-in Todo system breaks complex requirements into trackable subtasks. Check progress at any time, and get a structured summary when done.

Task Completion View

Forge's task list and feature verification report after completing the Snake game

Skills — Slash-Command Workflows

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.

Four Permission Modes

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.

Session Management & Undo

  • 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

Editor Integration — ACP Native

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 server

ACP Integration: Tetris in VS Code

Forge 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


Architecture

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
Loading

Dependency Rules

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

Communication Architecture (ACP-Native)

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)
Loading

ACP-Native Design:

  • SessionUpdate: ACP v1.2 standard wire type, doubles as the internal Engine→UI channel type
  • EngineCommand: UI→Engine command enum (Prompt, Cancel, SetMode, ChangeModel, etc.)
  • PermissionRpc / DiffRpc: Reverse RPC pattern — Engine uses oneshot::Sender to request a response from the UI
  • ClientExtension + ForgeAdapter: Extracts Forge-specific data (status updates, subagent lifecycle, diff previews) from SessionUpdate._meta's forge:* keys — no raw JSON parsing in the TUI

Tool System (48 Tools)

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

File System

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

Shell & Execution

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

Web Access

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

Todo

Tool Permission Description
TodoWrite Write Create / update session todo items
TodoRead ReadOnly Read the session todo list

Agent Orchestration

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)

Task Management

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

Scheduling

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

Team Collaboration

Tool Permission Description
TeamCreate Execute Create an agent team
TeamDelete Execute Delete an agent team
SendMessage Execute Send a message to a team member

MCP Integration

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

Meta Tools

Tool Permission Exposure Description
ToolSearch ReadOnly Essential Search available tools by name / description
StructuredOutput ReadOnly Hidden Force the model to output structured JSON

Tool Call Guard

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

Context Compression (5-Level Progressive)

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

Skills System

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.).

Discovery Order

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

File Formats

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"

Directory Structure

.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)

Plugin System

Forge offers two plugin channels: directory plugins (forge-plugin) for distributable community plugins, and config hooks (forge-config HooksConfig) for quick project-level scripts.

Directory Plugins

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"
    }
  ]
}

Config Hooks

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" }
    ]
  }
}

Hook Lifecycle

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.


Auto-Lint on Write

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.


Project Structure

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

Development

cargo check --workspace                                    # Compile check
cargo clippy --workspace --all-targets -- -D warnings      # Lint
cargo fmt --all                                            # Format
cargo test --workspace                                     # Test

Build & Release

Local Build

make build      # Debug build (current platform)
make release    # Release build (current platform)
make install    # Install to ~/.cargo/bin

Cross-Platform Packaging

All 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.


Documentation

Doc Description
Technical Design Early technical proposal (planning version)

License

MIT

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages