Разрешения
Разрешения решают, что Command Code может делать, до того как он это сделает. Каждый вызов инструмента — shell, правка файла, веб-запрос, инструмент MCP, субагент — попадает в один движок, который отвечает на один вопрос:
разрешить, спросить или запретить?
Впервые здесь? Прочитайте минутную версию и частые рецепты. За полным справочником переходите к разделам как принимается решение и таблица решений.
INFO
Правила применяет Command Code, а не модель. Ваш запрос или AGENTS.md формируют то, что агент попытается сделать; это не меняет того, что разрешено. Чтобы выдать или отозвать права, используйте правило, режим или хук PreToolUse.
Минутная версия
Три вещи покрывают почти всё.
1. Режим задаёт базовую линию. Переключайте по кругу через shift+tab или переходите командой /mode.
Режим и флаг, который его включает, — разные имена, поэтому обе колонки:
| Режим | Как включить | В одной строке |
|---|---|---|
default | значение по умолчанию; /mode:default, shift+tab | Спрашивать перед всем, что что-то меняет. Чтения бесплатны. |
accept-edits | /mode:accept-edits, shift+tab, --accept-edits | Делать обычные правки (и безопасные файловые команды), не спрашивая. |
plan | /mode:plan, shift+tab, --plan | Только чтение. Исследовать и планировать; записывать можно только файл плана. |
yolo | shift+tab или --yolo / --dangerously-skip-permissions, чтобы стартовать в нём | Обход разрешений: делать практически всё, не спрашивая. |
dont-ask | "defaultMode": "dont-ask" в настройках или --permission-mode dont-ask | Никогда не спрашивать. Выполнять предодобренное, остальное запрещать. Режим для CI/CD. |
auto-accept и bypass — принимаемые псевдонимы для accept-edits и yolo везде, где вводится имя режима (настройки, флаги, /mode).
2. Три списка правил настраивают его. Порядок: deny побеждает, затем ask, затем allow.
.commandcode/settings.json
{
"permissions": {
"deny": ["Read(secrets/**)"],
"ask": ["Shell(git push:*)"],
"allow": ["Shell(git status:*)", "mcp__github__get_issue"]
}
}3. Кое-что никогда не спрашивает. Чтения и shell только для чтения (ls, cat, git status), а также инструменты управления потоком ask_user_question, agent и run_command.
INFO
deny побеждает ask, ask побеждает allow — в любом режиме. Режим решает только те вызовы, которые правила оставили неразрешёнными. yolo по-прежнему не может пройти мимо правила deny, правила ask или защиты от удаления корня и домашнего каталога.
Частые рецепты
Добавьте любой из них в .commandcode/settings.json (общий, хранится в репозитории) или в .commandcode/settings.local.json (личный, в gitignore).
Git только для чтения, вопрос перед пушем, блокировка перезаписи истории:
.commandcode/settings.json
{
"permissions": {
"allow": ["Shell(git status:*)", "Shell(git log:*)", "Shell(git diff:*)"],
"ask": ["Shell(git push:*)", "Shell(git pull:*)"],
"deny": ["Shell(git push --force*)", "Shell(git reset --hard*)", "Shell(git clean -*)"]
}
}Ограничить чтение секретов (по умолчанию бесплатно — чтения никогда не блокируются, если правило не скажет иначе):
.commandcode/settings.json
{
"permissions": {
"ask": ["Read(.env*)"],
"deny": ["Read(secrets/**)", "Read(~/.ssh/**)"]
}
}Защитить lock-файлы и каталог git:
.commandcode/settings.json
{
"permissions": {
"ask": ["Edit(package.json)", "Edit(pnpm-lock.yaml)"],
"deny": ["Edit(.git/**)", "Edit(.ssh/**)"]
}
}Разрешить один инструмент MCP или целый сервер:
.commandcode/settings.json
{
"permissions": {
"allow": ["mcp__github__get_issue", "mcp__linear__*"]
}
}Запуск без присмотра (CI/CD) — никогда не спрашивать; предодобрить ровно то, что CI может менять:
.commandcode/settings.json
{
"permissions": {
"defaultMode": "dont-ask",
"allow": ["Edit(src/**)", "Write(src/generated/**)"]
}
}Такие правки проходят молча; всё, что вне списка разрешений, запрещается. dont-ask — это fail-closed список разрешений, а не режим автоправок: неверный вызов завершается ошибкой вместо того, чтобы зависнуть на запросе, на который никто не ответит.
Режимы разрешений
Режим задаёт базовую линию. Переключайте по кругу через shift+tab или переходите командой /mode.
| Режим | Значение |
|---|---|
default | Спрашивать перед всем, что что-то меняет; чтения бесплатны. |
accept-edits | Делать обычные правки в рабочем пространстве (и безопасные файловые команды shell: mkdir, touch, cp, mv, нерекурсивный rm, rmdir, sed), не спрашивая. Не принимает автоматически произвольный shell, инструменты MCP или рекурсивные удаления. |
plan | Исследование только для чтения. Чтения, поиск и shell только для чтения (git status) выполняются; записывать можно только файл плана. |
yolo | Обход разрешений: делать практически всё, не спрашивая. Правила deny, явные правила ask и защита от удаления корня и домашнего каталога всё равно действуют. Вход по shift+tab или --yolo / --dangerously-skip-permissions, чтобы стартовать в нём; только для одноразовых окружений. |
dont-ask | Никогда не спрашивать. Выполнять только то, что политика уже разрешает (чтения, shell только для чтения, правила allow); остальное запрещать. Зеркальное отражение yolo: для запусков без присмотра, где неверный запрос должен приводить к ошибке, а не ждать. |
Псевдонимы: auto-accept → accept-edits, bypass → yolo. Написания из Claude Code тоже работают: manual → default, acceptEdits → accept-edits, dontAsk → dont-ask, bypassPermissions → yolo. Устаревший standard также отображается на default.
Переключение режимов
Три способа, посреди сессии:
- shift+tab перебирает
default→accept-edits→plan→yolo→default. (alt+m— эквивалентная привязка для терминалов, которые проглатывают shift+tab.)--yoloтакже запускает сессию сразу вyolo.dont-askне является ступенью этого цикла — задайте его настройками или через CLI; shift+tab из него возвращает в цикл наaccept-edits. /modeпоказывает текущий режим;/mode:default,/mode:accept-edits,/mode:plan(или/mode <имя>, любое написание) переключают напрямую. Yolo намеренно не переключается слэш-командой — слэш-команды может вызывать агент, поэтому путь в обход разрешений посреди сессии дал бы модели возможность отключить собственные запросы. На/mode yoloответ будет: "press shift+tab to cycle into it, or launch with--yolo."- Флаги CLI выбирают стартовый режим:
Терминал
cmd --permission-mode accept-edits # default | standard | plan | accept-edits | yolo | dont-ask
cmd --accept-edits # shorthand for --permission-mode accept-edits
cmd --plan # start in plan mode
cmd --yolo # yolo (permission bypass) - alias for --dangerously-skip-permissions; use with care--permission-mode побеждает --plan. В интерактивной сессии --permission-mode yolo стартует в обходе разрешений, так же как --yolo / --dangerously-skip-permissions; выключатель disableBypass покрывает все три.
Print-режим (-p) отличается. Он блокирует запись файлов, правки файлов и команды shell, если вы не передали --yolo или --dangerously-skip-permissions. --permission-mode yolo задаёт режим, но не снимает этот блок, поэтому headless-запуску, которому нужно менять файлы, нужен --yolo. См. разрешения в headless-режиме.
Переключение режима также отвечает на запрос, который уже на экране: accept-edits или yolo его одобряют (вы сказали «хватит спрашивать»), plan его отклоняет. Запрос, вынужденный проверкой безопасности — разрушительная команда, чувствительный файл, явное правило ask, — так не отвечается никогда; он остаётся ждать явного «да» или «нет».
Написание правил
Три списка внутри permissions, проверяются по порядку: deny (всегда побеждает) → ask (всегда спрашивает, даже в yolo; в dont-ask запрещает) → allow. Три инструмента обходят списки: ask_user_question (его интерфейс и есть взаимодействие), agent (делегирование не имеет побочных эффектов) и run_command (он лишь запускает названную вами слэш-команду). Инструменты, которые вызывает субагент, всё равно проходят проверку.
Правило — это имя инструмента, при необходимости со спецификатором:
Форма правила
Tool # the whole tool
Tool(specifier) # a specific use| Правило | Действие |
|---|---|
Shell | Каждая команда shell |
Shell(git status) | git status (и git status --short) |
Shell(npm run *) | Любая команда npm run … |
Read(./.env) | Чтение .env в корне проекта |
Edit(src/**) | Правки где угодно под src/ |
WebFetch(domain:example.com) | Запросы к example.com |
mcp__github__get_issue | Один инструмент сервера MCP github |
mcp__github__* | Каждый инструмент сервера github |
mcp__github__get_* | Каждый инструмент get_ сервера github |
mcp__* | Каждый инструмент каждого сервера MCP |
* | Каждый инструмент |
Shell(run_in_background:true) | Команда shell, запущенная в фоне |
Имена инструментов нечувствительны к регистру. Tool() и Tool(*) оба означают весь инструмент.
Шаблоны
* в имени инструмента (не в спецификаторе) сопоставляется по имени:
*— каждый инструмент, проходящий проверку разрешений (ask_user_question,agent,run_commandостаются разрешёнными).mcp__*— каждый инструмент каждого сервера MCP.mcp__github__get_*— каждый инструмент чтения одного сервера.edit_*— каждый инструмент, чьё имя начинается сedit_.
Шаблоны имён инструментов работают в deny и ask (deny: ["mcp__*"] блокирует все инструменты MCP). В allow они игнорируются, если не назван сервер (mcp__github__get_* допустим, а голый * или mcp__* — нет): правило allow должно говорить, что оно выдаёт, а не раздавать всё подряд. Шаблоны в спецификаторах (Shell(npm *), Edit(src/**), WebFetch(domain:*.example.com)) работают везде.
Сопоставление по входному параметру
Правило deny или ask может проверять один входной параметр верхнего уровня через Tool(param:value):
Shell(run_in_background:true)— фоновая команда shell.
Значение принимает шаблон *; параметр, который модель опустила, никогда не совпадает. Один параметр на правило — чтобы проверять два, напишите два правила.
Сопоставление по параметрам работает только для deny/ask — правило allow для одного параметра не может доказать, что весь вызов безопасен. Поля, которые инструмент уже сопоставляет своим синтаксисом — command (Shell), file_path (Read/Edit/Write), path (Grep/Glob), notebook_path, url (WebFetch), — не сопоставляются как параметры; используйте спецификатор (Shell(rm *), а не Shell(command:rm *)).
Имена инструментов
Используйте дружественные имена или точные имена, которые видит модель:
| Дружественное | Что покрывает |
|---|---|
Shell | shell_command, monitor_command, kill_shell |
Read | read_file, read_directory, glob, grep |
Edit | edit_file, write_file |
Write | write_file |
WebFetch | web_fetch |
WebSearch | web_search |
INFO
Shell — это имя, потому что инструмент оболочки называется shell_command. Bash(...) — устаревший псевдоним для Shell(...), чтобы старые конфиги продолжали работать, но используйте Shell.
Шаблоны shell
Спецификаторы shell принимают шаблоны *:
Shell(npm run build)— точная команда.Shell(npm run *)— любая команда, которая начинается сnpm runи следующего за ним пробела.Shell(git * main)—git checkout main,git merge main, …Shell(git:*)— суффикс:*— это завершающий шаблон, то же самое, чтоShell(git *).
Пробел имеет значение: Shell(ls *) совпадает с ls -la, но не с lsof; Shell(ls*) совпадает с обоими.
Command Code разбирает операторы shell, поэтому Shell(git status) не выдаёт права на git status && rm -rf .. Каждая подкоманда составной команды (&&, ||, ;, |, &, переводы строк) должна совпасть сама по себе.
Шаблоны путей к файлам
Read и Edit используют сопоставление в стиле gitignore с четырьмя якорями:
| Шаблон | Привязан к | Пример |
|---|---|---|
//path | Корню файловой системы | Read(//etc/**) |
~/path | Домашнему каталогу | Edit(~/.config/**) |
/path | Корню проекта | Edit(/src/**) |
path | Любой глубине внутри проекта | Read(.env) ≡ Read(**/.env) |
* совпадает внутри одного сегмента пути; ** переходит через каталоги. Для символической ссылки проверяются и ссылка, и цель. Завершающий слэш не помогает обойти правило для точного пути (read_directory /repo/secrets/ всё равно совпадает с Read(//repo/secrets)).
INFO
Чтения разрешены по умолчанию. allow: ["Read(src/**)"] принимается, но не блокирует чтения за пределами src/** — для чувствительных чтений используйте ask/deny. Строгий список разрешённых чтений стал бы отдельным изменением (см. Известные ограничения).
Агрессивный deny, консервативный allow
Списки сопоставляются по-разному намеренно — ошибаться в сторону запроса безопаснее:
- Deny и ask сопоставляются агрессивно. Они видят сквозь ведущие переменные окружения (
FOO=bar rm -rf xсовпадает сShell(rm *)), обёртки процессов (timeout 30 …,nice …) и каждую подкоманду; неразбираемая команда сопоставляется с исходной строкой; сопоставление путей складывает регистр (на macOS/Windows.ENVоткрывает.env) и срабатывает, когда совпадает либо путь, либо цель его символической ссылки. - Allow сопоставляется консервативно. Переменные окружения не срезаются (
PATH=/tmp git statusне совпадает сShell(git status:*)); составная команда разрешается, только когда совпадает каждая подкоманда; неразбираемая команда никогда не разрешается автоматически; сопоставление путей чувствительно к регистру и требует совпадения и пути, и цели его символической ссылки.
MCP и субагенты
Инструменты MCP задаются своим каноническим именем mcp__server__tool — отображаемые имена в качестве ключей не используются никогда. mcp__github и mcp__github__* оба совпадают со всем сервером github; mcp__github__get_* совпадает с его инструментами get_; mcp__* (только deny/ask) совпадает с каждым сервером.
Инструмент agent разрешён всегда и никогда не спрашивает. Субагент проходит тот же упорядоченный конвейер, что и основной цикл, с одним отличием: там, где основной цикл показал бы интерактивный запрос, политика субагента разрешает автоматически — он работает автономно, и человека, который ответил бы, нет. Жёсткие ограничители сохраняются: субагент не может запустить инструмент, который блокируют ваши правила deny, не может писать в режиме планирования, а всё, о чём основной цикл спросил бы из-за безопасности — разрушительная команда, чувствительный файл, запись вне рабочего пространства, явное правило ask, — завершается fail-closed (запрещается).
Что происходит при запросе
Каждый запрос предлагает три варианта: разрешить один раз, разрешить и запомнить или запретить с обратной связью. Запоминаемая область соответствует субъекту:
- Файловые операции — "Yes, allow all edits this session" включает принятие правок для сессии (то же, что shift+tab).
- Shell — "Yes, don't ask again for
gitcommands in this project" записывает правило allowShell(git:*)в настройки проекта. Для составной команды — по одному правилу на каждую базу, не относящуюся к чтению. Базы, выполняющие произвольный код (bash,python,curl, …), сохраняются как точная команда, а не как префикс. - MCP / прочее — "Yes, don't ask again for
mcp__server__toolin this project" записывает имя инструмента в настройки проекта.
Пояснения команд по запросу
Запрос shell умеет объяснять команду: нажмите ctrl+e (ctrl+y в терминалах семейства VS Code, где IDE забирает ctrl+e), и фоновый вызов модели кратко пересказывает её прямо на месте. Управляется настройкой on-demand-tool-descriptions (включена по умолчанию): пояснения только когда их попросят. Выключите её (через /config), чтобы каждое генерировалось заранее.
Поведение безопасности
Некоторые запросы вызываются не режимом или правилом, а проверкой безопасности. Они предлагают только разовые Yes/No и баннер с названием проверки. Возможности «для сессии» и «для проекта» намеренно скрыты — одобрения разрушительной команды, чувствительного пути, выхода за пределы рабочего пространства и явного правила ask никогда не кешируются, поэтому следующий рискованный вызов спросит снова. Чтобы остановить повторяющийся случай, добавьте правило allow для конкретного содержимого (например, Edit(.commandcode/settings.json)).
Автоматический предохранитель при удалении корня и домашнего каталога
Единственный встроенный запрос безопасности, который переживает yolo: удаление корня файловой системы или вашего домашнего каталога — rm -rf /, rm -rf ~, rm -rf $HOME — всегда останавливается на подтверждение в любом режиме, который умеет спрашивать (в dont-ask и plan вместо этого запрещается).
Устойчив к подделкам. Он ловит удаления через префиксы переменных окружения, обёртки процессов (timeout, nice, …), составные команды, закавыченные полезные нагрузки (bash -c "rm -rf /; echo ok"), подстановку команд (echo $(rm -rf /;)), слипшиеся разделители (/;) и написания $HOME/${HOME} (в кавычках или без, с суффиксами / или /* — $HOMEDIR остаётся литералом).
Рекурсивные удаления спрашивают в режиме accept edits
Быстрый путь безопасной файловой системы в accept-edits отказывается от rm -r/-R/-rf/--recursive (и find … -delete): rm -rf dist спрашивает точно так же, как в default. Обычный rm одного файла по-прежнему проходит быстро. Это осознанное безопасное направление: принимать правки не значит принимать массовое необратимое удаление. Правило allow для конкретного содержимого (Shell(rm -rf dist)) всё равно разрешает автоматически, а yolo его выполняет.
Чувствительные записи
Запись любого из перечисленного вызывает запрос в default и accept-edits, если правило allow для конкретного содержимого не разрешит её (yolo эту проверку пропускает):
Чувствительные пути (запрос при записи)
Secret material: .env, .env.*, *.pem, *.key, id_rsa, id_ed25519, credentials
Persistence vectors: .bashrc, .zshrc, .profile, .gitconfig, .gitmodules, .mcp.json, …
Control surfaces: .git/**, .ssh/**, .aws/**, .gnupg/**, .kube/**, .vscode/**, .idea/**,
.husky/**, .devcontainer/**, node_modules/.bin/**, .commandcode settingsПравило allow «для конкретного содержимого» должно называть путь (Edit(.env.local)) — голое разрешение всего инструмента (Edit) не протащит вызов мимо проверки безопасности.
INFO
Чувствительные чтения через файловые инструменты не спрашивают. Чтение .env разрешено по умолчанию. Ограничьте его правилом: ask: ["Read(.env*)"] или deny: ["Read(.env*)", "Read(secrets/**)"]. Быстрый путь shell только для чтения строже: cat .env или head id_rsa из него выпадают и вызывают запрос.
Внешние каталоги
Чтения, записи и рабочие каталоги shell вне рабочего пространства сначала просят принять каталог в набор корней сессии — то же разрешение, что /add-dir или permissions.additionalDirectories, — а затем применяется обычное правило режима.
yoloразрешает каталог молча;dont-askзапрещает, если он не предодобрен в настройках.- Временный каталог ОС (
/tmp,$TMPDIR,os.tmpdir()) разрешается молча в любом режиме — временные файлы одноразовые, так что просить «расширить доступ» к временному каталогу самой машины — это трения, а не защита. Чтения проходят без запросов; записи пропускают эскалацию, но всё равно подтверждаются, как любая запись в рабочем пространстве (чувствительные имена вроде/tmp/.envпо-прежнему вызывают запрос). Правилаdeny/askвсё равно важнее разрешения каталога, а символическая ссылка, ведущая за пределы временного каталога, проходит обычную проверку. - Одобрение правила
askдля внешнего пути также разрешает каталог, поэтому страховка уровня инструмента никогда не отклонит вызов, который вы только что одобрили. - Зарегистрированные каталоги skills читаются без разрешения (ресурсы skills по замыслу лежат вне рабочего пространства). Записи в них всё равно проходят проверку.
- Запись файла плана в режиме планирования освобождена от проверки — это санкционированный вывод режима.
- Абсолютные пути внутри строки команды shell не проверяются как внешний каталог — аргумент команды не является надёжной границей файлов. Используйте правила shell
ask/deny.
Отключение yolo (обхода разрешений)
Задайте permissions.disableBypass в "disable" (или true), чтобы в yolo нельзя было войти. Проверка применяется на каждом уровне: движок оценивает запрошенный yolo как default, а CLI нейтрализует --dangerously-skip-permissions (и --yolo) при входе, поэтому цикл режимов TUI и сохранённые решения об автоподтверждении не могут молча отвечать на запросы так, будто yolo активен. Лучше всего задавать это в пользовательском глобальном файле, который проект не может изменить.
Как принимается решение
Каждый вызов инструмента проходит одну фиксированную лестницу. Побеждает первая совпавшая ступень:
tool call
│
▼
1 deny rules ───────────► DENY
│ (even yolo)
2 ask rules ────────────► ASK
│ (even yolo)
3 outside workspace? ───► ASK to admit
│
4 plan mode + mutates? ─► DENY
│
5 taste-dir write ──────► redirect
│
6 malformed write ──────► DENY
│
7 read-only? ───────────► ALLOW
│ (every mode)
8 rm -rf / ~ $HOME ─────► ASK
│ (even yolo)
9 yolo mode? ───────────► ALLOW
│
10 sensitive write? ─────► ASK
│
11 allow rules ──────────► ALLOW
│
12 accept edits + in ws? ─► ALLOW
│
▼
ASK (DENY in dont-ask)Прочитайте сверху вниз, и вытекают две вещи. Deny побеждает ask, ask побеждает allow в любом режиме. И yolo стоит на ступени 9, после ваших правил, проверки внешних каталогов и предохранителя, поэтому --yolo пропускает обычные запросы и запрос о чувствительной записи, но никогда — ваши явные правила и никогда — защиту от удаления корня и домашнего каталога.
Подробно о каждой ступени:
- Правила deny — блокируются в любом режиме, включая yolo.
- Правила ask — всегда спрашивают, даже под yolo. В
dont-askбудущий запрос превращается в запрет. - Проверка внешних каталогов — чтение, запись или рабочий каталог shell вне рабочего пространства сначала просят принять каталог (как
/add-dir/permissions.additionalDirectories); затем применяется обычное правило режима. Yolo разрешает молча. Временный каталог ОС (/tmp,$TMPDIR,os.tmpdir()) разрешается молча в любом режиме — чтения никогда не спрашивают, записи пропускают эскалацию, но следуют обычному правилу режима. Каталоги skills читаются без разрешения; записи файла плана в режиме планирования эту проверку пропускают. - Проверка режима планирования — по типу операции: чтения, поиск, shell только для чтения выполняются; всё, что пишет или меняет, запрещается. Единственная разрешённая запись — файл плана в
~/.commandcode/plans/. - Записи в каталог вкуса — защита продуктового сценария (разрешено, когда обучение вкусу включено, иначе перенаправляется в инструмент
taste); это не запрос безопасности, поэтому yolo её пропускает. - Некорректные записи — запись или правка без разрешимого пути к файлу запрещается сразу, с указанием на исправление.
- Быстрый путь только для чтения — чтения и shell только для чтения (
ls,cat,grep,echo,head, …) выполняются без запроса в любом режиме. Составная команда считается такой, когда каждая часть только читает и ничто не перенаправляет вывод:cat file | head -5 || echo noneбесплатна. Команда только для чтения, нацеленная на секретный материал (cat .env,head id_rsa), из этого пути выпадает и вызывает запрос. - Предохранитель удаления корня и домашнего каталога —
rm -rf /,rm -rf ~,rm -rf $HOMEи их поддельные варианты спрашивают даже под yolo (запрет вdont-ask/plan). - Yolo (обход разрешений) — всё, что прошло предыдущие проверки, разрешается автоматически.
- Запрос при чувствительной записи — запись секретного файла, вектора закрепления (
.bashrc,.gitconfig, …) или поверхности управления (настройки.git/**,.ssh/**,.commandcode) вызывает запрос вdefaultиaccept-edits, если правило allow для конкретного содержимого не разрешит её. - Правила allow — предодобренные вызовы выполняются без запроса.
- Быстрый путь accept edits — в
accept-editsправки файлов и безопасные файловые команды внутри рабочего пространства выполняются без запроса. Рекурсивные удаления исключены — они по-прежнему спрашивают. - В остальных случаях — спросить, а в
dont-ask— запретить.
INFO
Каждый отказ политики (правило deny, проверка режима, некорректный ввод) несёт указание, на которое модель может отреагировать, и ход продолжается. Ход завершает только человеческое «нет».
Таблица решений
Полная матрица — каждая операция против каждого режима. Источник истины; тесты закрепляют каждую строку.
| Операция | default | accept-edits | plan | yolo | dont-ask | Почему |
|---|---|---|---|---|---|---|
Совпадает с правилом deny | deny | deny | deny | deny | deny | Правила deny побеждают. ask_user_question, agent, run_command — безусловные исключения. |
Совпадает с правилом ask | ask | ask | ask | ask | deny | Ask переживает yolo; dont-ask не может спрашивать. Те же три инструмента — исключения. |
Совпадает с правилом allow | allow | allow | allow, если совместимо с планом | allow | allow | Учитывается после deny/ask и проверок режима. |
| Прямое чтение или поиск по файлам внутри рабочего пространства | allow | allow | allow | allow | allow | Чтения бесплатны, если правила не говорят иное. |
| Прямое чтение или поиск по файлам вне рабочего пространства | ask external-dir, затем allow | ask external-dir, затем allow | ask external-dir, затем allow | allow | deny, если не предодобрено | Внешние каталоги проверяются отдельно, затем чтения разрешаются. |
Чтение во временном каталоге ОС (/tmp, $TMPDIR) | allow (каталог разрешён молча) | allow (каталог разрешён молча) | allow (каталог разрешён молча) | allow | allow | Одноразовые рабочие данные — эскалация пропускается. Deny/ask по-прежнему важнее; символическая ссылка, ведущая за пределы временного каталога, проходит обычную проверку. |
| Запись во временном каталоге ОС | ask, как запись в рабочем пространстве | allow; чувствительное всё равно спрашивает | deny | allow | deny, если нет правила allow | Эскалации нет, затем обычное правило режима для правки/записи (чувствительные имена вроде /tmp/.env всё равно вызывают запрос). |
| Чтение в зарегистрированном каталоге skill | allow | allow | allow | allow | allow | Ресурсы skills читаются без разрешения; записи в каталоги skills всё равно проходят проверку. |
| Веб-инструмент или нативный инструмент только для чтения | allow | allow | allow | allow | allow | Инструменты только для чтения вне файловой системы бесплатны, если правила не говорят иное. |
ask_user_question | allow | allow | allow | allow | allow | Спрашивать пользователя — это и есть взаимодействие; ни один запрос не может встать перед ним. |
agent | allow | allow | allow | allow | allow | Делегирование разрешено всегда. Каждый инструмент субагента всё равно проверяется. |
run_command | allow | allow | - | allow | allow | Запускает названную вами слэш-команду — удалён в режиме планирования (инструмент записи), никогда не выдаётся субагентам. |
Shell только для чтения, например git status, cat README.md | head -5 | allow | allow | allow | allow | allow | План может исследовать с помощью shell только для чтения. Составная команда подходит, когда каждая часть только читает и ничто не перенаправляет вывод. Рабочий каталог shell — по строке про внешние каталоги. |
Похожее на секрет чтение через файловый инструмент, например read_file .env | allow | allow | allow | allow | allow | Чтения по умолчанию бесплатны; встроенного запроса на чтение секретов для файловых инструментов нет. Используйте ask/deny. |
Похожее на секрет чтение через shell, например cat .env | ask | ask | deny | allow | deny, если нет правила allow | Команда shell только для чтения с секретным аргументом (.env, id_rsa, *.pem) выпадает из быстрого пути. |
| Правка файла в рабочем пространстве | ask | allow | deny | allow | deny, если нет правила allow | accept-edits принимает обычные правки; dont-ask выполняет только предодобренные. |
Защищённая запись в рабочем пространстве, например .env или .git/config | ask | ask | deny | allow | deny, если не предодобрено | Yolo пропускает обычные запросы о риске записи; accept edits — нет. |
| Прямая запись файла вне рабочего пространства | ask external-dir, затем ask edit/write | ask external-dir, затем allow обычной правки/записи; чувствительное всё равно спрашивает | deny, кроме записи файла плана | allow | deny, если не предодобрено | Сначала проверка внешнего каталога, затем правило режима для правки/записи. |
Запись файла плана в ~/.commandcode/plans/ | ask, как запись вне рабочего пространства | ask external-dir, затем allow | allow (без запроса про внешний каталог) | allow | deny, если не предодобрено | Санкционированный вывод режима планирования; в режиме планирования не проверяется никогда. |
Безопасный файловый shell внутри рабочего пространства: mkdir, touch, cp, mv, нерекурсивный rm, rmdir, sed | ask | allow | deny | allow | deny, если нет правила allow | Принятие правок распространяется на безопасные файловые команды по нечувствительным целям в рабочем пространстве. Рекурсивный rm исключён. |
| Рабочий каталог shell вне рабочего пространства | ask external-dir, затем применить правило/режим shell | ask external-dir, затем применить правило/режим shell | ask external-dir для shell только для чтения; deny для меняющего shell | allow | deny, если не предодобрено | Рабочий каталог shell проходит проверку внешнего каталога. |
| Аргументы команды shell вне рабочего пространства | правило/режим shell | правило/режим shell | правило/режим shell | allow | правило/режим shell | Пути-аргументы внутри строки команды никогда не проверяются как внешний каталог; используйте правила shell ask/deny. |
| Прочий меняющий shell | ask | ask | deny | allow | deny, если нет правила allow | Управляется правилами shell и активным режимом. |
| MCP / пользовательский инструмент с побочными эффектами или неизвестный | ask | ask | deny | allow | deny, если нет правила allow | Неизвестные побочные эффекты спрашивают, если не yolo и нет явного правила. |
Удаление корня или домашнего каталога, например rm -rf / или rm -rf ~ | ask | ask | deny | ask | deny | Предохранитель переживает yolo. |
Рекурсивное удаление в рабочем пространстве, например rm -rf dist | ask | ask | deny | allow | deny, если нет правила allow | Рекурсивные удаления спрашивают вне yolo. Правило allow для конкретного содержимого (Shell(rm -rf dist)) всё равно разрешает автоматически. |
Что значит «читать столбец»: режим меняет только те вызовы, которые правила оставили неразрешёнными. deny и ask ведут себя одинаково во всех интерактивных режимах; dont-ask превращает каждый будущий ask в deny; yolo разрешает автоматически всё, кроме правил deny, правил ask и предохранителя.
Справочник по настройкам
Правила живут в permissions в .commandcode/settings.json (общий, хранится в репозитории) или в .commandcode/settings.local.json (личный, в gitignore). Интерактивные одобрения обычно записываются в settings.json, а в settings.local.json — при запуске с --local:
.commandcode/settings.json
{
"permissions": {
"defaultMode": "default",
"allow": [
"Shell(git status:*)",
"Shell(git log:*)",
"Shell(npm run *)",
"mcp__github__get_issue"
],
"ask": ["Shell(git push:*)", "Read(.env*)"],
"deny": ["Shell(git reset --hard*)", "Read(secrets/**)", "Edit(.git/**)"],
"additionalDirectories": ["~/shared-libs"],
"disableBypass": "disable"
}
}defaultMode— стартовый режим (default,accept-edits,plan,yolo,dont-ask;auto-acceptиbypassпринимаются как псевдонимы, как иacceptEditsи устаревшийstandard).allow/ask/deny— списки правил. Они накапливаются между файлами настроек:denyв ваших пользовательских глобальных настройках нельзя стереть файлом проекта.additionalDirectories— дополнительные каталоги, которые считаются частью рабочего пространства для чтений и записей (накапливаются так же).disableBypass—"disable"(илиtrue) делает вход в yolo (обход разрешений) невозможным.
Приоритет
Запрещено на любом уровне — не разрешено ни на одном. Управляемый или пользовательский глобальный deny побеждает проектный allow; deny побеждает ask; ask побеждает allow. Конкретность ничего не переупорядочивает — широкий deny всё равно блокирует более узкий allow.
Проектные решения
Логика, стоящая за поведением, чтобы вам не приходилось реконструировать её самому:
- Правила важнее жёстко зашитой матрицы безопасности. Никакого встроенного запроса на чтение файла
.env, никакого переживающего yolo запроса на рекурсивное удаление. Чувствительные чтения — забота правил (ask/deny), поэтому каждый проект сам решает, что считать чувствительным. Одно исключение: быстрый путь shell только для чтения отсеивает секретные аргументы, поэтомуcat .envспрашивает, а не едет на бесплатном пропускеcat. - Один упорядоченный конвейер. Порядок в разделе Как принимается решение и есть спецификация; тесты его закрепляют.
- Несимметричное сопоставление. Deny/ask агрессивно, allow консервативно. Ошибаться в сторону запроса — безопасное направление.
- Внешние каталоги — отдельная проверка, до правила режима, с исключениями для корней чтения skills и записи файла плана там, где режим это санкционирует.
- Предохранитель переживает yolo и устойчив к подделкам.
disableBypassприменяется на каждом уровне — движок, вход CLI, цикл режимов TUI, хранилище решений.- Аргументы команды shell — не граница файлов. Абсолютные пути в строке команды следуют правилам shell и режиму, а не границе файловых инструментов.
- Общие инструменты получают настоящий запрос. Инструменты MCP и пользовательские инструменты показывают общий запрос разрешения, а не поддельный запрос правки файла.
- Рекурсивные удаления спрашивают в режиме accept edits. Безопасное направление: массовое необратимое удаление — не правка.
- Отказы политики направляют модель; ход завершает только вето человека. Каждый отказ движка несёт действенное указание, поэтому модель адаптируется и ход продолжается.
Известные ограничения
Документированные края текущего движка:
- Шаблонные записи в вызове
read_fileс несколькими файлами разворачиваются внутри инструмента, поэтому правило deny для точного файла (Read(.env)) не может совпасть с записью-шаблоном (*.env) до разворачивания. Правила для деревьев каталогов (Read(//etc/**)) это всё равно покрывают, потому чтоtarget_directoryвызова (или первая абсолютная запись) сопоставляется как затронутый путь. - Нет строгого списка разрешённых чтений.
allow: ["Read(src/**)"]не запрещает чтения за пределамиsrc/**— чтения бесплатны по умолчанию, их ограничивают толькоask/deny. Режим чтения «запретить всё, что не перечислено» выходит за рамки этого изменения. - Пути-аргументы shell не проверяются как внешние каталоги.
cat /outside/fileследует правилам shell и режиму, а не границе рабочего пространства. Ограничьте его правилами видаdeny: ["Shell(cat /outside/*)"]. - Правило allow никогда не совпадает с непрозрачной командой. Если парсер не может полностью понять команду, она всё равно может быть сопоставлена с deny/ask по исходной строке, но автоматически не разрешается никогда — она вызывает запрос.
- Правила по параметрам видят только те параметры, что присылает модель. Опущенный параметр никогда не совпадает.
См. также
- Режим планирования — исследование и планирование только для чтения.
- Хуки — свои скрипты, которые разрешают, запрещают или журналируют вызовы инструментов во время выполнения.
- MCP — подключение внешних инструментов, которые движок проверяет по серверу и имени инструмента.
Источник
Сверено с оригиналом 13 ноября 2026.