Crush — API Surface#
API types#
Crush exposes two distinct API surfaces: a CLI and an optional REST/HTTP API. There is no gRPC, no public library API, and no formal plugin interface — though MCP (Model Context Protocol) integration acts as a runtime extension mechanism.
CLI#
Framework#
Cobra (github.com/spf13/cobra) wrapped with charm.land/fang/v2 (Charmbracelet’s Cobra wrapper that adds Ctrl-C handling and colorprofile-aware output).
Command structure#
crush Interactive TUI mode (default command)
crush run [prompt...] Non-interactive single-prompt execution
crush session Session management (alias: sessions, s)
session list List all sessions (alias: ls)
session show <id> Show session details with message history
session last Show most recent session
session delete <id> Delete a session
session rename <id> <title> Rename a session
crush server Start the background server daemon
crush login [platform] Authenticate with a provider (alias: auth)
crush models [filter] List available models from configured providers
crush stats Show usage statistics (opens HTML report)
crush projects List tracked project directories
crush dirs Print config/data directory paths
dirs config Print only config directory
dirs data Print only data directory
crush logs View crush log output (--follow for tail)
crush update-providers [path] Update Catwalk / Hyper provider data
crush schema Generate JSON schema for config (hidden)Flag patterns#
Global (persistent) flags — available on all subcommands:
| Flag | Short | Description |
|---|---|---|
--cwd | -c | Override working directory |
--data-dir | -D | Custom data directory |
--debug | -d | Enable debug logging |
--host | -H | Connect to specific server socket/address |
Root command (TUI) flags:
| Flag | Short | Description |
|---|---|---|
--yolo | -y | Auto-accept all permissions (dangerous) |
--session | -s | Continue session by ID |
--continue | -C | Continue most recent session |
run subcommand flags:
| Flag | Short | Description |
|---|---|---|
--quiet | -q | Hide spinner |
--verbose | -v | Show log output inline |
--model | -m | Override LLM model (model or provider/model) |
--small-model | — | Override small/compact model |
--session | -s | Continue session by ID |
--continue | -C | Continue most recent session |
session list/show/last/delete/rename flags:
All session subcommands support --json for machine-readable output — explicitly designed for agent-to-agent use.
Notable design choices#
crush runaccepts stdin piping (cat file | crush run "analyze this") — first-class scripting surface--session/--continueare declared mutually exclusive viacobra.MarkFlagsMutuallyExclusive--yolois a root-level flag only (not onrun), limiting the blast radius of auto-permission to intentional invocationscrush sessionsubcommands include--jsonoutput mode for machine-readable results, anticipating agent-as-caller use cases
REST/HTTP API (client/server mode)#
Overview#
The REST API is used internally when CRUSH_CLIENT_SERVER=1 is set. The server daemon is auto-started by the client binary (see architecture result). The API is also the foundation for future IDE integrations (VS Code extension, etc.) and multi-client access.
- Transport: stdlib
net/httpover a Unix socket (/tmp/crush-<uid>.sock) on Linux/macOS or a Windows named pipe. TCP is also supported (tcp://host:port). - Protocol: HTTP/1.1 and unencrypted HTTP/2 (both enabled via
http.Protocols) - Router: stdlib
http.ServeMuxwith Go 1.22+ pattern syntax (e.g.,GET /v1/health,DELETE /v1/workspaces/{id}) - Versioning: All routes are under
/v1/ - Documentation: Swagger UI served at
/v1/docs/viaswaggo/http-swagger - Authentication: None — the Unix socket provides OS-level access control (only the owning user can connect); TCP mode relies on network-level controls
Middleware chain#
A single middleware is applied globally:
loggingHandler → http.ServeMux (route dispatch)loggingHandler is a minimal inline implementation (no third-party middleware library) that logs method, path, remote addr, user agent, status code, and duration via slog.
Route catalog#
System endpoints#
| Method | Path | Description |
|---|---|---|
GET | /v1/health | Health check — returns 200 OK |
GET | /v1/version | Server version info (proto.VersionInfo) |
GET | /v1/config | Global server configuration |
POST | /v1/control | Server control commands (e.g., {"command":"shutdown"}) |
Workspace management#
| Method | Path | Description |
|---|---|---|
GET | /v1/workspaces | List all workspaces |
POST | /v1/workspaces | Create workspace |
GET | /v1/workspaces/{id} | Get workspace details |
DELETE | /v1/workspaces/{id} | Delete workspace |
Session management#
| Method | Path | Description |
|---|---|---|
GET | /v1/workspaces/{id}/sessions | List sessions |
POST | /v1/workspaces/{id}/sessions | Create session |
GET | /v1/workspaces/{id}/sessions/{sid} | Get session |
PUT | /v1/workspaces/{id}/sessions/{sid} | Update session |
DELETE | /v1/workspaces/{id}/sessions/{sid} | Delete session |
GET | /v1/workspaces/{id}/sessions/{sid}/history | Session history (file edits) |
GET | /v1/workspaces/{id}/sessions/{sid}/messages | All messages in session |
GET | /v1/workspaces/{id}/sessions/{sid}/messages/user | User messages only |
GET | /v1/workspaces/{id}/messages/user | All user messages across workspace |
Agent control#
| Method | Path | Description |
|---|---|---|
GET | /v1/workspaces/{id}/agent | Get agent status |
POST | /v1/workspaces/{id}/agent | Run agent with prompt |
POST | /v1/workspaces/{id}/agent/init | Initialize agent |
POST | /v1/workspaces/{id}/agent/update | Update agent (model/config) |
GET | /v1/workspaces/{id}/agent/sessions/{sid} | Get agent session details |
POST | /v1/workspaces/{id}/agent/sessions/{sid}/cancel | Cancel running agent |
GET | /v1/workspaces/{id}/agent/sessions/{sid}/prompts/queued | Get queued prompts |
GET | /v1/workspaces/{id}/agent/sessions/{sid}/prompts/list | List all prompts |
POST | /v1/workspaces/{id}/agent/sessions/{sid}/prompts/clear | Clear prompt queue |
POST | /v1/workspaces/{id}/agent/sessions/{sid}/summarize | Summarize session |
GET | /v1/workspaces/{id}/agent/default-small-model | Get default small model |
Events (SSE streaming)#
| Method | Path | Description |
|---|---|---|
GET | /v1/workspaces/{id}/events | SSE event stream for workspace |
The events stream carries typed payloads via pubsub.Payload envelope with a PayloadType discriminator. Event types published:
LSPEvent— LSP server state changes, diagnostic countsMCPEvent— MCP connection state, tool/prompt/resource list changesPermissionRequest— agent requests permission before a tool callPermissionNotification— permission granted/denied resultMessage— new or updated LLM message (streaming-friendly)Session— session created/updatedFile— file history entry (edit tracked)AgentEvent— agent lifecycle notifications (started, finished, error)
Permissions#
| Method | Path | Description |
|---|---|---|
GET | /v1/workspaces/{id}/permissions/skip | Get skip-permission list |
POST | /v1/workspaces/{id}/permissions/skip | Add to skip-permission list |
POST | /v1/workspaces/{id}/permissions/grant | Grant a pending permission request |
File tracking#
| Method | Path | Description |
|---|---|---|
GET | /v1/workspaces/{id}/sessions/{sid}/filetracker/files | Files modified in session |
POST | /v1/workspaces/{id}/filetracker/read | Record file read |
GET | /v1/workspaces/{id}/filetracker/lastread | Last read file per path |
Configuration management#
| Method | Path | Description |
|---|---|---|
GET | /v1/workspaces/{id}/config | Get workspace config |
POST | /v1/workspaces/{id}/config/set | Set config key |
POST | /v1/workspaces/{id}/config/remove | Remove config key |
POST | /v1/workspaces/{id}/config/model | Change active model |
POST | /v1/workspaces/{id}/config/compact | Configure compaction |
POST | /v1/workspaces/{id}/config/provider-key | Update provider API key |
POST | /v1/workspaces/{id}/config/import-copilot | Import GitHub Copilot credentials |
POST | /v1/workspaces/{id}/config/refresh-oauth | Refresh OAuth token |
LSP management#
| Method | Path | Description |
|---|---|---|
GET | /v1/workspaces/{id}/lsps | List active LSP servers |
GET | /v1/workspaces/{id}/lsps/{lsp}/diagnostics | Get diagnostics from LSP |
POST | /v1/workspaces/{id}/lsps/start | Start an LSP server |
POST | /v1/workspaces/{id}/lsps/stop | Stop all LSP servers |
Workspace configuration#
| Method | Path | Description |
|---|---|---|
GET | /v1/workspaces/{id}/providers | List configured providers |
Project initialization#
| Method | Path | Description |
|---|---|---|
GET | /v1/workspaces/{id}/project/needs-init | Check if project needs init |
POST | /v1/workspaces/{id}/project/init | Initialize project (generate CRUSH.md) |
GET | /v1/workspaces/{id}/project/init-prompt | Get init prompt |
MCP management#
| Method | Path | Description |
|---|---|---|
GET | /v1/workspaces/{id}/mcp/states | Get MCP server states |
POST | /v1/workspaces/{id}/mcp/refresh-tools | Refresh MCP tool list |
POST | /v1/workspaces/{id}/mcp/refresh-prompts | Refresh MCP prompt list |
POST | /v1/workspaces/{id}/mcp/refresh-resources | Refresh MCP resource list |
POST | /v1/workspaces/{id}/mcp/read-resource | Read an MCP resource |
POST | /v1/workspaces/{id}/mcp/get-prompt | Fetch an MCP prompt |
POST | /v1/workspaces/{id}/mcp/docker/enable | Enable Docker MCP server |
POST | /v1/workspaces/{id}/mcp/docker/disable | Disable Docker MCP server |
MCP — Extension / Plugin Mechanism#
While crush has no formal plugin system, MCP (Model Context Protocol) serves as the runtime extension point for adding tools, prompts, and resources to the agent.
- Mechanism: JSON-RPC over stdio or HTTP, following the MCP specification. Crush connects to externally configured MCP servers at startup.
- Extension points: External MCP servers can register additional tools (callable by the LLM), prompts (reusable instruction templates), and resources (file-like content the LLM can read).
- Configuration: MCP servers are listed in
crush.jsonunder themcpsection with command + args or HTTP URL. - First-class support: The REST API exposes MCP management routes (
/mcp/states,/mcp/refresh-*,/mcp/docker/*) and the TUI has MCP state display. - Docker integration: A dedicated Docker MCP server can be enabled/disabled via the API, suggesting first-party container tooling integration.
Library API#
Crush is not designed as a library. All packages reside under internal/ — the only public entry point is main.go. There are no exported packages for third-party import.
The Workspace interface (internal/workspace) is the natural seam for IDE integration, but it is explicitly internal. Future IDE clients would consume the REST API over the Unix socket rather than importing the Go package directly.
Notable API design observations#
REST API mirrors the
Workspaceinterface 1:1. Every method on theWorkspaceinterface has a corresponding HTTP endpoint. The REST API is a faithful HTTP translation of the in-process Go interface — generated manually but mechanically consistent. This makes the client-server mode a thin HTTP wrapper rather than a separate design.SSE over HTTP/2 for real-time events. The
GET /v1/workspaces/{id}/eventsendpoint is a Server-Sent Events stream. Using unencrypted HTTP/2 on Unix sockets means the single connection can multiplex SSE alongside REST calls without separate WebSocket infrastructure.No authentication. Security relies on Unix socket file permissions. This is idiomatic for local daemon patterns (Docker, containerd, systemd socket activation) but means TCP mode is explicitly for “advanced users” and not production-hardened.
Swagger docs auto-generated. All handler functions carry
@Summary,@Tags, and@Routerannotations, and the OpenAPI spec is embedded viagithub.com/swaggo/http-swagger. This suggests the REST API is intended as a stable, documented interface for future tooling.--jsonflag pattern for agent-as-caller. Thesessionsubcommands all support--jsonoutput — an explicit acknowledgment that CLI commands will be called by other agents or automation scripts, not just humans.