Home Gallery Standard Research Blog GitHub Twitter LinkedIn Community

crush system prompt

Category: General-purpose assistants. Audited against the AISPA standard.

What is in crush's system prompt?

crush's full system prompt: 1 version, 10,785 characters. Audited against AISPA.

The full text of 1 prompt is reproduced below, 10,785 characters in all, each read instruction by instruction against the eight AISPA dimensions. Nothing was flagged as working against the person on the other end.

1 Prompts on record
0 Flagged instructions
AI audit Audit source
D3 · Privacy & Data Protection D4 · Tool/Action Safety D5 · User Agency & Manipulation Prevention

crush - internal skills builtin crush config SKILL

10785 characters

--- 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): 1. `.crush.json` (project-local, hidden) 2. `crush.json` (project-local) 3. `$XDG_CONFIG_HOME/crush/crush.json` or `$HOME/.config/crush/crush.json` (global) ## Basic Structure ```json { "$schema": "https://charm.land/crush.json", "models": {}, "providers": {}, "mcp": {}, "lsp": {}, "hooks": {}, "options": {}, "permissions": {}, "tools": {} } ``` The `$schema` property enables IDE autocomplete but is optional. ## Shell Expansion Crush runs selected string fields through an embedded bash-compatible shell at load time, so values can pull from env vars, files, or helper commands. Supported constructs (match the `bash` tool): - `$VAR` and `${VAR}` - `${VAR:-default}`, `${VAR:+alt}`, `${VAR:?message}` - `$(command)` with full quoting and nesting - Single- and double-quoted strings, escapes Default semantics match bash: an unset variable expands to an empty string, no error. A failing `$(command)` is always a hard error. For required credentials, use `${VAR:?message}` so a missing variable fails loudly at load time with your message. ```json { "api_key": "${CODEBERG_TOKEN:?set CODEBERG_TOKEN}" } ``` ### Which fields expand | Surface | Expansion | | --------------------------------------------------- | --------- | | Provider `api_key`, `base_url`, `api_endpoint` | yes | | Provider `extra_headers` | yes | | Provider `extra_body` | **no** | | MCP `command`, `args`, `env`, `headers`, `url` | yes | | LSP `command`, `args`, `env` | yes | | Hook `command` | runs via `sh -c`, not the resolver | `extra_body` is a JSON passthrough. If you need env-driven values in a request body, put them in `extra_headers`, `api_key`, or `base_url` instead. ### Empty-resolved headers are dropped When a header value resolves to the empty string (unset variable, `$(echo)`, or literal `""`), the header is omitted from the outgoing request. This keeps optional env-gated headers like `"OpenAI-Organization": "$OPENAI_ORG_ID"` working cleanly when the var isn't set. Applies to MCP `headers` and provider `extra_headers`. ### Security note `crush.json` is trusted code. Any `$(...)` in it runs at load time with the invoking user's shell privileges, before the UI appears. Don't launch Crush in a directory whose `crush.json` you haven't reviewed. ## Common Tasks - Add a custom provider: add an entry under `providers` with `type`, `base_url`, `api_key`, and `models`. - Disable a builtin or local skill: add the skill name to `options.disabled_skills`. - Add an MCP server: add an entry under `mcp` with `type` and either `command` (stdio) or `url` (http/sse). ## Model Selection ```json { "models": { "large": { "model": "claude-sonnet-4-20250514", "provider": "anthropic", "max_tokens": 16384 }, "small": { "model": "claude-haiku-4-20250514", "provider": "anthropic" } } } ``` - `large` is the primary coding model; `small` is for summarization. - Only `model` and `provider` are required. - Optional tuning: `reasoning_effort`, `think`, `max_tokens`, `temperature`, `top_p`, `top_k`, `frequency_penalty`, `presence_penalty`, `provider_options`. ## Custom Providers ```json { "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`, or `anthropic` - `api_key`, `base_url`, `api_endpoint`, and `extra_headers` are shell-expanded (see [Shell Expansion](#shell-expansion)). - `extra_body` is a JSON passthrough and is **not** expanded. - Additional fields: `disable`, `system_prompt_prefix`, `extra_headers`, `extra_body`, `provider_options`. ## LSP Configuration ```json { "lsp": { "go": { "command": "gopls", "env": { "GOPATH": "$HOME/go" } }, "typescript": { "command": "typescript-language-server", "args": ["--stdio"] } } } ``` - `command` (required), `args`, `env` cover most setups. - `command`, `args`, and `env` values are shell-expanded (see [Shell Expansion](#shell-expansion)). - Additional fields: `disabled`, `filetypes`, `root_markers`, `init_options`, `options`, `timeout`. ## MCP Servers ```json { "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`, or `http` - `command`, `args`, `env`, `headers`, and `url` are shell-expanded (see [Shell Expansion](#shell-expansion)). - Additional fields: `env`, `disabled`, `disabled_tools`, `timeout`. ## Options ```json { "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`. ## User-Invocable Skills Skills can be made invocable as commands from the commands palette. Add `user-invocable: true` to the skill's YAML frontmatter: ```yaml --- name: my-skill description: A skill that can be invoked as a command. user-invocable: true --- ``` User-invocable skills appear in the commands palette with a prefix: - Skills from global directories: `user:skill-name` - Skills from project directories: `project:skill-name` When invoked, the skill's instructions are loaded into the conversation context. To prevent the model from auto-triggering a skill (while still allowing user invocation), add `disable-model-invocation: true`: ```yaml --- name: my-skill description: Only invocable by users, not the model. user-invocable: true disable-model-invocation: true --- ``` Skills with `disable-model-invocation` won't appear in the model's available skills list but can still be invoked manually by users. ## Hooks Hooks are user-defined shell commands that fire on agent events. Currently only `PreToolUse` is supported, which runs before a tool is executed. ```json { "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 via `sh -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 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**. ### Hook Input (stdin) A JSON payload is piped to the hook command: ```json { "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: ```json {"decision": "allow", "context": "optional context appended to tool result"} ``` - `decision`: `allow` to explicitly allow, `deny` to 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. ```bash 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: ```json { "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 ```json { "permissions": { "allowed_tools": ["view", "ls", "grep", "edit"] } } ``` ## Environment Variables - `CRUSH_GLOBAL_CONFIG` - Override global config location - `CRUSH_GLOBAL_DATA` - Override data directory location - `CRUSH_SKILLS_DIR` - Override default skills directory

Questions about crush's system prompt

Does crush's system prompt contain instructions that work against the user?

No. Nothing in crush's system prompt was flagged as working against the person the product is talking to. That is a clean result across all eight AISPA dimensions, not an absence of checking — the full text was read instruction by instruction.

How long is crush's system prompt?

10,785 characters across 1 prompt on this page. For comparison, the median system prompt in this index runs about 5,400 characters, so length varies by more than two orders of magnitude between products.

How many versions of crush's system prompt are on record?

1. Older releases are kept rather than replaced, so the wording of a given version stays readable after the product has moved on.

Where did this crush system prompt come from?

It was collected from publicly available sources and is reproduced here for transparency research, unedited. This site does not extract prompts from products itself.

How was crush's system prompt audited?

Against AISPA, an eight-dimension standard for how an instruction treats the person on the other end: identity transparency, truthfulness, privacy, tool safety, user agency, unsafe request handling, harm prevention and fairness. This audit was ai audit. The method is described in the paper behind the standard.

How this page was made

The prompt text above is reproduced verbatim from a public source. Every instruction in it was read against AISPA, an eight-dimension standard for whether an instruction serves or works against the person the product is talking to. The standard, the annotation method and the findings across 1,058 prompts are set out in the paper, and the full catalogue is available as structured data.

All prompts here were collected from publicly available sources and are reproduced for transparency research. Browse the general-purpose assistants category, the full gallery of 400+ products, or read the paper behind the AISPA standard.