Crush is a terminal-based AI coding assistant built in Go by Charm. It connects to LLMs and gives them tools to read, write, and execute code. It supports multiple providers (Anthropic, OpenAI, Gemini, Bedrock, Copilot, Hyper, MiniMax, Vercel, and more), integrates with LSPs for code intelligence, and supports extensibility via MCP servers and agent skills.
The module path is github.com/charmbracelet/crush.
main.go CLI entry point (cobra via internal/cmd)
internal/
app/app.go Top-level wiring: DB, config, agents, LSP, MCP, events
cmd/ CLI commands (root, run, login, models, stats, sessions)
config/
config.go Config struct, context file paths, agent definitions
load.go crush.json loading and validation
provider.go Provider configuration and model resolution
agent/
agent.go SessionAgent: runs LLM conversations per session
coordinator.go Coordinator: manages named agents ("coder", "task")
prompts.go Loads Go-template system prompts
templates/ System prompt templates (coder.md.tpl, task.md.tpl, etc.)
tools/ All built-in tools (bash, edit, view, grep, glob, etc.)
mcp/ MCP client integration
session/session.go Session CRUD backed by SQLite
message/ Message model and content types
db/ SQLite via sqlc, with migrations
sql/ Raw SQL queries (consumed by sqlc)
migrations/ Schema migrations
lsp/ LSP client manager, auto-discovery, on-demand startup
ui/ Bubble Tea v2 TUI (see internal/ui/AGENTS.md)
permission/ Tool permission checking and allow-lists
skills/ Skill file discovery and loading
shell/ Bash command execution with background job support
event/ Telemetry (PostHog)
pubsub/ Internal pub/sub for cross-component messaging
filetracker/ Tracks files touched per session
history/ Prompt history
charm.land/fantasy: LLM provider abstraction layer. Handles protocol
differences between Anthropic, OpenAI, Gemini, etc. Used in internal/app
and internal/agent.charm.land/bubbletea/v2: TUI framework powering the interactive UI.charm.land/lipgloss/v2: Terminal styling.charm.land/glamour/v2: Markdown rendering in the terminal.charm.land/catwalk: Snapshot/golden-file testing for TUI components.sqlc: Generates Go code from SQL queries in internal/db/sql/.config.Service, not global state..go implementation and a
.md description file in internal/agent/tools/.internal/agent/templates/*.md.tpl
with runtime data injected..local variants) from the working directory for project-specific
instructions.internal/db/sql/,
generated code in internal/db/. Migrations in internal/db/migrations/.internal/pubsub for decoupled communication between agent,
UI, and services.CGO_ENABLED=0 and
GOEXPERIMENT=greenteagc.go build . or go run .task test or go test ./... (run single test:
go test ./internal/llm/prompt -run TestGetContextFromPaths)go test ./... -update (regenerates .golden
files when test output changes)
go test ./internal/tui/components/core -update (in this case,
we're updating "core")task lint:fixtask fmt (gofumpt -w .)task modernize (runs modernize which makes code
simplifications)task dev (runs with profiling enabled)goimports formatting, group stdlib, external, internal
packages.type AgentName string).fmt.Errorf for
wrapping.context.Context as first parameter for
operations.require package, parallel tests with
t.Parallel(), t.SetEnv() to set environment variables. Always use
t.Tempdir() when in need of a temporary directory. This directory does
not need to be removed.task lint:log which runs as part of task lint.When writing tests that involve provider configurations, use the mock providers to avoid API calls:
func TestYourFunction(t *testing.T) {
// Enable mock providers for testing
originalUseMock := config.UseMockProviders
config.UseMockProviders = true
defer func() {
config.UseMockProviders = originalUseMock
config.ResetProviders()
}()
// Reset providers to ensure fresh mock data
config.ResetProviders()
// Your test code here - providers will now return mock data
providers := config.Providers()
// ... test logic
}
gofumpt -w ..gofumpt is not available, use goimports.goimports is not available, use gofmt.task fmt to run gofumpt -w . on the entire project,
as long as gofumpt is on the PATH.fix:, feat:, chore:, refactor:,
docs:, sec:, etc).Anytime you need to work on the TUI, read internal/ui/AGENTS.md before
starting work.