command-code 0.52.5 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2541 -0
- package/dist/bundled/command-code-knowledge/SKILL.md +52 -0
- package/dist/bundled/command-code-knowledge/reference/checkpoints.md +366 -0
- package/dist/bundled/command-code-knowledge/reference/custom-agents.md +91 -0
- package/dist/bundled/command-code-knowledge/reference/custom-slash-commands.md +345 -0
- package/dist/bundled/command-code-knowledge/reference/headless.md +234 -0
- package/dist/bundled/command-code-knowledge/reference/hooks.md +1097 -0
- package/dist/bundled/command-code-knowledge/reference/mcp.md +626 -0
- package/dist/bundled/command-code-knowledge/reference/memory.md +98 -0
- package/dist/bundled/command-code-knowledge/reference/models.md +81 -0
- package/dist/bundled/command-code-knowledge/reference/permissions.md +412 -0
- package/dist/bundled/command-code-knowledge/reference/plan-mode.md +101 -0
- package/dist/bundled/command-code-knowledge/reference/product-help.md +421 -0
- package/dist/bundled/command-code-knowledge/reference/skills.md +993 -0
- package/dist/bundled/mod-builder/SKILL.md +128 -0
- package/dist/bundled/mod-builder/examples/block-dangerous-commands.ts +41 -0
- package/dist/bundled/mod-builder/examples/custom-entry-renderer.ts +32 -0
- package/dist/bundled/mod-builder/examples/custom-tool.ts +53 -0
- package/dist/bundled/mod-builder/examples/flags-and-options.ts +29 -0
- package/dist/bundled/mod-builder/examples/input-shortcuts.ts +41 -0
- package/dist/bundled/mod-builder/examples/kitchen-sink.ts +110 -0
- package/dist/bundled/mod-builder/examples/lifecycle-hooks.ts +64 -0
- package/dist/bundled/mod-builder/examples/observe-events.ts +30 -0
- package/dist/bundled/mod-builder/examples/slash-command.ts +33 -0
- package/dist/bundled/mod-builder/reference/api.md +81 -0
- package/dist/bundled/mod-builder/reference/hooks-and-events.md +308 -0
- package/dist/bundled/mod-builder/reference/overview.md +161 -0
- package/dist/bundled/mod-builder/reference/packaging.md +63 -0
- package/dist/bundled/mod-builder/reference/ui.md +63 -0
- package/dist/bundled/mod-builder/reference/verify.md +58 -0
- package/dist/bundled/skill-builder/SKILL.md +104 -0
- package/dist/cli.mjs +5 -5
- package/package.json +35 -26
- package/vsix/commandcode-vscode.vsix +0 -0
- /package/{skills → dist/bundled}/agent-browser/SKILL.md +0 -0
- /package/{skills → dist/bundled}/design/SKILL.md +0 -0
- /package/{skills → dist/bundled}/design/references/border.md +0 -0
- /package/{skills → dist/bundled}/design/references/button.md +0 -0
- /package/{skills → dist/bundled}/design/references/checkup.md +0 -0
- /package/{skills → dist/bundled}/design/references/color.md +0 -0
- /package/{skills → dist/bundled}/design/references/create.md +0 -0
- /package/{skills → dist/bundled}/design/references/design-html.md +0 -0
- /package/{skills → dist/bundled}/design/references/deslop.md +0 -0
- /package/{skills → dist/bundled}/design/references/finish.md +0 -0
- /package/{skills → dist/bundled}/design/references/interaction.md +0 -0
- /package/{skills → dist/bundled}/design/references/layout.md +0 -0
- /package/{skills → dist/bundled}/design/references/motion.md +0 -0
- /package/{skills → dist/bundled}/design/references/redesign.md +0 -0
- /package/{skills → dist/bundled}/design/references/refine.md +0 -0
- /package/{skills → dist/bundled}/design/references/relayout.md +0 -0
- /package/{skills → dist/bundled}/design/references/report-html.md +0 -0
- /package/{skills → dist/bundled}/design/references/responsive.md +0 -0
- /package/{skills → dist/bundled}/design/references/review.md +0 -0
- /package/{skills → dist/bundled}/design/references/setup.md +0 -0
- /package/{skills → dist/bundled}/design/references/shadow.md +0 -0
- /package/{skills → dist/bundled}/design/references/smell.md +0 -0
- /package/{skills → dist/bundled}/design/references/surface.md +0 -0
- /package/{skills → dist/bundled}/design/references/tokenize.md +0 -0
- /package/{skills → dist/bundled}/design/references/typeset.md +0 -0
- /package/{skills → dist/bundled}/design/references/voice.md +0 -0
- /package/{skills → dist/bundled}/design/references/writing.md +0 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<!-- GENERATED FILE — do not edit. Source: packages/docs/src/app/core-concepts/memory/page.mdx. Regenerate: pnpm generate:knowledge -->
|
|
2
|
+
|
|
3
|
+
# Memory
|
|
4
|
+
|
|
5
|
+
Set custom instructions for Command Code by creating an `AGENTS.md` file. It contains instructions that customize Command Code's behavior for your project.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Initialize
|
|
10
|
+
|
|
11
|
+
Create a new `AGENTS.md` in your project:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
/init
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This creates an `AGENTS.md` file in your project root with a starter template.
|
|
18
|
+
|
|
19
|
+
Commit your project's `AGENTS.md` to git.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Example
|
|
24
|
+
|
|
25
|
+
The `/init` command creates a template like this:
|
|
26
|
+
|
|
27
|
+
**AGENTS.md template**
|
|
28
|
+
```markdown
|
|
29
|
+
# Memory
|
|
30
|
+
|
|
31
|
+
## Project Overview
|
|
32
|
+
|
|
33
|
+
See @README.md for project overview and @package.json for available npm/pnpm commands for this project.
|
|
34
|
+
|
|
35
|
+
## Code Style Guidelines
|
|
36
|
+
|
|
37
|
+
- Use descriptive variable names
|
|
38
|
+
- Follow existing patterns in the codebase
|
|
39
|
+
- Extract complex conditions into meaningful boolean variables
|
|
40
|
+
|
|
41
|
+
## Architecture Notes
|
|
42
|
+
|
|
43
|
+
Add important architectural decisions and patterns here.
|
|
44
|
+
|
|
45
|
+
## Common Workflows
|
|
46
|
+
|
|
47
|
+
Document frequently used workflows and commands here.
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Customize it for your project.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## File Locations
|
|
56
|
+
|
|
57
|
+
Command Code reads `AGENTS.md` from two locations:
|
|
58
|
+
|
|
59
|
+
### Project-level
|
|
60
|
+
|
|
61
|
+
**Location:** `./AGENTS.md` or `./.commandcode/AGENTS.md`
|
|
62
|
+
|
|
63
|
+
Team-shared project instructions. Commit this to Git along with your code.
|
|
64
|
+
|
|
65
|
+
### User-level
|
|
66
|
+
|
|
67
|
+
**Location:** `~/.commandcode/AGENTS.md`
|
|
68
|
+
|
|
69
|
+
Personal preferences for all your projects.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Edit Memory Files
|
|
74
|
+
|
|
75
|
+
Edit `AGENTS.md` files:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
/memory
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Opens a selector to choose which file to edit (project or user).
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Commands
|
|
86
|
+
|
|
87
|
+
| **Command** | **Description** |
|
|
88
|
+
| ----------- | --------------- |
|
|
89
|
+
| `/init` | Create `AGENTS.md` in project root |
|
|
90
|
+
| `/memory` | Open file selector to edit `AGENTS.md` |
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Next steps
|
|
95
|
+
|
|
96
|
+
* [Skills](./skills.md) for specialized agent capabilities
|
|
97
|
+
* [Slash commands](https://commandcode.ai/docs/reference/slash-commands) for custom prompts
|
|
98
|
+
* Join our [Discord community](https://commandcode.ai/discord) for support
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<!-- GENERATED FILE — do not edit. Source: packages/shared/src/model-catalog.ts (registry + billing). Regenerate: pnpm generate:knowledge -->
|
|
2
|
+
|
|
3
|
+
# Command Code Models
|
|
4
|
+
|
|
5
|
+
The model catalog — every id `/model`, `--model`, `model:effort` shorthand, and agent-file `model:` pinning accept, with context windows, reasoning efforts, and advertised per-1M-token rates. Ids are EXACT — never invent or guess a model id. A BYO-provider id (from a configured custom provider) also works and is passed through as-is.
|
|
6
|
+
|
|
7
|
+
## Open Source
|
|
8
|
+
|
|
9
|
+
| Id (use EXACTLY this) | Name | Context | Efforts | $/1M in/out | Best for |
|
|
10
|
+
|---|---|---|---|---|---|
|
|
11
|
+
| `deepseek/deepseek-v4-pro` | DeepSeek V4 Pro | 1M | high, max | $0.435/$0.87 | hybrid-attention long-context reasoning |
|
|
12
|
+
| `deepseek/deepseek-v4-flash` | DeepSeek V4 Flash | 1M | high, max | $0.14/$0.28 | fast hybrid-attention reasoning |
|
|
13
|
+
| `moonshotai/Kimi-K3` | Kimi K3 | 1M | — | $3/$15 | long-horizon coding & knowledge work with 1M context |
|
|
14
|
+
| `moonshotai/Kimi-K2.7-Code` | Kimi K2.7 Code | 256K | — | $0.95/$4 | improved long-horizon coding with vision |
|
|
15
|
+
| `moonshotai/Kimi-K2.7-Code-Highspeed` | Kimi K2.7 Code HighSpeed | 262K | — | $1.9/$8 | high-speed long-horizon coding with vision |
|
|
16
|
+
| `moonshotai/Kimi-K2.6` | Kimi K2.6 | 256K | — | $0.95/$4 | long-horizon coding with vision |
|
|
17
|
+
| `moonshotai/Kimi-K2.5` | Kimi K2.5 | 256K | — | $0.6/$3 | multimodal frontend coding |
|
|
18
|
+
| `zai-org/GLM-5.2` | GLM-5.2 | 1M | high, max | $1.4/$4.4 | powerful coding with 1M context and long-horizon tasks |
|
|
19
|
+
| `zai-org/GLM-5.2-Fast` | GLM-5.2 Fast | 1M | — | $3/$10.25 | high-throughput GLM-5.2 with 1M context |
|
|
20
|
+
| `zai-org/GLM-5.1` | GLM-5.1 | — | — | $1.4/$4.4 | long-horizon autonomous coding agent |
|
|
21
|
+
| `zai-org/GLM-5` | GLM-5 | 200K | — | $1/$3.2 | multi-mode thinking & long-range planning |
|
|
22
|
+
| `MiniMaxAI/MiniMax-M3` | MiniMax M3 | 1M | — | $0.3/$1.2 | frontier coding, agents & native multimodality |
|
|
23
|
+
| `MiniMaxAI/MiniMax-M2.7` | MiniMax M2.7 | — | — | $0.3/$1.2 | end-to-end software engineering agent |
|
|
24
|
+
| `MiniMaxAI/MiniMax-M2.5` | MiniMax M2.5 | 200K | — | $0.3/$1.2 | cross-platform full-stack agentic dev |
|
|
25
|
+
| `xiaomi/mimo-v2.5-pro` | MiMo V2.5 Pro | 1M | — | $0.435/$0.87 | high-capability long-context agentic coding |
|
|
26
|
+
| `xiaomi/mimo-v2.5` | MiMo V2.5 | 1M | — | $0.14/$0.28 | efficient long-context agentic coding |
|
|
27
|
+
| `Qwen/Qwen3.6-Max-Preview` | Qwen 3.6 Max Preview | — | — | $1.3/$7.8 | vibe coding & efficient agent execution |
|
|
28
|
+
| `Qwen/Qwen3.6-Plus` | Qwen 3.6 Plus | — | — | $0.5/$3 | agentic coding & reasoning |
|
|
29
|
+
| `Qwen/Qwen3.7-Max` | Qwen 3.7 Max | 1M | — | $1.25/$3.75 | frontier coding & long-horizon agent execution |
|
|
30
|
+
| `Qwen/Qwen3.7-Plus` | Qwen 3.7 Plus | 1M | — | $0.4/$1.6 | agentic coding & reasoning at lower cost |
|
|
31
|
+
| `stepfun/Step-3.7-Flash` | Step 3.7 Flash | 256K | — | $0.2/$1.15 | multimodal sparse-MoE reasoning |
|
|
32
|
+
| `stepfun/Step-3.5-Flash` | Step 3.5 Flash | 1M | — | $0.1/$0.3 | fast sparse-MoE agentic reasoning |
|
|
33
|
+
| `nvidia/nemotron-3-ultra-550b-a55b` | Nemotron 3 Ultra | 1M | — | $0.6/$2.4 | open reasoning model for long-horizon autonomous agents |
|
|
34
|
+
| `thinkingmachines/inkling` | Inkling | 256K | — | $1/$4.05 | multimodal MoE reasoning |
|
|
35
|
+
| `poolside/laguna-s-2.1-free` | Laguna S 2.1 | 256K | — | $0/$0 | open-weight agentic coding and long-horizon work |
|
|
36
|
+
## Anthropic
|
|
37
|
+
|
|
38
|
+
| Id (use EXACTLY this) | Name | Context | Efforts | $/1M in/out | Best for |
|
|
39
|
+
|---|---|---|---|---|---|
|
|
40
|
+
| `claude-sonnet-5` | Claude Sonnet 5 | 1M | low, medium, high, xhigh, max | $2/$10 | best combo of speed & intelligence (recommended) |
|
|
41
|
+
| `claude-sonnet-4-6` | Claude Sonnet 4.6 | 1M | low, medium, high, xhigh, max | $3/$15 | prev Sonnet, still fast & capable |
|
|
42
|
+
| `claude-fable-5` | Claude Fable 5 | 1M | low, medium, high, xhigh, max | $10/$50 | most capable for demanding reasoning & long-horizon agents |
|
|
43
|
+
| `claude-opus-4-8` | Claude Opus 4.8 | 1M | low, medium, high, xhigh, max | $5/$25 | most intelligent Opus for agents and coding |
|
|
44
|
+
| `claude-opus-4-7` | Claude Opus 4.7 | 1M | low, medium, high, xhigh, max | $5/$25 | prev flagship, still strong for agents and coding |
|
|
45
|
+
| `claude-haiku-4-5-20251001` | Claude Haiku 4.5 | 200K | — | $1/$5 | fastest & most compact, great for quick tasks |
|
|
46
|
+
## OpenAI
|
|
47
|
+
|
|
48
|
+
| Id (use EXACTLY this) | Name | Context | Efforts | $/1M in/out | Best for |
|
|
49
|
+
|---|---|---|---|---|---|
|
|
50
|
+
| `gpt-5.6-sol` | GPT-5.6 Sol | 1.05M | low, medium, high, xhigh, max | $5/$30 | frontier model for complex professional work |
|
|
51
|
+
| `gpt-5.6-terra` | GPT-5.6 Terra | 1.05M | low, medium, high, xhigh, max | $2.5/$15 | balances intelligence and cost |
|
|
52
|
+
| `gpt-5.6-luna` | GPT-5.6 Luna | 1.05M | low, medium, high, xhigh, max | $1/$6 | optimized for cost-sensitive workloads |
|
|
53
|
+
| `gpt-5.5` | GPT-5.5 | — | low, medium, high, xhigh | $5/$30 | latest frontier model for general complex work |
|
|
54
|
+
| `gpt-5.4` | GPT-5.4 | 400K | low, medium, high, xhigh | $2.5/$15 | frontier model for general complex work |
|
|
55
|
+
| `gpt-5.3-codex` | GPT-5.3 Codex | 400K | low, medium, high, xhigh | $2/$8 | frontier coding model |
|
|
56
|
+
| `gpt-5.4-mini` | GPT-5.4 Mini | 400K | low, medium, high | $0.75/$4.5 | fast, cost-effective model for everyday tasks |
|
|
57
|
+
## Google
|
|
58
|
+
|
|
59
|
+
| Id (use EXACTLY this) | Name | Context | Efforts | $/1M in/out | Best for |
|
|
60
|
+
|---|---|---|---|---|---|
|
|
61
|
+
| `google/gemini-3.6-flash` | Gemini 3.6 Flash | 1M | low, medium, high | $1.5/$7.5 | higher-quality coding & agentic workflows, fewer tokens |
|
|
62
|
+
| `google/gemini-3.5-flash` | Gemini 3.5 Flash | 1M | low, medium, high | $1.5/$9 | Pro-level coding proficiency, parallel agentic execution |
|
|
63
|
+
| `google/gemini-3.5-flash-lite` | Gemini 3.5 Flash Lite | 1M | low, medium, high | $0.3/$2.5 | upgraded agentic capabilities, ideal for subagents |
|
|
64
|
+
| `google/gemini-3.1-flash-lite` | Gemini 3.1 Flash Lite | 1M | low, medium, high | $0.25/$1.5 | high-volume workhorse model with implicit caching |
|
|
65
|
+
## Sakana
|
|
66
|
+
|
|
67
|
+
| Id (use EXACTLY this) | Name | Context | Efforts | $/1M in/out | Best for |
|
|
68
|
+
|---|---|---|---|---|---|
|
|
69
|
+
| `sakana/fugu-ultra` | Fugu Ultra | 1M | high, xhigh | $5/$30 | multi-agent orchestration across frontier models |
|
|
70
|
+
## Meta
|
|
71
|
+
|
|
72
|
+
| Id (use EXACTLY this) | Name | Context | Efforts | $/1M in/out | Best for |
|
|
73
|
+
|---|---|---|---|---|---|
|
|
74
|
+
| `meta/muse-spark-1.1` | Muse Spark 1.1 | 1.05M | — | $1.25/$4.25 | agentic performance, tool use, and computer use |
|
|
75
|
+
## xAI
|
|
76
|
+
|
|
77
|
+
| Id (use EXACTLY this) | Name | Context | Efforts | $/1M in/out | Best for |
|
|
78
|
+
|---|---|---|---|---|---|
|
|
79
|
+
| `xai/grok-4.5` | Grok 4.5 | 500K | low, medium, high | $2/$6 | smartest model for coding, agentic tasks, knowledge work |
|
|
80
|
+
|
|
81
|
+
Rates are the advertised price list resolved from the billing source of truth (promos are already baked in). Models without an effort column entry decide their own reasoning depth. Full pricing detail: https://commandcode.ai/docs/resources/pricing-limits
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
<!-- GENERATED FILE — do not edit. Source: packages/docs/src/app/permissions/page.mdx. Regenerate: pnpm generate:knowledge -->
|
|
2
|
+
|
|
3
|
+
# Permissions
|
|
4
|
+
|
|
5
|
+
Permissions decide what Command Code is allowed to do before it does it. Every tool call — a shell command, a file edit, a web fetch, an MCP tool, a sub-agent — passes through **one central permission engine** that answers a single question: **allow, ask, or deny?**
|
|
6
|
+
|
|
7
|
+
The semantics match **Claude Code permission modes**: `deny`/`ask` rules win for permission-gated tools, `plan` is read-only exploration, `auto-accept` accepts edits plus safe filesystem commands, `bypass` skips normal prompts, and `dont-ask` denies anything that would need a prompt. The `ask_user_question` and `agent` control-flow tools — plus `run_command`, which just dispatches a slash command you named — are always allowed. This page is the complete reference — the pipeline, the modes, the rule syntax, the full decision table, and the known limits.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## How a decision is made
|
|
12
|
+
|
|
13
|
+
Every tool call is evaluated in a fixed order. The order **is** the spec — tests pin it:
|
|
14
|
+
|
|
15
|
+
1. **Deny rules** — blocked in every mode, including bypass.
|
|
16
|
+
2. **Ask rules** — always prompt, even under bypass. In `dont-ask` mode the would-be prompt becomes a deny.
|
|
17
|
+
3. **External-directory gate** — a read, write, or shell working directory **outside the workspace** first asks to admit the directory into the session's root set (like `/add-dir` / `permissions.additionalDirectories`); then the normal mode rule applies. Bypass grants the directory silently. The **OS temp directory** (`/tmp`, `$TMPDIR`, `os.tmpdir()`) is granted silently in every mode — reads there never prompt, and writes skip the escalation but still follow the normal mode rule. Registered skill directories are readable without a grant; plan-file writes in plan mode skip this gate.
|
|
18
|
+
4. **Plan mode gate** — operation-based: reads, searches, and read-only shell run; everything that writes or runs a mutating command is denied. The only write allowed is a plan file under `~/.commandcode/plans/`.
|
|
19
|
+
5. **Taste-directory writes** — a product workflow guard (allowed when taste learning is on, otherwise redirected to the `taste` tool); not a safety prompt, so bypass skips it.
|
|
20
|
+
6. **Malformed writes** — a write/edit with no resolvable file path is denied up front with a correction.
|
|
21
|
+
7. **Read-only fast path** — reads and read-only shell commands (`ls`, `cat`, `grep`, `echo`, `head`, …) run without a prompt, in every mode. A compound command counts when **every** part is read-only and nothing redirects — `cat file | head -5 || echo none` is free. A read-only command pointed at secret material (`cat .env`, `head id_rsa`) falls out of the fast path and prompts.
|
|
22
|
+
8. **Root/home removal circuit breaker** — `rm -rf /`, `rm -rf ~`, `rm -rf $HOME` and spoofed variants **ask even under bypass** (deny in `dont-ask`/`plan`, where nothing can ask).
|
|
23
|
+
9. **Bypass** — everything that survived the gates above auto-allows.
|
|
24
|
+
10. **Sensitive-write ask** — writing a secret file, a persistence vector (`.bashrc`, `.gitconfig`, …), or a control surface (`.git/**`, `.ssh/**`, `.commandcode` settings) prompts in `default` and `auto-accept` unless a content-specific allow rule opts in.
|
|
25
|
+
11. **Allow rules** — pre-approved calls run without a prompt.
|
|
26
|
+
12. **Accept-edits fast path** — in `auto-accept` mode, file edits and safe filesystem commands inside the workspace run without a prompt. Recursive deletes are excluded — they still prompt.
|
|
27
|
+
13. Otherwise, **ask** — and in `dont-ask` mode, **deny**.
|
|
28
|
+
|
|
29
|
+
Two things follow from the order. First, **deny beats ask, which beats allow**, in every mode. Second, `bypass` sits *after* the deny/ask rules, the external-dir gate, and the circuit breaker — so `--yolo` skips ordinary prompts and the sensitive-write prompt, but not your explicit rules and not the root/home breaker.
|
|
30
|
+
|
|
31
|
+
Rules are enforced by Command Code, not by the model. Instructions in your prompt or `AGENTS.md` shape what the agent *tries* to do, but they don't change what Command Code *allows*. To grant or revoke access, use permission rules, a permission mode, or a `PreToolUse` hook.
|
|
32
|
+
|
|
33
|
+
Every policy denial (a deny rule, a mode gate, a malformed input) carries guidance the model can act on, and the turn continues. Only a **human** answering "no" to a prompt ends the turn.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Permission modes
|
|
38
|
+
|
|
39
|
+
A mode sets the baseline behavior. Cycle modes at any time with **shift+tab**, or switch by name with **`/mode`**.
|
|
40
|
+
|
|
41
|
+
| Mode | Meaning |
|
|
42
|
+
| :------------ | :------------------------------------------------------------------------------------------------ |
|
|
43
|
+
| `default` | Prompt for anything mutating; reads are free. |
|
|
44
|
+
| `auto-accept` | Do normal workspace edits (and safe filesystem shell: `mkdir`, `touch`, `cp`, `mv`, non-recursive `rm`, `rmdir`, `sed`) without asking. Does **not** auto-accept arbitrary shell, MCP tools, or recursive deletes. |
|
|
45
|
+
| `plan` | Read-only exploration. Reads, searches, and read-only shell (`git status`) run; the only write allowed is the plan file. |
|
|
46
|
+
| `bypass` | Do basically everything without asking. Deny rules, explicit ask rules, and the root/home removal breaker still apply. Enter with `--yolo` / `--dangerously-skip-permissions`; use only in throwaway environments. |
|
|
47
|
+
| `dont-ask` | Never ask. Only run things already allowed by policy (reads, read-only shell, `allow` rules); **deny** the rest. The mirror image of bypass: for unattended runs where a wrong prompt should fail, not wait. |
|
|
48
|
+
|
|
49
|
+
Claude Code mode names are accepted as aliases: `manual` → `default`, `acceptEdits` → `auto-accept`, `dontAsk` → `dont-ask`, `bypassPermissions` → `bypass`. The legacy name `standard` also maps to `default`.
|
|
50
|
+
|
|
51
|
+
### Switching modes
|
|
52
|
+
|
|
53
|
+
Three ways to switch mid-session:
|
|
54
|
+
|
|
55
|
+
- **shift+tab** cycles `default` → `auto-accept` → `plan` → `default`. When Command Code was launched with `--yolo`, `bypass` joins as a fourth rung after `plan`. (`alt+m` is an equivalent binding for terminals that don't deliver shift+tab.) `dont-ask` is not a rung — it's selected via settings or the CLI; pressing shift+tab from it re-enters the normal cycle at `auto-accept`.
|
|
56
|
+
- **`/mode`** shows the current mode; **`/mode:default`**, **`/mode:auto-accept`**, and **`/mode:plan`** (or `/mode <name>`, any accepted spelling) switch directly. Bypass is deliberately **not** switchable from a slash command — slash commands are agent-invokable, so a mid-session route into bypass would let the model disable its own prompts. `/mode:yolo` no longer exists; the command answers "launch with `--yolo` to use it."
|
|
57
|
+
- **CLI flags** pick the starting mode:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
cmd --permission-mode auto-accept # default | standard | plan | auto-accept | dont-ask
|
|
61
|
+
cmd --auto-accept # shorthand for --permission-mode auto-accept
|
|
62
|
+
cmd --plan # start in plan mode
|
|
63
|
+
cmd --yolo # bypass — alias for --dangerously-skip-permissions; use with care
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`--permission-mode` wins over `--plan`. Bypass has no `--permission-mode` value — it is **launch-flag-only** (`--yolo` / `--dangerously-skip-permissions`).
|
|
67
|
+
|
|
68
|
+
Switching modes also resolves a permission prompt already on screen: entering `auto-accept` or `bypass` **approves** the pending prompt (you just said "stop asking"), and entering `plan` **denies** it. A safety-forced prompt — a destructive command, a sensitive file, an explicit `ask` rule — is never answered by a mode change; it stays on screen for an explicit yes/no.
|
|
69
|
+
|
|
70
|
+
### `dont-ask` is the CI/CD mode
|
|
71
|
+
|
|
72
|
+
`dont-ask` is a **fail-closed allowlist**, not an auto-edit mode. If CI should edit files, pre-approve the surface in settings:
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"permissions": {
|
|
77
|
+
"defaultMode": "dont-ask",
|
|
78
|
+
"allow": ["Edit(src/**)", "Write(src/generated/**)"]
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Those edits run without prompting; anything outside the allowlist is denied.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## The decision table
|
|
88
|
+
|
|
89
|
+
The complete matrix — every kind of operation against every mode. This is the authoritative behavior reference; the permission tests pin each row.
|
|
90
|
+
|
|
91
|
+
| Operation | `default` | `auto-accept` | `plan` | `bypass` | `dont-ask` | Why |
|
|
92
|
+
|---|---|---|---|---|---|---|
|
|
93
|
+
| Matches `deny` rule | deny | deny | deny | deny | deny | Deny rules win for permission-gated tools. `ask_user_question`, `agent`, and `run_command` are unconditional exceptions. |
|
|
94
|
+
| Matches `ask` rule | ask | ask | ask | ask | deny | Ask rules survive bypass; `dont-ask` cannot prompt. `ask_user_question`, `agent`, and `run_command` are exempt. |
|
|
95
|
+
| Matches `allow` rule | allow | allow | allow if plan-compatible | allow | allow | Allow rules are honored after deny/ask and mode gates. |
|
|
96
|
+
| Direct file read/search inside workspace | allow | allow | allow | allow | allow | Reads are free unless rules say otherwise. |
|
|
97
|
+
| Direct file read/search outside workspace | ask external-dir, then allow | ask external-dir, then allow | ask external-dir, then allow | allow | deny unless pre-approved | Outside dirs are gated separately, then reads are allowed. |
|
|
98
|
+
| Read under the OS temp directory (`/tmp`, `$TMPDIR`) | allow (dir granted silently) | allow (dir granted silently) | allow (dir granted silently) | allow | allow | Temp files are disposable working data — the external-dir escalation is skipped. Deny/ask rules still outrank; a symlink resolving outside temp takes the normal gate. |
|
|
99
|
+
| Write under the OS temp directory | ask like a workspace write | allow; sensitive still asks | deny | allow | deny unless allow rule | No external-dir escalation, then the normal mode edit/write rule applies (sensitive names like `/tmp/.env` still force the prompt). |
|
|
100
|
+
| Read under a registered skill directory | allow | allow | allow | allow | allow | Skill resources are readable without a grant; writes into skill dirs still gate. |
|
|
101
|
+
| Web / read-only native tool | allow | allow | allow | allow | allow | Non-filesystem read-only tools are free unless rules say otherwise. |
|
|
102
|
+
| `ask_user_question` | allow | allow | allow | allow | allow | Asking the user is the interaction; a permission prompt must never stack in front of the question. |
|
|
103
|
+
| `agent` | allow | allow | allow | allow | allow | Delegation itself is always allowed. Every tool used by the sub-agent is still checked under its own permission policy. |
|
|
104
|
+
| `run_command` | allow | allow | — | allow | allow | Dispatches a slash command you named, exactly as if you'd typed it — removed from the toolset in plan mode (a write tool) and never granted to sub-agents. |
|
|
105
|
+
| Read-only shell, e.g. `git status`, `cat README.md \| head -5` | allow | allow | allow | allow | allow | Plan may explore with read-only shell. Compound commands qualify when every part is read-only and nothing redirects. Shell cwd follows the external-dir row below. |
|
|
106
|
+
| Secret-looking read via a file tool, e.g. `read_file .env` | allow | allow | allow | allow | allow | No built-in secret-read prompt for file tools (Claude parity). Use `ask`/`deny` rules for sensitive reads. |
|
|
107
|
+
| Secret-looking read via shell, e.g. `cat .env` | ask | ask | deny | allow | deny unless allow rule | A read-only shell command with a secret-material argument (`.env`, `id_rsa`, `*.pem`) falls out of the read-only fast path. |
|
|
108
|
+
| Workspace file edit | ask | allow | deny | allow | deny unless allow rule | `auto-accept` accepts normal edits; `dont-ask` only runs pre-approved edits. |
|
|
109
|
+
| Protected workspace write, e.g. `.env` or `.git/config` | ask | ask | deny | allow | deny unless pre-approved | Bypass skips normal write-risk prompts; auto-accept does not. |
|
|
110
|
+
| Direct file write outside workspace | ask external-dir, then ask edit/write | ask external-dir, then allow normal edit/write; sensitive still asks | deny, except plan-file writes | allow | deny unless pre-approved | External-dir gate comes first, then the mode-specific edit/write rule. |
|
|
111
|
+
| Plan file write under `~/.commandcode/plans/` | ask like outside write | ask external-dir, then allow | allow (no external-dir prompt) | allow | deny unless pre-approved | Plan mode's sanctioned output; never gated in plan mode. |
|
|
112
|
+
| Safe filesystem shell inside workspace: `mkdir`, `touch`, `cp`, `mv`, non-recursive `rm`, `rmdir`, `sed` | ask | allow | deny | allow | deny unless allow rule | Claude `acceptEdits` filesystem behavior, constrained to non-sensitive workspace targets. Recursive `rm` is excluded — see the recursive-delete row. |
|
|
113
|
+
| Shell cwd outside workspace | ask external-dir, then apply shell rule/mode | ask external-dir, then apply shell rule/mode | ask external-dir for read-only shell; deny mutating shell | allow | deny unless pre-approved | The shell working directory is external-dir gated. |
|
|
114
|
+
| Shell command args outside workspace | shell rule/mode | shell rule/mode | shell rule/mode | allow | shell rule/mode | Path arguments inside a command string are never external-dir gated (not a reliable file boundary); use shell `ask`/`deny` rules for sensitive commands. |
|
|
115
|
+
| Other mutating shell | ask | ask | deny | allow | deny unless allow rule | Shell command arguments are governed by shell rules and the active mode. |
|
|
116
|
+
| MCP / custom side-effecting or unknown tool | ask | ask | deny | allow | deny unless allow rule | Unknown side effects prompt unless bypass or an explicit rule. |
|
|
117
|
+
| Root/home removal, e.g. `rm -rf /` or `rm -rf ~` | ask | ask | deny | **ask** | deny | The circuit breaker survives bypass. |
|
|
118
|
+
| Recursive workspace delete, e.g. `rm -rf dist` | ask | ask | deny | allow | deny unless allow rule | Recursive deletes prompt outside bypass — accepting edits is not accepting bulk irreversible deletion. A content-specific allow rule (`Shell(rm -rf dist)`) still auto-allows. |
|
|
119
|
+
|
|
120
|
+
Reading down a column: a mode only changes the outcome of calls the rules leave **unresolved**. A `deny` rule and an `ask` rule behave the same in every interactive mode; `dont-ask` turns every would-be ask into a deny; `bypass` auto-allows everything except deny rules, ask rules, and the circuit breaker.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Rule syntax
|
|
125
|
+
|
|
126
|
+
Three lists in `permissions` settings, checked in this order: **deny** (always wins) → **ask** (always prompts, even in bypass; denies in dont-ask) → **allow**. Three tools bypass these lists: `ask_user_question`, because its question UI is already the interaction; `agent`, because delegation itself has no side effect; and `run_command`, because it just dispatches a slash command you named, exactly as if you'd typed it. Tools called by a delegated sub-agent remain permission-gated.
|
|
127
|
+
|
|
128
|
+
A rule is a tool name, optionally with a specifier in parentheses:
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
Tool # the whole tool
|
|
132
|
+
Tool(specifier) # a specific use
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
| Rule | Effect |
|
|
136
|
+
| :-------------------------------- | :------------------------------------------------- |
|
|
137
|
+
| `Shell` | Matches every shell command |
|
|
138
|
+
| `Shell(git status)` | Matches `git status` (and `git status --short`) |
|
|
139
|
+
| `Shell(npm run *)` | Matches any `npm run …` command |
|
|
140
|
+
| `Read(./.env)` | Matches reading `.env` in the project root |
|
|
141
|
+
| `Edit(src/**)` | Matches edits anywhere under `src/` |
|
|
142
|
+
| `WebFetch(domain:example.com)` | Matches fetches to `example.com` |
|
|
143
|
+
| `mcp__github__get_issue` | Matches one tool from the `github` MCP server |
|
|
144
|
+
| `mcp__github__*` | Matches every tool from the `github` server |
|
|
145
|
+
| `mcp__github__get_*` | Matches every `get_` tool from the `github` server |
|
|
146
|
+
| `mcp__*` | Matches every tool from every MCP server |
|
|
147
|
+
| `*` | Matches every tool |
|
|
148
|
+
| `Shell(run_in_background:true)` | Matches a shell command run in the background |
|
|
149
|
+
|
|
150
|
+
Tool names are case-insensitive. `Tool()` and `Tool(*)` both mean the whole tool.
|
|
151
|
+
|
|
152
|
+
### Wildcards
|
|
153
|
+
|
|
154
|
+
A `*` in a **tool name** (not a specifier) matches by name, so you can write broad rules without listing every tool:
|
|
155
|
+
|
|
156
|
+
- `*` — every permission-gated tool (`ask_user_question`, `agent`, and `run_command` remain allowed).
|
|
157
|
+
- `mcp__*` — every tool from every MCP server.
|
|
158
|
+
- `mcp__github__get_*` — every read-style tool from one server.
|
|
159
|
+
- `edit_*` — every tool whose name starts with `edit_`.
|
|
160
|
+
|
|
161
|
+
Tool-name wildcards are honored in `deny` and `ask` lists, where a broad rule is what you want (`deny: ["mcp__*"]` blocks all MCP tools). They are **ignored in `allow` lists** unless the server is named (`mcp__github__get_*` is fine; a bare `*` or `mcp__*` is not) — an allow rule should say what it grants, not hand out everything. Specifier wildcards (`Shell(npm *)`, `Edit(src/**)`, `WebFetch(domain:*.example.com)`) work in every list.
|
|
162
|
+
|
|
163
|
+
### Match by input parameter
|
|
164
|
+
|
|
165
|
+
Beyond a tool's own specifier, a `deny` or `ask` rule can gate on a single **top-level input parameter** with `Tool(param:value)`:
|
|
166
|
+
|
|
167
|
+
- `Shell(run_in_background:true)` — a background shell command.
|
|
168
|
+
|
|
169
|
+
The value takes a `*` wildcard, and a parameter the model **omits** never matches. Each rule names one parameter — to gate on two, write two rules.
|
|
170
|
+
|
|
171
|
+
Parameter matching is **deny/ask only**. An allow rule for one parameter can't establish that the whole call is safe, so `allow` rules keep to each tool's own specifier. The fields a tool already matches with its own syntax — `command` (Shell), `file_path` (Read/Edit/Write), `path` (Grep/Glob), `notebook_path`, and `url` (WebFetch) — are **not** parameter-matchable; use the tool's specifier for those (`Shell(rm *)`, not `Shell(command:rm *)`).
|
|
172
|
+
|
|
173
|
+
### Tool names
|
|
174
|
+
|
|
175
|
+
Use the friendly capitalized names, or the exact tool names the model sees:
|
|
176
|
+
|
|
177
|
+
| Friendly | Covers |
|
|
178
|
+
| :----------- | :----------------------------------------------------------- |
|
|
179
|
+
| `Shell` | `shell_command`, `monitor_command`, `kill_shell` |
|
|
180
|
+
| `Read` | `read_file`, `read_multiple_files`, `read_directory`, `glob`, `grep` |
|
|
181
|
+
| `Edit` | `edit_file`, `write_file` |
|
|
182
|
+
| `Write` | `write_file` |
|
|
183
|
+
| `WebFetch` | `web_fetch` |
|
|
184
|
+
| `WebSearch` | `web_search` |
|
|
185
|
+
|
|
186
|
+
`Shell` is the name for shell commands, because the shell tool is called `shell_command`. `Bash(...)` is accepted as a legacy alias for `Shell(...)`, so older configurations keep working — but `Shell` is the name to use.
|
|
187
|
+
|
|
188
|
+
### Shell patterns
|
|
189
|
+
|
|
190
|
+
Shell specifiers support `*` wildcards:
|
|
191
|
+
|
|
192
|
+
- `Shell(npm run build)` — the exact command.
|
|
193
|
+
- `Shell(npm run *)` — any command starting with `npm run `.
|
|
194
|
+
- `Shell(git * main)` — `git checkout main`, `git merge main`, …
|
|
195
|
+
- `Shell(git:*)` — the `:*` suffix is a trailing wildcard, the same as `Shell(git *)`.
|
|
196
|
+
|
|
197
|
+
The space before `*` matters: `Shell(ls *)` matches `ls -la` but not `lsof`; `Shell(ls*)` matches both.
|
|
198
|
+
|
|
199
|
+
Command Code understands shell operators, so a rule like `Shell(git status)` does **not** grant `git status && rm -rf .`. Every subcommand of a compound command (`&&`, `||`, `;`, `|`, `&`, newlines) must match on its own.
|
|
200
|
+
|
|
201
|
+
### Asymmetric matching: deny/ask are aggressive, allow is conservative
|
|
202
|
+
|
|
203
|
+
The matcher deliberately treats the lists differently — failing toward a prompt is always the safe direction:
|
|
204
|
+
|
|
205
|
+
- **Deny and ask rules match aggressively:** They see through leading environment variables (`FOO=bar rm -rf x` matches `Shell(rm *)`), process wrappers (`timeout 30 …`, `nice …`), and every subcommand of a compound command; a command the parser can't fully understand is matched against the raw string; path matching folds case (on macOS/Windows `.ENV` opens `.env`) and fires when either the given path or its symlink target matches.
|
|
206
|
+
- **Allow rules match conservatively:** No env stripping (`PATH=/tmp git status` does **not** match an allow for `Shell(git status:*)`); a compound command allows only when *every* subcommand matches some allow pattern; an unparseable command never auto-allows; path matching is case-exact and requires **both** the given path and its symlink target to match.
|
|
207
|
+
|
|
208
|
+
### File-path patterns
|
|
209
|
+
|
|
210
|
+
`Read` and `Edit` patterns follow gitignore-style matching with four anchors:
|
|
211
|
+
|
|
212
|
+
| Pattern | Anchored at | Example |
|
|
213
|
+
| :------------- | :----------------------------------- | :----------------------------- |
|
|
214
|
+
| `//path` | Filesystem root | `Read(//etc/**)` |
|
|
215
|
+
| `~/path` | Home directory | `Edit(~/.config/**)` |
|
|
216
|
+
| `/path` | Project root | `Edit(/src/**)` |
|
|
217
|
+
| `path` | Any depth under the project | `Read(.env)` ≡ `Read(**/.env)` |
|
|
218
|
+
|
|
219
|
+
`*` matches within one path segment; `**` matches across directories. When a rule points at a symlink, both the link and its target are checked. A trailing slash on the tool's input path can't dodge an exact-path rule (`read_directory /repo/secrets/` still matches `Read(//repo/secrets)`).
|
|
220
|
+
|
|
221
|
+
Reads are allowed by default. `allow: ["Read(src/**)"]` is accepted but does **not** block reads outside `src/**` — use `ask`/`deny` rules for sensitive reads. A strict read allowlist would be a separate behavior change (see Known limits).
|
|
222
|
+
|
|
223
|
+
### MCP and sub-agents
|
|
224
|
+
|
|
225
|
+
MCP tools are named by their canonical `mcp__server__tool` name — display names are never permission keys. `mcp__github` and `mcp__github__*` both match every tool from the `github` server; `mcp__github__get_*` matches just its `get_` tools; and `mcp__*` (deny/ask only) matches every tool from every server.
|
|
226
|
+
|
|
227
|
+
The `agent` tool itself is always allowed and never displays a permission prompt. A sub-agent runs under its own permission policy — the **same ordered pipeline** as the main loop, with one difference: where the main loop would draw an interactive prompt, the sub-agent policy **auto-allows**, because a sub-agent runs autonomously and has no human in its loop to answer. The hard guards still hold: a sub-agent can never run a tool your `deny` rules block, never write in plan mode, and anything the main loop would have prompted about for **safety** — a destructive command, a sensitive file, an outside-workspace write, an explicit `ask` rule — fails **closed** (denied) instead of sailing through.
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Prompt choices
|
|
232
|
+
|
|
233
|
+
Every permission prompt offers exactly **three** choices: allow once, allow **and remember**, or deny with feedback. The remembered scope matches the subject:
|
|
234
|
+
|
|
235
|
+
- **File operations** — *"Yes, allow all edits this session"* turns on auto-accept for the rest of the session (same as shift+tab).
|
|
236
|
+
- **Shell commands** — *"Yes, don't ask again for `git` commands in this project"* persists a `Shell(git:*)` allow rule to project settings. For a compound command, one rule is written per non-read-only base. Bases that execute arbitrary code (`bash`, `python`, `curl`, …) persist the exact command instead of a prefix grant.
|
|
237
|
+
- **MCP / other tools** — *"Yes, don't ask again for `mcp__server__tool` in this project"* persists the tool name to project settings.
|
|
238
|
+
|
|
239
|
+
### Command explanations on demand
|
|
240
|
+
|
|
241
|
+
The shell permission prompt can explain the command it's asking about: press **ctrl+e** (**ctrl+y** in VS Code-family terminals, where the IDE intercepts ctrl+e) and a background model call summarizes what the command does, inline in the prompt. This is governed by the `on-demand-tool-descriptions` setting (**on by default**): explanations are generated only when you ask for one. Turn the setting off (via `/config`) to generate every explanation upfront instead.
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Safety behaviors
|
|
246
|
+
|
|
247
|
+
Safety-forced prompts only offer one-time **Yes** or **No** choices, plus a banner saying which safety check fired. Session and project choices are intentionally hidden because destructive-command, sensitive-path, outside-workspace, and explicit `ask` approvals are never cached — the next risky call must ask again. To stop a recurring safety prompt, add a content-specific allow rule (e.g. `Edit(.commandcode/settings.json)`).
|
|
248
|
+
|
|
249
|
+
### The root/home removal circuit breaker
|
|
250
|
+
|
|
251
|
+
The **only** built-in safety prompt that survives `bypass`: a removal targeting the filesystem root or your home directory — `rm -rf /`, `rm -rf ~`, `rm -rf $HOME` — always stops for confirmation, in every mode that can ask (`dont-ask` and `plan` deny instead, since they can't prompt).
|
|
252
|
+
|
|
253
|
+
The breaker is spoof-resistant. It detects removals through environment-variable prefixes, process wrappers (`timeout`, `nice`, …), compound commands, quoted payloads (`bash -c "rm -rf /; echo ok"`), command substitution (`echo $(rm -rf /;)`), glued separators (`/;`), and `$HOME`/`${HOME}` spellings (quoted or not, with `/` or `/*` suffixes — `$HOMEDIR` stays literal).
|
|
254
|
+
|
|
255
|
+
### Recursive deletes prompt under auto-accept
|
|
256
|
+
|
|
257
|
+
The `auto-accept` safe-filesystem fast path refuses `rm -r/-R/-rf/--recursive` (and `find … -delete`): a recursive delete like `rm -rf dist` prompts exactly as it would in `default`. Plain single-file `rm` stays fast-pathed. This is a deliberate divergence from strict Claude `acceptEdits` parity, in the safe direction — accepting edits is not accepting bulk irreversible deletion. A content-specific allow rule (`Shell(rm -rf dist)`) still auto-allows, and `bypass` runs it without a prompt.
|
|
258
|
+
|
|
259
|
+
### Sensitive writes
|
|
260
|
+
|
|
261
|
+
Writing these prompts in `default` and `auto-accept` unless a content-specific allow rule opts in (`bypass` skips this gate, like Claude `bypassPermissions`):
|
|
262
|
+
|
|
263
|
+
```
|
|
264
|
+
Secret material: .env, .env.*, *.pem, *.key, id_rsa, id_ed25519, credentials
|
|
265
|
+
Persistence vectors: .bashrc, .zshrc, .profile, .gitconfig, .gitmodules, .mcp.json, …
|
|
266
|
+
Control surfaces: .git/**, .ssh/**, .aws/**, .gnupg/**, .kube/**, .vscode/**, .idea/**,
|
|
267
|
+
.husky/**, .devcontainer/**, node_modules/.bin/**, .commandcode settings
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
A "content-specific" allow rule must carry a specifier that names the path (`Edit(.env.local)`) — a bare whole-tool allow (`Edit`) is deliberately not enough to wave a call past a safety check.
|
|
271
|
+
|
|
272
|
+
Sensitive **reads** through file tools do not prompt. Matching Claude Code, reading `.env` is allowed by default — if you want it gated, say so with a rule: `ask: ["Read(.env*)"]` or `deny: ["Read(.env*)", "Read(secrets/**)"]`. The read-only **shell** fast path is stricter: `cat .env` or `head id_rsa` falls out of it and prompts like any other command.
|
|
273
|
+
|
|
274
|
+
### External directories
|
|
275
|
+
|
|
276
|
+
Outside-workspace reads, writes, and shell working directories first ask to admit the directory into the session's root set — the same grant as `/add-dir` or `permissions.additionalDirectories` — and then the normal mode rule applies. Details:
|
|
277
|
+
|
|
278
|
+
- `bypass` grants the directory silently; `dont-ask` denies unless the directory is pre-approved in settings.
|
|
279
|
+
- The **OS temp directory** (`/tmp`, `$TMPDIR`, `os.tmpdir()`) is granted silently in every mode — temp files are disposable working data, so asking to "extend access" to the machine's own temp dir is friction, not protection. Reads there run prompt-free; writes skip the outside-workspace escalation but still confirm like any workspace write (and sensitive names like `/tmp/.env` still force the sensitive-file prompt). Explicit `deny`/`ask` rules still outrank the grant, and a symlink under the temp dir that resolves outside it takes the normal gate. (Claude Code has no temp exemption — its answer is the per-session scratchpad, which Command Code also has; codex auto-approves `/tmp` and `$TMPDIR`.)
|
|
280
|
+
- Approving an `ask` rule on an outside path **also grants the directory**, so the tool-level backstop never rejects a call you just approved.
|
|
281
|
+
- **Registered skill directories** are readable without a grant (skill resources live outside the workspace by design). Writes into skill directories still gate.
|
|
282
|
+
- **Plan-file writes are exempt in plan mode** — they are the mode's sanctioned output.
|
|
283
|
+
- Absolute paths **inside a shell command string** are *not* external-dir gated — a command argument is not a reliable file boundary. Use shell `ask`/`deny` rules for sensitive commands.
|
|
284
|
+
|
|
285
|
+
### Disabling bypass
|
|
286
|
+
|
|
287
|
+
Set `permissions.disableBypass` to `"disable"` (or `true`) to make bypass mode unenterable. This is enforced at every layer: the engine evaluates a requested `bypass` as `default`, and the CLI neutralizes `--dangerously-skip-permissions` (and its `--yolo` alias) at entry, so the TUI mode cycle and stored auto-approve decisions can never silently answer prompts as if bypass were live. Most useful in the user-global settings file a project can't edit.
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Settings
|
|
292
|
+
|
|
293
|
+
Permission rules live under `permissions` in `.commandcode/settings.json` (shared, checked in) or `.commandcode/settings.local.json` (personal, gitignored). Interactive project approvals write to `settings.json` in a normal run and to `settings.local.json` when Command Code starts with `--local`:
|
|
294
|
+
|
|
295
|
+
```json
|
|
296
|
+
{
|
|
297
|
+
"permissions": {
|
|
298
|
+
"defaultMode": "default",
|
|
299
|
+
"allow": [
|
|
300
|
+
"Shell(git status:*)",
|
|
301
|
+
"Shell(git log:*)",
|
|
302
|
+
"Shell(npm run *)",
|
|
303
|
+
"mcp__github__get_issue"
|
|
304
|
+
],
|
|
305
|
+
"ask": [
|
|
306
|
+
"Shell(git push:*)",
|
|
307
|
+
"Read(.env*)"
|
|
308
|
+
],
|
|
309
|
+
"deny": [
|
|
310
|
+
"Shell(git reset --hard*)",
|
|
311
|
+
"Read(secrets/**)",
|
|
312
|
+
"Edit(.git/**)"
|
|
313
|
+
],
|
|
314
|
+
"additionalDirectories": ["~/shared-libs"],
|
|
315
|
+
"disableBypass": "disable"
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
- **`defaultMode`** — the starting mode (`default`, `auto-accept`, `plan`, `bypass`, or `dont-ask`; Claude spellings like `acceptEdits` and the legacy `standard` also work).
|
|
321
|
+
- **`allow` / `ask` / `deny`** — rule lists. These **accumulate across settings files**: a `deny` rule in your user-global settings can't be erased by a project file.
|
|
322
|
+
- **`additionalDirectories`** — extra directories that count as inside the workspace for reads and writes (same accumulation).
|
|
323
|
+
- **`disableBypass`** — set to `"disable"` (or `true`) to make bypass mode unenterable.
|
|
324
|
+
|
|
325
|
+
### Precedence
|
|
326
|
+
|
|
327
|
+
If a tool is denied at any level, no other level can allow it. A managed or user-global `deny` beats a project `allow`; deny beats ask; ask beats allow. Specificity doesn't change the order — a broad `deny` still blocks a narrower `allow`.
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Examples
|
|
332
|
+
|
|
333
|
+
**Read-only git, ask before pushing, block history rewrites:**
|
|
334
|
+
|
|
335
|
+
```json
|
|
336
|
+
{
|
|
337
|
+
"permissions": {
|
|
338
|
+
"allow": ["Shell(git status:*)", "Shell(git log:*)", "Shell(git diff:*)"],
|
|
339
|
+
"ask": ["Shell(git push:*)", "Shell(git pull:*)"],
|
|
340
|
+
"deny": ["Shell(git push --force*)", "Shell(git reset --hard*)", "Shell(git clean -*)"]
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
**Gate secret reads (they're free by default):**
|
|
346
|
+
|
|
347
|
+
```json
|
|
348
|
+
{
|
|
349
|
+
"permissions": {
|
|
350
|
+
"ask": ["Read(.env*)"],
|
|
351
|
+
"deny": ["Read(secrets/**)", "Read(~/.ssh/**)"]
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
**Protect lockfiles and the git directory:**
|
|
357
|
+
|
|
358
|
+
```json
|
|
359
|
+
{
|
|
360
|
+
"permissions": {
|
|
361
|
+
"ask": ["Edit(package.json)", "Edit(pnpm-lock.yaml)"],
|
|
362
|
+
"deny": ["Edit(.git/**)", "Edit(.ssh/**)"]
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
**Allow one MCP tool, or a whole server:**
|
|
368
|
+
|
|
369
|
+
```json
|
|
370
|
+
{
|
|
371
|
+
"permissions": {
|
|
372
|
+
"allow": ["mcp__github__get_issue", "mcp__linear__*"]
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## Design decisions
|
|
380
|
+
|
|
381
|
+
The choices behind the behavior above, so you don't have to reverse-engineer them:
|
|
382
|
+
|
|
383
|
+
1. **Claude Code parity over a custom safety matrix.** There is no built-in `.env` file-read prompt and no bypass-surviving recursive-delete prompt. Sensitive file reads are a rules concern (`ask`/`deny`), not a hardcoded prompt. The one stricter carve-out: the read-only **shell** fast path screens secret-material arguments, so `cat .env` prompts instead of riding `cat`'s free pass.
|
|
384
|
+
2. **One ordered pipeline.** The order in [How a decision is made](#how-a-decision-is-made) is the spec; tests pin it.
|
|
385
|
+
3. **Asymmetric rule matching.** Deny/ask match aggressively; allow matches conservatively. Failing toward a prompt is always the safe direction.
|
|
386
|
+
4. **External directories are a separate gate**, applied before the mode rule, with skill read roots and plan-file writes exempted where the mode sanctions them.
|
|
387
|
+
5. **The circuit breaker survives bypass and is spoof-resistant.**
|
|
388
|
+
6. **`disableBypass` is enforced at every layer** — engine, CLI entry, TUI mode cycle, and decision store.
|
|
389
|
+
7. **Shell command arguments are not a file boundary.** Absolute paths inside a command string are governed by shell rules and the active mode, not the file-tool boundary.
|
|
390
|
+
8. **Generic tools get a real prompt.** MCP/custom tools render a generic permission prompt instead of a fake file-edit prompt.
|
|
391
|
+
9. **Recursive deletes prompt under auto-accept** — a deliberate, safe-direction divergence from strict `acceptEdits` parity.
|
|
392
|
+
10. **Policy denials guide the model; only human vetoes end the turn.** Every engine denial carries actionable guidance so the model adapts and the turn continues.
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## Known limits
|
|
397
|
+
|
|
398
|
+
Documented edges of the current engine — behaviors to know about when writing rules:
|
|
399
|
+
|
|
400
|
+
- **Wildcard `include` patterns in `read_multiple_files` expand inside the tool**, so an exact-file deny rule (`Read(.env)`) cannot match a wildcard include (`*.env`) before expansion. Directory-tree rules (`Read(//etc/**)`) still cover this, because the tool's `targetDirectory` is matched as a touched path.
|
|
401
|
+
- **No strict read allowlist:** `allow: ["Read(src/**)"]` does not deny reads outside `src/**` — reads are allowed by default and only `ask`/`deny` rules restrict them. A deny-everything-not-listed read mode is intentionally out of scope as a separate behavior change.
|
|
402
|
+
- **Shell path arguments are not external-dir gated:** `cat /outside/file` is governed by shell rules and the mode, not the workspace boundary — a command string is not a reliable file boundary. Gate it with `deny: ["Shell(cat /outside/*)"]`-style rules if you need to.
|
|
403
|
+
- **An allow rule never matches an opaque command:** If the shell parser can't fully understand a command, it can still be deny/ask-matched against the raw string, but it will never auto-allow — it prompts instead.
|
|
404
|
+
- **Parameter rules only see parameters the model sends:** An omitted parameter never matches.
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## See also
|
|
409
|
+
|
|
410
|
+
- [Plan Mode](./plan-mode.md) — read-only exploration and planning.
|
|
411
|
+
- [Hooks](./hooks.md) — run your own scripts to allow, deny, or audit tool calls at runtime.
|
|
412
|
+
- [MCP](./mcp.md) — connect external tools that the permission engine gates by server and tool name.
|