Permission modes
Switch modes with the/permissions slash command or persistently
with /config permission_mode.
| Mode | Behavior |
|---|---|
dontAsk | Silent denial of tools not in the session-allowed set. No prompt. Default. |
default | Discord message with reaction buttons for each tool use. |
acceptEdits | File edits and filesystem commands (mkdir, touch, rm, mv, cp) auto-approved, others prompt. |
bypassPermissions | All tools auto-approved in the main session, no prompts. Background forks still use their own tool restrictions. |
Persistence
/permissions changes the mode for the current session only — it
resets to the default (dontAsk) on restart. Use /config permission_mode
to persist the mode across restarts.
Fork scoping
Permission modes are fork-scoped — changing the mode inside an interactive fork leaves the main session unchanged once the fork exits. Note thatdontAsk uses a module-level flag, so switching to or from
dontAsk in a fork temporarily affects the main session during the fork.
The original mode is restored when you exit the fork.
Approval flow
Indefault mode, unapproved tool use triggers an interactive approval
prompt in your Discord DM. (acceptEdits auto-approves file edits and
filesystem commands, and bypassPermissions approves everything in the
main session — neither triggers the approval flow below.)
Bot sends an approval message
A message appears in your DM showing the tool label
(name + arguments). Three emoji reactions are added automatically.
You react
React with one of the three emojis to respond:
| Reaction | Effect |
|---|---|
| ✅ | Allow — approve this single tool use |
| ❌ | Deny — reject this tool use |
| 🔓 | Always — approve and add the tool to the session-allowed set |
expired.
Session-allowed set
When you react with 🔓 (Always), the tool is added to a session-allowed set. Future uses of that tool are auto-approved without prompting — even indontAsk mode.
- The session-allowed set is shared across the main session and interactive forks.
/clearresets the session-allowed set (and cancels any pending approvals).- The set is in-memory only — it does not persist across bot restarts.
Background forks
Background forks always run withpermission_mode="default" —
regardless of your main session’s setting. Even if you’ve set
bypassPermissions or acceptEdits, background forks don’t inherit
that mode. This ensures tool gating and ping budget enforcement
are always active for background tasks.
Beyond permission mode, background forks have their own tool
restrictions based on the job’s YAML configuration:
- Ping tools (
ping_user,discord_embed) — allowed only whenallow-pingistruein the job’s YAML - Reporting tools (
report_updates,follow_up_chain) — allowed unlessupdate-main-sessionisblocked
allowed-tools list are denied. The
agent in a background fork cannot trigger approval prompts — see
Background forks for details.
Deny messages
The deny message varies by context so the agent understands why a tool was blocked:| Situation | Deny message |
|---|---|
| Background fork (pings disabled) | "pings disabled for this job" |
| Background fork (reporting blocked) | "reporting blocked for this job" |
| Background fork (other tools) | "{tool} is not available in background forks" |
dontAsk mode (not session-allowed) | "{tool} requires permission — denied silently in current mode" |
State directory write-protection
Thestate/ directory under ~/.ollim-bot/ contains infrastructure
files — session IDs, credentials, ping budget, and runtime config. These
files are managed by ollim-bot itself, not by the agent.
The agent can read files in state/ but cannot modify them. Any
write or edit attempt targeting state/ is automatically denied — this
applies in the main session, interactive forks, and background forks.
How write-protection works
How write-protection works
Protection is enforced at two layers:
- Tool hook — a pre-execution hook intercepts Write and Edit calls.
If the target path falls inside
state/, the call is denied with"state/ is write-protected". - Pattern validation — tool patterns are validated at startup and
dispatch time. Patterns that could match the
state/directory (likeEdit(**)) are rejected before the job runs.
Customizing tool sets
Both the main session and background forks start with hard-coded default tool sets. You can extend — or, for background forks, completely replace — those defaults by creating atool-policy.yaml
file in ~/.ollim-bot/.
The file is optional. When it doesn’t exist, the built-in defaults
apply. Changes take effect without a restart — the file is re-read
when its modification time changes.
Keys
| Key | Type | Effect |
|---|---|---|
main_session.additional_allowed | list[str] | Merged into the main session’s default tools. Duplicates are ignored. |
bg_forks.additional_allowed | list[str] | Merged into the default background fork tools. Duplicates are ignored. |
bg_forks.override | list[str] | Replaces the default background fork tools entirely. Takes precedence over additional_allowed. |
Example
A minimaltool-policy.yaml that adds git status to the main session and calendar access to background forks:
~/.ollim-bot/tool-policy.yaml
Agent-managed additions
When the agent creates a routine that needs tools beyond the defaults, it can either addallowed-tools to the routine’s YAML frontmatter
(scoped to that job) or append to bg_forks.additional_allowed in
tool-policy.yaml (applies to all background forks).
See File formats
for the full key reference.
Visual feedback
Inline labels during streaming show what the agent is doing — and what got blocked. WhendontAsk mode or an explicit rejection denies a tool, the label
shows with strikethrough text:
| Outcome | Rendering |
|---|---|
| Approved/executed | -# *Read(reminders/foo.md)* |
| Denied | -# *~~Read(reminders/foo.md)~~ — denied (use /permissions ask to approve)* |
| Errored | -# *~~Read(reminders/foo.md)~~ — error* |
dontAsk mode, the stream shows denied tools with strikethrough so
you see what the agent tried without receiving approval prompts.
In default mode, tools you reject via the ❌ reaction also appear
struck through. Tools that fail during execution also render with
strikethrough and an ” — error” suffix.
Cancellation
Pending approval prompts are automatically cancelled (treated as denials) when any of the following occur:- You use
/clear— resets the session-allowed set and cancels all pending approvals - You interrupt the agent — cancels pending approvals for the current turn
- You exit an interactive fork — cancels any approvals pending inside the fork
Examples
- dontAsk (default)
- default (interactive)
- bypassPermissions
In This is the default. The agent operates autonomously within its
allowed toolset without interrupting you for approvals.
dontAsk mode, any tool not in the session-allowed set is silently
denied — no message appears.Next steps
Slash commands
Full reference for all slash commands including
/permissions.Forks
How interactive and background forks interact with permission scoping.
Discord tools
Reference for all Discord tools the agent can use.
Background forks
Tool restrictions and allowed tool configuration for background forks.
