Skip to content

Разрешения ​

Разрешения решают, что 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Только чтение. Исследовать и планировать; записывать можно только файл плана.
yoloshift+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

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

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

json
{
  "permissions": {
    "ask": ["Read(.env*)"],
    "deny": ["Read(secrets/**)", "Read(~/.ssh/**)"]
  }
}

Защитить lock-файлы и каталог git:

.commandcode/settings.json

json
{
  "permissions": {
    "ask": ["Edit(package.json)", "Edit(pnpm-lock.yaml)"],
    "deny": ["Edit(.git/**)", "Edit(.ssh/**)"]
  }
}

Разрешить один инструмент MCP или целый сервер:

.commandcode/settings.json

json
{
  "permissions": {
    "allow": ["mcp__github__get_issue", "mcp__linear__*"]
  }
}

Запуск без присмотра (CI/CD) — никогда не спрашивать; предодобрить ровно то, что CI может менять:

.commandcode/settings.json

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 выбирают стартовый режим:

Терминал

bash
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 (он лишь запускает названную вами слэш-команду). Инструменты, которые вызывает субагент, всё равно проходят проверку.

Правило — это имя инструмента, при необходимости со спецификатором:

Форма правила

text
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 *)).

Имена инструментов ​

Используйте дружественные имена или точные имена, которые видит модель:

ДружественноеЧто покрывает
Shellshell_command, monitor_command, kill_shell
Readread_file, read_directory, glob, grep
Editedit_file, write_file
Writewrite_file
WebFetchweb_fetch
WebSearchweb_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 git commands in this project" записывает правило allow Shell(git:*) в настройки проекта. Для составной команды — по одному правилу на каждую базу, не относящуюся к чтению. Базы, выполняющие произвольный код (bash, python, curl, …), сохраняются как точная команда, а не как префикс.
  • MCP / прочее — "Yes, don't ask again for mcp__server__tool in 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 эту проверку пропускает):

Чувствительные пути (запрос при записи)

text
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 активен. Лучше всего задавать это в пользовательском глобальном файле, который проект не может изменить.

Как принимается решение ​

Каждый вызов инструмента проходит одну фиксированную лестницу. Побеждает первая совпавшая ступень:

text
            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 пропускает обычные запросы и запрос о чувствительной записи, но никогда — ваши явные правила и никогда — защиту от удаления корня и домашнего каталога.

Подробно о каждой ступени:

  1. Правила deny — блокируются в любом режиме, включая yolo.
  2. Правила ask — всегда спрашивают, даже под yolo. В dont-ask будущий запрос превращается в запрет.
  3. Проверка внешних каталогов — чтение, запись или рабочий каталог shell вне рабочего пространства сначала просят принять каталог (как /add-dir / permissions.additionalDirectories); затем применяется обычное правило режима. Yolo разрешает молча. Временный каталог ОС (/tmp, $TMPDIR, os.tmpdir()) разрешается молча в любом режиме — чтения никогда не спрашивают, записи пропускают эскалацию, но следуют обычному правилу режима. Каталоги skills читаются без разрешения; записи файла плана в режиме планирования эту проверку пропускают.
  4. Проверка режима планирования — по типу операции: чтения, поиск, shell только для чтения выполняются; всё, что пишет или меняет, запрещается. Единственная разрешённая запись — файл плана в ~/.commandcode/plans/.
  5. Записи в каталог вкуса — защита продуктового сценария (разрешено, когда обучение вкусу включено, иначе перенаправляется в инструмент taste); это не запрос безопасности, поэтому yolo её пропускает.
  6. Некорректные записи — запись или правка без разрешимого пути к файлу запрещается сразу, с указанием на исправление.
  7. Быстрый путь только для чтения — чтения и shell только для чтения (ls, cat, grep, echo, head, …) выполняются без запроса в любом режиме. Составная команда считается такой, когда каждая часть только читает и ничто не перенаправляет вывод: cat file | head -5 || echo none бесплатна. Команда только для чтения, нацеленная на секретный материал (cat .env, head id_rsa), из этого пути выпадает и вызывает запрос.
  8. Предохранитель удаления корня и домашнего каталога — rm -rf /, rm -rf ~, rm -rf $HOME и их поддельные варианты спрашивают даже под yolo (запрет в dont-ask/plan).
  9. Yolo (обход разрешений) — всё, что прошло предыдущие проверки, разрешается автоматически.
  10. Запрос при чувствительной записи — запись секретного файла, вектора закрепления (.bashrc, .gitconfig, …) или поверхности управления (настройки .git/**, .ssh/**, .commandcode) вызывает запрос в default и accept-edits, если правило allow для конкретного содержимого не разрешит её.
  11. Правила allow — предодобренные вызовы выполняются без запроса.
  12. Быстрый путь accept edits — в accept-edits правки файлов и безопасные файловые команды внутри рабочего пространства выполняются без запроса. Рекурсивные удаления исключены — они по-прежнему спрашивают.
  13. В остальных случаях — спросить, а в dont-ask — запретить.

INFO

Каждый отказ политики (правило deny, проверка режима, некорректный ввод) несёт указание, на которое модель может отреагировать, и ход продолжается. Ход завершает только человеческое «нет».

Таблица решений ​

Полная матрица — каждая операция против каждого режима. Источник истины; тесты закрепляют каждую строку.

Операцияdefaultaccept-editsplanyolodont-askПочему
Совпадает с правилом denydenydenydenydenydenyПравила deny побеждают. ask_user_question, agent, run_command — безусловные исключения.
Совпадает с правилом askaskaskaskaskdenyAsk переживает yolo; dont-ask не может спрашивать. Те же три инструмента — исключения.
Совпадает с правилом allowallowallowallow, если совместимо с планомallowallowУчитывается после deny/ask и проверок режима.
Прямое чтение или поиск по файлам внутри рабочего пространстваallowallowallowallowallowЧтения бесплатны, если правила не говорят иное.
Прямое чтение или поиск по файлам вне рабочего пространстваask external-dir, затем allowask external-dir, затем allowask external-dir, затем allowallowdeny, если не предодобреноВнешние каталоги проверяются отдельно, затем чтения разрешаются.
Чтение во временном каталоге ОС (/tmp, $TMPDIR)allow (каталог разрешён молча)allow (каталог разрешён молча)allow (каталог разрешён молча)allowallowОдноразовые рабочие данные — эскалация пропускается. Deny/ask по-прежнему важнее; символическая ссылка, ведущая за пределы временного каталога, проходит обычную проверку.
Запись во временном каталоге ОСask, как запись в рабочем пространствеallow; чувствительное всё равно спрашиваетdenyallowdeny, если нет правила allowЭскалации нет, затем обычное правило режима для правки/записи (чувствительные имена вроде /tmp/.env всё равно вызывают запрос).
Чтение в зарегистрированном каталоге skillallowallowallowallowallowРесурсы skills читаются без разрешения; записи в каталоги skills всё равно проходят проверку.
Веб-инструмент или нативный инструмент только для чтенияallowallowallowallowallowИнструменты только для чтения вне файловой системы бесплатны, если правила не говорят иное.
ask_user_questionallowallowallowallowallowСпрашивать пользователя — это и есть взаимодействие; ни один запрос не может встать перед ним.
agentallowallowallowallowallowДелегирование разрешено всегда. Каждый инструмент субагента всё равно проверяется.
run_commandallowallow-allowallowЗапускает названную вами слэш-команду — удалён в режиме планирования (инструмент записи), никогда не выдаётся субагентам.
Shell только для чтения, например git status, cat README.md | head -5allowallowallowallowallowПлан может исследовать с помощью shell только для чтения. Составная команда подходит, когда каждая часть только читает и ничто не перенаправляет вывод. Рабочий каталог shell — по строке про внешние каталоги.
Похожее на секрет чтение через файловый инструмент, например read_file .envallowallowallowallowallowЧтения по умолчанию бесплатны; встроенного запроса на чтение секретов для файловых инструментов нет. Используйте ask/deny.
Похожее на секрет чтение через shell, например cat .envaskaskdenyallowdeny, если нет правила allowКоманда shell только для чтения с секретным аргументом (.env, id_rsa, *.pem) выпадает из быстрого пути.
Правка файла в рабочем пространствеaskallowdenyallowdeny, если нет правила allowaccept-edits принимает обычные правки; dont-ask выполняет только предодобренные.
Защищённая запись в рабочем пространстве, например .env или .git/configaskaskdenyallowdeny, если не предодобреноYolo пропускает обычные запросы о риске записи; accept edits — нет.
Прямая запись файла вне рабочего пространстваask external-dir, затем ask edit/writeask external-dir, затем allow обычной правки/записи; чувствительное всё равно спрашиваетdeny, кроме записи файла планаallowdeny, если не предодобреноСначала проверка внешнего каталога, затем правило режима для правки/записи.
Запись файла плана в ~/.commandcode/plans/ask, как запись вне рабочего пространстваask external-dir, затем allowallow (без запроса про внешний каталог)allowdeny, если не предодобреноСанкционированный вывод режима планирования; в режиме планирования не проверяется никогда.
Безопасный файловый shell внутри рабочего пространства: mkdir, touch, cp, mv, нерекурсивный rm, rmdir, sedaskallowdenyallowdeny, если нет правила allowПринятие правок распространяется на безопасные файловые команды по нечувствительным целям в рабочем пространстве. Рекурсивный rm исключён.
Рабочий каталог shell вне рабочего пространстваask external-dir, затем применить правило/режим shellask external-dir, затем применить правило/режим shellask external-dir для shell только для чтения; deny для меняющего shellallowdeny, если не предодобреноРабочий каталог shell проходит проверку внешнего каталога.
Аргументы команды shell вне рабочего пространстваправило/режим shellправило/режим shellправило/режим shellallowправило/режим shellПути-аргументы внутри строки команды никогда не проверяются как внешний каталог; используйте правила shell ask/deny.
Прочий меняющий shellaskaskdenyallowdeny, если нет правила allowУправляется правилами shell и активным режимом.
MCP / пользовательский инструмент с побочными эффектами или неизвестныйaskaskdenyallowdeny, если нет правила allowНеизвестные побочные эффекты спрашивают, если не yolo и нет явного правила.
Удаление корня или домашнего каталога, например rm -rf / или rm -rf ~askaskdenyaskdenyПредохранитель переживает yolo.
Рекурсивное удаление в рабочем пространстве, например rm -rf distaskaskdenyallowdeny, если нет правила 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

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.

Проектные решения ​

Логика, стоящая за поведением, чтобы вам не приходилось реконструировать её самому:

  1. Правила важнее жёстко зашитой матрицы безопасности. Никакого встроенного запроса на чтение файла .env, никакого переживающего yolo запроса на рекурсивное удаление. Чувствительные чтения — забота правил (ask/deny), поэтому каждый проект сам решает, что считать чувствительным. Одно исключение: быстрый путь shell только для чтения отсеивает секретные аргументы, поэтому cat .env спрашивает, а не едет на бесплатном пропуске cat.
  2. Один упорядоченный конвейер. Порядок в разделе Как принимается решение и есть спецификация; тесты его закрепляют.
  3. Несимметричное сопоставление. Deny/ask агрессивно, allow консервативно. Ошибаться в сторону запроса — безопасное направление.
  4. Внешние каталоги — отдельная проверка, до правила режима, с исключениями для корней чтения skills и записи файла плана там, где режим это санкционирует.
  5. Предохранитель переживает yolo и устойчив к подделкам.
  6. disableBypass применяется на каждом уровне — движок, вход CLI, цикл режимов TUI, хранилище решений.
  7. Аргументы команды shell — не граница файлов. Абсолютные пути в строке команды следуют правилам shell и режиму, а не границе файловых инструментов.
  8. Общие инструменты получают настоящий запрос. Инструменты MCP и пользовательские инструменты показывают общий запрос разрешения, а не поддельный запрос правки файла.
  9. Рекурсивные удаления спрашивают в режиме accept edits. Безопасное направление: массовое необратимое удаление — не правка.
  10. Отказы политики направляют модель; ход завершает только вето человека. Каждый отказ движка несёт действенное указание, поэтому модель адаптируется и ход продолжается.

Известные ограничения ​

Документированные края текущего движка:

  • Шаблонные записи в вызове 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.