name: crush-config description: Use when the user needs help configuring Crush — working with crush.json, setting up providers, configuring LSPs, adding MCP servers, managing skills or permissions, or changing Crush behavior.
Crush Configuration
Crush uses JSON configuration files with the following priority (highest to lowest):
.crush.json(project-local, hidden)crush.json(project-local)$XDG_CONFIG_HOME/crush/crush.jsonor$HOME/.config/crush/crush.json(global)
Basic Structure
{
"$schema": "https://charm.land/crush.json",
"models": {},
"providers": {},
"mcp": {},
"lsp": {},
"hooks": {},
"options": {},
"permissions": {},
"tools": {}
}
The $schema property enables IDE autocomplete but is optional.
Common Tasks
- Add a custom provider: add an entry under
providerswithtype,base_url,api_key, andmodels. - Disable a builtin or local skill: add the skill name to
options.disabled_skills. - Add an MCP server: add an entry under
mcpwithtypeand eithercommand(stdio) orurl(http/sse).
Model Selection
{
"models": {
"large": {
"model": "claude-sonnet-4-20250514",
"provider": "anthropic",
"max_tokens": 16384
},
"small": {
"model": "claude-haiku-4-20250514",
"provider": "anthropic"
}
}
}
largeis the primary coding model;smallis for summarization.- Only
modelandproviderare required. - Optional tuning:
reasoning_effort,think,max_tokens,temperature,top_p,top_k,frequency_penalty,presence_penalty,provider_options.
Custom Providers
{
"providers": {
"deepseek": {
"type": "openai-compat",
"base_url": "https://api.deepseek.com/v1",
"api_key": "$DEEPSEEK_API_KEY",
"models": [
{
"id": "deepseek-chat",
"name": "Deepseek V3",
"context_window": 64000
}
]
}
}
}
type(required):openai,openai-compat, oranthropicapi_keysupports$ENV_VARsyntax.- Additional fields:
disable,system_prompt_prefix,extra_headers,extra_body,provider_options.
LSP Configuration
{
"lsp": {
"go": {
"command": "gopls",
"env": { "GOTOOLCHAIN": "go1.24.5" }
},
"typescript": {
"command": "typescript-language-server",
"args": ["--stdio"]
}
}
}
command(required),args,envcover most setups.- Additional fields:
disabled,filetypes,root_markers,init_options,options,timeout.
MCP Servers
{
"mcp": {
"filesystem": {
"type": "stdio",
"command": "node",
"args": ["/path/to/mcp-server.js"]
},
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/",
"headers": {
"Authorization": "Bearer $GH_PAT"
}
}
}
}
type(required):stdio,sse, orhttp- Additional fields:
env,disabled,disabled_tools,timeout.
Options
{
"options": {
"skills_paths": ["./skills"],
"disabled_tools": ["bash", "sourcegraph"],
"disabled_skills": ["crush-config"],
"tui": {
"compact_mode": false,
"diff_mode": "unified",
"transparent": false
},
"auto_lsp": true,
"debug": false,
"debug_lsp": false,
"attribution": {
"trailer_style": "assisted-by",
"generated_with": true
}
}
}
[!IMPORTANT] The following skill paths are loaded by default and DO NOT NEED to be added to
skills_paths:.agents/skills,.crush/skills,.claude/skills,.cursor/skills
Other options: context_paths, progress, disable_notifications, disable_auto_summarize, disable_metrics, disable_provider_auto_update, disable_default_providers, data_directory, initialize_as.
Hooks
Hooks are user-defined shell commands that fire on agent events. Currently only PreToolUse is supported, which runs before a tool is executed.
{
"hooks": {
"PreToolUse": [
{
"matcher": "^(edit|write|multiedit)$",
"command": ".crush/hooks/protect-files.sh"
},
{
"matcher": "^bash$",
"command": ".crush/hooks/no-haskell.sh"
}
]
}
}
Hook Properties
command(required): Shell command to execute. Runs viash -c.matcher(optional): Regex pattern tested against the tool name. Empty or absent means match all tools.timeout(optional): Timeout in seconds. Defaults to 30.
Event Name Normalization
Event names are case-insensitive and accept snake_case variants: PreToolUse, pretooluse, pre_tool_use, and PRE_TOOL_USE all work.
How Hooks Work
- When a tool is about to be called, all
PreToolUsehooks with a matchingmatcher(or no matcher) run in parallel. - Duplicate commands are deduplicated — each unique command runs at most once.
- The hook receives JSON on stdin and hook-specific environment variables.
Hook Input (stdin)
A JSON payload is piped to the hook command:
{
"event": "PreToolUse",
"session_id": "abc-123",
"cwd": "/path/to/project",
"tool_name": "bash",
"tool_input": {"command": "ls -la"}
}
Hook Environment Variables
| Variable | Description |
|---|---|
CRUSH_EVENT | Event name (e.g. PreToolUse) |
CRUSH_TOOL_NAME | Name of the tool being called |
CRUSH_SESSION_ID | Current session ID |
CRUSH_CWD | Current working directory |
CRUSH_PROJECT_DIR | Project root directory |
CRUSH_TOOL_INPUT_COMMAND | Value of command from tool input (if present) |
CRUSH_TOOL_INPUT_FILE_PATH | Value of file_path from tool input (if present) |
Hook Output
Exit code 0 — the hook succeeded. Stdout is parsed as JSON:
{"decision": "allow", "context": "optional context appended to tool result"}
decision:allowto explicitly allow,denyto block,none(or omit) for no opinion.reason: Explanation text (used when denying).context: Extra context appended to the tool result.updated_input: Replacement JSON for the tool input. Last non-empty value wins.
Exit code 2 — the tool call is blocked. Stderr is used as the deny reason.
echo "No Haskell allowed" >&2
exit 2
Any other exit code — non-blocking error. The tool call proceeds as normal.
Claude Code Compatibility
Crush also supports the Claude Code hook output format:
{
"hookSpecificOutput": {
"permissionDecision": "allow",
"permissionDecisionReason": "Auto-approved",
"updatedInput": {"command": "echo rewritten"}
}
}
Existing Claude Code hooks should work without modification.
Decision Aggregation
When multiple hooks match, their decisions are aggregated:
- Deny wins over allow — if any hook denies, the tool call is blocked.
- Allow wins over none — if no hook denies but at least one allows, the call proceeds.
- All deny reasons are concatenated (newline-separated).
- All context strings are concatenated (newline-separated).
- For
updated_input, the last non-empty value wins.
Tool Permissions
{
"permissions": {
"allowed_tools": ["view", "ls", "grep", "edit"]
}
}
Environment Variables
CRUSH_GLOBAL_CONFIG- Override global config locationCRUSH_GLOBAL_DATA- Override data directory locationCRUSH_SKILLS_DIR- Override default skills directory