Understand how the governance and permissions system of the Coder Mode works.
ChatCLI was designed to be a powerful tool, but power requires control. In Coder Mode (/coder), the AI has the ability to read, write, create, and execute commands on your system. To ensure you are always in control, we implemented a governance system inspired by ClaudeCode.
The action is executed automatically, without interruption. Ideal for read commands (read, tree, search) and read-only Git operations (git-status, git-diff, git-log, git-changed, git-branch).
Deny (Blocked)
The action is silently blocked (or with an error for the AI). Ideal for protecting sensitive files or destructive commands.
Ask (Prompt)
ChatCLI pauses and displays an interactive menu for you to decide. This is the default for unconfigured actions.
When the agent requests an action, policy_manager evaluates rules in the order below (first match wins):
Deny rules — explicit user rules always win
Safety-immune — operations that ALWAYS prompt (@coder exec)
Explicit allow vs ask — longest pattern wins
Read-only exec heuristic — @coder exec with a provably read-only command auto-allows
Capability gate (new) — plugins that declare IsReadOnly=true via the capability interface auto-allow
Default — Ask
Layer 5 covers @read, @search, @tree, @websearch, @webfetch (GET), @scheduler query/list, @coder read/search/tree, @recall (reads back output this session compressed) and @memory recall/timeline/map/neighbors/list — all pass without a prompt while write/exec stay gated (@memory link/unlink change memory and stay gated like remember).
Deny rules always beat the capability gate. You can block @websearch in a corporate environment via a @websearch → Deny rule even if the plugin advertises read-only.
Channel drain — non-blocking drain of the centralized stdin reader channel (10-line buffer).
Intent debounce — discards any input arriving in the first 250ms after the prompt mounts (humans don’t react that fast to a new UI).
Without this, accidentally typing during the LLM stream would let the security box consume the buffered bytes as the y/n answer.Instructions are kept, answers are not. A complete line you submitted for the agent (for example also update the changelog) never answers the prompt, but it is no longer thrown away: the drain re-queues it and it reaches the model at the next turn boundary. From the drain, only lines shaped like a prompt answer (y, n, yes, no, sim, a, always, d, deny, or a bare Enter) stay discarded.
The prompt displays the action in human language (e.g., “Write file”, “Execute shell command”, “Modify file (patch)”) and the parsed details from the JSON arguments, instead of showing raw JSON.
Rules are saved locally in ~/.chatcli/coder_policy.json. You can edit this file manually if desired, but the interactive menu is the easiest way to configure.
The matching uses the effective @coder subcommand even when args is JSON (e.g., {"cmd":"read"} becomes @coder read).
You can add a local policy in the project directory:
Local: ./coder_policy.json
Global: ~/.chatcli/coder_policy.json
A local coder_policy.json loads only from a trusted workspace, and it can only tighten the global policy — it can never widen it. This changed in the security release; the older merge/replace behaviour is gone.
A local rule may add an ask or deny on top of the global policy.
A local allow rule is ignored — a project file can never grant a permission your global policy does not already grant.
When you choose “Always allow” at a prompt while working in a project, that new allow rule is written to the global file (~/.chatcli/coder_policy.json), never to the project file.
In an untrusted folder the local file is not read at all (a warning is printed on stderr). Trust the folder first with chatcli trust [dir].
The local file above only tightens: it forces @coder write back to ask and denies a destructive rm -rf even if the global policy was more permissive. Any allow it contained would be dropped.
For evals, the per-case policy no longer comes from a coder_policy.json placed in the sandbox. It comes from CHATCLI_CODER_POLICY_OVERLAY, a path read only from the process environment; that overlay is a full merge and is never persisted.
The command validator and the permission policy gate what a command is allowed to run. The exec sandbox is a second, complementary layer that confines what a permitted command can touch — file writes and network — using the operating system’s own sandboxing.It is opt-in and default OFF, selected with CHATCLI_CODER_SANDBOX:
Mode
File writes
Network
When to use
off (default)
unrestricted
allowed
Trust the validator + policy alone
workspace
confined to the workspace and build caches
allowed
Contain accidental writes outside the project
strict
confined to the workspace and build caches
cut (no network)
Fully offline, contained builds and tests
In workspace and strict, writes are allowed to the workspace plus a generous allowlist of toolchain caches — Go module cache / GOCACHE, .npm, .cargo, .rustup, .gradle, .m2, ~/.chatcli, and the temp dir — so ordinary builds keep working while stray writes elsewhere are blocked.
ChatCLI picks the strongest available backend for the host, and the container backend makes confinement work on any operating system, Windows included:
Platform
Backend
Mechanism
macOS
sandbox-exec (built-in)
Generated SBPL profile: writes confined, network denied in strict
Linux
bubblewrap (bwrap)
Read-only root, workspace + caches bound read-write, --unshare-net in strict
Any OS (Windows, *BSD, or as a fallback)
Docker / Podman
Workspace mounted read-write in a container, --network none in strict
Selection order: an explicit container request (CHATCLI_CODER_SANDBOX=docker, podman, or container) wins; otherwise the native backend is used; if none is present, the portable container backend takes over; only when no backend at all is installed does it degrade to unconfined — printing a one-line note, never failing the command.The container image is configurable with CHATCLI_CODER_SANDBOX_IMAGE (default alpine:3).
The sandbox is opt-in on purpose: a silently confined build that can’t reach its module cache is worse than no sandbox at all. Turn it on deliberately.With the container backend, the command runs inside the image — so host toolchains (go, node, …) are only available if the image ships them. Point CHATCLI_CODER_SANDBOX_IMAGE at an image that carries your toolchain, or use the native macOS/Linux backends when you need the host tools.
When the AI responds with XML-format tool calls (e.g., <tool_call name="@coder" args='{"cmd":"read",...}' />), ChatCLI’s parser uses two extraction methods:
XML Parser — extracts complete <tool_call> tags
JSON Parser — looks for JSON objects that represent tool calls (for models that respond in pure JSON)
The JSON embedded inside the XML args attribute (e.g., {"cmd":"read",...}) could be incorrectly recognized by the JSON parser as a second tool call. Without deduplication, this would cause:
The security check displayed twice for the same action
ParseToolCalls applies automatic deduplication: tool calls extracted by the JSON parser that already exist as part of an XML tool call are discarded. The comparison uses the tool name, arguments, and raw text to detect duplicates.
This mechanism is transparent — you don’t need to do anything. The security check appears exactly once per action.
Keep write commands (write, patch, exec) as ask until you feel confident in the agent.
2
Allow Reads
Generally, it is safe to give “Always” for coder read, coder tree, coder search, and read-only Git (git-status, git-diff, git-log).
3
Be Specific
Matching uses word boundary for subcommand prefixes and path-prefix for arguments. You can allow coder exec --cmd 'ls but block coder exec --cmd 'rm.
4
Safe Exec
@coder exec blocks dangerous patterns by default (50+ rules). A --allow-unsafe or --allow-sudo flag coming from the model is ignored — only the human operator can lift these guards, via CHATCLI_CODER_ALLOW_UNSAFE=true and CHATCLI_AGENT_ALLOW_SUDO=true in the environment. Set them deliberately and only when necessary.
Security policies are fully respected by multi-agent mode workers. When /coder or /agent operates in parallel mode, each worker checks the coder_policy.json rules before executing any action.
Action blocked; the worker receives [BLOCKED BY POLICY] and continues its flow
ask
The worker pauses, the progress spinner is suspended, and the security prompt is displayed
Security prompts from multiple workers are serialized — only one prompt at a time is displayed, avoiding visual overlap. Rules created during the session (via “Always” or “Deny”) are immediately visible to all subsequent workers.
Ask Rules on Unattended Surfaces (ACP, MCP, Gateway, headless one-shot)
In the interactive terminal an ask rule shows the security prompt. On unattended surfaces — where stdin carries a protocol or nobody is watching — the rule is resolved per surface.
When no human can answer, an ask now DENIES, fail-safe. This is the release default across the gateway, the server pipeline, ACP/MCP without a dialog, chatcli tool, and chatcli eval. To let an unattended surface auto-approve its ask verdicts, the operator opts in with CHATCLI_POLICY_AUTOMODE=true (process-wide) or /policy mode auto (per session). deny rules and the safety-immune list keep blocking regardless. See the security hardening upgrade guide.
Surface
What an ask rule does
ACP (IDE)
Raises the IDE’s native dialog via session/request_permission with the full terminal vocabulary — Allow / Always allow / Reject / Always reject; the always choices persist a rule exactly like a/d in the terminal prompt. A denial blocks and the model replans. The wait is bounded by the same CHATCLI_MCP_PERMISSION_TIMEOUT (default 600s); an unanswered dialog denies fail-safe with unanswered-request feedback
MCP with elicitation capability
Raises an elicitation/create form in the client with the same four-way decision; always choices persist rules. The wait is bounded by CHATCLI_MCP_PERMISSION_TIMEOUT (default 600s): an unanswered form denies fail-safe and the model is told the request went unanswered. CHATCLI_MCP_ELICITATION=off disables the forms entirely
MCP without the capability
Denies unless automode is on (CHATCLI_POLICY_AUTOMODE=true or /policy mode auto); dangerous exec commands are still refused in-band
Gateway daemon
Denies unless the operator enabled automode (CHATCLI_POLICY_AUTOMODE=true or /policy mode auto) — autonomy at the messaging edge is now an explicit opt-in, not the default
One-shot without a terminal (chatcli -p "/coder …" from a script, CI, a pipe or chatcli eval)
Denies at once, fail-safe: nobody can answer the prompt, which would otherwise wait until the run’s timeout. Parallel workers get the same denial. The model is told the action needs approval and was not executed (not that you refused it), and continues without it. Use an explicit allow rule, or automode (CHATCLI_POLICY_AUTOMODE=true / /policy mode auto), for what a headless run must do
exec commands never receive the always choices on any surface — the same restriction the interactive prompt applies, since any shell command could be destructive.
deny rules block on every surface, and the dangerous-command validation applies everywhere regardless of policy. A client that doesn’t implement the permission round-trip (answers method not found) falls back to the auto-approve contract instead of having every gated action denied.
Sometimes you want a session to just flow — a long refactor you already trust, a scripted run — without approving every ask one by one. /policy switches the session-scoped policy mode:
Command
Effect
/policy or /policy status
Show the current mode, rule count and policy file
/policy mode auto
Automode: every policy ask verdict auto-approves for this session
/policy mode interactive
Back to the default: ask prompts for approval
Automode is also what lets an unattended surface act on an ask instead of denying it fail-safe — set it process-wide with CHATCLI_POLICY_AUTOMODE=true, or per session with /policy mode auto. See Ask Rules on Unattended Surfaces.What automode does not change:
deny rules still block — they resolve before ask in the policy check.
Safety-immune operations (rm -rf, sudo, force push, …) still prompt — automode widens convenience, never the blast radius the safety-immune tier protects against.
The mode is never persisted: every new session starts interactive. Every auto-approval is logged for auditability, and the current mode is visible in /policy status and /config security.Available on all three surfaces: the terminal REPL, the ACP slash-command menu in the IDE, and MCP via the manage_session tool’s policy_mode action (name: auto | interactive | status).
You can control the style and banner of /coder via environment variables:
Variable
Values
Description
CHATCLI_CODER_UI
full (default), minimal
Interface style
CHATCLI_CODER_BANNER
true (default), false
Show/hide the cheat sheet
These settings appear in /status and /config.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/schema.json","name":"ChatCLI","description":"Official ChatCLI documentation — a multi-provider AI CLI with agent mode, gRPC server and Kubernetes operator.","colors":{"primary":"#0F766E","light":"#2DD4BF","dark":"#0D9488"},"logo":{"light":"https://mintcdn.com/encom/Rcdb5Pr5hpjwN46r/images/logo-light.svg?fit=max\u0026auto=format\u0026n=Rcdb5Pr5hpjwN46r\u0026q=85\u0026s=965a0feb9bd2f65a11b3c486e2488101","dark":"https://mintcdn.com/encom/Rcdb5Pr5hpjwN46r/images/logo-dark.svg?fit=max\u0026auto=format\u0026n=Rcdb5Pr5hpjwN46r\u0026q=85\u0026s=ac3f6607cdea0039d0b66b80f700e512","href":"/"},"favicon":"https://mintcdn.com/encom/Rcdb5Pr5hpjwN46r/images/favicon.svg?fit=max\u0026auto=format\u0026n=Rcdb5Pr5hpjwN46r\u0026q=85\u0026s=c774e29d1b243b7c3b4bf5e173fef299","api":{"openapi":"api-reference/openapi.json","playground":{"display":"interactive"}},"appearance":{"default":"dark","strict":false},"background":{"color":{"light":"#F7F7F5","dark":"#0E0F10"}},"navbar":{"links":[{"href":"/cookbook/agent-refactoring","label":"Cookbook"},{"href":"/releases","label":"Releases"},{"href":"https://github.com/diillson/chatcli","type":"github"}],"primary":{"type":"button","label":"Install","href":"/start/installation"}},"footer":{"socials":{"github":"https://github.com/diillson/chatcli","x":"https://x.com/diillson"},"links":[{"header":"Resources","items":[{"label":"Documentation","href":"/"},{"label":"Cookbook","href":"/cookbook/agent-refactoring"},{"label":"API Reference","href":"/reference/api/overview"}]},{"header":"Community","items":[{"label":"GitHub","href":"https://github.com/diillson/chatcli"},{"label":"Issues","href":"https://github.com/diillson/chatcli/issues"},{"label":"Discussions","href":"https://github.com/diillson/chatcli/discussions"},{"label":"Releases","href":"https://github.com/diillson/chatcli/releases"}]},{"header":"Distribution","items":[{"label":"ArtifactHub","href":"https://artifacthub.io/packages/search?ts_query_web=chatcli"},{"label":"Helm Charts","href":"https://artifacthub.io/packages/helm/chatcli/chatcli"},{"label":"Container Registry","href":"https://github.com/diillson/chatcli/pkgs/container/chatcli"}]}]},"search":{"prompt":"Search"},"seo":{"metatags":{"og:type":"website","og:site_name":"ChatCLI Documentation","twitter:card":"summary_large_image","twitter:site":"@diillson"}},"fonts":{"heading":{"family":"Geist","weight":600},"body":{"family":"Geist"}},"styling":{"eyebrows":"section","codeblocks":"system","latex":true},"integrations":{},"errors":{"404":{"redirect":false}},"contextual":{"options":["copy","view","chatgpt","claude","perplexity"],"display":"header"},"interaction":{"drilldown":true},"navigation":{"languages":[{"language":"en","default":true,"href":""},{"language":"pt-BR","footer":{"socials":{"github":"https://github.com/diillson/chatcli","x":"https://x.com/diillson"},"links":[{"header":"Recursos","items":[{"label":"Documentação","href":"/pt"},{"label":"Cookbook","href":"/pt/cookbook/agent-refactoring"},{"label":"API Reference","href":"/pt/reference/api/overview"}]},{"header":"Comunidade","items":[{"label":"GitHub","href":"https://github.com/diillson/chatcli"},{"label":"Issues","href":"https://github.com/diillson/chatcli/issues"},{"label":"Discussions","href":"https://github.com/diillson/chatcli/discussions"},{"label":"Releases","href":"https://github.com/diillson/chatcli/releases"}]},{"header":"Distribuição","items":[{"label":"ArtifactHub","href":"https://artifacthub.io/packages/search?ts_query_web=chatcli"},{"label":"Helm Charts","href":"https://artifacthub.io/packages/helm/chatcli/chatcli"},{"label":"Container Registry","href":"https://github.com/diillson/chatcli/pkgs/container/chatcli"}]}]},"navbar":{"links":[{"href":"/pt/cookbook/agent-refactoring","label":"Cookbook"},{"href":"/pt/releases","label":"Releases"},{"href":"https://github.com/diillson/chatcli","type":"github"}],"primary":{"type":"button","label":"Instalar","href":"/pt/start/installation"}},"href":"pt"}]}},"deployment":{"deploymentMetadataValue":{"subdomain":"encom","hasAudioNarration":false,"actualSubdomain":"encom","customDomains":["chatcli.edilsonfreitas.com"],"gitSource":{"type":"github","owner":"diillson","repo":"chatcli.ai","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6add34299e1712172edc47d1","collectionId":"277f6ff4-3a3c-4d0e-b0a1-dcd5341a5370","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6add34299e1712172edc47d1"},"entitlements":{},"buildId":"6add3f6f4a5b340ece6c5bdc","clientVersion":"0.0.3965","searchFilterCounts":[{"language":"en","tag":"Documentation","count":206},{"language":"pt-BR","tag":"Documentação","count":206},{"language":"en","tag":"Reference","count":55},{"language":"pt-BR","tag":"Referência","count":55},{"language":"en","tag":"REST API","count":50},{"language":"pt-BR","tag":"REST API","count":50},{"language":"en","tag":"Agents","count":20},{"language":"pt-BR","tag":"Agentes","count":20},{"language":"en","tag":"Context \u0026 memory","count":16},{"language":"en","tag":"Cookbook","count":16},{"language":"pt-BR","tag":"Contexto e memória","count":16},{"language":"pt-BR","tag":"Cookbook","count":16},{"language":"en","tag":"Using ChatCLI","count":15},{"language":"pt-BR","tag":"Usando o ChatCLI","count":15},{"language":"en","tag":"Kubernetes \u0026 AIOps","count":14},{"language":"pt-BR","tag":"Kubernetes e AIOps","count":14},{"language":"en","tag":"Tools","count":13},{"language":"pt-BR","tag":"Ferramentas","count":13},{"language":"en","tag":"Channels \u0026 gateway","count":11},{"language":"pt-BR","tag":"Canais e gateway","count":11}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableAskAiSearchBar":true},"hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-v7-file-tree","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"pause-universal-search-reconcile","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"per-site-search-delta","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-private-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-nav-generations","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-agent-model-picker","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"isAtlas":false,"googleFontsInlined":true},"customCss":[{"filePath":"style.css","content":"/* cyrillic-ext */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFrodmgPn.woff2) format('woff2');\n unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFrMdmgPn.woff2) format('woff2');\n unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* symbols2 */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFg08vz7ehw.woff2) format('woff2');\n unicode-range: U+2000-2001, U+2004-2008, U+200A, U+23B8-23BD, U+2500-259F;\n}\n/* vietnamese */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFrgdmgPn.woff2) format('woff2');\n unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFrkdmgPn.woff2) format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFrcdmg.woff2) format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* cyrillic-ext */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFrodmgPn.woff2) format('woff2');\n unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFrMdmgPn.woff2) format('woff2');\n unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* symbols2 */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFg08vz7ehw.woff2) format('woff2');\n unicode-range: U+2000-2001, U+2004-2008, U+200A, U+23B8-23BD, U+2500-259F;\n}\n/* vietnamese */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFrgdmgPn.woff2) format('woff2');\n unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFrkdmgPn.woff2) format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFrcdmg.woff2) format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* cyrillic-ext */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 600;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFrodmgPn.woff2) format('woff2');\n unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 600;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFrMdmgPn.woff2) format('woff2');\n unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* symbols2 */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 600;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFg08vz7ehw.woff2) format('woff2');\n unicode-range: U+2000-2001, U+2004-2008, U+200A, U+23B8-23BD, U+2500-259F;\n}\n/* vietnamese */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 600;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFrgdmgPn.woff2) format('woff2');\n unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 600;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFrkdmgPn.woff2) format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n font-family: 'Geist Mono';\n font-style: normal;\n font-weight: 600;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/geistmono/v6/or3nQ6H-1_WfwkMZI_qYFrcdmg.woff2) format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n@keyframes cb-blink{50%{opacity:0}}@keyframes cc-nav-in{0%{opacity:0;transform:translateX(18px)}}@keyframes cc-nav-out{0%{opacity:0;transform:translateX(-18px)}}:root{--cc-accent:#0f766e;--cc-accent-strong:#115e59;--cc-accent-soft:rgb(13 148 136 / 0.08);--cc-accent-ring:rgb(13 148 136 / 0.32);--cc-glow:rgb(20 184 166 / 0.07);--cc-text:#17171a;--cc-text-2:#46464e;--cc-text-3:#6b6b74;--cc-surface:#ffffff;--cc-surface-2:#f1f0ed;--cc-code-bg:#f3f2ef;--cc-border:rgb(23 23 26 / 0.10);--cc-border-strong:rgb(23 23 26 / 0.18);--cc-shadow:0 1px 2px rgb(0 0 0 / 0.04), 0 8px 24px -12px rgb(0 0 0 / 0.10);--cc-radius:0.75rem;--cc-radius-sm:0.5rem;--cc-mono:\"Geist Mono\", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace}html.dark{--cc-accent:#2dd4bf;--cc-accent-strong:#5eead4;--cc-accent-soft:rgb(45 212 191 / 0.12);--cc-accent-ring:rgb(45 212 191 / 0.40);--cc-glow:rgb(45 212 191 / 0.08);--cc-text:#ededed;--cc-text-2:#bcbcc4;--cc-text-3:#8e8e96;--cc-surface:#161719;--cc-surface-2:#1c1d20;--cc-code-bg:#121314;--cc-border:rgb(154 154 162 / 0.16);--cc-border-strong:rgb(154 154 162 / 0.28);--cc-shadow:0 1px 2px rgb(0 0 0 / 0.25), 0 12px 32px -16px rgb(0 0 0 / 0.6);--cc-live:#4ade80;--cc-live-soft:rgb(74 222 128 / 0.12)}::selection{background:var(--cc-accent-ring)}body::before{content:\"\";position:fixed;inset:0 0 auto auto;width:60vw;height:32rem;pointer-events:none;z-index:0;background:radial-gradient(ellipse at 75% 0%,var(--cc-glow),transparent 65%)}#navbar{backdrop-filter:saturate(140%) blur(12px)}#navbar #search-bar-entry{border-color:var(--cc-border);background:var(--cc-surface);box-shadow:none}#sidebar-title,#topbar-cta-button a{font-weight:500}#sidebar-title{font-size:.75rem;letter-spacing:.01em;color:var(--cc-text-3)}#navbar #search-bar-entry,#sidebar #navigation-items a,#topbar-cta-button a{border-radius:var(--cc-radius-sm)}#sidebar #navigation-items a.text-primary,#sidebar #navigation-items a[class*=bg-primary]{background:var(--cc-accent-soft);color:var(--cc-accent);text-shadow:none;font-weight:500}.nav-tag-pill-text{font-family:var(--cc-mono);font-weight:500!important;letter-spacing:.02em}#header .eyebrow{color:var(--cc-accent);font-size:.8125rem;font-weight:500}#page-title{font-size:clamp(2rem,3.2vw,2.5rem);font-weight:600;letter-spacing:-.025em;line-height:1.15}#header .prose{color:var(--cc-text-2)}#page-context-menu button,#page-context-menu-button{border-radius:var(--cc-radius-sm)}#content{font-size:.975rem}#content h2,#content h3{letter-spacing:-.02em;font-weight:600}#content h3{letter-spacing:-.01em}#content a:not(.card):not([class*=cc-]){text-decoration-color:var(--cc-accent-ring);text-underline-offset:3px}#content a:not(.card):not([class*=cc-]):hover{text-decoration-color:var(--cc-accent)}.font-mono,code,kbd,pre{font-family:var(--cc-mono)!important}#content :not(pre)>code{font-size:.85em;padding:.1em .38em;border-radius:.375rem;border:1px solid var(--cc-border);background:var(--cc-surface-2)}.code-block,[data-component-part=code-block-root]{border-radius:var(--cc-radius)!important;border-color:var(--cc-border)!important}.callout,.code-block-background{border-radius:var(--cc-radius)!important}html.dark .code-block-background{background:var(--cc-code-bg)!important}#content table{font-size:.9rem}#content table thead th{font-size:.8125rem;font-weight:600;color:var(--cc-text-2);border-bottom:1px solid var(--cc-border-strong)}#content table td{border-color:var(--cc-border)}.callout{border:1px solid var(--cc-border)!important;background:var(--cc-surface)!important;box-shadow:var(--cc-shadow)}.callout>div:last-child,.callout>div:last-child *{color:var(--cc-text-2)}.callout>div:last-child code,.callout>div:last-child strong{color:var(--cc-text)!important}.callout[data-callout-type=warning]{border-left:3px solid #f59e0b!important}.callout[data-callout-type=danger]{border-left:3px solid #ef4444!important}.card{border-radius:var(--cc-radius)!important;border-color:var(--cc-border)!important;background:var(--cc-surface)!important;transition:border-color 160ms ease,transform 160ms ease}a.card:hover{border-color:var(--cc-accent-ring)!important}.card [data-component-part=card-icon]{display:grid;place-items:center;width:2.25rem;height:2.25rem;margin-bottom:.25rem;border-radius:var(--cc-radius-sm);border:1px solid var(--cc-border);background:var(--cc-surface-2)}.card [data-component-part=card-icon] svg{width:1rem!important;height:1rem!important;background-color:var(--cc-accent)!important}.steps [data-component-part=step-number]>div{background:var(--cc-surface)!important;box-shadow:0 0 0 1px var(--cc-accent-ring);color:var(--cc-accent)!important;font-family:var(--cc-mono)}[role=tablist] [data-state=active],[role=tablist] button[aria-selected=true]{color:var(--cc-accent)!important;border-color:var(--cc-accent)!important}#content-area:has([data-chatcli-banner]) #header,#content-area:has([data-chatcli-banner]) #header .eyebrow,#content-area:has([data-chatcli-banner]) #header .prose,#content-area:has([data-chatcli-banner]) #page-title{display:none}#content-area:has([data-chatcli-banner]) #content{margin-top:0}.chatcli-banner{margin:3rem 0 .75rem}.chatcli-banner-art{--cb-a:#0d9488;--cb-b:#0891b2;--cb-c:#2563eb;--cb-edge:rgb(23 23 26 / 0.28);--cb-glow:rgb(13 148 136 / 0.18);display:block;width:min(100%,30rem);height:auto;overflow:visible}html.dark .chatcli-banner-art{--cb-a:#2dd4bf;--cb-b:#22d3ee;--cb-c:#60a5fa;--cb-edge:rgb(237 237 237 / 0.22);--cb-glow:rgb(45 212 191 / 0.34)}.chatcli-banner .cb-fills rect{shape-rendering:crispEdges}.chatcli-banner .cb-fills{filter:drop-shadow(0 0 14px var(--cb-glow))}.chatcli-banner .cb-edges path{fill:none;stroke:var(--cb-edge);stroke-width:.55;stroke-linecap:square}.cb-prompt{margin:0 0 1.25rem;font-family:var(--cc-mono);font-size:.95rem;color:var(--cc-text-2)}.cb-prompt-sign{color:var(--cc-accent)}.cb-cursor{display:inline-block;width:.55em;height:1.1em;margin-left:.3em;vertical-align:-.18em;background:var(--cc-accent);animation:cb-blink 1.1s steps(1) infinite}@media (prefers-reduced-motion:reduce){.cb-cursor{animation:none}}.chatcli-banner-tagline{font-size:1.125rem;line-height:1.6;margin:0 0 2rem;max-width:44rem;color:var(--cc-text-2)}.chatcli-banner-tagline strong{color:var(--cc-text);font-weight:500}.cc-entry>div,a.cc-release{border:1px solid var(--cc-border);border-radius:var(--cc-radius);background:var(--cc-surface)}a.cc-release{display:flex;align-items:center;gap:.75rem;padding:.85rem 1.1rem;margin:0 0 1.25rem;color:var(--cc-text-2);font-size:.875rem;text-decoration:none!important;border-bottom-width:1px;transition:border-color 160ms ease}a.cc-release:hover{border-color:var(--cc-accent-ring)}.cc-release-label{color:var(--cc-text-3);white-space:nowrap}.cc-release-version{display:inline-flex;align-items:center;gap:.4rem;font-weight:600;color:var(--cc-text);white-space:nowrap}.cc-release-version::before{content:\"\";width:.4rem;height:.4rem;border-radius:999px;background:var(--cc-live);box-shadow:0 0 0 3px var(--cc-live-soft)}.cc-release-summary{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cc-release-cta{font-weight:500;color:var(--cc-text);white-space:nowrap}.cc-entry{margin:0 0 3rem}.cc-entry>div{gap:0!important;overflow:hidden}.cc-entry .card{margin:0!important;border:0!important;border-radius:0!important;background:0 0!important;height:100%}.cc-entry .card:hover{background:var(--cc-accent-soft)!important}@media (min-width:1024px){.cc-entry .card{border-left:1px solid var(--cc-border)!important}.cc-entry>div>.card:first-child,.cc-entry>div>:first-child .card{border-left:0!important}}@media (max-width:1023px){.cc-entry .card{border-top:1px solid var(--cc-border)!important}.cc-entry>div>.card:first-child,.cc-entry>div>:first-child .card{border-top:0!important}a.cc-release{flex-wrap:wrap}.cc-release-summary{flex-basis:100%;white-space:normal}}.cc-release-meta{display:flex;flex-wrap:wrap;gap:.5rem 1.25rem;margin:0 0 1.5rem;font-size:.875rem;color:var(--cc-text-3)}.cc-release-meta a{color:var(--cc-text-2)!important}.cc-scope{display:inline-block;margin-right:.35rem;padding:.05rem .4rem;border-radius:.375rem;border:1px solid var(--cc-border);background:var(--cc-surface-2);font-family:var(--cc-mono);font-size:.78em;color:var(--cc-text-2);vertical-align:.08em}a.cc-scope{text-decoration:none!important;color:var(--cc-accent)!important}.cc-refs{font-size:.85em;color:var(--cc-text-3);white-space:nowrap}.cc-refs a{color:var(--cc-text-3)!important}html{--cc-live:#15803d;--cc-live-soft:rgb(21 128 61 / 0.10)}.nav-tag-pill-text[data-nav-tag=\"Mais recente\"],.nav-tag-pill-text[data-nav-tag=Latest],.nav-tag-pill-text[data-nav-tag^=v]{display:inline-flex;align-items:center;gap:.3rem;color:var(--cc-live)!important;background:var(--cc-live-soft)!important}.nav-tag-pill-text[data-nav-tag=\"Mais recente\"]::before,.nav-tag-pill-text[data-nav-tag=Latest]::before,.nav-tag-pill-text[data-nav-tag^=v]::before{content:\"\";width:.35rem;height:.35rem;border-radius:999px;background:currentColor}.cc-nav-back{display:flex;align-items:center;gap:.6rem;width:100%;margin:0 0 1rem;padding:.6rem .85rem;border:1px solid var(--cc-border);border-radius:var(--cc-radius-sm);background:var(--cc-surface);color:var(--cc-text);font-weight:600;text-align:left;cursor:pointer;transition:border-color 160ms ease,background 160ms ease}#navigation-items[data-cc-focus] [data-cc-focused]>button,.cc-nav-back[hidden]{display:none}.cc-nav-back:hover,a.cc-channel:hover{border-color:var(--cc-accent-ring)}.cc-nav-back svg{flex:none;color:var(--cc-text-3)}#navigation-items[data-cc-focus] ul.sidebar-group>li:not([data-cc-focused]),#navigation-items[data-cc-focus]>div:not(:has([data-cc-focused])){display:none}#navigation-items[data-cc-focus]>div:has([data-cc-focused]){margin-top:0}#navigation-items[data-cc-focus]>div:has([data-cc-focused])>:not(ul){display:none}#navigation-items[data-cc-focus] [data-cc-focused]>ul>li>a,#navigation-items[data-cc-focus] [data-cc-focused]>ul>li>button{padding-left:1rem!important}#navigation-items[data-cc-focus] [data-cc-focused]>ul>li>ul a,#navigation-items[data-cc-focus] [data-cc-focused]>ul>li>ul button{padding-left:1.75rem!important}#navigation-items.cc-nav-in{animation:cc-nav-in 220ms cubic-bezier(.23,1,.32,1)}#navigation-items.cc-nav-out{animation:cc-nav-out 220ms cubic-bezier(.23,1,.32,1)}@media (prefers-reduced-motion:reduce){#navigation-items.cc-nav-in,#navigation-items.cc-nav-out{animation:none}}.cc-channels{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:.85rem;margin:1.25rem 0 2rem}@media (max-width:900px){.cc-channels{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width:520px){.cc-channels{grid-template-columns:1fr}}a.cc-channel{display:flex;align-items:center;gap:.85rem;padding:1rem 1.1rem;border:1px solid var(--cc-border);border-radius:var(--cc-radius);background:var(--cc-surface);color:var(--cc-text)!important;font-weight:500;font-size:.95rem;text-decoration:none!important;transition:border-color 160ms ease,transform 160ms ease}.cc-channel-icon{display:grid;place-items:center;flex:none;width:1.6rem;height:1.6rem}.cc-channel-icon svg{width:1.45rem;height:1.45rem}.cc-channel-name{flex:1;min-width:0}.cc-channel-arrow{flex:none;width:1rem;height:1rem;color:var(--cc-text-3);transition:transform 160ms ease,color 160ms ease}a.cc-channel:hover .cc-channel-arrow{color:var(--cc-text);transform:translateX(2px)}.cc-ch-telegram{color:#26a5e4}.cc-ch-slack{color:#e01e5a}.cc-ch-discord{color:#5865f2}.cc-ch-whatsapp{color:#25d366}.cc-ch-webhook{color:var(--cc-accent)}.cc-ch-all{color:var(--cc-text-3)}html.dark .cc-ch-discord{color:#8991ff}#sidebar #navigation-items a,#sidebar #navigation-items button{font-size:.8125rem!important;line-height:1.35rem;padding-top:.3rem!important;padding-bottom:.3rem!important}#sidebar #navigation-items svg{width:.95rem;height:.95rem}.cc-nav-back{font-size:.8125rem}#table-of-contents,#table-of-contents a,#table-of-contents li{font-size:.8125rem!important;line-height:1.3rem}#table-of-contents a{padding-top:.2rem;padding-bottom:.2rem}#content-container:has([data-chatcli-banner]){max-width:min(100%,1440px)!important}#content-container:has([data-chatcli-banner]) #content-area{max-width:none!important}#navigation-items li[data-title]:not([id])>button>div:not(:has(svg)){flex:1 1 auto;min-width:0;text-align:left}body::after{content:\"\";position:absolute;top:0;right:0;z-index:0;width:min(78vw,1100px);height:440px;pointer-events:none;background:linear-gradient(225deg,#2dd4bf 0,#22d3ee 40%,#60a5fa 75%,transparent 100%);-webkit-mask:url(/images/hero-halftone.svg) right top/100% 100% no-repeat;mask:url(/images/hero-halftone.svg) right top/100% 100% no-repeat;opacity:.6}html:not(.dark) body::after{background:linear-gradient(225deg,#0d9488 0,#0891b2 40%,#2563eb 75%,transparent 100%);opacity:.38}@media (max-width:760px){body::after{width:100vw;height:280px;opacity:.4}html:not(.dark) body::after{opacity:.26}}#navigation-items li[data-title]:not([id])>button{position:relative}#navigation-items li[data-title]:not([id])>button>:last-child svg,#navigation-items li[data-title]:not([id])>button>svg:last-child{visibility:hidden}#navigation-items li[data-title]:not([id])>button::after{content:\"\";position:absolute;top:50%;right:.7rem;width:12px;height:12px;margin-top:-6px;background:currentColor;-webkit-mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='m6 3.5 4.5 4.5L6 12.5' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\") center/contain no-repeat;mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='m6 3.5 4.5 4.5L6 12.5' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\") center/contain no-repeat;opacity:.42;pointer-events:none;transition:rotate 200ms cubic-bezier(.23,1,.32,1),opacity 160ms ease}#navigation-items li[data-title]:not([id])>button[aria-expanded=true]::after{rotate:90deg}#navigation-items li[data-title]:not([id])>button:hover::after{opacity:.75}@media (prefers-reduced-motion:reduce){#navigation-items li[data-title]:not([id])>button::after{transition:none}}"}],"page":{"pagePath":"coder/coder-security","slug":"/coder/coder-security","pageMetadata":{"title":"Coder Mode Security (Governance)","sidebarTitle":"Coder Mode Security (Governance)","description":"Understand how the governance and permissions system of the Coder Mode works.","icon":"shield-halved","href":"/coder/coder-security"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Understand how the governance and permissions system of the Coder Mode works.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,em:`em`,hr:`hr`,li:`li`,ol:`ol`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,..._provideComponents(),...props.components},{Card,CardGroup,CodeBlock,Heading,Info,Note,Step,Steps,Table,Tip,Warning}=_components;if(!Card)_missingMdxReference(`Card`,true);if(!CardGroup)_missingMdxReference(`CardGroup`,true);if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Info)_missingMdxReference(`Info`,true);if(!Note)_missingMdxReference(`Note`,true);if(!Step)_missingMdxReference(`Step`,true);if(!Steps)_missingMdxReference(`Steps`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Tip)_missingMdxReference(`Tip`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[`ChatCLI was designed to be a powerful tool, but power requires control. In `,_jsx(_components.strong,{children:`Coder Mode`}),` (`,_jsx(_components.code,{children:`/coder`}),`), the AI has the ability to read, write, create, and execute commands on your system. To ensure you are always in control, we implemented a governance system inspired by ClaudeCode.`]}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`how-does-it-work`,children:`How Does It Work?`}),`\n`,_jsx(_components.p,{children:`Every time the AI suggests an action (such as creating a file or running a script), ChatCLI checks your local security rules before executing.`}),`\n`,_jsx(Heading,{level:`3`,id:`the-3-permission-states`,children:`The 3 Permission States`}),`\n`,_jsxs(CardGroup,{cols:3,children:[_jsx(Card,{title:`Allow (Permitted)`,icon:`circle-check`,children:_jsxs(_components.p,{children:[`The action is executed automatically, without interruption. Ideal for read commands (`,_jsx(_components.code,{children:`read`}),`, `,_jsx(_components.code,{children:`tree`}),`, `,_jsx(_components.code,{children:`search`}),`) and read-only Git operations (`,_jsx(_components.code,{children:`git-status`}),`, `,_jsx(_components.code,{children:`git-diff`}),`, `,_jsx(_components.code,{children:`git-log`}),`, `,_jsx(_components.code,{children:`git-changed`}),`, `,_jsx(_components.code,{children:`git-branch`}),`).`]})}),_jsx(Card,{title:`Deny (Blocked)`,icon:`circle-xmark`,children:_jsx(_components.p,{children:`The action is silently blocked (or with an error for the AI). Ideal for protecting sensitive files or destructive commands.`})}),_jsx(Card,{title:`Ask (Prompt)`,icon:`circle-question`,children:_jsxs(_components.p,{children:[`ChatCLI pauses and displays an interactive menu for you to decide. This is the `,_jsx(_components.strong,{children:`default`}),` for unconfigured actions.`]})})]}),`\n`,_jsx(Heading,{level:`3`,id:`policy_manager-priority-order`,children:`policy_manager priority order`}),`\n`,_jsxs(_components.p,{children:[`When the agent requests an action, `,_jsx(_components.code,{children:`policy_manager`}),` evaluates rules in the order below (first match wins):`]}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Deny rules`}),` — explicit user rules always win`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Safety-immune`}),` — operations that ALWAYS prompt (`,_jsx(_components.code,{children:`@coder exec`}),`)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Explicit allow vs ask`}),` — longest pattern wins`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Read-only exec heuristic`}),` — `,_jsx(_components.code,{children:`@coder exec`}),` with a provably read-only command auto-allows`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Capability gate`}),` (new) — plugins that declare `,_jsx(_components.code,{children:`IsReadOnly=true`}),` via the capability interface auto-allow`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Default`}),` — Ask`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Layer 5 covers `,_jsx(_components.code,{children:`@read`}),`, `,_jsx(_components.code,{children:`@search`}),`, `,_jsx(_components.code,{children:`@tree`}),`, `,_jsx(_components.code,{children:`@websearch`}),`, `,_jsx(_components.code,{children:`@webfetch`}),` (GET), `,_jsx(_components.code,{children:`@scheduler query/list`}),`, `,_jsx(_components.code,{children:`@coder read/search/tree`}),`, `,_jsx(_components.code,{children:`@recall`}),` (reads back output this session compressed) and `,_jsx(_components.code,{children:`@memory recall/timeline/map/neighbors/list`}),` — all pass `,_jsx(_components.strong,{children:`without a prompt`}),` while write/exec stay gated (`,_jsx(_components.code,{children:`@memory link`}),`/`,_jsx(_components.code,{children:`unlink`}),` change memory and stay gated like `,_jsx(_components.code,{children:`remember`}),`).`]}),`\n`,_jsx(Tip,{children:_jsxs(_components.p,{children:[`Deny rules always beat the capability gate. You can block `,_jsx(_components.code,{children:`@websearch`}),` in a corporate environment via a `,_jsx(_components.code,{children:`@websearch → Deny`}),` rule even if the plugin advertises read-only.`]})}),`\n`,_jsx(Heading,{level:`3`,id:`typeahead-protection-input-guard`,children:`Typeahead protection (input guard)`}),`\n`,_jsxs(_components.p,{children:[`When the LLM is streaming and the security box appears, any character you typed `,_jsx(_components.strong,{children:`before`}),` the prompt rendered is discarded automatically. Three layers:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Kernel TTY flush`}),` — `,_jsx(_components.code,{children:`TCIFLUSH`}),` (Linux), `,_jsx(_components.code,{children:`TIOCFLUSH`}),` (BSD/Darwin), `,_jsx(_components.code,{children:`FlushConsoleInputBuffer`}),` (Windows) clears the kernel’s input queue.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Channel drain`}),` — non-blocking drain of the centralized stdin reader channel (10-line buffer).`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Intent debounce`}),` — discards any input arriving in the first 250ms after the prompt mounts (humans don’t react that fast to a new UI).`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`Without this, accidentally typing during the LLM stream would let the security box consume the buffered bytes as the y/n answer.`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Instructions are kept, answers are not.`}),` A complete line you submitted for the agent (for example `,_jsx(_components.code,{children:`also update the changelog`}),`) never answers the prompt, but it is no longer thrown away: the drain re-queues it and it reaches the model at the next turn boundary. From the drain, only lines shaped like a prompt answer (`,_jsx(_components.code,{children:`y`}),`, `,_jsx(_components.code,{children:`n`}),`, `,_jsx(_components.code,{children:`yes`}),`, `,_jsx(_components.code,{children:`no`}),`, `,_jsx(_components.code,{children:`sim`}),`, `,_jsx(_components.code,{children:`a`}),`, `,_jsx(_components.code,{children:`always`}),`, `,_jsx(_components.code,{children:`d`}),`, `,_jsx(_components.code,{children:`deny`}),`, or a bare Enter) stay discarded.`]}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`interactive-approval-menu`,children:`Interactive Approval Menu`}),`\n`,_jsx(_components.p,{children:`When an action falls into the “Ask” state, you will see a security box with contextual information about the action:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`15`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`15`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`+========================================================+`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`| SECURITY CHECK |`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`+========================================================+`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` Action: Write file`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` file: main.go`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` Rule: no rule for '@coder write'`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` --------------------------------------------------------`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` Choice:`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` [y] Yes, execute (once)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` [a] Always allow (@coder write)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` [n] No, skip`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` [d] Always block (@coder write)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` > _`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsxs(_components.p,{children:[`The prompt displays the `,_jsx(_components.strong,{children:`action in human language`}),` (e.g., “Write file”, “Execute shell command”, “Modify file (patch)”) and the `,_jsx(_components.strong,{children:`parsed details`}),` from the JSON arguments, instead of showing raw JSON.`]}),`\n`,_jsx(Heading,{level:`4`,id:`recognized-action-types`,children:`Recognized Action Types`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Subcommand`}),_jsx(_components.th,{children:`Prompt Label`}),_jsx(_components.th,{children:`Details Displayed`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`exec`})}),_jsx(_components.td,{children:`Execute shell command`}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`$ \u003ccommand>`}),`, `,_jsx(_components.code,{children:`dir: \u003ccwd>`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`test`})}),_jsx(_components.td,{children:`Run tests`}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`$ \u003ccommand>`}),`, `,_jsx(_components.code,{children:`dir: \u003ccwd>`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`write`})}),_jsx(_components.td,{children:`Write file`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`file: \u003cpath>`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`patch`})}),_jsx(_components.td,{children:`Modify file (patch)`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`file: \u003cpath>`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`read`})}),_jsx(_components.td,{children:`Read file`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`file: \u003cpath>`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`search`})}),_jsx(_components.td,{children:`Search code`}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`term: \u003cpattern>`}),`, `,_jsx(_components.code,{children:`dir: \u003cpath>`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`tree`})}),_jsx(_components.td,{children:`List directory structure`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`dir: \u003cpath>`})})]})]})]}),`\n`,_jsx(Heading,{level:`3`,id:`prompt-with-context-in-parallel-mode`,children:`Prompt with Context in Parallel Mode`}),`\n`,_jsxs(_components.p,{children:[`When the action is requested by a `,_jsx(_components.strong,{children:`multi-agent mode worker`}),`, the prompt includes additional information about which agent is making the request:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`11`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`11`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`+========================================================+`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`| SECURITY CHECK |`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`+========================================================+`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` Agent: shell`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` Task: Run auth module tests`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` --------------------------------------------------------`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` Action: Execute shell command`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` $ go test ./pkg/auth/...`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` Rule: no rule for '@coder exec'`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` --------------------------------------------------------`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsxs(Info,{children:[`This allows you to know `,_jsx(_components.strong,{children:`exactly`}),` which agent is requesting the action and why, facilitating informed security decisions.`]}),`\n`,_jsx(Heading,{level:`3`,id:`options`,children:`Options`}),`\n`,_jsxs(Steps,{children:[_jsx(Step,{title:`y (Yes)`,children:_jsx(_components.p,{children:`Executes only this time. Next time, it will ask again.`})}),_jsx(Step,{title:`a (Always)`,children:_jsxs(_components.p,{children:[`Creates a permanent `,_jsx(_components.strong,{children:`ALLOW`}),` rule for this command (e.g., allows all writes with `,_jsx(_components.code,{children:`@coder write`}),`).`]})}),_jsx(Step,{title:`n (No)`,children:_jsx(_components.p,{children:`Skips execution. The AI receives an error informing that the user denied.`})}),_jsx(Step,{title:`d (Deny)`,children:_jsxs(_components.p,{children:[`Creates a permanent `,_jsx(_components.strong,{children:`DENY`}),` rule. The action will be automatically blocked in the future.`]})})]}),`\n`,_jsxs(Note,{children:[`For `,_jsx(_components.code,{children:`exec`}),` commands, the “Always” and “Deny Forever” options are not available, as each execution is unique and requires individual approval.`]}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`rule-management`,children:`Rule Management`}),`\n`,_jsxs(_components.p,{children:[`Rules are saved locally in `,_jsx(_components.code,{children:`~/.chatcli/coder_policy.json`}),`. You can edit this file manually if desired, but the interactive menu is the easiest way to configure.\nThe matching uses the effective @coder subcommand even when `,_jsx(_components.code,{children:`args`}),` is JSON (e.g., `,_jsx(_components.code,{children:`{\"cmd\":\"read\"}`}),` becomes `,_jsx(_components.code,{children:`@coder read`}),`).`]}),`\n`,_jsx(Heading,{level:`3`,id:`local-policy-per-project`,children:`Local Policy (Per Project)`}),`\n`,_jsx(_components.p,{children:`You can add a local policy in the project directory:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Local: `,_jsx(_components.code,{children:`./coder_policy.json`})]}),`\n`,_jsxs(_components.li,{children:[`Global: `,_jsx(_components.code,{children:`~/.chatcli/coder_policy.json`})]}),`\n`]}),`\n`,_jsxs(Warning,{children:[_jsxs(_components.p,{children:[_jsxs(_components.strong,{children:[`A local `,_jsx(_components.code,{children:`coder_policy.json`}),` loads only from a trusted workspace, and it can only `,_jsx(_components.em,{children:`tighten`}),` the global policy — it can never widen it.`]}),` This changed in the security release; the older merge/replace behaviour is gone.`]}),_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`A local rule may add an `,_jsx(_components.code,{children:`ask`}),` or `,_jsx(_components.code,{children:`deny`}),` on top of the global policy.`]}),`\n`,_jsxs(_components.li,{children:[`A local `,_jsx(_components.code,{children:`allow`}),` rule is `,_jsx(_components.strong,{children:`ignored`}),` — a project file can never grant a permission your global policy does not already grant.`]}),`\n`,_jsxs(_components.li,{children:[`When you choose `,_jsx(_components.strong,{children:`“Always allow”`}),` at a prompt while working in a project, that new `,_jsx(_components.code,{children:`allow`}),` rule is written to the `,_jsx(_components.strong,{children:`global`}),` file (`,_jsx(_components.code,{children:`~/.chatcli/coder_policy.json`}),`), never to the project file.`]}),`\n`,_jsxs(_components.li,{children:[`In an untrusted folder the local file is not read at all (a warning is printed on stderr). Trust the folder first with `,_jsx(_components.code,{children:`chatcli trust [dir]`}),`.`]}),`\n`]}),_jsxs(_components.p,{children:[`See the `,_jsx(_components.a,{href:`/security/hardening-upgrade`,children:`security hardening upgrade guide`}),` for the full workspace-trust model.`]})]}),`\n`,_jsx(CodeBlock,{filename:`./coder_policy.json`,numberOfLines:`6`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`6`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"rules\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"pattern\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"@coder write\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"action\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"ask\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"pattern\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"@coder exec --cmd 'rm -rf'\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"action\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"deny\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ]`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`The local file above only tightens: it forces `,_jsx(_components.code,{children:`@coder write`}),` back to `,_jsx(_components.code,{children:`ask`}),` and denies a destructive `,_jsx(_components.code,{children:`rm -rf`}),` even if the global policy was more permissive. Any `,_jsx(_components.code,{children:`allow`}),` it contained would be dropped.`]}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[`For `,_jsx(_components.a,{href:`/agents/harness/evals`,children:`evals`}),`, the per-case policy no longer comes from a `,_jsx(_components.code,{children:`coder_policy.json`}),` placed in the sandbox. It comes from `,_jsx(_components.code,{children:`CHATCLI_CODER_POLICY_OVERLAY`}),`, a path read only from the process environment; that overlay is a full merge and is never persisted.`]})}),`\n`,_jsx(Heading,{level:`3`,id:`policy-example-coder_policy-json`,children:`Policy Example (coder_policy.json)`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`20`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`20`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"rules\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"pattern\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"@coder read\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"action\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"allow\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"pattern\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"@coder git-status\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"action\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"allow\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"pattern\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"@coder write\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"action\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"ask\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"action\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"deny\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"pattern\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"@coder exec --cmd 'rm -rf'\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ]`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`word-boundary-matching`,children:`Word Boundary Matching`}),`\n`,_jsxs(_components.p,{children:[`The policy system uses `,_jsx(_components.strong,{children:`word boundary matching`}),`, ensuring that rules do not partially match different subcommands:`]}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Rule`}),_jsx(_components.th,{children:`Command`}),_jsx(_components.th,{children:`Result`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.code,{children:`@coder read`}),` = allow`]}),_jsx(_components.td,{children:_jsx(_components.code,{children:`@coder read file.txt`})}),_jsx(_components.td,{children:`Allowed`})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.code,{children:`@coder read`}),` = allow`]}),_jsx(_components.td,{children:_jsx(_components.code,{children:`@coder readlink /tmp`})}),_jsxs(_components.td,{children:[_jsx(_components.strong,{children:`Does not match`}),` (falls to Ask)`]})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.code,{children:`@coder read --file /etc`}),` = deny`]}),_jsx(_components.td,{children:_jsx(_components.code,{children:`@coder read --file /etc/passwd`})}),_jsx(_components.td,{children:`Deny (path-prefix match)`})]})]})]}),`\n`,_jsxs(Tip,{children:[`This means `,_jsx(_components.code,{children:`@coder read`}),` will `,_jsx(_components.strong,{children:`never`}),` allow `,_jsx(_components.code,{children:`@coder readlink`}),` or `,_jsx(_components.code,{children:`@coder readwrite`}),` accidentally.`]}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`command-validation-50+-patterns`,children:`Command Validation (50+ Patterns)`}),`\n`,_jsxs(_components.p,{children:[`Beyond policy governance, `,_jsx(_components.code,{children:`@coder exec`}),` validates each command against `,_jsx(_components.strong,{children:`50+ regex patterns`}),` that detect:`]}),`\n`,_jsxs(CardGroup,{cols:2,children:[_jsx(Card,{title:`Data destruction`,icon:`trash`,children:_jsxs(_components.p,{children:[_jsx(_components.code,{children:`rm -rf`}),`, `,_jsx(_components.code,{children:`dd if=`}),`, `,_jsx(_components.code,{children:`mkfs`}),`, `,_jsx(_components.code,{children:`drop database`})]})}),_jsx(Card,{title:`Remote execution`,icon:`globe`,children:_jsxs(_components.p,{children:[_jsx(_components.code,{children:`curl | bash`}),`, `,_jsx(_components.code,{children:`base64 | sh`})]})}),_jsx(Card,{title:`Code injection`,icon:`syringe`,children:_jsxs(_components.p,{children:[_jsx(_components.code,{children:`python -c`}),`, `,_jsx(_components.code,{children:`eval`}),`, `,_jsx(_components.code,{children:`$(curl ...)`})]})}),_jsx(Card,{title:`Process substitution`,icon:`arrows-left-right`,children:_jsxs(_components.p,{children:[_jsx(_components.code,{children:`\u003c(cmd)`}),`, `,_jsx(_components.code,{children:`>(cmd)`})]})}),_jsx(Card,{title:`Kernel manipulation`,icon:`microchip`,children:_jsxs(_components.p,{children:[_jsx(_components.code,{children:`insmod`}),`, `,_jsx(_components.code,{children:`modprobe`}),`, `,_jsx(_components.code,{children:`rmmod`})]})}),_jsx(Card,{title:`Evasion`,icon:`mask`,children:_jsxs(_components.p,{children:[_jsx(_components.code,{children:\"${IFS;cmd}\"}),`, `,_jsx(_components.code,{children:`VAR=x; bash`})]})})]}),`\n`,_jsxs(_components.p,{children:[`You can add custom patterns via `,_jsx(_components.code,{children:`CHATCLI_AGENT_DENYLIST`}),`:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`export`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` CHATCLI_AGENT_DENYLIST`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"terraform destroy;kubectl delete namespace\"`})]}),`\n`]})})}),`\n`,_jsxs(Info,{children:[`For the complete list of ChatCLI security protections, see the `,_jsx(_components.a,{href:`/security/overview`,children:`Security and Hardening documentation`}),`.`]}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`exec-sandbox-os-level-confinement`,children:`Exec Sandbox (OS-level confinement)`}),`\n`,_jsxs(_components.p,{children:[`The command validator and the permission policy gate `,_jsx(_components.strong,{children:`what`}),` a command is allowed to run. The exec sandbox is a second, complementary layer that confines `,_jsx(_components.strong,{children:`what a permitted command can touch`}),` — file writes and network — using the operating system’s own sandboxing.`]}),`\n`,_jsxs(_components.p,{children:[`It is `,_jsx(_components.strong,{children:`opt-in and default OFF`}),`, selected with `,_jsx(_components.code,{children:`CHATCLI_CODER_SANDBOX`}),`:`]}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Mode`}),_jsx(_components.th,{children:`File writes`}),_jsx(_components.th,{children:`Network`}),_jsx(_components.th,{children:`When to use`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.code,{children:`off`}),` (default)`]}),_jsx(_components.td,{children:`unrestricted`}),_jsx(_components.td,{children:`allowed`}),_jsx(_components.td,{children:`Trust the validator + policy alone`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`workspace`})}),_jsxs(_components.td,{children:[`confined to the workspace `,_jsx(_components.strong,{children:`and build caches`})]}),_jsx(_components.td,{children:`allowed`}),_jsx(_components.td,{children:`Contain accidental writes outside the project`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`strict`})}),_jsx(_components.td,{children:`confined to the workspace and build caches`}),_jsxs(_components.td,{children:[_jsx(_components.strong,{children:`cut`}),` (no network)`]}),_jsx(_components.td,{children:`Fully offline, contained builds and tests`})]})]})]}),`\n`,_jsxs(_components.p,{children:[`In `,_jsx(_components.code,{children:`workspace`}),` and `,_jsx(_components.code,{children:`strict`}),`, writes are allowed to the workspace plus a generous allowlist of toolchain caches — Go module cache / `,_jsx(_components.code,{children:`GOCACHE`}),`, `,_jsx(_components.code,{children:`.npm`}),`, `,_jsx(_components.code,{children:`.cargo`}),`, `,_jsx(_components.code,{children:`.rustup`}),`, `,_jsx(_components.code,{children:`.gradle`}),`, `,_jsx(_components.code,{children:`.m2`}),`, `,_jsx(_components.code,{children:`~/.chatcli`}),`, and the temp dir — so ordinary builds keep working while stray writes elsewhere are blocked.`]}),`\n`,_jsx(Heading,{level:`3`,id:`backends-—-confinement-on-any-os`,children:`Backends — confinement on any OS`}),`\n`,_jsxs(_components.p,{children:[`ChatCLI picks the strongest available backend for the host, and the container backend makes confinement work `,_jsx(_components.strong,{children:`on any operating system, Windows included`}),`:`]}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Platform`}),_jsx(_components.th,{children:`Backend`}),_jsx(_components.th,{children:`Mechanism`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.strong,{children:`macOS`})}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`sandbox-exec`}),` (built-in)`]}),_jsxs(_components.td,{children:[`Generated SBPL profile: writes confined, network denied in `,_jsx(_components.code,{children:`strict`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.strong,{children:`Linux`})}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`bubblewrap`}),` (`,_jsx(_components.code,{children:`bwrap`}),`)`]}),_jsxs(_components.td,{children:[`Read-only root, workspace + caches bound read-write, `,_jsx(_components.code,{children:`--unshare-net`}),` in `,_jsx(_components.code,{children:`strict`})]})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.strong,{children:`Any OS`}),` (Windows, *BSD, or as a fallback)`]}),_jsx(_components.td,{children:_jsx(_components.strong,{children:`Docker / Podman`})}),_jsxs(_components.td,{children:[`Workspace mounted read-write in a container, `,_jsx(_components.code,{children:`--network none`}),` in `,_jsx(_components.code,{children:`strict`})]})]})]})]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Selection order:`}),` an explicit container request (`,_jsx(_components.code,{children:`CHATCLI_CODER_SANDBOX=docker`}),`, `,_jsx(_components.code,{children:`podman`}),`, or `,_jsx(_components.code,{children:`container`}),`) wins; otherwise the native backend is used; if none is present, the portable container backend takes over; only when `,_jsx(_components.strong,{children:`no backend at all`}),` is installed does it degrade to unconfined — printing a one-line note, never failing the command.`]}),`\n`,_jsxs(_components.p,{children:[`The container image is configurable with `,_jsx(_components.code,{children:`CHATCLI_CODER_SANDBOX_IMAGE`}),` (default `,_jsx(_components.code,{children:`alpine:3`}),`).`]}),`\n`,_jsxs(Warning,{children:[_jsxs(_components.p,{children:[`The sandbox is `,_jsx(_components.strong,{children:`opt-in`}),` on purpose: a silently confined build that can’t reach its module cache is worse than no sandbox at all. Turn it on deliberately.`]}),_jsxs(_components.p,{children:[`With the `,_jsx(_components.strong,{children:`container backend`}),`, the command runs inside the image — so host toolchains (`,_jsx(_components.code,{children:`go`}),`, `,_jsx(_components.code,{children:`node`}),`, …) are only available if the image ships them. Point `,_jsx(_components.code,{children:`CHATCLI_CODER_SANDBOX_IMAGE`}),` at an image that carries your toolchain, or use the native macOS/Linux backends when you need the host tools.`]})]}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`tool-call-deduplication`,children:`Tool Call Deduplication`}),`\n`,_jsxs(_components.p,{children:[`ChatCLI includes a deduplication mechanism that ensures each tool call is verified and executed `,_jsx(_components.strong,{children:`exactly once`}),`.`]}),`\n`,_jsx(Heading,{level:`3`,id:`the-problem`,children:`The Problem`}),`\n`,_jsxs(_components.p,{children:[`When the AI responds with XML-format tool calls (e.g., `,_jsx(_components.code,{children:`\u003ctool_call name=\"@coder\" args='{\"cmd\":\"read\",...}' />`}),`), ChatCLI’s parser uses two extraction methods:`]}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`XML Parser`}),` — extracts complete `,_jsx(_components.code,{children:`\u003ctool_call>`}),` tags`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`JSON Parser`}),` — looks for JSON objects that represent tool calls (for models that respond in pure JSON)`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`The JSON embedded inside the XML `,_jsx(_components.code,{children:`args`}),` attribute (e.g., `,_jsx(_components.code,{children:`{\"cmd\":\"read\",...}`}),`) could be incorrectly recognized by the JSON parser as a second tool call. Without deduplication, this would cause:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`The security check displayed `,_jsx(_components.strong,{children:`twice`}),` for the same action`]}),`\n`,_jsxs(_components.li,{children:[`The same action executed `,_jsx(_components.strong,{children:`twice`})]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`the-solution`,children:`The Solution`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`ParseToolCalls`}),` applies automatic deduplication: tool calls extracted by the JSON parser that already exist as part of an XML tool call are discarded. The comparison uses the tool name, arguments, and raw text to detect duplicates.`]}),`\n`,_jsx(Info,{children:`This mechanism is transparent — you don’t need to do anything. The security check appears exactly once per action.`}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`best-practices`,children:`Best Practices`}),`\n`,_jsxs(Steps,{children:[_jsx(Step,{title:`Start with Caution`,children:_jsxs(_components.p,{children:[`Keep write commands (`,_jsx(_components.code,{children:`write`}),`, `,_jsx(_components.code,{children:`patch`}),`, `,_jsx(_components.code,{children:`exec`}),`) as `,_jsx(_components.code,{children:`ask`}),` until you feel confident in the agent.`]})}),_jsx(Step,{title:`Allow Reads`,children:_jsxs(_components.p,{children:[`Generally, it is safe to give “Always” for `,_jsx(_components.code,{children:`coder read`}),`, `,_jsx(_components.code,{children:`coder tree`}),`, `,_jsx(_components.code,{children:`coder search`}),`, and read-only Git (`,_jsx(_components.code,{children:`git-status`}),`, `,_jsx(_components.code,{children:`git-diff`}),`, `,_jsx(_components.code,{children:`git-log`}),`).`]})}),_jsx(Step,{title:`Be Specific`,children:_jsxs(_components.p,{children:[`Matching uses word boundary for subcommand prefixes and path-prefix for arguments. You can allow `,_jsx(_components.code,{children:`coder exec --cmd 'ls`}),` but block `,_jsx(_components.code,{children:`coder exec --cmd 'rm`}),`.`]})}),_jsx(Step,{title:`Safe Exec`,children:_jsxs(_components.p,{children:[_jsx(_components.code,{children:`@coder exec`}),` blocks dangerous patterns by default (50+ rules). A `,_jsx(_components.code,{children:`--allow-unsafe`}),` or `,_jsx(_components.code,{children:`--allow-sudo`}),` flag `,_jsx(_components.strong,{children:`coming from the model is ignored`}),` — only the human operator can lift these guards, via `,_jsx(_components.code,{children:`CHATCLI_CODER_ALLOW_UNSAFE=true`}),` and `,_jsx(_components.code,{children:`CHATCLI_AGENT_ALLOW_SUDO=true`}),` in the environment. Set them deliberately and only when necessary.`]})})]}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`governance-in-multi-agent-mode-parallel`,children:`Governance in Multi-Agent Mode (Parallel)`}),`\n`,_jsxs(_components.p,{children:[`Security policies are `,_jsx(_components.strong,{children:`fully respected`}),` by multi-agent mode workers. When `,_jsx(_components.code,{children:`/coder`}),` or `,_jsx(_components.code,{children:`/agent`}),` operates in parallel mode, each worker checks the `,_jsx(_components.code,{children:`coder_policy.json`}),` rules before executing any action.`]}),`\n`,_jsx(Heading,{level:`3`,id:`behavior`,children:`Behavior`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Rule`}),_jsx(_components.th,{children:`Worker Action`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.strong,{children:`allow`})}),_jsx(_components.td,{children:`Action executed automatically by the worker`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.strong,{children:`deny`})}),_jsxs(_components.td,{children:[`Action blocked; the worker receives `,_jsx(_components.code,{children:`[BLOCKED BY POLICY]`}),` and continues its flow`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.strong,{children:`ask`})}),_jsxs(_components.td,{children:[`The worker `,_jsx(_components.strong,{children:`pauses`}),`, the progress spinner is suspended, and the security prompt is displayed`]})]})]})]}),`\n`,_jsxs(Note,{children:[`Security prompts from multiple workers are `,_jsx(_components.strong,{children:`serialized`}),` — only one prompt at a time is displayed, avoiding visual overlap. Rules created during the session (via “Always” or “Deny”) are immediately visible to all subsequent workers.`]}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`ask-rules-on-unattended-surfaces-acp-mcp-gateway-headless-one-shot`,children:`Ask Rules on Unattended Surfaces (ACP, MCP, Gateway, headless one-shot)`}),`\n`,_jsxs(_components.p,{children:[`In the interactive terminal an `,_jsx(_components.code,{children:`ask`}),` rule shows the security prompt. On unattended surfaces — where stdin carries a protocol or nobody is watching — the rule is resolved per surface.`]}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[_jsxs(_components.strong,{children:[`When no human can answer, an `,_jsx(_components.code,{children:`ask`}),` now DENIES, fail-safe.`]}),` This is the release default across the gateway, the server pipeline, ACP/MCP without a dialog, `,_jsx(_components.code,{children:`chatcli tool`}),`, and `,_jsx(_components.a,{href:`/agents/harness/evals`,children:_jsx(_components.code,{children:`chatcli eval`})}),`. To let an unattended surface auto-approve its `,_jsx(_components.code,{children:`ask`}),` verdicts, the operator opts in with `,_jsx(_components.code,{children:`CHATCLI_POLICY_AUTOMODE=true`}),` (process-wide) or `,_jsx(_components.code,{children:`/policy mode auto`}),` (per session). `,_jsx(_components.code,{children:`deny`}),` rules and the safety-immune list keep blocking regardless. See the `,_jsx(_components.a,{href:`/security/hardening-upgrade`,children:`security hardening upgrade guide`}),`.`]})}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Surface`}),_jsxs(_components.th,{children:[`What an `,_jsx(_components.code,{children:`ask`}),` rule does`]})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.strong,{children:`ACP`}),` (IDE)`]}),_jsxs(_components.td,{children:[`Raises the IDE’s native dialog via `,_jsx(_components.code,{children:`session/request_permission`}),` with the full terminal vocabulary — `,_jsx(_components.em,{children:`Allow`}),` / `,_jsx(_components.em,{children:`Always allow`}),` / `,_jsx(_components.em,{children:`Reject`}),` / `,_jsx(_components.em,{children:`Always reject`}),`; the `,_jsx(_components.em,{children:`always`}),` choices persist a rule exactly like `,_jsx(_components.code,{children:`a`}),`/`,_jsx(_components.code,{children:`d`}),` in the terminal prompt. A denial blocks and the model replans. The wait is bounded by the same `,_jsx(_components.code,{children:`CHATCLI_MCP_PERMISSION_TIMEOUT`}),` (default `,_jsx(_components.code,{children:`600s`}),`); an unanswered dialog denies fail-safe with unanswered-request feedback`]})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.strong,{children:`MCP`}),` with `,_jsx(_components.code,{children:`elicitation`}),` capability`]}),_jsxs(_components.td,{children:[`Raises an `,_jsx(_components.code,{children:`elicitation/create`}),` form in the client with the same four-way decision; `,_jsx(_components.em,{children:`always`}),` choices persist rules. The wait is bounded by `,_jsx(_components.code,{children:`CHATCLI_MCP_PERMISSION_TIMEOUT`}),` (default `,_jsx(_components.code,{children:`600s`}),`): an unanswered form denies fail-safe and the model is told the request went unanswered. `,_jsx(_components.code,{children:`CHATCLI_MCP_ELICITATION=off`}),` disables the forms entirely`]})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.strong,{children:`MCP`}),` without the capability`]}),_jsxs(_components.td,{children:[_jsx(_components.strong,{children:`Denies`}),` unless automode is on (`,_jsx(_components.code,{children:`CHATCLI_POLICY_AUTOMODE=true`}),` or `,_jsx(_components.code,{children:`/policy mode auto`}),`); dangerous exec commands are still refused in-band`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.strong,{children:`Gateway daemon`})}),_jsxs(_components.td,{children:[_jsx(_components.strong,{children:`Denies`}),` unless the operator enabled automode (`,_jsx(_components.code,{children:`CHATCLI_POLICY_AUTOMODE=true`}),` or `,_jsx(_components.code,{children:`/policy mode auto`}),`) — autonomy at the messaging edge is now an explicit opt-in, not the default`]})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.strong,{children:`One-shot without a terminal`}),` (`,_jsx(_components.code,{children:`chatcli -p \"/coder …\"`}),` from a script, CI, a pipe or `,_jsx(_components.a,{href:`/agents/harness/evals`,children:_jsx(_components.code,{children:`chatcli eval`})}),`)`]}),_jsxs(_components.td,{children:[`Denies at once, fail-safe: nobody can answer the prompt, which would otherwise wait until the run’s timeout. Parallel workers get the same denial. The model is told the action needs approval and was not executed (not that you refused it), and continues without it. Use an explicit `,_jsx(_components.code,{children:`allow`}),` rule, or automode (`,_jsx(_components.code,{children:`CHATCLI_POLICY_AUTOMODE=true`}),` / `,_jsx(_components.code,{children:`/policy mode auto`}),`), for what a headless run must do`]})]})]})]}),`\n`,_jsxs(Note,{children:[_jsx(_components.code,{children:`exec`}),` commands never receive the `,_jsx(_components.em,{children:`always`}),` choices on any surface — the same restriction the interactive prompt applies, since any shell command could be destructive.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`deny`}),` rules block on `,_jsx(_components.strong,{children:`every`}),` surface, and the `,_jsx(_components.a,{href:`#command-validation-50-patterns`,children:`dangerous-command validation`}),` applies everywhere regardless of policy. A client that doesn’t implement the permission round-trip (answers `,_jsx(_components.em,{children:`method not found`}),`) falls back to the auto-approve contract instead of having every gated action denied.`]}),`\n`,_jsx(_components.hr,{}),`\n`,_jsxs(Heading,{level:`2`,id:`session-policy-mode-/policy`,children:[`Session Policy Mode (`,_jsx(_components.code,{children:`/policy`}),`)`]}),`\n`,_jsxs(_components.p,{children:[`Sometimes you want a session to just `,_jsx(_components.em,{children:`flow`}),` — a long refactor you already trust, a scripted run — without approving every `,_jsx(_components.code,{children:`ask`}),` one by one. `,_jsx(_components.code,{children:`/policy`}),` switches the `,_jsx(_components.strong,{children:`session-scoped`}),` policy mode:`]}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Command`}),_jsx(_components.th,{children:`Effect`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.code,{children:`/policy`}),` or `,_jsx(_components.code,{children:`/policy status`})]}),_jsx(_components.td,{children:`Show the current mode, rule count and policy file`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`/policy mode auto`})}),_jsxs(_components.td,{children:[_jsx(_components.strong,{children:`Automode`}),`: every policy `,_jsx(_components.code,{children:`ask`}),` verdict auto-approves for this session`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`/policy mode interactive`})}),_jsxs(_components.td,{children:[`Back to the default: `,_jsx(_components.code,{children:`ask`}),` prompts for approval`]})]})]})]}),`\n`,_jsxs(_components.p,{children:[`Automode is also what lets an `,_jsx(_components.strong,{children:`unattended`}),` surface act on an `,_jsx(_components.code,{children:`ask`}),` instead of denying it fail-safe — set it process-wide with `,_jsx(_components.code,{children:`CHATCLI_POLICY_AUTOMODE=true`}),`, or per session with `,_jsx(_components.code,{children:`/policy mode auto`}),`. See `,_jsx(_components.a,{href:`#ask-rules-on-unattended-surfaces-acp-mcp-gateway-headless-one-shot`,children:`Ask Rules on Unattended Surfaces`}),`.`]}),`\n`,_jsxs(_components.p,{children:[`What automode does `,_jsx(_components.strong,{children:`not`}),` change:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsxs(_components.strong,{children:[_jsx(_components.code,{children:`deny`}),` rules`]}),` still block — they resolve before `,_jsx(_components.code,{children:`ask`}),` in the policy check.`]}),`\n`,_jsxs(_components.li,{children:[`The `,_jsx(_components.strong,{children:_jsx(_components.a,{href:`#command-validation-50-patterns`,children:`dangerous-command validation`})}),` still applies.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Safety-immune operations`}),` (`,_jsx(_components.code,{children:`rm -rf`}),`, `,_jsx(_components.code,{children:`sudo`}),`, force push, …) still prompt — automode widens convenience, never the blast radius the `,_jsx(_components.a,{href:`#policy_manager-priority-order`,children:`safety-immune tier`}),` protects against.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`The mode is `,_jsx(_components.strong,{children:`never persisted`}),`: every new session starts interactive. Every auto-approval is logged for auditability, and the current mode is visible in `,_jsx(_components.code,{children:`/policy status`}),` and `,_jsx(_components.code,{children:`/config security`}),`.`]}),`\n`,_jsxs(_components.p,{children:[`Available on all three surfaces: the terminal REPL, the ACP slash-command menu in the IDE, and MCP via the `,_jsx(_components.code,{children:`manage_session`}),` tool’s `,_jsx(_components.code,{children:`policy_mode`}),` action (`,_jsx(_components.code,{children:`name: auto | interactive | status`}),`).`]}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(Heading,{level:`2`,id:`coder-mode-ui`,children:`Coder Mode UI`}),`\n`,_jsxs(_components.p,{children:[`You can control the style and banner of `,_jsx(_components.code,{children:`/coder`}),` via environment variables:`]}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Variable`}),_jsx(_components.th,{children:`Values`}),_jsx(_components.th,{children:`Description`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`CHATCLI_CODER_UI`})}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`full`}),` (default), `,_jsx(_components.code,{children:`minimal`})]}),_jsx(_components.td,{children:`Interface style`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`CHATCLI_CODER_BANNER`})}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`true`}),` (default), `,_jsx(_components.code,{children:`false`})]}),_jsx(_components.td,{children:`Show/hide the cheat sheet`})]})]})]}),`\n`,_jsxs(Tip,{children:[`These settings appear in `,_jsx(_components.code,{children:`/status`}),` and `,_jsx(_components.code,{children:`/config`}),`.`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"codeStyling":"system","config":{},"pageMetadata":{"title":"Coder Mode Security (Governance)","sidebarTitle":"Coder Mode Security (Governance)","description":"Understand how the governance and permissions system of the Coder Mode works.","icon":"shield-halved","href":"/coder/coder-security"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"How Does It Work?","slug":"how-does-it-work","depth":2,"children":[{"title":"The 3 Permission States","slug":"the-3-permission-states","depth":3,"children":[]},{"title":"policy_manager priority order","slug":"policy_manager-priority-order","depth":3,"children":[]},{"title":"Typeahead protection (input guard)","slug":"typeahead-protection-input-guard","depth":3,"children":[]}]},{"title":"Interactive Approval Menu","slug":"interactive-approval-menu","depth":2,"children":[{"title":"Recognized Action Types","slug":"recognized-action-types","depth":4,"children":[]},{"title":"Prompt with Context in Parallel Mode","slug":"prompt-with-context-in-parallel-mode","depth":3,"children":[]},{"title":"Options","slug":"options","depth":3,"children":[]}]},{"title":"Rule Management","slug":"rule-management","depth":2,"children":[{"title":"Local Policy (Per Project)","slug":"local-policy-per-project","depth":3,"children":[]},{"title":"Policy Example (coder_policy.json)","slug":"policy-example-coder_policy-json","depth":3,"children":[]}]},{"title":"Word Boundary Matching","slug":"word-boundary-matching","depth":2,"children":[]},{"title":"Command Validation (50+ Patterns)","slug":"command-validation-50+-patterns","depth":2,"children":[]},{"title":"Exec Sandbox (OS-level confinement)","slug":"exec-sandbox-os-level-confinement","depth":2,"children":[{"title":"Backends — confinement on any OS","slug":"backends-—-confinement-on-any-os","depth":3,"children":[]}]},{"title":"Tool Call Deduplication","slug":"tool-call-deduplication","depth":2,"children":[{"title":"The Problem","slug":"the-problem","depth":3,"children":[]},{"title":"The Solution","slug":"the-solution","depth":3,"children":[]}]},{"title":"Best Practices","slug":"best-practices","depth":2,"children":[]},{"title":"Governance in Multi-Agent Mode (Parallel)","slug":"governance-in-multi-agent-mode-parallel","depth":2,"children":[{"title":"Behavior","slug":"behavior","depth":3,"children":[]}]},{"title":"Ask Rules on Unattended Surfaces (ACP, MCP, Gateway, headless one-shot)","slug":"ask-rules-on-unattended-surfaces-acp-mcp-gateway-headless-one-shot","depth":2,"children":[]},{"title":"Session Policy Mode (/policy)","slug":"session-policy-mode-/policy","depth":2,"children":[]},{"title":"Coder Mode UI","slug":"coder-mode-ui","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":["/_mintlify/custom/encom/03414b2589eb02b8/flags.js","/_mintlify/custom/encom/f19b212850d023b6/sidebar-focus.js"],"subdomain":"encom","siteName":"ChatCLI","title":"Coder Mode Security (Governance) - ChatCLI","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{"en":{"href":"/coder/coder-security","matchLevel":0},"pt-BR":{"href":"/pt/coder/coder-security","matchLevel":1}}},"lastModified":"2026-10-24T14:09:17.523Z","originalFileLocation":"coder/coder-security.mdx","locale":"en"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"dark\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Understand how the governance and permissions system of the Coder Mode works.\">\u003cmeta data-mint-head name=\"application-name\" content=\"ChatCLI\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/encom/ilreks3OQttPbvib/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/encom/ilreks3OQttPbvib/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/encom/ilreks3OQttPbvib/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/encom/ilreks3OQttPbvib/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/encom/ilreks3OQttPbvib/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/encom/ilreks3OQttPbvib/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/encom/ilreks3OQttPbvib/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/encom/ilreks3OQttPbvib/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/encom/ilreks3OQttPbvib/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Coder Mode Security (Governance) - ChatCLI\">\u003cmeta data-mint-head property=\"og:description\" content=\"Understand how the governance and permissions system of the Coder Mode works.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"ChatCLI Documentation\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://chatcli.edilsonfreitas.com/coder/coder-security\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://encom.mintlify.app/_mintlify/api/og/v2?division=Coder\u0026amp;title=Coder+Mode+Security+%28Governance%29\u0026amp;description=Understand+how+the+governance+and+permissions+system+of+the+Coder+Mode+works.\u0026amp;theme=2d0e9c637e1db3aa3847e8f6\u0026amp;signature=5efd8c58d482719c251864e843aa303791b9acd2908d7def0b4ec98505301e73\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Coder Mode Security (Governance) - ChatCLI\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Understand how the governance and permissions system of the Coder Mode works.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://encom.mintlify.app/_mintlify/api/og/v2?division=Coder\u0026amp;title=Coder+Mode+Security+%28Governance%29\u0026amp;description=Understand+how+the+governance+and+permissions+system+of+the+Coder+Mode+works.\u0026amp;theme=2d0e9c637e1db3aa3847e8f6\u0026amp;signature=5efd8c58d482719c251864e843aa303791b9acd2908d7def0b4ec98505301e73\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/encom/ilreks3OQttPbvib/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"ChatCLI\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#0F766E\">\u003clink data-mint-head rel=\"canonical\" href=\"https://chatcli.edilsonfreitas.com/coder/coder-security\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/coder/coder-security.md\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"en\" href=\"https://chatcli.edilsonfreitas.com/coder/coder-security\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"pt-BR\" href=\"https://chatcli.edilsonfreitas.com/pt/coder/coder-security\">\u003clink data-mint-head rel=\"alternate\" hreflang=\"x-default\" href=\"https://chatcli.edilsonfreitas.com/coder/coder-security\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://chatcli.edilsonfreitas.com/#organization\",\"name\":\"ChatCLI\",\"url\":\"https://chatcli.edilsonfreitas.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/encom/Rcdb5Pr5hpjwN46r/images/logo-light.svg?fit=max\u0026auto=format\u0026n=Rcdb5Pr5hpjwN46r\u0026q=85\u0026s=965a0feb9bd2f65a11b3c486e2488101\"}},{\"@type\":\"WebSite\",\"@id\":\"https://chatcli.edilsonfreitas.com#website\",\"name\":\"ChatCLI\",\"url\":\"https://chatcli.edilsonfreitas.com\",\"publisher\":{\"@id\":\"https://chatcli.edilsonfreitas.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://chatcli.edilsonfreitas.com/coder/coder-security#webpage\",\"url\":\"https://chatcli.edilsonfreitas.com/coder/coder-security\",\"name\":\"Coder Mode Security (Governance)\",\"description\":\"Understand how the governance and permissions system of the Coder Mode works.\",\"dateModified\":\"2026-10-24T14:09:17.523Z\",\"isPartOf\":{\"@id\":\"https://chatcli.edilsonfreitas.com#website\"},\"breadcrumb\":{\"@id\":\"https://chatcli.edilsonfreitas.com/coder/coder-security#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://chatcli.edilsonfreitas.com/coder/coder-security#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Documentation\",\"item\":\"https://chatcli.edilsonfreitas.com/usage/basic-usage\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Coder\",\"item\":\"https://chatcli.edilsonfreitas.com/coder/coder-plugin\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Coder Mode Security (Governance)\",\"item\":\"https://chatcli.edilsonfreitas.com/coder/coder-security\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://chatcli.edilsonfreitas.com/coder/coder-security#article\",\"headline\":\"Coder Mode Security (Governance)\",\"name\":\"Coder Mode Security (Governance)\",\"description\":\"Understand how the governance and permissions system of the Coder Mode works.\",\"url\":\"https://chatcli.edilsonfreitas.com/coder/coder-security\",\"mainEntityOfPage\":{\"@id\":\"https://chatcli.edilsonfreitas.com/coder/coder-security#webpage\"},\"dateModified\":\"2026-10-24T14:09:17.523Z\",\"publisher\":{\"@id\":\"https://chatcli.edilsonfreitas.com/#organization\"},\"isPartOf\":{\"@id\":\"https://chatcli.edilsonfreitas.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"ChatCLI\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"ChatCLI","nav":{"global":null,"languages":[{"language":"en","default":true,"groups":[{"group":"Get started","pages":[{"title":"ChatCLI","sidebarTitle":"Overview","icon":"house","mode":"wide","href":""},{"title":"Quickstart","icon":"rocket","href":"/start/quickstart"},{"title":"Installation and Configuration","sidebarTitle":"Installation","icon":"download","href":"/start/installation"},{"title":"Deploy with Docker and Kubernetes","sidebarTitle":"Docker \u0026 Kubernetes","icon":"docker","href":"/start/docker-deployment"},{"title":"Auto-Update","sidebarTitle":"Auto-Update","icon":"arrows-rotate","href":"/start/auto-update"},{"title":"Configuration Migration","sidebarTitle":"Config Migration","icon":"arrows-rotate","href":"/start/config-migration"}]},{"group":"Documentation","pages":[{"group":"Using ChatCLI","icon":"terminal","pages":[{"title":"Basic Usage and Main Commands","sidebarTitle":"Basic Usage","icon":"terminal","href":"/usage/basic-usage"},{"title":"Adding Context (@ Commands)","sidebarTitle":"Context Commands","icon":"at","href":"/usage/context-commands"},{"title":"Agent Mode: Task Execution","sidebarTitle":"Agent Mode (/agent)","icon":"robot","href":"/usage/agent-mode"},{"title":"Coder Mode (/coder)","sidebarTitle":"Coder Mode (/coder)","icon":"code","href":"/usage/coder-mode"},{"title":"Non-Interactive Mode (One-Shot)","sidebarTitle":"One-Shot Mode","icon":"terminal","href":"/usage/non-interactive-mode"},{"title":"Conversation Control","sidebarTitle":"Conversation Control","icon":"clock-rotate-left","href":"/usage/conversation-control"},{"title":"Multiline Input","sidebarTitle":"Multiline Input","icon":"bars-staggered","href":"/usage/multiline-input"},{"title":"Real-Time Streaming","sidebarTitle":"Streaming","icon":"bolt","href":"/usage/streaming"},{"title":"Image Input (Vision)","sidebarTitle":"Image Input (Vision)","icon":"eye","href":"/usage/vision-input"},{"title":"PDF Input","sidebarTitle":"PDF Input","icon":"file-pdf","href":"/usage/pdf-input"},{"title":"Web UI","sidebarTitle":"Web UI","icon":"browser","href":"/usage/web-ui"},{"title":"Live Dashboard","sidebarTitle":"Live Dashboard","icon":"chart-network","href":"/usage/live-dashboard"},{"title":"Compact UI Mode","sidebarTitle":"Compact UI","icon":"minimize","href":"/usage/compact-ui"},{"title":"Theme System (Colors)","sidebarTitle":"Theme System","icon":"palette","href":"/usage/ui-theme"},{"title":"Internationalization (i18n)","sidebarTitle":"Internationalization","icon":"language","href":"/usage/i18n"}]},{"group":"Coder","icon":"code","pages":[{"title":"Plugin @coder","sidebarTitle":"Plugin @coder","icon":"hammer","href":"/coder/coder-plugin"},{"title":"Atomic Tools (@read, @search, @tree, @todo)","sidebarTitle":"Atomic Tools","description":"Narrow builtin plugins with flat schema — parity with Claude Code's Read, Grep, TodoWrite. Parallelizable, JSON-Schema-validated, with per-tool truncation policy.","icon":"wand-magic-sparkles","href":"/coder/atomic-tools"},{"title":"Coder Mode Security (Governance)","sidebarTitle":"Coder Mode Security (Governance)","icon":"shield-halved","href":"/coder/coder-security"},{"title":"Enhanced Permissions System","sidebarTitle":"Permissions","description":"Multi-source policy resolution, denial tracking, safety immunity, and read-only command allowlist","icon":"shield-halved","href":"/coder/enhanced-permissions"},{"title":"Git Worktrees","sidebarTitle":"Git Worktrees","icon":"code-branch","href":"/coder/worktrees"},{"title":"File Staleness Detection","sidebarTitle":"File Staleness","icon":"eye","href":"/coder/file-staleness"},{"title":"JSON Recovery","sidebarTitle":"JSON Recovery","icon":"screwdriver-wrench","href":"/coder/json-recovery"},{"title":"LSP Diagnostics","sidebarTitle":"LSP Diagnostics","icon":"stethoscope","href":"/coder/lsp-diagnostics"},{"title":"Interactive Questions (ask_user)","sidebarTitle":"Interactive Questions","icon":"list-check","href":"/coder/interactive-ask"},{"title":"Live Agent Progress","sidebarTitle":"Live Progress","icon":"chart-bar","href":"/coder/agent-progress-ui"}]},{"group":"Agents","icon":"robot","pages":[{"title":"Native Tool Use (Structured API)","sidebarTitle":"Native Tool Use","icon":"wrench","href":"/agents/native-tool-use"},{"title":"Agentic AI and Plugin System","sidebarTitle":"Agentic AI \u0026 Plugins","icon":"puzzle-piece","href":"/agents/agentic-plugins"},{"title":"Customizable Agents (Personas)","sidebarTitle":"Customizable Agents","icon":"user-gear","href":"/agents/customizable-agents"},{"title":"Multi-Agent Orchestration","sidebarTitle":"Multi-Agent","icon":"users","href":"/agents/multi-agent-orchestration"},{"title":"Agent Squad","sidebarTitle":"Agent Squad","icon":"people-group","href":"/agents/agent-squad"},{"title":"Task Graph","sidebarTitle":"Task Graph","icon":"diagram-project","href":"/agents/task-graph"},{"title":"Subagent Delegation","sidebarTitle":"Subagent Delegate","icon":"diagram-project","href":"/agents/subagent-delegation"},{"title":"Mixture-of-Agents (MoA)","sidebarTitle":"Mixture-of-Agents","icon":"layer-group","href":"/agents/mixture-of-agents"},{"title":"Model Routing (@model)","sidebarTitle":"Model Routing","icon":"shuffle","href":"/agents/model-routing"},{"title":"Agent Park \u0026 Resume — Non-blocking suspension","sidebarTitle":"Park \u0026 Resume","icon":"circle-pause","href":"/agents/agent-park"},{"group":"Harness (7 patterns + evals)","icon":"wand-magic-sparkles","pages":[{"title":"Agent Harness/Quality Pipeline","sidebarTitle":"Overview","icon":"sparkles","href":"/agents/harness/overview"},{"title":"#1 ReAct — Reason + Act","sidebarTitle":"ReAct","icon":"rotate","href":"/agents/harness/react"},{"title":"#2 Plan-and-Solve / ReWOO","sidebarTitle":"Plan-and-Solve","icon":"list-check","href":"/agents/harness/plan-and-solve"},{"title":"#3 Reflexion — Learn from Failures","sidebarTitle":"Reflexion","icon":"lightbulb","href":"/agents/harness/reflexion"},{"title":"#4 RAG + HyDE — Semantic Retrieval","sidebarTitle":"RAG + HyDE","icon":"database","href":"/agents/harness/rag-hyde"},{"title":"#5 Self-Refine — Critique and Rewrite","sidebarTitle":"Self-Refine","icon":"wand-magic-sparkles","href":"/agents/harness/self-refine"},{"title":"#6 Chain-of-Verification (CoVe)","sidebarTitle":"CoVe","icon":"check-double","href":"/agents/harness/cove"},{"title":"#7 Cross-Provider Reasoning Backbone","sidebarTitle":"Reasoning Backbone","icon":"brain-circuit","href":"/agents/harness/reasoning-backbone"},{"title":"Configuration — Env, Slashes and /config","sidebarTitle":"Configuration","icon":"sliders","href":"/agents/harness/configuration"},{"title":"Evals: measuring ChatCLI","sidebarTitle":"Evals","icon":"flask","href":"/agents/harness/evals"}]}]},{"group":"Context \u0026 memory","icon":"layer-group","pages":[{"title":"LongMemEval: how well chatcli remembers","sidebarTitle":"LongMemEval results","icon":"chart-simple","href":"/context/longmemeval"},{"title":"Persistent Context Management","sidebarTitle":"Contexts (/context)","icon":"database","href":"/context/persistent-context"},{"title":"Knowledge Base (keyless RAG)","sidebarTitle":"Knowledge Base","icon":"book-open","href":"/context/knowledge-base"},{"title":"Bootstrap and Persistent Memory","sidebarTitle":"Bootstrap and Memory","icon":"memory","href":"/context/bootstrap-memory"},{"title":"Knowledge Graph and Obsidian Vault","sidebarTitle":"Knowledge Graph","icon":"diagram-project","href":"/context/knowledge-graph"},{"title":"Path-Specific Rules","sidebarTitle":"Path Rules","icon":"folder-tree","href":"/context/path-rules"},{"title":"Filtering with .chatignore","sidebarTitle":".chatignore","icon":"filter","href":"/context/chatignore"},{"group":"Sessions","icon":"clock-rotate-left","pages":[{"title":"Session Management","sidebarTitle":"Sessions","icon":"clock-rotate-left","href":"/context/session-management"},{"title":"Conversation Search (@session)","sidebarTitle":"Conversation Search","icon":"magnifying-glass","href":"/context/session-search"},{"title":"Session Workspace (Scratch Dir)","sidebarTitle":"Session Workspace","icon":"folder-tree","href":"/context/session-workspace"},{"title":"Trajectory Export (ShareGPT)","sidebarTitle":"Export Trajectory","icon":"file-export","href":"/context/trajectory-export"}]},{"group":"Token efficiency","icon":"gauge-high","pages":[{"title":"Token Efficiency","sidebarTitle":"Token Efficiency","icon":"gauge-high","href":"/context/token-efficiency"},{"title":"Context Compression (CCR)","sidebarTitle":"Context Compression","icon":"file-zipper","href":"/context/context-compression"},{"title":"Chat Prefix Curation","sidebarTitle":"Prefix Curation","icon":"scissors","href":"/context/prefix-curation"},{"title":"Tool Result Management","sidebarTitle":"Tool Results","icon":"database","href":"/context/tool-result-management"},{"title":"Context Recovery","sidebarTitle":"Context Recovery","icon":"life-ring","href":"/context/context-recovery"}]}]},{"group":"Models \u0026 providers","icon":"shuffle","pages":[{"title":"Supported AI Models","sidebarTitle":"Supported Models","icon":"microchip","href":"/providers/supported-models"},{"title":"OAuth Authentication","sidebarTitle":"OAuth Authentication","icon":"key","href":"/providers/oauth-authentication"},{"title":"AWS Bedrock","sidebarTitle":"AWS Bedrock","icon":"aws","href":"/providers/bedrock"},{"title":"Devin Provider — the local Devin CLI as an LLM transport","sidebarTitle":"Devin Provider","icon":"robot","href":"/providers/devin-provider"},{"title":"Provider Fallback","sidebarTitle":"Provider Fallback","icon":"rotate","href":"/providers/provider-fallback"},{"title":"Rate Limits — provider limit visibility","sidebarTitle":"Rate Limits","icon":"gauge-high","href":"/providers/rate-limits"},{"title":"Cost Tracking","sidebarTitle":"Cost Tracking","icon":"money-bill-trend-up","href":"/providers/cost-tracking"}]},{"group":"Tools","icon":"toolbox","pages":[{"title":"WebFetch \u0026 WebSearch","sidebarTitle":"Web Tools","icon":"globe","href":"/tools/web-tools"},{"title":"Browser Automation (@browser)","sidebarTitle":"Browser Automation","icon":"chrome","href":"/tools/browser-automation"},{"title":"API Explorer (@api-explorer)","sidebarTitle":"API Explorer","icon":"compass","href":"/tools/api-explorer"},{"title":"Git Forge (@forge)","sidebarTitle":"Git Forge","icon":"code-pull-request","href":"/tools/git-forge"},{"title":"Image Generation \u0026 Editing (@image)","sidebarTitle":"Image Generation \u0026 Editing","icon":"image","href":"/tools/image-generation"},{"title":"Diagrams (@diagram)","sidebarTitle":"Diagrams","icon":"diagram-project","href":"/tools/diagram"},{"title":"Interactive graph (@graphview)","sidebarTitle":"Interactive graph","icon":"circle-nodes","href":"/tools/graphview"},{"title":"Image Tags (@registry-tags)","sidebarTitle":"Registry Tags","icon":"tags","href":"/tools/registry-tags"},{"title":"Structured data and diffs (@json, @diff)","sidebarTitle":"JSON \u0026 Diff","icon":"brackets-curly","href":"/tools/json-diff"},{"title":"Calendar arithmetic (@date)","sidebarTitle":"Dates","icon":"calendar-days","href":"/tools/date"},{"title":"Archives (@archive)","sidebarTitle":"Archives","icon":"file-zipper","href":"/tools/archive"},{"title":"Builtin Skills","sidebarTitle":"Builtin Skills","icon":"boxes-stacked","href":"/tools/builtin-skills"},{"title":"Scheduler (Chronos) — Durable scheduling","sidebarTitle":"Scheduler","icon":"clock","href":"/tools/scheduler"}]},{"group":"Extensions","icon":"plug","pages":[{"title":"Plugin System","sidebarTitle":"Plugin System","icon":"plug","href":"/extensions/plugin-system"},{"title":"Provider Plugins","sidebarTitle":"Provider Plugins","icon":"plug-circle-bolt","href":"/extensions/provider-plugins"},{"title":"MCP (Model Context Protocol)","sidebarTitle":"Connect MCP Servers","icon":"link","href":"/extensions/mcp-integration"},{"title":"Skill Registry","sidebarTitle":"Skill Registry","icon":"store","tag":"NEW","href":"/extensions/skill-registry"},{"title":"Skill Authoring (@skill)","sidebarTitle":"Skill Authoring","icon":"wand-magic-sparkles","href":"/extensions/skill-authoring"},{"title":"Slash Commands","sidebarTitle":"Slash Commands","icon":"terminal","tag":"NEW","href":"/extensions/slash-commands"},{"title":"Hooks System","sidebarTitle":"Hooks","icon":"webhook","href":"/extensions/hooks-system"}]},{"group":"Channels \u0026 gateway","icon":"comments","pages":[{"title":"Chat gateway","sidebarTitle":"Chat gateway","icon":"messages","href":"/gateway/chat-gateway"},{"title":"Telegram","icon":"telegram","href":"/gateway/telegram"},{"title":"Slack","icon":"slack","href":"/gateway/slack"},{"title":"Discord","icon":"discord","href":"/gateway/discord"},{"title":"WhatsApp","icon":"whatsapp","href":"/gateway/whatsapp"},{"title":"Webhook","icon":"webhook","href":"/gateway/webhook"},{"title":"Conversation Hub — conversation continuity across channels","sidebarTitle":"Conversation Hub","icon":"share-nodes","href":"/gateway/conversation-hub"},{"title":"MCP Channels","sidebarTitle":"MCP Channels","icon":"tower-broadcast","href":"/gateway/mcp-channels"},{"title":"Proactive Messaging (@send)","sidebarTitle":"Proactive Messaging","icon":"paper-plane","href":"/gateway/proactive-messaging"},{"title":"Text-to-Speech \u0026 Gateway Voice","sidebarTitle":"Text-to-Speech","icon":"volume-high","href":"/gateway/text-to-speech"},{"title":"Gateway Voice Replies","sidebarTitle":"Voice Replies","icon":"microphone","href":"/gateway/voice-replies"}]},{"group":"Server \u0026 IDE","icon":"server","pages":[{"title":"Server Mode (chatcli server)","sidebarTitle":"Server Mode","icon":"server","href":"/server/server-mode"},{"title":"Remote Connection (chatcli connect)","sidebarTitle":"Remote Connection","icon":"plug","href":"/server/remote-connect"},{"title":"MCP Server — ChatCLI as a server (and ACP)","sidebarTitle":"ChatCLI MCP Server","icon":"server","href":"/server/mcp-server"},{"title":"ACP — ChatCLI inside your IDE","sidebarTitle":"ACP (IDE Agent)","icon":"plug-circle-bolt","href":"/server/acp"}]},{"group":"Kubernetes \u0026 AIOps","icon":"dharmachakra","pages":[{"title":"Kubernetes Monitoring (K8s Watcher)","sidebarTitle":"K8s Watcher","icon":"binoculars","href":"/kubernetes/k8s-watcher"},{"title":"Kubernetes Operator (AIOps)","sidebarTitle":"K8s Operator","icon":"dharmachakra","href":"/kubernetes/k8s-operator"},{"title":"AIOps Platform (Deep-Dive)","sidebarTitle":"AIOps Platform","icon":"brain","href":"/kubernetes/aiops-platform"},{"title":"ArtifactHub","sidebarTitle":"ArtifactHub","icon":"cube","href":"/kubernetes/artifacthub"},{"group":"AIOps platform","icon":"siren-on","pages":[{"title":"Incident Lifecycle","sidebarTitle":"Lifecycle","icon":"arrows-spin","href":"/kubernetes/aiops/incident-lifecycle"},{"title":"Notifications and Escalation","sidebarTitle":"Notifications","icon":"bell","href":"/kubernetes/aiops/notifications"},{"title":"SLOs and SLAs","sidebarTitle":"SLOs and SLAs","icon":"gauge-high","href":"/kubernetes/aiops/slo-sla"},{"title":"Approval Workflow","sidebarTitle":"Approvals","icon":"shield-check","href":"/kubernetes/aiops/approval-workflow"},{"title":"AI-Powered Decision Engine","sidebarTitle":"Decision Engine","icon":"brain-circuit","href":"/kubernetes/aiops/decision-engine"},{"title":"Multi-Cluster Federation","sidebarTitle":"Multi-Cluster Federation","icon":"network-wired","href":"/kubernetes/aiops/federation"},{"title":"Chaos Engineering","sidebarTitle":"Chaos Engineering","icon":"explosion","href":"/kubernetes/aiops/chaos-engineering"},{"title":"Audit and Compliance","sidebarTitle":"Audit and Compliance","icon":"clipboard-check","href":"/kubernetes/aiops/audit-compliance"},{"title":"Capacity Planning and Cost Attribution","sidebarTitle":"Capacity \u0026 Costs","icon":"chart-line","href":"/kubernetes/aiops/capacity-cost"},{"title":"Web Dashboard and Grafana","sidebarTitle":"Dashboard \u0026 Grafana","icon":"chart-mixed","href":"/kubernetes/aiops/web-dashboard"}]}]},{"group":"Security","icon":"shield-halved","pages":[{"title":"Enterprise Security","sidebarTitle":"Security","icon":"shield-halved","href":"/security/overview"},{"title":"Encryption at Rest","sidebarTitle":"Encryption at Rest","icon":"lock","href":"/security/encryption-at-rest"},{"title":"Security Hardening Upgrade Guide","sidebarTitle":"Hardening upgrade","icon":"shield-exclamation","href":"/security/hardening-upgrade"},{"title":"Vulnerability Scan (@osv)","sidebarTitle":"Dependency Scan","icon":"shield-halved","href":"/security/dependency-scan"},{"title":"Secrets Scan (@secrets)","sidebarTitle":"Secrets Scan","icon":"key","href":"/security/secrets-scan"}]},{"group":"Cookbook","icon":"kitchen-set","pages":[{"title":"Recipe: Safe Refactoring with Agent Mode","sidebarTitle":"Refactoring with Agent","icon":"screwdriver-wrench","href":"/cookbook/agent-refactoring"},{"title":"Fix tests with /coder","sidebarTitle":"Fix tests with /coder","icon":"vial","href":"/cookbook/coder-fix-tests"},{"title":"Recipe: Catching a Regression with Evals","sidebarTitle":"Catching a Regression with Evals","icon":"flask","href":"/cookbook/eval-regression"},{"title":"Recipe: Debugging Error Logs with Pipes","sidebarTitle":"Debug Error Logs","icon":"bug","href":"/cookbook/debugging-logs-with-pipes"},{"title":"One-Shot, Pipes, and Automation","sidebarTitle":"One-Shot and Pipes","icon":"wand-magic-sparkles","href":"/cookbook/oneshot-pipelines"},{"title":"Recipe: K8s Monitoring with AI","sidebarTitle":"K8s Monitoring","icon":"chart-line","href":"/cookbook/k8s-monitoring"},{"title":"Recipe: Managing Multiple Projects with Contexts and Sessions","sidebarTitle":"Multi-Project Workflow","icon":"folder-tree","href":"/cookbook/multi-project-workflow"},{"title":"Recipe: Understanding a Code Project","sidebarTitle":"Understand a New Project","icon":"rocket","href":"/cookbook/onboarding-new-project"},{"title":"Recipe: Generating Release Notes with @git","sidebarTitle":"Generate Release Notes","icon":"scroll","href":"/cookbook/release-notes-automation"},{"title":"Recipe: Remote Server for Teams","sidebarTitle":"Team Server","icon":"network-wired","href":"/cookbook/remote-server-setup"},{"title":"AIOps: Complete Production Setup","sidebarTitle":"AIOps Production Setup","icon":"rocket","href":"/cookbook/aiops-production-setup"},{"title":"Recipe: Scaling Instances","sidebarTitle":"Scaling Instances","icon":"arrows-left-right","href":"/cookbook/scaling-instances"},{"title":"AIOps: Incident Response Guide","sidebarTitle":"Incident Response","icon":"siren-on","href":"/cookbook/aiops-incident-response"},{"title":"Production Security Hardening","sidebarTitle":"Security Hardening","icon":"lock","href":"/cookbook/security-hardening-production"},{"title":"Scheduler automation recipes","sidebarTitle":"Scheduler: automations","icon":"book-open","href":"/cookbook/scheduler-automations"},{"title":"Recipe: Cross-Layer Debugging with 3 Knowledge Bases","sidebarTitle":"Cross-Layer Debugging","icon":"diagram-project","href":"/cookbook/cross-layer-knowledge-debug"}]},{"group":"Reference","icon":"rectangle-list","pages":[{"title":"Complete Command Reference","sidebarTitle":"Command Reference","icon":"rectangle-list","href":"/reference/command-reference"},{"title":"Environment Variables","sidebarTitle":"Environment Variables","icon":"sliders","href":"/reference/environment-variables"},{"title":"Configuration Reference (.env)","sidebarTitle":"Configuration (.env)","icon":"gear","href":"/reference/configuration"},{"title":"MCP Configuration (mcp_servers.json)","sidebarTitle":"MCP Config","icon":"gear","href":"/reference/mcp-config"},{"title":"Architecture and Code Structure","sidebarTitle":"Architecture","icon":"sitemap","href":"/reference/architecture"},{"group":"REST API","icon":"code","pages":[{"group":"Introduction","icon":"compass","pages":[{"title":"API Overview","sidebarTitle":"Overview","icon":"compass","href":"/reference/api/overview"}]},{"group":"Incidents","icon":"siren-on","pages":[{"title":"List Incidents","openapi":"GET /incidents","icon":"list","href":"/reference/api/list-incidents"},{"title":"Get Incident","openapi":"GET /incidents/{name}","icon":"magnifying-glass","href":"/reference/api/get-incident"},{"title":"Acknowledge Incident","openapi":"POST /incidents/{name}/acknowledge","icon":"check","href":"/reference/api/acknowledge-incident"},{"title":"Resolve Incident","openapi":"POST /incidents/{name}/resolve","icon":"circle-check","href":"/reference/api/resolve-incident"},{"title":"Snooze Incident","openapi":"POST /incidents/{name}/snooze","icon":"clock","href":"/reference/api/snooze-incident"},{"title":"Get Incident Timeline","openapi":"GET /incidents/{name}/timeline","icon":"timeline","href":"/reference/api/get-timeline"},{"title":"Get Incident Remediation","openapi":"GET /incidents/{name}/remediation","icon":"wrench","href":"/reference/api/get-remediation"}]},{"group":"AI Insights","icon":"lightbulb","pages":[{"title":"List AI Insights","openapi":"GET /aiinsights","icon":"list","href":"/reference/api/list-aiinsights"},{"title":"Get AI Insight","openapi":"GET /aiinsights/{name}","icon":"lightbulb","href":"/reference/api/get-aiinsight"}]},{"group":"Remediations","icon":"wrench","pages":[{"title":"List Remediations","openapi":"GET /remediations","icon":"list","href":"/reference/api/list-remediations"},{"title":"Get Remediation Plan","openapi":"GET /remediations/{name}","icon":"wrench","href":"/reference/api/get-remediation-detail"}]},{"group":"Runbooks","icon":"book-open","pages":[{"title":"List Runbooks","openapi":"GET /runbooks","icon":"list","href":"/reference/api/list-runbooks"},{"title":"Get Runbook","openapi":"GET /runbooks/{name}","icon":"book-open","href":"/reference/api/get-runbook"},{"title":"Create Runbook","openapi":"POST /runbooks","icon":"plus","href":"/reference/api/create-runbook"},{"title":"Update Runbook","openapi":"PUT /runbooks/{name}","icon":"pen-to-square","href":"/reference/api/update-runbook"},{"title":"Delete Runbook","openapi":"DELETE /runbooks/{name}","icon":"trash","href":"/reference/api/delete-runbook"}]},{"group":"Approvals","icon":"circle-check","pages":[{"title":"List Approvals","openapi":"GET /approvals","icon":"list","href":"/reference/api/list-approvals"},{"title":"Get Approval","openapi":"GET /approvals/{name}","icon":"magnifying-glass","href":"/reference/api/get-approval"},{"title":"Approve Request","openapi":"POST /approvals/{name}/approve","icon":"circle-check","href":"/reference/api/approve"},{"title":"Reject Request","openapi":"POST /approvals/{name}/reject","icon":"circle-xmark","href":"/reference/api/reject"}]},{"group":"SLOs","icon":"gauge","pages":[{"title":"List SLOs","openapi":"GET /slos","icon":"list","href":"/reference/api/list-slos"},{"title":"Get SLO","openapi":"GET /slos/{name}","icon":"gauge","href":"/reference/api/get-slo"},{"title":"Get SLO Error Budget","openapi":"GET /slos/{name}/budget","icon":"coins","href":"/reference/api/get-slo-budget"}]},{"group":"PostMortems","icon":"magnifying-glass-chart","pages":[{"title":"List PostMortems","openapi":"GET /postmortems","icon":"list","href":"/reference/api/list-postmortems"},{"title":"Get PostMortem","openapi":"GET /postmortems/{name}","icon":"magnifying-glass","href":"/reference/api/get-postmortem"},{"title":"Review PostMortem","openapi":"POST /postmortems/{name}/review","icon":"user-pen","href":"/reference/api/review-postmortem"},{"title":"Developer Feedback","openapi":"POST /postmortems/{name}/feedback","icon":"comment","href":"/reference/api/feedback-postmortem"},{"title":"Acknowledge Human Action","openapi":"POST /postmortems/{name}/ack-human-action","icon":"user-check","href":"/reference/api/ack-human-action-postmortem"},{"title":"Close PostMortem","openapi":"POST /postmortems/{name}/close","icon":"lock","href":"/reference/api/close-postmortem"}]},{"group":"Analytics","icon":"chart-line","pages":[{"title":"Analytics Summary","openapi":"GET /analytics/summary","icon":"chart-line","href":"/reference/api/analytics-summary"},{"title":"Analytics MTTR","openapi":"GET /analytics/mttr","icon":"stopwatch","href":"/reference/api/analytics-mttr"},{"title":"Analytics MTTD","openapi":"GET /analytics/mttd","icon":"stopwatch","href":"/reference/api/analytics-mttd"},{"title":"Analytics Trends","openapi":"GET /analytics/trends","icon":"arrow-trend-up","href":"/reference/api/analytics-trends"},{"title":"Analytics Top Resources","openapi":"GET /analytics/top-resources","icon":"ranking-star","href":"/reference/api/analytics-top-resources"},{"title":"Analytics Remediation Stats","openapi":"GET /analytics/remediation-stats","icon":"chart-pie","href":"/reference/api/analytics-remediation-stats"},{"title":"Analytics Compliance","openapi":"GET /analytics/compliance","icon":"clipboard-check","href":"/reference/api/analytics-compliance"},{"title":"Analytics Capacity","openapi":"GET /analytics/capacity","icon":"server","href":"/reference/api/analytics-capacity"},{"title":"Analytics Cost","openapi":"GET /analytics/cost","icon":"coins","href":"/reference/api/analytics-cost"}]},{"group":"Clusters","icon":"diagram-project","pages":[{"title":"List Clusters","openapi":"GET /clusters","icon":"list","href":"/reference/api/list-clusters"},{"title":"Get Cluster","openapi":"GET /clusters/{name}","icon":"diagram-project","href":"/reference/api/get-cluster"},{"title":"List Policies","openapi":"GET /policies/{kind}","icon":"list-check","href":"/reference/api/list-policies"},{"title":"Get Policy","openapi":"GET /policies/{kind}/{name}","icon":"file-lines","href":"/reference/api/get-policy"},{"title":"Global Cluster Status","openapi":"GET /clusters/global-status","icon":"globe","href":"/reference/api/global-status"}]},{"group":"Federation","icon":"network-wired","pages":[{"title":"Federation Status","openapi":"GET /federation/status","icon":"network-wired","href":"/reference/api/federation-status"},{"title":"Federation Clusters","openapi":"GET /federation/clusters","icon":"list","href":"/reference/api/federation-clusters"},{"title":"Federation Correlations","openapi":"GET /federation/correlations","icon":"diagram-project","href":"/reference/api/federation-correlations"}]},{"group":"Audit","icon":"clipboard-check","pages":[{"title":"List Audit Events","openapi":"GET /audit","icon":"list","href":"/reference/api/list-audit"},{"title":"Export Audit","openapi":"GET /audit/export","icon":"file-export","href":"/reference/api/export-audit"}]},{"group":"Health","icon":"heart-pulse","pages":[{"title":"Health Endpoints","openapi":"GET /healthz","icon":"heart-pulse","href":"/reference/api/health-endpoints"}]}]}]},{"group":"Releases","icon":"rocket","tag":"v1.226.0","pages":[{"title":"Release notes","icon":"tag","href":"/releases"},{"title":"v1.226.0","tag":"Latest","href":"/releases/1.226.0"},{"title":"v1.225.0","href":"/releases/1.225.0"},{"title":"v1.224.0","href":"/releases/1.224.0"},{"title":"v1.223.0","href":"/releases/1.223.0"},{"title":"v1.222.0","href":"/releases/1.222.0"},{"title":"v1.221.3","href":"/releases/1.221.3"},{"title":"v1.221.2","href":"/releases/1.221.2"},{"title":"v1.221.1","href":"/releases/1.221.1"},{"title":"v1.221.0","href":"/releases/1.221.0"},{"title":"v1.220.0","href":"/releases/1.220.0"}]},{"group":"Help","icon":"life-ring","pages":[{"title":"Troubleshooting","sidebarTitle":"Troubleshooting","icon":"life-ring","href":"/help/troubleshooting"},{"title":"Contributing to ChatCLI","sidebarTitle":"Contributing","icon":"code-pull-request","href":"/help/contributing"}]}]}]},{"language":"pt-BR","footer":{"socials":{"github":"https://github.com/diillson/chatcli","x":"https://x.com/diillson"},"links":[{"header":"Recursos","items":[{"label":"Documentação","href":"/pt"},{"label":"Cookbook","href":"/pt/cookbook/agent-refactoring"},{"label":"API Reference","href":"/pt/reference/api/overview"}]},{"header":"Comunidade","items":[{"label":"GitHub","href":"https://github.com/diillson/chatcli"},{"label":"Issues","href":"https://github.com/diillson/chatcli/issues"},{"label":"Discussions","href":"https://github.com/diillson/chatcli/discussions"},{"label":"Releases","href":"https://github.com/diillson/chatcli/releases"}]},{"header":"Distribuição","items":[{"label":"ArtifactHub","href":"https://artifacthub.io/packages/search?ts_query_web=chatcli"},{"label":"Helm Charts","href":"https://artifacthub.io/packages/helm/chatcli/chatcli"},{"label":"Container Registry","href":"https://github.com/diillson/chatcli/pkgs/container/chatcli"}]}]},"navbar":{"links":[{"href":"/pt/cookbook/agent-refactoring","label":"Cookbook"},{"href":"/pt/releases","label":"Releases"},{"href":"https://github.com/diillson/chatcli","type":"github"}],"primary":{"type":"button","label":"Instalar","href":"/pt/start/installation"}},"pages":[{"title":"pt-BR","href":"/pt/coder/coder-security"}]}]},"title":"Coder Mode Security (Governance) - ChatCLI","buildId":"dpl_849ArpqvBiCczQiT1Y1stNGpbqHT","deploymentId":"dpl_849ArpqvBiCczQiT1Y1stNGpbqHT","dynamics":[],"chunks":[]}