Skip to main content
Every tool call passes a gate before it runs, on every OS. The gate is the base safety layer, and nothing else in seri reaches around it.

Modes

/mode takes no argument and cycles read-only to approve-each to auto and back around. Shift-Tab does the same without typing. There is no /mode auto form, and typing one is a command error rather than a mode change. The current mode is shown in the session. approve-each is the default, not read-only, and that was a measured decision rather than a preference. A fresh session defaulting to read-only and given a write task was blocked repeatedly and produced nothing: five denials, then a turn that ended with no tool call and no file created. What keeps approve-each from being an every-call prompt is the remembered approval below. A task that needs to write in read-only reports the block rather than failing the run, and the run still exits successfully. Cycle out of it and ask again.

What counts as a write

The classification is per tool, and it is deliberately asymmetric. A name the gate does not recognise is treated as a write. That direction is the point. MCP opens the tool set to third parties, so “absent from the write list” stops being evidence of safety. An unfamiliar tool costs you an approval instead of being waved through in all three modes. Two names are exceptions, and neither writes. dispatch_subagents hands the child the parent’s own permission mode, so a subagent’s bash re-enters this same gate at the same mode rather than escaping it. skill reads one file you put in .seri/skills/ yourself. See Tools for what each one does.

Remembering an answer

An approval prompt can remember your answer. “Always” is narrower than it sounds, in two directions at once. It is scoped to that one tool, and to the project you granted it in. Grants live in permissions.yaml in your profile root, in two tiers. Answering “always” only ever writes the project tier. Nothing in seri promotes a grant to global:, so an approval you gave in one repository does not follow you into the next one. The project is keyed on the resolved worktree path, case-folded on Windows and macOS, where the same directory routinely has two spellings. Only three kinds of grant can persist at all, and the list is closed. bash and powershell cannot be approved permanently at all. A grant keyed on a tool name says nothing about what a shell command will do, so an entry reading bash would hand over the shell for good. seri refuses such an entry on read as well as on write, so hand-editing one into the file does not work either. An MCP grant is stored as mcp_<server>_<tool>@<digest>. The digest fingerprints that tool’s name, description and input schema at the moment you approved it, because a server is a third party and those three together are the whole contract you were shown. Change the tool on the server’s end and the digest stops matching, so seri asks again rather than trusting your old answer about a tool you never actually saw.

Reviewing what you granted

/permissions lists the write_file and edit grants in effect for the project you are in, and labels each one by the tier it came from. A tool with no grant in either tier is left out rather than shown as a third state, and grants belonging to other projects are not listed.
An MCP grant does not appear in /permissions. The prompt offers “always” for an MCP tool and the store accepts it, but the panel only ever renders the two built-in names, so a permanent MCP approval can be made and then neither seen nor revoked there. Edit permissions.yaml in your profile root to remove one.

Skipping the gate

--dangerously-skip-permissions runs every tool with no prompt for the whole process. Cycling to auto is the same idea inside the session, with a keystroke to get back out of it.
Both are for attended, high-trust work. Neither is a default, and neither is remembered for you.

What the gate cannot override

A PreToolUse hook runs before the gate. A hook that blocks a call blocks it in every mode, auto and --dangerously-skip-permissions included, and you are never asked to approve a call a hook is about to refuse. See Hooks.