Learn about Qoder CN CLI permission modes, rule configuration, and the tool-call approval flow.
A permission mode determines how Qoder CN CLI handles tool calls. Each mode sits at a different point on two axes: how much runs automatically, and how permissive it is with sensitive actions.
Plan is a standalone working state (not a permission policy) and can coexist with any of the permission modes above. Toggle it with the
Goal is an autonomous execution state. Enter it with
In an interactive session, press Shift+Tab to cycle through the permission modes. Press Ctrl+Y to jump straight to YOLO.
Use
Inside an interactive session, you can also press Ctrl+Y to switch to YOLO quickly.
Multiple naming formats are supported (case-insensitive):
Examples:
Non-default modes only take effect inside trusted directories. If the current directory is not trusted, Qoder CN CLI falls back to
Qoder CN CLI runs a permission check before every tool call. The check has exactly three possible outcomes:
Qoder CN CLI evaluates permissions in a fixed order:
In headless mode (
Rules are merged from multiple sources, from lowest to highest priority:
Rules from higher-priority sources override lower-priority ones. If your organization policy enables
Set the default mode — configure
Disable YOLO mode — organization administrators can prevent users from entering bypass_permissions mode with the following configuration:
Once set,
Once set, the
These rules are soft guidance — they are injected into the classifier prompt as a reference, and the final decision still comes from the AI classifier. For security reasons,
Rules are grouped into
Use canonical tool names:
Qoder CN CLI treats the current working directory (CWD) at startup as the primary trusted directory. Inside a trusted directory:
Add extra trusted working directories with
You can also configure
Some paths are protected because editing them can change execution behavior, credentials, or tool behavior. Examples include
Read rules with a path scope use
Example:
Example:
Shell matching is conservative:
Web tools can be controlled with tool-level rules. Use
MCP tools use fully-qualified names:
Supported MCP patterns include:
Example:
An MCP server's own configuration can also grant automatic approval for its tools via
The Qoder CN CLI Hooks system has two injection points in the permission decision chain, letting custom scripts influence whether a tool call is allowed or denied.
Other hook events (
Fires before a tool runs. The hook script inspects the tool name and arguments and returns a permission decision:
The hook script receives JSON on stdin (including
Possible
Fires after the pipeline outputs
Output format:
Hook permission decisions outrank permission modes. Even in
Permission modes
A permission mode determines how Qoder CN CLI handles tool calls. Each mode sits at a different point on two axes: how much runs automatically, and how permissive it is with sensitive actions.
| Mode | When to use it | Behavior |
|---|---|---|
default | Regular interactive use. | Safe reads and internal actions run automatically. Sensitive actions ask for confirmation. |
accept_edits | Day-to-day coding tasks. | Auto-approves safe file edits inside the working directory. Shell commands, external actions, and sensitive paths still go through the normal checks. |
auto | Automated runs and Goal execution. | Zero prompts. Safe reads and in-workspace edits are auto-approved. Risky actions are denied or handed to an AI classifier for judgment. |
bypass_permissions (YOLO) | Trusted local experiments only. | Skips all approval prompts. Every tool call is auto-approved. |
dont_ask | Headless flows that must never prompt. | Never asks. Anything that would have prompted is denied. |
Plan mode
Plan is a standalone working state (not a permission policy) and can coexist with any of the permission modes above. Toggle it with the /plan command. While in Plan, Qoder CN CLI performs read-only exploration of the code and produces a plan; writes are restricted to the plan file. When you exit Plan, you can pick the next permission mode or move directly into Goal execution.
Goal mode
Goal is an autonomous execution state. Enter it with /goal set <goal> — the CLI automatically switches to auto mode and locks Shift+Tab so nothing interrupts the run. Goal can coexist with Plan (plan first, then execute). Exit with /goal clear or /goal pause.
Cycling through modes
In an interactive session, press Shift+Tab to cycle through the permission modes. Press Ctrl+Y to jump straight to YOLO.
Launch flags
Use --permission-mode to choose the default behavior for the current session:
| Canonical value (snake_case) | camelCase | Aliases |
|---|---|---|
accept_edits | acceptEdits | — |
bypass_permissions | bypassPermissions | yolo, YOLO |
dont_ask | dontAsk | — |
default.
How permissions are decided
Qoder CN CLI runs a permission check before every tool call. The check has exactly three possible outcomes:
allow: run the tool immediately.ask: require external confirmation before running.deny: block this tool call.
Decision order
Qoder CN CLI evaluates permissions in a fixed order:
- Check
denyrules first — any hit denies immediately. - Run the tool's own safety checks (dangerous-command detection, sensitive-path detection, and so on).
- Check
askrules — any hit marks the call as requiring confirmation. - Apply tool-level
allowrules and the auto-allow behavior contributed by the current mode. - If the result is still
ask, the runtime decides how to consume it.
ask rules take precedence.
How ask is resolved in each runtime
| Runtime | Where ask goes | Notes |
|---|---|---|
| TUI (interactive terminal) | In-terminal confirmation prompt | You choose allow or deny in the terminal. |
Headless (-p/--prompt) | Auto-denied | No human present, so ask becomes deny. |
| SDK (stdio protocol) | Sends a canUseTool callback to the host | The host program decides allow or deny. |
| ACP (IDE integration) | Sends a requestPermission RPC to the IDE | The IDE prompts or decides automatically. |
-p/--prompt), you can combine a permission mode with the flag:
Permission configuration
Rule sources (8-layer priority)
Rules are merged from multiple sources, from lowest to highest priority:
| Level | Source | Description |
|---|---|---|
| 1 | userSettings | ~/.qoder-cn/settings.json (user-global). |
| 2 | projectSettings | /.qoder/settings.json (project-scoped, shared with the team). |
| 3 | localSettings | /.qoder/settings.local.json (personal to this machine — add it to .gitignore). |
| 4 | flagSettings | The file passed via the --settings CLI argument. |
| 5 | cliArg | The --allowed-tools and --disallowed-tools command-line arguments. |
| 6 | command | /allow and /deny commands entered during a session. |
| 7 | session | Runtime rules created ad hoc ("allow for this session" in a prompt). |
allowManagedPermissionRulesOnly, only the policy-managed rules are used.
How to configure each source:
- Levels 1-3 (settings files): write
permissions.allow/permissions.deny/permissions.askarrays into the JSON file at the corresponding path.settings.local.jsonis the recommended place for personal per-machine approval rules and should be added to.gitignore. - Level 4 (flagSettings):
qoderclicn --settings ./custom-settings.jsonpoints to an additional settings file. The file uses the same format as a standardsettings.json. - Level 5 (cliArg): configure with the
--permission-mode,--allowed-tools,--disallowed-tools,--tools, and similar command-line flags. Only affects the current session. - Level 6 (command): type
/allow Bash(npm test)or/deny WebFetchduring a session; the rule is persisted tosettings.local.json. - Level 7 (session): choosing "allow for this session" in a prompt produces a temporary rule that expires when the process exits.
Mode configuration
Set the default mode — configure general.defaultPermissionMode in settings:
--yolo, --permission-mode bypass_permissions, and Ctrl+Y are all unavailable, and the Shift+Tab cycle skips the mode. A subagent that declares bypass is downgraded to acceptEdits.
Disable Plan mode — if you do not need the Plan workflow, turn it off:
/plan command is unavailable, --permission-mode plan falls back to default, and the EnterPlanMode / ExitPlanMode tools are not registered.
Auto mode classifier configuration — you can use natural-language rules to steer the AI classifier's judgment:
| Field | Purpose |
|---|---|
allow | Descriptions of operations the classifier should tend to approve automatically. |
soft_deny | Descriptions of operations the classifier should tend to deny. |
environment | Environment context provided to the classifier. |
autoMode configuration is only read from trusted sources (user-global settings and localSettings). Project settings are excluded to prevent malicious privilege escalation.
Permission rule configuration
Rules are grouped into allow, ask, and deny:
Rule syntax
| Form | Meaning |
|---|---|
ToolName | Applies to the whole tool. |
ToolName(content) | Applies to a specific path, command, agent type, or any other content the tool supports. |
* | Matches every tool. |
Read, Edit, Write, Bash, Grep, Glob, WebFetch, WebSearch, and Agent, as well as MCP tool names like mcp__github__create_issue.
Escape parentheses inside the content when they appear:
ToolName(*) is equivalent to ToolName (a tool-level rule).
Command-line overrides
--allowed-tools and --disallowed-tools use the same syntax as settings rules. --tools restricts the set of built-in tools available for this run — anything not listed is denied.
Trusted directories
Qoder CN CLI treats the current working directory (CWD) at startup as the primary trusted directory. Inside a trusted directory:
- File reads are allowed by default.
- File writes can be auto-approved in
accept_editsandautomodes. - Non-default permission modes (auto, bypass, and so on) are able to take effect.
default.
Extending trust
Add extra trusted working directories with --add-dir, the /add-dir command, or permissions.additionalDirectories:
permissions.trustDirectories in your global settings to permanently trust frequently-used directories.
Protected paths
Some paths are protected because editing them can change execution behavior, credentials, or tool behavior. Examples include .git, .vscode, .idea, .husky, most .qoder configuration files, shell startup files like .bashrc and .zshrc, Git configuration, .mcp.json, and .ripgreprc. In regular interactive modes these paths require explicit approval; in auto mode they are denied.
File access rules
Read rules with a path scope use Read(...). Write rules with a path scope use Edit(...); the write scope covers file-write checks for Edit, Write, and NotebookEdit. An Edit(...) allow rule on a path also implicitly allows reads on the same path.
File rules use gitignore-style matching.
| Pattern | Meaning |
|---|---|
/src/** | A path rooted at the rule source's root directory. In project or local settings, that is the project root; in user settings, it is the home directory. |
~/Documents/** | A path rooted at the home directory. |
//tmp/data/** | An absolute path starting at system /. Absolute paths require a double slash. |
*.secret | A rootless filename pattern that matches anywhere. |
Bash rules
Bash(...) rules can match an exact command, a command prefix, or a glob pattern.
| Rule | What it matches |
|---|---|
Bash(npm run build) | Exact match for npm run build. |
Bash(npm run test:*) | Matches npm run test and any command starting with npm run test. |
Bash(git log *) | Glob-style wildcard matching. |
Bash(git status) | Exact match for git status. |
denyandaskrules see through common wrappers and environment-variable prefixes, soBash(rm -rf:*)still blocks a wrapped destructive command.- Prefix and wildcard
allowrules do not silently approve compound commands unless every top-level command fragment can be allowed on its own. - Some shell commands that can be proven read-only may be auto-allowed after deny, ask, and path checks pass.
- Dangerous commands (such as destructive deletes or force pushes) may still require confirmation even when a broad allow rule exists. In
automode, dangerous shell commands are denied.
Bash or Bash(*) unless you fully trust the current session.
Web and MCP rules
Web tools can be controlled with tool-level rules. Use ask if every web fetch should require confirmation, or deny to disable network access for a session or project.
| Rule | Meaning |
|---|---|
mcp__github__create_issue | A single MCP tool. |
mcp__github__* | Every tool provided by the github MCP server. |
mcp__github | Every tool provided by the github MCP server. |
mcp__* | Every MCP tool. |
alwaysAllow. To limit a single run to specific MCP servers, use --allowed-mcp-server-names.
Hooks and permissions
The Qoder CN CLI Hooks system has two injection points in the permission decision chain, letting custom scripts influence whether a tool call is allowed or denied.
Hook events that affect permissions
Hook event | When it fires | Permission impact |
| Before the tool runs (during permission checks). | Can return |
| After the pipeline produces | Can return |
PostToolUse, SessionStart, Stop, and so on) do not take part in permission decisions.
PreToolUse hook
Fires before a tool runs. The hook script inspects the tool name and arguments and returns a permission decision:
tool_name, tool_input, and session_id) and writes JSON to stdout:
permissionDecision values:
"allow": skip the permission pipeline and approve directly."deny": skip the pipeline and deny directly."ask": continue through the normal pipeline (the default behavior).
PermissionRequest hook
Fires after the pipeline outputs ask but before the prompt or callback. This is a good fit for automated approval systems or external notifications such as Slack or email alerts.
Hook priority vs. permission modes
Hook permission decisions outrank permission modes. Even in bypass_permissions mode, a PreToolUse hook that returns deny still blocks execution. This gives organizations an unbypassable safety net.
Execution order:
PreToolUsehook — a returned allow or deny short-circuits the rest.- Permission pipeline (rules + mode + safety checks).
- If the result is
ask, thePermissionRequesthook fires — a returned allow or deny short-circuits. - The runtime consumes the remaining
ask(prompt, deny, or callback).