Permissions & policy
Every action the agent takes (read a file, write one, run a shell command, hit the network, call an MCP tool) is checked against a policy before it runs. The policy is deny-first: the order is critical denies → your config rules → the active mode’s default. Nothing ambiguous is ever silently allowed.
A mode sets the baseline posture. Pick one with --policy-mode <mode>, or policy.mode in tsforge.config.json (the flag wins). Plan mode (--plan / /plan) overrides to plan while it’s on.
| Mode | Writes | Shell | Network | Delete | Use it for |
|---|---|---|---|---|---|
default | allow | allow | allow | deny | Interactive day-to-day (the default). |
plan | deny | read-only | allow | deny | Read-only exploration before you approve a plan. |
acceptEdits | allow | ask | deny | deny | Auto-accept edits, but still confirm shell. |
ci | allow | deny | deny | deny | Non-interactive pipelines; anything that would prompt is denied. |
dontAsk | allow | deny | deny | deny | A local “never prompt me” run (identical to ci). |
bypassPermissions | allow | allow | allow | allow | The escape hatch: allow everything (critical denies still apply). |
In plan mode the run tool is allowed through but its own read-only guard restricts it to read-only commands, so exploration can’t mutate. delete is denied in every mode except bypassPermissions. Anything that would otherwise ask collapses to deny when there’s no interactive approval path (non-interactive runs).
Config rules
Section titled “Config rules”Refine a mode with deny / allow / ask lists under policy.rules. They’re evaluated before the mode default, in that order (deny wins over allow wins over ask):
{ "policy": { "mode": "default", "rules": { "deny": [{ "kind": "shell", "commandPrefix": "rm " }], "allow": [{ "kind": "network" }], "ask": [{ "kind": "delete_file", "pathPattern": "src/**" }] } }}A rule matches when every field it specifies matches the action (an empty rule matches everything as a deliberate catch-all). Available fields: kind, toolName, pathPattern (glob), commandPrefix, commandPattern (regex), mcpServer. Action kinds are read_file, write_file, edit_file, delete_file, shell, network, mcp_tool, plugin_tool, unknown.
Critical denies (always win)
Section titled “Critical denies (always win)”These fire in every mode, including bypassPermissions. They have no safe override:
- Destructive shell: commands like
rm -rf /are blocked. - Private-key reads: reading an SSH/PEM private-key path is blocked.
- Unregistered MCP servers: an
mcp__*call to a server not in your config is blocked.
The run ledger
Section titled “The run ledger”With --log, tsforge records every tool call, its policy decision (allow / ask / deny, with the matched rule and a risk level), the model’s reasoning, and each gate verdict as JSONL under ~/.tsforge/logs/. tsforge trace turns that ledger into a one-screen summary. Deterministically, with no model call, you can audit exactly what ran and why.