diff --git a/AGENTS.md b/AGENTS.md index 0691c3b7bdef8bdd1adfde6cb75e5fd0e2e01d60..f6095e44bb08552c8dfa4e429762aa5422228951 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,39 +1,130 @@ # Crush Development Guide +## Project Overview + +Crush is a terminal-based AI coding assistant built in Go by +[Charm](https://charm.land). 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`. + +## Architecture + +``` +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 +``` + +### Key Dependency Roles + +- **`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/`. + +### Key Patterns + +- **Config is a Service**: accessed via `config.Service`, not global state. +- **Tools are self-documenting**: each tool has a `.go` implementation and a + `.md` description file in `internal/agent/tools/`. +- **System prompts are Go templates**: `internal/agent/templates/*.md.tpl` + with runtime data injected. +- **Context files**: Crush reads AGENTS.md, CRUSH.md, CLAUDE.md, GEMINI.md + (and `.local` variants) from the working directory for project-specific + instructions. +- **Persistence**: SQLite + sqlc. All queries live in `internal/db/sql/`, + generated code in `internal/db/`. Migrations in `internal/db/migrations/`. +- **Pub/sub**: `internal/pubsub` for decoupled communication between agent, + UI, and services. +- **CGO disabled**: builds with `CGO_ENABLED=0` and + `GOEXPERIMENT=greenteagc`. + ## Build/Test/Lint Commands - **Build**: `go build .` or `go run .` -- **Test**: `task test` or `go test ./...` (run single test: `go test ./internal/llm/prompt -run TestGetContextFromPaths`) -- **Update Golden Files**: `go test ./... -update` (regenerates .golden files when test output changes) - - Update specific package: `go test ./internal/tui/components/core -update` (in this case, we're updating "core") +- **Test**: `task test` or `go test ./...` (run single test: + `go test ./internal/llm/prompt -run TestGetContextFromPaths`) +- **Update Golden Files**: `go test ./... -update` (regenerates `.golden` + files when test output changes) + - Update specific package: + `go test ./internal/tui/components/core -update` (in this case, + we're updating "core") - **Lint**: `task lint:fix` - **Format**: `task fmt` (`gofumpt -w .`) -- **Modernize**: `task modernize` (runs `modernize` which make code simplifications) +- **Modernize**: `task modernize` (runs `modernize` which makes code + simplifications) - **Dev**: `task dev` (runs with profiling enabled) ## Code Style Guidelines -- **Imports**: Use `goimports` formatting, group stdlib, external, internal packages -- **Formatting**: Use gofumpt (stricter than gofmt), enabled in golangci-lint -- **Naming**: Standard Go conventions - PascalCase for exported, camelCase for unexported -- **Types**: Prefer explicit types, use type aliases for clarity (e.g., `type AgentName string`) -- **Error handling**: Return errors explicitly, use `fmt.Errorf` for wrapping -- **Context**: Always pass `context.Context` as first parameter for operations -- **Interfaces**: Define interfaces in consuming packages, keep them small and focused -- **Structs**: Use struct embedding for composition, group related fields -- **Constants**: Use typed constants with iota for enums, group in const blocks -- **Testing**: Use testify's `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. -- **JSON tags**: Use snake_case for JSON field names -- **File permissions**: Use octal notation (0o755, 0o644) for file permissions -- **Log messages**: Log messages must start with a capital letter (e.g., "Failed to save session" not "failed to save session") - - This is enforced by `task lint:log` which runs as part of `task lint` -- **Comments**: End comments in periods unless comments are at the end of the line. +- **Imports**: Use `goimports` formatting, group stdlib, external, internal + packages. +- **Formatting**: Use gofumpt (stricter than gofmt), enabled in + golangci-lint. +- **Naming**: Standard Go conventions — PascalCase for exported, camelCase + for unexported. +- **Types**: Prefer explicit types, use type aliases for clarity (e.g., + `type AgentName string`). +- **Error handling**: Return errors explicitly, use `fmt.Errorf` for + wrapping. +- **Context**: Always pass `context.Context` as first parameter for + operations. +- **Interfaces**: Define interfaces in consuming packages, keep them small + and focused. +- **Structs**: Use struct embedding for composition, group related fields. +- **Constants**: Use typed constants with iota for enums, group in const + blocks. +- **Testing**: Use testify's `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. +- **JSON tags**: Use snake_case for JSON field names. +- **File permissions**: Use octal notation (0o755, 0o644) for file + permissions. +- **Log messages**: Log messages must start with a capital letter (e.g., + "Failed to save session" not "failed to save session"). + - This is enforced by `task lint:log` which runs as part of `task lint`. +- **Comments**: End comments in periods unless comments are at the end of the + line. ## Testing with Mock Providers -When writing tests that involve provider configurations, use the mock providers to avoid API calls: +When writing tests that involve provider configurations, use the mock +providers to avoid API calls: ```go func TestYourFunction(t *testing.T) { @@ -70,9 +161,12 @@ func TestYourFunction(t *testing.T) { ## Committing -- ALWAYS use semantic commits (`fix:`, `feat:`, `chore:`, `refactor:`, `docs:`, `sec:`, etc). +- ALWAYS use semantic commits (`fix:`, `feat:`, `chore:`, `refactor:`, + `docs:`, `sec:`, etc). - Try to keep commits to one line, not including your attribution. Only use multi-line commits when additional context is truly necessary. ## Working on the TUI (UI) -Anytime you need to work on the tui before starting work read the internal/ui/AGENTS.md file + +Anytime you need to work on the TUI, read `internal/ui/AGENTS.md` before +starting work.