Skip to content

Latest commit

 

History

1,148 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AstrCode

English | 中文

BE PI OR BETTER THAN PI
Inspired by Claude Code, Codex, OpenCode, and Pi — but built as a Rust-native

Interface Preview
CLI (TUI) astrcode TUI screenshot
Web / Desktop image

A Rust-built AI coding agent platform.

AstrCode is a full-stack AI coding assistant with a Rust workspace and a React + TypeScript frontend. It features an agent loop with tool execution, a streaming SSE-based multi-provider LLM layer (Anthropic and OpenAI-compatible providers), typed authoring APIs for bundled and disk IPC subprocess extensions, background pre-warm, health checks, and a startup event channel, a persistent MCP process pool (reusing long-lived connections across turns), built-in web search and URL fetch tools, context window management with auto-compaction, an eval framework for automated benchmarking, and multiple interfaces: a terminal TUI, Web frontend, Tauri desktop app, HTTP/SSE API, and ACP (Agent Client Protocol) adapter.

Table of Contents

Installation

NPM Package

npm i @whatevertogo/astrcode

The @whatevertogo/astrcode npm package provides pre-built binaries for Linux, macOS, and Windows (x64 + arm64). After installation, the astrcode command will be available globally.

Package: @whatevertogo/astrcode

Build from Source

See Quick Start below for building from source.

Configuration (Recommended Before First Run)

AstrCode requires LLM provider and API key configuration to function properly. It is recommended to complete the following configuration before the first run.

Configuration File Locations

File Path Purpose
Main config ~/.astrcode/config.toml LLM providers, models, runtime parameters
Project config <workspace>/.astrcode/config.toml Project-level overrides (optional)
Global MCP ~/.astrcode/mcp.json MCP server configuration
Project MCP <workspace>/.astrcode/mcp.json Project-level MCP configuration (optional)

LLM Provider Configuration

Example ~/.astrcode/config.toml:

version = "1"
activeProfile = "deepseek"
activeModel = "deepseek-v4-flash"
activeSmallProfile = "deepseek"
activeSmallModel = "deepseek-v4-flash"

[[profiles]]
name = "deepseek"
providerKind = "deepseek"
baseUrl = "https://api.deepseek.com"
apiKey = "env:DEEPSEEK_API_KEY"
wireFormat = "openai_chat_completions"
authScheme = "bearer"

[[profiles.models]]
id = "deepseek-v4-flash"
maxTokens = 393216
contextLimit = 1000000
modelOptions = { thinking = { enabled = true } }

[[profiles]]
name = "openai"
providerKind = "openai"
baseUrl = "https://api.openai.com/v1"
apiKey = "env:OPENAI_API_KEY"
wireFormat = "openai_responses"
authScheme = "bearer"

[[profiles.models]]
id = "gpt-4.1"
maxTokens = 16384
contextLimit = 128000

[[profiles]]
name = "anthropic"
providerKind = "anthropic"
baseUrl = "https://api.anthropic.com/v1"
wireFormat = "anthropic_messages"
authScheme = "x_api_key"
apiKey = "env:ANTHROPIC_API_KEY"

[[profiles.models]]
id = "claude-sonnet-4-6"
maxTokens = 64000
contextLimit = 1000000

API Key Note: Use apiKey = "env:VARIABLE_NAME" to reference environment variables instead of writing keys directly in the configuration file.

Set the corresponding environment variables beforehand:

export ANTHROPIC_API_KEY="sk-ant-..."
export OPENAI_API_KEY="sk-..."
export DEEPSEEK_API_KEY="sk-..."

MCP Server Configuration

~/.astrcode/mcp.json registers external MCP tool servers. Both stdio (subprocess) and HTTP transports are supported:

Stdio example:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/dir"],
      "env": {}
    }
  }
}

HTTP example:

{
  "mcpServers": {
    "web-reader": {
      "type": "http",
      "url": "https://mcp.example.com/mcp",
      "headers": { "Authorization": "Bearer <token>" }
    }
  }
}

Field descriptions:

Field Required Description
command Yes (stdio) Command to start the MCP server
args No Command line arguments array
env No Environment variables to pass to the process
cwd No Working directory (validated to be within workspace in project-level config)
type No Transport type: "stdio" (default) or "http"
url Yes (http) MCP server HTTP endpoint
headers No Custom HTTP headers for the MCP endpoint

MCP servers start at extension initialization and persist across turns via a long-lived process pool. Global servers (~/.astrcode/mcp.json) are pre-warmed at startup; project-level servers (<workspace>/.astrcode/mcp.json) are pre-warmed in the background when a session is created or resumed. The first turn only blocks if the background pre-warm has not yet completed.

Extension Configuration

Extensions can be enabled or disabled via ~/.astrcode/config.toml. By default, all extensions are enabled except memory and channels, which are disabled by default.

version = "1"

[runtime.extensionStates]
"astrcode.memory" = true
"astrcode-channels" = true

To enable the memory extension, set "astrcode.memory": true under runtime.extensionStates. To enable the channels extension, set "astrcode-channels": true there and configure Telegram under extensions. See the Configuration Guide. Telegram channels are configured under extensions.astrcode-channels.telegram; keep allowedChatIds populated unless you explicitly set allowAllChats to true.

[extensions.astrcode-channels.telegram]
enabled = true
botTokenEnv = "TELEGRAM_BOT_TOKEN"
allowedChatIds = ["123456789"]

Built-in Extensions

First-party extensions are wired through astrcode-bundled-extensions. Authors of new extensions should depend on astrcode-extension-sdk rather than internal host crates.

Extension Crate Description
Agent Tools astrcode-extension-agent-tools Sub-agent delegation, agent discovery
MCP astrcode-extension-mcp MCP protocol client with persistent process pool, background pre-warm, inflight merge
Skill astrcode-extension-skill Slash-command skill discovery and dispatch
Todo Tool astrcode-extension-todo-tool Progress tracking todo list tool
Mode astrcode-extension-mode Agent running mode switching (Code / Plan), with Exit Gate, plan artifact persistence, keybinding & status item registration
Goal astrcode-extension-goal Codex-style session goal tracking, token budgets, and automatic continuation
Memory astrcode-extension-memory Project-scoped markdown memory storage (disabled by default)
Channels astrcode-extension-channels Telegram channel bridge for using AstrCode from an external chat (disabled by default)
Web Tools astrcode-extension-web-tools Built-in web-search and fetch-url tools (DuckDuckGo default; Brave/Serper optional)

Configure Web Tools under extensions.astrcode-web-tools (enabled by default):

[extensions.astrcode-web-tools.search]
provider = "duckduckgo"
braveApiKeyEnv = "BRAVE_API_KEY"

See Configuration Guide for full options.

Quick Start

# 1. Build backend
cargo build

# 2. Create config directory and config file
mkdir -p ~/.astrcode
cat > ~/.astrcode/config.toml << 'EOF'
version = "1"
activeProfile = "openai"
activeModel = "gpt-4o"
activeSmallProfile = "openai"
activeSmallModel = "gpt-4o-mini"

[[profiles]]
name = "openai"
providerKind = "openai"
wireFormat = "openai_chat_completions"
authScheme = "bearer"
baseUrl = "https://api.openai.com/v1"
apiKey = "env:OPENAI_API_KEY"

[[profiles.models]]
id = "gpt-4o"
maxTokens = 128000
contextLimit = 128000

[[profiles.models]]
id = "gpt-4o-mini"
maxTokens = 128000
contextLimit = 128000
EOF

# 3. Set API key environment variable
export OPENAI_API_KEY="your-api-key-here"

# 4. Run interactive terminal UI
cargo run -- tui

# Headless single-shot execution
cargo run -- exec "explain the agent loop architecture"

# HTTP/SSE server
cargo run -- server

# Web frontend (dev server)
cd frontend && npm ci && npm run dev

# Tauri desktop app (dev mode)
cd frontend && npm ci && npm run tauri:dev

# Eval framework (requires dev-mode feature)
cargo run --features dev-mode -- eval

Configuration

AstrCode uses a TOML-based configuration system stored in ~/.astrcode/config.toml. The configuration supports multiple LLM providers, model selection, runtime behavior tuning, and project-level overrides.

Key configuration features:

  • Multi-provider support (Anthropic and OpenAI-compatible providers)
  • Separate small LLM configuration for extensions (e.g., memory extraction)
  • Project-level config overrides via .astrcode/config.toml
  • Environment variable substitution for API keys (env:VAR_NAME)
  • Runtime behavior tuning (timeouts, retries, compaction, agent limits)
  • Compact circuit breaker and optional predictive compact

For detailed configuration documentation, see Configuration Guide.

Architecture

          ┌──────────┐  ┌──────────────────────┐  ┌───────────┐
          │   TUI    │  │ Web / Tauri Frontend  │  │ ACP Client│
          │ (ratatui)│  │ React 19 + TypeScript │  │  (stdio)  │
          └────┬─────┘  └────────┬─────────────┘  └─────┬─────┘
               │                  │ SSE / JSON-RPC       │ ACP JSON-RPC
               │    stdio         │                      │ over stdio
               └────────┬────────┘──────────────────────┘
                   ┌─────┴──────┐
                   │astrcode-cli│  TUI / exec / server launcher
                   └─────┬──────┘
                         │
                   ┌─────┴──────┐
                   │astrcode-   │  Session management, JSON-RPC + HTTP handler
                   │server      │  ACP adapter, transport, concurrency control
                   └─────┬──────┘
                         │
                   ┌─────┴───────┐
                   │astrcode-    │  Agent loop core: turn runner, tool pipeline
                   │session      │  LLM stream, context compaction orchestration
                   └─────┬───────┘
             ┌───────────┼───────────┐
             │           │           │
    ┌────────┴───┐ ┌─────┴─────┐ ┌───┴──────────┐
    │ astrcode-ai│ │astrcode-  │ │ astrcode-    │
    │            │ │context    │ │ extensions   │
    │ Anthropic  │ │Token      │ │Host runtime  │
    │ OpenAI     │ │budget and │ │hooks + S5R   │
    │ compatible │ │compaction │ │capabilities  │
    │ SSE+retry  │ │           │ │              │
    └────────────┘ └───────────┘ └──────┬───────┘
                                      │
                   ┌──────────────────┴─────────┐
                   │ Extension layer             │
                   │ bundled-extensions          │
                   │ astrcode-extension-coding   │
                   │ mode · goal · skill · todo  │
                   │ agent-tools · mcp · memory  │
                   │ channels · web-tools + IPC  │
                   └────────────────────────────┘
        ┌─────────────────────────────────────┐
        │              Shared layer            │
        │ core · protocol · storage · log      │
        │ client                               │
        └─────────────────────────────────────┘

Crates

The Cargo workspace under crates/ contains 28 crates, plus src-tauri/ as the desktop shell (29 workspace members total). Crates are grouped by architectural layer (details in Architecture).

Layer 0: Foundation Contracts

Crate Description
astrcode-core Shared domain types, traits, config system, and prompt composition
astrcode-session-projection Pure durable-event reducer and session read model
astrcode-protocol JSON-RPC 2.0 wire types, commands, events, and HTTP/UI DTOs

Layer 1: Core Implementations

Crate Description
astrcode-ai Multi-provider LLM layer (Anthropic and OpenAI-compatible providers), SSE streaming, and retry
astrcode-storage JSONL event log, snapshots, config persistence, and file locking
astrcode-context Token estimation, context window budgeting, auto-compact, and prompt engine
astrcode-log File rotation, stderr output, and env-filter logging

Layer 2: Session Runtime

Crate Description
astrcode-session Agent loop: turn runner, tool pipeline, LLM stream, compact orchestration, and runtime services

Layer 3: Extension System

Crate Description
astrcode-extension-sdk Extension authoring API plus the shared S5R wire, framing, peer, and host-operation contract
astrcode-extension-worker S5R subprocess worker runtime, handler dispatch, and remote typed HostClient
astrcode-extensions Host-side extension lifecycle, hook dispatch, capability gating, and disk IPC loader
astrcode-bundled-extensions Composition root that registers all first-party extension crates
astrcode-extension-agent-tools Sub-agent delegation and agent discovery (Claude Code compatible)
astrcode-extension-coding Eight first-party tools—read, read_tool_result, write, edit, patch, glob, grep, and shell—using only SDK host capabilities
astrcode-extension-mcp MCP client: stdio/HTTP transports, persistent process pool, pre-warm, and health checks
astrcode-extension-skill Slash-command skill discovery and Skill tool dispatch
astrcode-extension-todo-tool Progress-tracking todo list tool
astrcode-extension-mode Code / Plan mode switching, exit gate, plan artifact, keybindings, and status bar
astrcode-extension-ask-user Structured user questions, pending interaction state, and protected replies
astrcode-extension-goal Codex-style session goals, token budgets, and automatic continuation
astrcode-extension-memory Project-scoped markdown memory (disabled by default)
astrcode-extension-channels Telegram channel bridge (disabled by default)
astrcode-extension-web-tools Web search and URL fetch tools with SSRF guards and fetch cache

Layer 4: Services & Clients

Crate Description
astrcode-server Session manager, JSON-RPC/HTTP/ACP handlers, transport, HTTP projection, and SSE
astrcode-client Typed JSON-RPC client, transport abstraction, and stream subscription

Layer 5: User Entry Points

Crate Description
astrcode-cli CLI entry: TUI (ratatui), headless exec, and server launcher
src-tauri/ Tauri v2 desktop shell: sidecar management, single-instance coordination, and native dialogs

Layer 6: Evaluation

Crate Description
astrcode-eval Benchmark runner: HTTP server control, event-log metrics, and structured reports

Key Design Decisions

Agent Loop

The agent loop (astrcode-session) follows a phased pipeline pattern:

  1. Prepare context — token budget check, auto-compact if needed
  2. Build provider request — hook dispatch, message assembly, collect tools (MCP tools served from pre-warmed cache; deferred tools activated via tool_search_tool)
  3. Stream LLM response — SSE parsing, UTF-8 safe decoding, event accumulation
  4. Execute tools — parallel batch execution with pre/post hooks, result persistence
  5. Loop or return — tool calls loop back; text-only responses terminate

The agent supports running mode switching (Code / Plan). Plan mode restricts tools to read-only and plan management, enforces an exit gate (self-review checklist + required heading validation), and persists the plan artifact to <session>/plan/plan.md. Mode instructions are injected via BeforeProviderRequest, preserving the system prompt KV cache.

The ToolPipeline struct owns tool preprocessing, parallel scheduling, and result persistence. The SharedTurnContext struct carries session-level identifiers. consume_llm_stream returns a StreamOutcome enum (Complete | ToolCalls) that makes the loop body read as a linear sequence of named phases.

LLM Provider Layer

astrcode-ai supports Anthropic's native Messages API and OpenAI-compatible Chat Completions and Responses APIs. Key components:

  • Utf8StreamDecoder — handles multi-byte UTF-8 boundaries and bad-byte recovery across TCP chunks
  • SseLineReader — generic SSE line buffering (reusable across all providers)
  • RetryPolicy — exponential backoff with jitter for 429/5xx errors

Context Window Management

When conversation history approaches 83.5% of the model's context limit, astrcode-context triggers automatic compaction:

  1. LLM-backed compaction (model generates a structured 9-section summary) runs by default for both auto and manual compact
  2. On LLM failure (network error, parse error, timeout), the system falls back to deterministic rule-based summarization
  3. A compact circuit breaker temporarily skips auto-compact after consecutive LLM failures, with configurable cooldown
  4. Optional predictive compact estimates turn token growth and compacts before the context window is exceeded
  5. Compact results are persisted with CAS conflict detection; concurrent writes fail safely instead of corrupting history
  6. Compact transcripts are persisted as snapshots for debugging
  7. Post-compact context restoration re-reads recent files and preserves agent/skill/tool state
  8. Incremental compact — when a summary already exists, new compaction merges new information rather than rewriting from scratch

Tool Execution

Tools run in parallel batches (up to 5 concurrent). The pipeline:

  1. Prepare — parse JSON args (with repair for malformed LLM output), check visibility, dispatch PreToolUse hooks
  2. Execute — parallel batch via JoinSet, sequential tools flush the batch first
  3. Commit — dispatch PostToolUse for completed executions, persist large results, enforce message budget, and emit distinct completed / failed / cancelled events

Large tool results are automatically persisted to disk and replaced with preview summaries to stay within the message character budget. Each tool declares an ExecutionMode: read-only tools (glob/grep/read) are marked Parallel, writing tools (edit/write/shell) are marked Sequential.

Extension System

The extension system (astrcode-extensions) is a core architectural pillar, not an afterthought:

  • Extension trait — each extension declares hook subscriptions, contributes tools and slash commands, handles lifecycle events
  • Extension authoring — bundled extensions use astrcode-extension-sdk; disk S5R extensions use astrcode-extension-worker; neither couples to host-internal crates
  • Capability declarations — bundled extensions declare capabilities in Extension::manifest(); disk IPC extensions declare them during extension/initialize; the runtime authorizes astrcode.* invokes via HostRouter
  • Namespaced session state — session-scoped extension state is stored under <session>/extension_data/<extension-id>/, keeping the session root owned by the host
  • Hook modesBlocking (can modify input/output), NonBlocking (fire-and-forget), Advisory (observe-only); lifecycle Blocking is limited to turn-entry gates
  • Keybinding registration — extensions register keyboard shortcuts (e.g. Shift+Tab for mode toggle) via Registrar::keybinding()
  • Status bar items — extensions contribute status bar entries (e.g. current mode indicator) with runtime updates via StatusItemUpdate notifications
  • Disk s5r extensions — stdio length-prefixed frames + JSON WireMessage (protocol.s5r + command in extension.json); worker Initialize, handler.invoke, and capability-scoped astrcode.* invoke. See docs/extension-system.md
  • Extension runtime — session spawning with depth limits, tool registration queue, priority-based dispatch
  • Lifecycle hooksSessionStart / SessionResume / SessionShutdown, TurnStart / TurnEnd / TurnAborted, PreToolUse / PostToolUse, BeforeProviderRequest / AfterProviderResponse, PreCompact / PostCompact, PromptBuild, UserPromptSubmit
  • Extension runtime APIsExtension::start() receives an extension-scoped ExtensionStartContext with config, attributed paths, typed host clients, events, managed tasks, and cancellation; session-only operations remain unavailable until a session-scoped handler call. Extension::stop() receives StopReason; health() and on_config_changed() support health probes and hot config reloads
  • Active health checksExtensionRunner::check_health() provides an on-demand sampling API; polling strategy is decided by the host
  • Startup event channelbind_startup_event_channel() binds a process-level event channel so extensions can emit custom events during start()

ACP Adapter

The ACP adapter (astrcode-server::acp) bridges the standard Agent Client Protocol to astrcode's internal command/broadcast architecture:

  • Stdio JSON-RPC server implementing Initialize / NewSession / Prompt / Cancel
  • Real-time event streaming via broadcast channel to ACP SessionNotification
  • Deterministic event flushing with completion oneshot for turn lifecycle
  • Designed for IDE extensions and editor integrations

Event-Sourcing Architecture

AstrCode follows a session-first event-sourcing pattern:

  • EventLog is the single source of truth — all state changes are immutable, append-only events
  • Session is a projection — reconstructed by replaying from the event log; fork = replay from a specific sequence number
  • Agent is statelessTurnRunner is discarded after each turn; state lives in the event log
  • Recovery is replay — if the agent crashes, the session is intact; simply re-project from the event log

Prompt Engineering

System prompt assembly follows a pipeline pattern:

Identity → System → Task Guidelines → Communication → Environment
→ User Rules → Project Rules → Tool Summary → Extension → Additional

Stable sections (Identity, System, Task Guidelines) come first to leverage prompt cache prefix matching. Users can customize via ~/.astrcode/IDENTITY.md (identity override) and project-level AGENTS.md (project rules, searched upward from working directory).

Running Modes

Mode Command Description
TUI cargo run -- tui Interactive terminal UI with message history, tool display, slash commands, status bar
Exec cargo run -- exec "prompt" Headless single-shot execution, supports --jsonl
Server cargo run -- server [--addr 0.0.0.0:3847] HTTP/SSE server with JSON-RPC, session management, real-time event streaming
ACP cargo run -- acp ACP stdio adapter for IDE/editor integration
Eval cargo run --features dev-mode -- eval Run evaluation benchmarks (requires dev-mode feature)
Web cd frontend && npm run dev Browser-based chat interface connected to the server via SSE
Desktop cd frontend && npm run tauri:dev Tauri desktop app (auto-launches server as sidecar)

TUI Reference

Keyboard Shortcuts:

Key Action
Enter Submit prompt / accept slash command selection
Shift+Enter / Alt+Enter Insert newline
Esc Close slash palette / stop streaming turn
Tab Complete slash command selection
Shift+Tab Trigger extension-registered keybinding
Ctrl+A / Ctrl+E Move to start / end of line
Ctrl+U / Ctrl+K Delete before / after cursor
Ctrl+W Delete previous word
Ctrl+C Quit (with confirmation)

Slash Commands:

Command Description
/new Create a fresh session
/resume <id> or /r <id> Resume a previous session
/sessions or /ls Open session picker
/compact Compact the current session context
/help or /? Show command help
/quit or /q Exit astrcode

Extensions can register additional slash commands and keybindings at runtime.

Further Reading

Document Description
Architecture Event-sourcing, server layers, compact, prompt pipeline, tools, extensions
Configuration Guide Full config.toml reference
Extension System Built-in vs disk IPC extensions, host capabilities
Extension Author Guide Disk s5r extension development guide
UI Render Spec Structured rendering protocol for tool results
Release Guide Version sync, release workflows, and npm/GitHub distribution
TODO Project roadmap and pending items

Distribution

Pre-built binaries are available for Linux, macOS, and Windows (x86_64 + aarch64) via GitHub Releases on every version tag. Manual releases should use the Release workflow so version metadata, tags, npm packages, and GitHub assets stay in sync. The weekly workflow publishes a patch release only when commits landed since the previous version.

NPM Package: @whatevertogo/astrcode

See Release Guide for the release checklist.

Acknowledgments

This project drew inspiration and design patterns from several open-source projects:

  • Claude Code — tool execution pipeline, system prompt design, compact design
  • OpenCode — the frontend-backend separation (HTTP/SSE + JSON-RPC) references OpenCode's architecture.
  • Codex CLI — TUI layout and terminal UI design borrow from Codex's approach to rendering agent interactions in the terminal.

License

AGPL-3.0

About

一个开源的rust code agent,可扩展性非常强,与deepseek-harness架构同源并且比它早写两个月

Resources

Stars

58 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages