# Crush

Charm's open-source terminal coding agent with multi-model support, LSP-enhanced context, MCP extensibility, and first-class support on every major platform.

Schema: 1.0 · Data: ee5de863c30bdbe4fe7dd3e07c7e22ea9bf4ab2248dbc7c35cdbf60bc28be1db

## Configuration

### MCP

Status: supported

Configure MCP servers under the mcp key in crush.json. Supports stdio, HTTP, and SSE transports with shell-style value expansion for secrets.

- project: `crush.json` (json) — key: mcp — .crush.json takes precedence over crush.json.
- global: `~/.config/crush/crush.json` (json) — key: mcp
- `type`: "stdio" | "http" | "sse" (required) — Transport type: stdio for command-line servers, http for HTTP endpoints, sse for Server-Sent Events. Values: stdio, http, sse
- `command`: string (required) — For stdio servers: the command to run.
- `args`: string[] — Arguments passed to the stdio command.
- `env`: record<string, string> — Environment variables for stdio servers. Supports shell-style expansion.
- `url`: string (required) — For http/sse servers: the endpoint URL.
- `headers`: record<string, string> — HTTP headers for http/sse servers, e.g. Authorization: Bearer $GH_PAT.
- `timeout`: number — Timeout in seconds for the server.
- `disabled`: boolean — Disable the server without removing it from config.
- `disabled_tools`: string[] — Tool names from this server to hide from the agent.
- transports: stdio, http, sse
- auth: headers
- Tools: supported
- Prompts: supported — MCP prompts appear as invocable commands in the command palette (verified in source).
- Shell-style expansion ($VAR, ${VAR:-default}, ${VAR:?message}, $(command)) works in command, args, env, headers, and url, via Crush's embedded shell on all platforms including Windows.
- Headers whose value resolves to the empty string are dropped from the outgoing request.
- crush.json is trusted code: any $(...) in it runs at load time with your shell's privileges.
- Individual server tools can be hidden with disabled_tools; MCP tools are named mcp_<server>_<tool> and can be allowlisted in permissions.allowed_tools.

stdio, http, and sse servers
```json
{
  "$schema": "https://charm.land/crush.json",
  "mcp": {
    "filesystem": {
      "type": "stdio",
      "command": "node",
      "args": ["/path/to/mcp-server.js"],
      "env": { "NODE_ENV": "production" }
    },
    "github": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/",
      "disabled_tools": ["create_issue"],
      "headers": { "Authorization": "Bearer $GH_PAT" }
    },
    "streaming-service": {
      "type": "sse",
      "url": "https://example.com/mcp/sse"
    }
  }
}

```

Source: https://github.com/charmbracelet/crush#mcps
Checked: 2026-07-12

### Skills

Status: supported

SKILL.md skills following the Agent Skills open standard, discovered from many global and project paths and activated on demand; user-invocable skills appear in the command palette.

- project: `.crush/skills/<name>/SKILL.md` (markdown)
- global: `~/.config/crush/skills/<name>/SKILL.md` (markdown)
- `name`: string (required) — Skill identifier (required by the Agent Skills standard).
- `description`: string (required) — What the skill does and when to use it.
- `user-invocable`: boolean — Make the skill invocable as a command from the command palette (Ctrl+P).
- `disable-model-invocation`: boolean — Prevent the model from auto-triggering the skill while still allowing user invocation.
- `license`: string — Optional license identifier.
- `compatibility`: string — Optional compatibility hint.
- `metadata`: record<string, string> — Optional string-to-string metadata map.
- invocation: automatic (model-invoked), command palette (Ctrl+P) for user-invocable skills
- Additional global search paths: $CRUSH_SKILLS_DIR, ~/.config/agents/skills/, ~/.claude/skills/, ~/.agents/skills/, Windows %LOCALAPPDATA% equivalents, and any paths in options.skills_paths.
- Additional project search paths: .agents/skills/, .claude/skills/, and .cursor/skills/.
- User-invocable skills show in the palette as user:skill-name (global) or project:skill-name (project).
- disable-model-invocation hides a skill from the model's available skills list while keeping it user-invocable.
- Hide specific skills (including builtins like crush-config) with options.disabled_skills.
- Crush ships builtin skills including crush-config and crush-hooks for configuring itself.

User-invocable skill
```markdown
---
name: my-skill
description: A skill that can be invoked as a command.
user-invocable: true
---

Instructions the agent loads when the skill is activated.

```


Extra skill paths in crush.json
```json
{
  "$schema": "https://charm.land/crush.json",
  "options": {
    "skills_paths": ["~/.config/crush/skills", "./project-skills"]
  }
}

```

Source: https://github.com/charmbracelet/crush#agent-skills
Checked: 2026-07-12

### Rules

Status: supported

Project context files (AGENTS.md, CRUSH.md, and compatible variants) plus global context files in ~/.config, with configurable paths.

- project: `AGENTS.md` (markdown) — Default file created by project initialization; CRUSH.md and other case variants are also read.
- project: `CRUSH.md` (markdown) — Crush-specific project rules; .local and lowercase variants are also read.
- global: `~/.config/crush/CRUSH.md` (markdown) — Global Crush-specific rules.
- global: `~/.config/AGENTS.md` (markdown) — Global generic instructions shared with other agentic coding tools.
- `options.context_paths`: string[] — Additional project context file paths, appended to the built-in defaults.
- `options.global_context_paths`: string[] — Global context file or folder paths. Folders load all .md files recursively. Defaults to ~/.config/crush/CRUSH.md and ~/.config/AGENTS.md.
- `options.initialize_as`: string — Name of the context file created/updated during project initialization. Default AGENTS.md.
- Default project context paths also include compatible files from other tools: .github/copilot-instructions.md, .cursorrules, .cursor/rules/, CLAUDE.md, CLAUDE.local.md, GEMINI.md, and case variants of CRUSH.md/AGENTS.md (verified in source).
- Project initialization analyzes the codebase and writes a context file, AGENTS.md by default; customize the name/location with options.initialize_as.
- Add extra project context files with options.context_paths and replace the global defaults with options.global_context_paths (directories load all .md files recursively).
- Use ~/.config/crush/CRUSH.md for Crush-specific rules and ~/.config/AGENTS.md for generic instructions shared with other agentic tools.

Custom global context paths
```json
{
  "$schema": "https://charm.land/crush.json",
  "options": {
    "global_context_paths": [
      "~/path/to/custom/context/file.md",
      "/full/path/to/folder/of/files/"
    ]
  }
}

```

Source: https://github.com/charmbracelet/crush#global-context-files
Checked: 2026-07-12

### Hooks

Status: partial

Shell-command hooks configured under the hooks key in crush.json. Preliminary support: currently only PreToolUse fires, with plans to add more events.

- project: `crush.json` (json) — key: hooks — Relative command paths resolve against the working directory.
- global: `~/.config/crush/crush.json` (json) — key: hooks — Use absolute paths or inline commands; relative paths resolve against the working directory, not the config file.
- `name`: string — Friendly display name shown in the TUI. Falls back to command.
- `matcher`: string — Regex tested against the tool name (e.g. ^bash$, ^mcp_). Omit to match all tools.
- `command`: string (required) — Shell command or script path to run. Executed through Crush's embedded POSIX shell on all platforms.
- `timeout`: number — Seconds before the hook is killed. Defaults to 30.
- events: PreToolUse
- Hooks are broadly Claude Code-compatible: the config shape, stdin payload, output envelope, and exit codes line up.
- Hooks run in parallel through Crush's embedded POSIX shell but results compose in config order: deny wins over allow, updated_input patches shallow-merge in order.
- Exit codes: 0 = success (stdout parsed as JSON envelope), 2 = block the tool call (stderr is the deny reason), 49 = halt the whole turn, anything else = non-blocking error.
- The JSON output envelope supports decision (allow/deny), halt, reason, context, and updated_input; decision allow pre-approves the call and skips the permission prompt.
- Hooks receive event data via stdin JSON and env vars like CRUSH_EVENT, CRUSH_TOOL_NAME, CRUSH_TOOL_INPUT_COMMAND, and CRUSH_TOOL_INPUT_FILE_PATH.
- PreToolUse only fires on the top-level agent's tool calls; sub-agent tool calls are not intercepted.
- Crush ships a builtin crush-hooks skill for writing and configuring hooks.

Block destructive commands
```json
{
  "hooks": {
    "PreToolUse": [
      {
        "name": "no-rm-rf",
        "matcher": "^bash$",
        "command": "./hooks/no-rm-rf.sh",
        "timeout": 10
      }
    ]
  }
}

```


Auto-approve read-only tools (inline)
```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "^(view|ls|grep|glob)$",
        "command": "echo '{\"decision\":\"allow\"}'"
      }
    ]
  }
}

```

Source: https://github.com/charmbracelet/crush/tree/main/docs/hooks
Checked: 2026-07-12

### Commands

Status: supported

Custom commands (saved prompts) as plain markdown files, invoked from the command palette with user:/project: prefixes and $NAME argument placeholders.

- project: `.crush/commands/<name>.md` (markdown) — Location follows options.data_directory (default .crush).
- global: `~/.config/crush/commands/<name>.md` (markdown) — $XDG_CONFIG_HOME/crush/commands/; Windows: %USERPROFILE%\AppData\Local\crush\commands\.
- global: `~/.crush/commands/<name>.md` (markdown)
- invocation: command palette (Ctrl+P)
- The docs URL is the official repo's draft COMMANDS.md, confirmed by maintainers in issue #2219; paths and behavior verified against the main-branch source (internal/commands).
- The whole markdown file is the prompt; the file name (without extension) becomes the command name, prefixed with user: or project:.
- Sub-directories namespace commands with colons, e.g. commands/git/commit.md becomes user:git:commit.
- $NAME placeholders (uppercase letters, numbers, underscores) become required arguments that Crush prompts for when the command runs.
- Prompts from connected MCP servers also appear as commands in the palette, and user-invocable skills surface alongside them.

Command with named arguments
```markdown
# Fetch Context for Issue $ISSUE_NUMBER

RUN gh issue view $ISSUE_NUMBER --json title,body,comments
RUN grep -R "$SEARCH_PATTERN" $DIRECTORY

```

Source: https://github.com/charmbracelet/crush/blob/99edcbf1c17dbb1d74dc1a3f03a5e30bcfc58b39/COMMANDS.md
Checked: 2026-07-12

### Settings

Status: supported

crush.json configures providers, models, LSPs, MCP servers, hooks, permissions, and options, at project and global scope with a published JSON schema.

- project: `.crush.json` (json) — Highest priority.
- project: `crush.json` (json)
- global: `~/.config/crush/crush.json` (json) — Windows: %LOCALAPPDATA%\crush\crush.json equivalent via env overrides.
- `providers`: object — Custom provider configs (openai, openai-compat, anthropic, ollama, llamacpp, lmstudio, litellm, omlx) with base_url, api_key, and model definitions.
- `lsp`: object — Language servers Crush uses for extra context, e.g. { "go": { "command": "gopls" } }.
- `mcp`: object — MCP server definitions (see MCP surface).
- `hooks`: object — Lifecycle hook configuration (see Hooks surface).
- `permissions`: { allowed_tools?: string[] } — Tools allowed to run without a permission prompt, e.g. view, ls, grep, or mcp_<server>_<tool>.
- `options.context_paths`: string[] — Additional context file paths (see Rules surface).
- `options.global_context_paths`: string[] — Global context file/folder paths (see Rules surface).
- `options.initialize_as`: string — Context file name created during project initialization. Default AGENTS.md.
- `options.disabled_tools`: string[] — Built-in tools to disable and hide from the agent entirely.
- `options.disabled_skills`: string[] — Skills (builtin or discovered) to hide from the agent.
- `options.skills_paths`: string[] — Additional skill discovery paths.
- `options.data_directory`: string — Directory for per-project state such as the SQLite database. Default .crush.
- `options.attribution`: { trailer_style?: string, generated_with?: boolean } — Git commit/PR attribution. trailer_style: assisted-by (default), co-authored-by, or none.
- `options.disable_notifications`: boolean — Disable desktop notifications for permission requests and finished turns.
- `options.disable_provider_auto_update`: boolean — Disable automatic provider/model list updates from Catwalk.
- `options.disable_metrics`: boolean — Opt out of pseudonymous usage metrics.
- `options.debug`: boolean — Enable debug logging (also available via --debug).
- Config priority: .crush.json, then crush.json, then $HOME/.config/crush/crush.json. Schema: https://charm.land/crush.json.
- Override the global config and data locations with CRUSH_GLOBAL_CONFIG and CRUSH_GLOBAL_DATA; ephemeral app state lives in ~/.local/share/crush/crush.json.
- The --yolo flag skips all permission prompts entirely.
- A .crushignore file (gitignore syntax) excludes additional files from context.
- Opt out of pseudonymous metrics with options.disable_metrics, CRUSH_DISABLE_METRICS=1, or DO_NOT_TRACK=1.
- Crush ships a builtin crush-config skill, so you can ask Crush to configure itself.

Providers, LSP, and permissions
```json
{
  "$schema": "https://charm.land/crush.json",
  "lsp": {
    "go": { "command": "gopls" },
    "typescript": { "command": "typescript-language-server", "args": ["--stdio"] }
  },
  "permissions": {
    "allowed_tools": ["view", "ls", "grep", "edit"]
  },
  "options": {
    "disabled_tools": ["sourcegraph"]
  }
}

```

Source: https://github.com/charmbracelet/crush#configuration
Checked: 2026-07-12

## Search, browser & identification

Not researched. Unknown does not mean unsupported.
