Configuration
NOTE
This document was designed for both humans and agents.
TIP
Crush can configure itself via a builtin config skill. That is to say, can generally just tell Crush want you want to configure using natural language.
If you're migrating from the old JSON format, you can also ask Crush to convert the config for you.
Crush is configured with Bash via a set of Crush-specific builtin commands. By default, global config lives at ~/.config/crush/crushrc on Unix-like systems and %USERPROFILE%\.config\crush\crushrc on Windows. It works like a .bashrc: it runs when Crush starts and configures the agent.
# Add Ollama.
provider add ollama --type ollama --base-url "http://localhost:11434/v1"
# Register a model on Ollama.
model add ollama/llama3.3 --name "Llama 3.3" --context-window 128000
# Auto-approve some tools.
permissions allow view edit
# Add an MCP server
mcp add github \
--type http \
--url "https://api.githubcopilot.com/mcp/" \
--header Authorization "Bearer $GITHUB_TOKEN"Since it's Bash, so you can use logic, source other files, and so on. It's really handy.
# Change config based on the machine you're on.
if [[ $HOSTNAME == "babysquid" ]]; then
option skill-path "$HOME/squid-skills"
fi
# Load some extra config
source "$XDG_CONFIG_HOME/squid-config.sh"
# Get API keys from your password manager.
provider add my-secret-provider \
--type openai-compat \
--base-url "https://api.example.com/v1" \
--api-key "$(op read my-secret-key)"Because Crush has a native, built-in Bash interpreter, Bash-based config works identically across all platforms, including Windows.
Why Bash?
Two reasons:
- Crush ships with a first-class Bash interpreter, so we get the logic for free.
- Ultimately, Crush needs to be able to configure itself, and command-based config allows both users and the agent to use the same tools.
What about JSON?
JSON is still supported but is deprecated and, while it's supported, it won't be receiving new features. For more see Legacy JSON.
Where config lives
Crush looks for config in the following places, with lower numbers taking precedence:
| Priority | Unix-like | Windows |
|---|---|---|
| 1 | ./.crushrc | .\.crushrc |
| 2 | ./crushrc | .\crushrc |
| 3 | $XDG_CONFIG_HOME/crush/crushrc | %XDG_CONFIG_HOME%\crush\crushrc |
Legacy JSON uses .crush.json / crush.json in the same directories as the above. Everything found is merged, with project settings overriding global ones and crushrc overriding JSON in the same directory. If a folder has both, they merge and Crush logs a warning.
Data directories (~/.local/share/crush on Unix-like systems and %LOCALAPPDATA%\crush on Windows) contain machine-owned JSON state. Crush does not discover or execute a crushrc from those locations.
NOTE
Crush also stores state data in $XDG_DATA_HOME/crush (%LOCALAPPDATA%\crush on Windows). This is application state, and should not be edited by hand.
Crush respects the XDG Base Directory Specification, so your paths may differ depending on your XDG_CONFIG_HOME value.
TIP
You can override the user and data config locations by setting:
CRUSH_GLOBAL_CONFIGCRUSH_GLOBAL_DATA
Config versioning
Not breaking the config API is really important to us! That said, you can target specific Crush versions with $CRUSH_VERSION:
if [[ $CRUSH_VERSION == "0.85.*" ]]; then
option debug true
fiEnvironment Variables
The top-level env field sets environment variables at startup, before providers are configured. This is useful for variables that affect provider authentication (e.g. the AWS SDK credential chain) without wrapping the crush command in a shell script or exporting them in your shell profile:
{
"$schema": "https://charm.land/crush.json",
"env": {
"AWS_PROFILE": "my-sso-profile"
}
}Values support the same $VAR and $(command) expansion as other config fields, so you can reference existing environment variables or shell out for a value.
A note on security
Just like crush.json, crushrc is a trusted file. Guard it carefully and don't download random configs without reading them first.
Both crushrc and crush.json are trusted code; crushrc runs in a full shell, and any $(...) in crush.json runs at load time. Don't launch Crush in a directory whose config you haven't reviewed, and don't randomly source files from the internet into your config.
Composing configs
Because it's Bash, a shared base config is just a source:
# Unix-like: ~/.config/crush/crushrc
# Windows: %USERPROFILE%\.config\crush\crushrc
source ~/team/crush-base.sh # sets up providers, a few skills
# …but on this machine, drop a skill path the base added and add my own.
option reset skill-path
option skill-path ~/my/skillsremove, rm, and option reset all act on whatever was set earlier in the script or pulled in via source. Later lines win, just like a shell.
Command Reference
The sections below read like CLI help. Entity commands use add to create or update something and remove (or rm) to delete it. Booleans accept true/false/1/0/yes/no, in any case.
Available Commands:
provider Manage model providers
model Manage models and model selection
mcp Manage MCP servers
lsp Manage language servers
hook Manage hooks
permissions Configure tool permissions
option Configure general Crush behaviorDetailed references live on their own pages:
| Command | Where |
|---|---|
provider / model | Providers |
mcp | MCPs |
lsp | LSPs |
hook | Hooks |
permissions | Permissions |
option | Options |
Legacy JSON
crush.json is the original format and is now deprecated. We plan to support it for the forseeable future, but new configuration options will only be added to Bash-based config.
{
"$schema": "https://charm.land/crush.json",
"providers": {
"anthropic": { "api_key": "$ANTHROPIC_API_KEY" },
},
"models": {
"large": {
"provider": "anthropic",
"model": "claude-sonnet-4-20250514",
},
},
"permissions": { "allowed_tools": ["view", "ls", "grep"] },
}For a full reference, see the JSON schema.
In JSON, only selected string fields (API keys, URLs, MCP/LSP commands and args, headers) are shell-expanded at load time. In crushrc there's no such list — it's all just Bash.
Both formats are trusted code: they run with your shell privileges before the UI appears. Don't launch Crush in a directory whose config you haven't read.
