Your own rules
Three keys do most of the work. They go in~/.cortex/config.toml, or in a project .cortex/config.toml.
[sandbox_workspace_write] refines the default sandbox mode:
The permission table
[permission] sets policy per capability and per command. Every value is allow, ask or deny.
[permission.bash], a skill name under [permission.skill], a server name under [permission.mcp]. This is the surface to reach for when you want one dangerous command family blocked outright rather than approved case by case.
The same controls exist as flags for a single run, -a / --ask-for-approval, -s / --sandbox, --full-auto and --dangerously-bypass-approvals-and-sandbox, and as the slash commands /approval <ask|session|always|never>, /sandbox [on|off|network] and /auto [on|off] inside a session.
Project rules
A project.cortex/config.toml can carry approval_policy, sandbox_mode and the whole [permission] table, and it beats your own config. A repository can also commit .cortex/permissions.toml, a rules file the session loads and evaluates rather than merely displays: First matching rule wins; deny beats allow. /permissions rules shows how many allow, ask and deny rules are in effect, and answers No permission rules committed. Add .cortex/permissions.toml to pin allow / ask / deny. when there are none. And a repository can commit .cortex/sandbox.toml, which restricts network egress for runs in that repository, so every run and every CI job inherits the same restriction.
A hook is never consent
What a hook cannot do is stand in for your approval. A hook firing is not consent, and it does not remove the approval prompt that the policy above would otherwise raise. A hook cannot grant a permission either: every permission question starts at “ask”, a hook may answer “deny”, and a plugin that tries to answer “allow” is refused outright. Hooks are declared by a plugin, in that plugin’s manifest, rather than in a file of their own, and they do not fire around the tool calls an interactive session makes. The policy above is what gates a session. Hooks covers the events and which of them actually fire.If your organization pins settings
A managed policy is a separate mechanism from everything above. It is one directory, named byCORTEX_ORG_POLICY_DIR, holding one file, policy.json:
fast_mode and plugin_install. A missing document, or a document without a key, leaves that key on the host default. Two keys is the whole surface today.
Every key resolves fail-closed. A document that exists but cannot be read, cannot be parsed, or carries a value that is not recognized denies the restricted behavior. Policy failures never grant a permission.
When fast mode is disabled
A request to turn fast mode on is refused with this message, then a second line saying the session is staying where it is:Remote · Standard; the Fast chip appears only while fast mode is actually on.
When plugin installs require a review
Withplugin_install set to require an accepted command, installing or updating a plugin refuses until you have reviewed what it would run and passed the hash back:
The audit journal
Fail-closed decisions append one JSON object per line toaudit/events.jsonl in the Cortex home directory.
Records carry the plugin or source, the hashes, and the scope names. They never carry prompt text, file bodies, or secrets.
How an organization puts
policy.json on a machine is up to that organization, and there is no administration screen for it in the CLI. If you hit one of the refusals above and you do not manage the machine, the message is right: ask whoever does.