本文へ移動
cccskills
無料GitHub で公開

crush-config

Use when the user needs help configuring Crush — writing crushrc (the Bash config format) or crush.json, setting up providers, models, LSPs, MCP servers, hooks, skills, permissions, or changing Crush behavior.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md14.4 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Crush Configuration

Crush supports two config formats:

  • crushrc — a Bash script that builds config by calling Crush builtins. Preferred. Because it is real Bash you get includes, secrets, conditionals, and variables for free.
  • crush.json — static JSON. Fully supported; see Legacy JSON format.

Both are discovered together and deep-merged. Priority (highest to lowest):

  1. .crushrc / crushrc / .crush.json / crush.json (project-local, closer-to-cwd wins; Windows uses .\.crushrc / .\crushrc)
  2. $XDG_CONFIG_HOME/crush/crushrc or ~/.config/crush/crushrc (%XDG_CONFIG_HOME%\crush\crushrc or %USERPROFILE%\.config\crush\crushrc on Windows)

Data directories (~/.local/share/crush and %LOCALAPPDATA%\crush) contain machine-owned JSON state only; Crush does not discover or execute a crushrc from those locations.

If a directory has both crushrc and crush.json, they merge (crushrc wins on conflicts) and Crush logs a warning.

crushrc at a glance

A crushrc is a plain Bash script executed at load time with the same embedded shell the bash tool uses. It builds config by calling builtins (provider, model, mcp, lsp, hook, permissions, option). Statements run top to bottom; later statements win, and remove/reset operate on anything defined earlier or pulled in via source.

#!/usr/bin/env bash
# Includes and secrets are just Bash.
source ~/.config/crush/shared.sh

provider add anthropic --api-key "$ANTHROPIC_API_KEY"

model large anthropic/claude-sonnet-4-20250514 --max-tokens 16384
model small anthropic/claude-haiku-4-20250514

option skill-path ./skills
permissions allow view ls grep edit

Values are ordinary Bash — quote and expand normally ("$VAR", $(cmd), ${VAR:?required}). A failing $(command) aborts the load.

CRUSH_VERSION is exported into the script so you can feature-detect the running Crush (it is the literal devel for local builds):

[[ "$CRUSH_VERSION" != devel ]] && lsp add gopls --command gopls

Commands

All entity commands are verb-first. remove accepts rm as an alias. Booleans accept true/false/1/0/yes/no, case-insensitive.

providers

provider add <id> [flags]    # define/update; repeated calls merge
provider remove <id>         # alias: rm — removes the provider and its models

Flags: --name, --type (openai, openai-compat, anthropic, or a local type like ollama, lmstudio, llamacpp), --api-key, --base-url, --disable BOOL, --flat-rate BOOL, --discover-models BOOL, --system-prompt-prefix TEXT, --extra-header KEY VALUE (repeatable), --extra-body JSON, --provider-options JSON.

provider add deepseek \
  --type openai-compat \
  --base-url "https://api.deepseek.com/v1" \
  --api-key "${DEEPSEEK_API_KEY:?set DEEPSEEK_API_KEY}"

models

model add <provider>/<id> [flags]      # register a custom model (provider must exist)
model remove <provider>/<id>           # alias: rm
model large [<provider>/<id>] [flags]  # set the large slot; no arg prints it
model small [<provider>/<id>] [flags]  # set the small slot; no arg prints it
  • <provider>/<id> is the same form crush models prints. A missing slash is an error. model add requires the provider to already exist.
  • model add flags: --name, --context-window N, --default-max-tokens N, --can-reason BOOL, --supports-images BOOL, --price-input F, --price-output F, --price-cache-create F, --price-cache-hit F, --reasoning-effort low|medium|high.
  • model large/model small flags: --think, --reasoning-effort, --max-tokens N, --temperature F, --top-p F, --top-k N, --frequency-penalty F, --presence-penalty F, --provider-options JSON.
  • model large with no argument prints the current selection as provider/id, usable in $(model large).

large is the primary coding model; small is used for summarization.

mcp

mcp add <name> --type stdio|sse|http [flags]   # default type is stdio
mcp remove <name>                              # alias: rm

Flags: --command CMD, --args ARG (repeatable), --env KEY VALUE (repeatable), --url URL, --header KEY VALUE (repeatable), --timeout N, --disabled BOOL, --disabled-tools TOOL (repeatable), --enabled-tools TOOL (repeatable), --oauth BOOL, --oauth-client-id ID, --oauth-client-secret SECRET, --oauth-callback-port PORT.

mcp add github --type http \
  --url "https://api.githubcopilot.com/mcp/" \
  --header Authorization "Bearer $GH_PAT"

mcp add filesystem --command node --args /path/to/mcp-server.js

lsp

lsp add <name> --command CMD [flags]
lsp remove <name>                     # alias: rm

Flags: --args ARG (repeatable), --env KEY VALUE (repeatable), --filetypes TYPE (repeatable), --root-markers MARKER (repeatable), --timeout N, --disabled BOOL, --init-options JSON, --options JSON.

lsp add go --command gopls --env GOPATH "$HOME/go"
lsp add typescript --command typescript-language-server --args --stdio

hooks

hook add <event> --command CMD [--name NAME] [--matcher REGEX] [--timeout N]
hook remove <event> [--name NAME]    # alias: rm; without --name clears the event

Only named hooks can be removed individually — give a hook --name if you intend to remove it later. See Hooks runtime for how hooks execute (stdin payload, env vars, decisions).

hook add PreToolUse --matcher "^bash$" --command ".crush/hooks/no-haskell.sh" --name no-haskell

permissions

permissions allow <tool> [<tool> ...]   # tools that skip permission prompts
permissions deny <tool> [<tool> ...]    # hide tools from the agent entirely

deny is the inverse of allow: it writes options.disabled_tools. A denied tool is hidden from the agent, not merely prompted for.

options

option <key> [value]
option reset <list-key>    # clear a list option back to empty
  • Boolean keys (value optional, defaults true): debug, debug-lsp, auto-lsp, progress.
  • Boolean keys phrased positively (stored as the negated field): metrics, auto-summarize, provider-auto-update, default-providers. Example: option metrics false disables metrics.
  • String keys: data-directory, initialize-as, notifications.
  • Attribution keys: attribution-trailer-style (none, co-authored-by, assisted-by) and attribution-generated-with (boolean).
  • UI settings: option ui compact BOOL, option ui diff unified|split, option ui transparent BOOL, option ui mouse BOOL (default true; disable to let the terminal/tmux handle selection, copy/paste, and scrolling), option ui scrollbar default|always|never, option ui exit-banner default|compact|none, option ui completions-max-depth N, option ui completions-max-items N.
  • List keys (singular, one value per call, repeatable): context-path, global-context-path, skill-path, disable-skill. Use option reset <key> to wipe inherited values (e.g. after source).
option progress false
option skill-path ./skills
option disable-skill crush-config
option attribution-trailer-style assisted-by
option attribution-generated-with true
option ui compact true
option ui diff unified
option ui exit-banner compact

[!IMPORTANT] These skill paths are loaded by default and do NOT need skill-path: .agents/skills, .crush/skills, .claude/skills, .cursor/skills.

Hooks runtime

Hooks are user-defined shell commands that fire on agent events. Currently only PreToolUse is supported, which runs before a tool executes. This behavior is the same however the hook is defined (hook add or JSON).

How hooks work

  1. When a tool is about to be called, all PreToolUse hooks with a matching matcher (or no matcher) run in parallel.
  2. Duplicate commands are deduplicated — each unique command runs at most once.
  3. The hook receives JSON on stdin and hook-specific environment variables.

Event names are case-insensitive and accept snake_case: PreToolUse, pretooluse, pre_tool_use, PRE_TOOL_USE all work.

Hook input (stdin)

{
  "event": "PreToolUse",
  "session_id": "abc-123",
  "cwd": "/path/to/project",
  "tool_name": "bash",
  "tool_input": { "command": "ls -la" }
}

Hook environment variables

VariableDescription
CRUSH_EVENTEvent name (e.g. PreToolUse)
CRUSH_TOOL_NAMEName of the tool being called
CRUSH_SESSION_IDCurrent session ID
CRUSH_CWDCurrent working directory
CRUSH_PROJECT_DIRProject root directory
CRUSH_TOOL_INPUT_COMMANDValue of command from tool input (if present)
CRUSH_TOOL_INPUT_FILE_PATHValue of file_path from tool input (if present)

Hook output

Exit code 0 — hook succeeded. Stdout is parsed as JSON:

{ "decision": "allow", "context": "optional context appended to tool result" }
  • decision: allow to explicitly allow, deny to block, none (or omit).
  • reason: explanation (used when denying).
  • context: extra context appended to the tool result.
  • updated_input: replacement JSON for the tool input; last non-empty wins.

Exit code 2 — the tool call is blocked; stderr is the deny reason.

Any other exit code — non-blocking error; the tool call proceeds.

Decision aggregation

  • Deny wins over allow — any deny blocks the call.
  • Allow wins over none — a lone allow lets it proceed.
  • Deny reasons and context strings are concatenated (newline-separated).
  • For updated_input, the last non-empty value wins.

Claude Code compatibility

Crush also accepts the Claude Code hook output format, so existing hooks work unchanged:

{
  "hookSpecificOutput": {
    "permissionDecision": "allow",
    "permissionDecisionReason": "Auto-approved",
    "updatedInput": { "command": "echo rewritten" }
  }
}

User-invocable skills

Skills can be invoked as commands. Add user-invocable: true to the skill's YAML frontmatter:

---
name: my-skill
description: A skill that can be invoked as a command.
user-invocable: true
---
  • Global skills appear as user:skill-name; project skills as project:skill-name.
  • Add disable-model-invocation: true to keep a skill user-only (hidden from the model's available-skills list but still manually invocable).

Environment variables

  • CRUSH_VERSION — exported into crushrc at load; the running version (or devel for local builds).
  • CRUSH_GLOBAL_CONFIG — override global config location.
  • CRUSH_GLOBAL_DATA — override data directory location.
  • CRUSH_SKILLS_DIR — override default skills directory.

Legacy JSON format

crush.json is the original static format. It still works and merges with crushrc. Basic structure:

{
  "$schema": "https://charm.land/crush.json",
  "models": {},
  "providers": {},
  "mcp": {},
  "lsp": {},
  "hooks": {},
  "options": {},
  "permissions": {}
}

The $schema property enables IDE autocomplete but is optional.

crushrc ↔ crush.json mapping

crushrccrush.json
provider add openai --api-key "$K"providers.openai = {"api_key": "$K"}
model add openai/gpt-x --name Xappend to providers.openai.models[]
model large openai/gpt-xmodels.large = {"provider":"openai","model":"gpt-x"}
mcp add gh --type http --url Umcp.gh = {"type":"http","url":"U"}
lsp add go --command goplslsp.go = {"command":"gopls"}
hook add PreToolUse --command Cappend to hooks.PreToolUse[]
permissions allow view lspermissions.allowed_tools = ["view","ls"]
permissions deny bashoptions.disabled_tools = ["bash"]
option skill-path ./skillsoptions.skills_paths = ["./skills"]
option metrics falseoptions.disable_metrics = true
option request-timeout 300options.request_timeout = 300
option attribution-trailer-style noneoptions.attribution.trailer_style = "none"
option attribution-generated-with falseoptions.attribution.generated_with = false

Shell expansion in crush.json

In JSON, only selected string fields are run through the embedded shell at load time (in crushrc, everything is native Bash so this table does not apply):

SurfaceExpansion
Provider api_key, base_url, api_endpoint, extra_headersyes
Provider extra_bodyno (JSON passthrough)
MCP command, args, env, headers, urlyes
LSP command, args, envyes
Hook commandruns via sh -c, not the resolver

Supported constructs: $VAR, ${VAR}, ${VAR:-default}, ${VAR:+alt}, ${VAR:?message}, $(command). An unset variable expands to empty; a failing $(command) is a hard error. A header that resolves to empty is dropped from the request.

Security note

Both formats are trusted code. crushrc runs entirely, and any $(...) in crush.json runs at load time, with the invoking user's shell privileges, before the UI appears. Don't launch Crush in a directory whose config you haven't reviewed.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Use when creating a new builtin skill for Crush, editing an existing builtin skill (internal/skills/builtin/), or when the user needs to understand how the embedded skill system works.

日本語の概要は準備中です。原文の説明を表示しています。

charmbracelet/crush2.9万2026年10月12日 更新

Use when the user wants to add, write, debug, or configure a Crush hook — gating or blocking tool calls, approving or rewriting tool input before execution, injecting context into tool results, or troubleshooting hook behavior in crush.json.

日本語の概要は準備中です。原文の説明を表示しています。

charmbracelet/crush2.9万2026年10月12日 更新

jq

無料

Use when the user needs to query, filter, reshape, extract, create, or construct JSON data — including API responses, config files, log output, or any structured data — or when helping the user write or debug JSON transformations.

日本語の概要は準備中です。原文の説明を表示しています。

charmbracelet/crush2.9万2026年10月12日 更新

Use when creating a new shell builtin command for Crush (internal/shell/), editing an existing one, or when the user needs to understand how commands are intercepted in Crush's embedded shell.

日本語の概要は準備中です。原文の説明を表示しています。

charmbracelet/crush2.9万2026年10月12日 更新

charmbracelet のスキルをすべて見る

このスキルの問題を報告する