Skip to main content
Browse the documentation

Permissions and safety

Changing the rules

Turn a hard block into a prompt, grant an exception for a session or forever, and see what is currently granted — without disarming the built-in guards.

The defaults are strict because the wrong default is expensive. When they are too strict for what you actually do, here is how to move them.

See what is granted right now

> /permissions          # active grants — list and revoke
snaga permissions       # the long-term policy file and the audit log

The slash command shows grants held in memory for this session; the CLI subcommand shows the persistent policy and what has been decided over time.

Turn hard blocks into prompts

By default a privileged command — sudo, and its kin — is blocked outright. To be asked instead of refused, opt in through .snaga/trust.toml:

[shell]
enable_escalation = true

Now a privileged match produces an interactive consent prompt rather than a block. self_destructive patterns are not affected: a fork bomb is still blocked with escalation on. The setting moves one class, not both.

Answering a prompt

The prompt offers a scope, and the scope decides how long your answer lasts:

AnswerLasts
Oncethis command only
Sessionuntil you quit
Projectsaved for this project
Usersaved for you, everywhere
Nodenied

Project and User write the approved pattern into the policy file, preserving the comments already in it. Session keeps it in memory only.

Your rules are added on top of the built-ins, not instead of them

This is the part worth reading twice, because the intuitive assumption is wrong and the wrong assumption is dangerous.

Writing your own rules does not replace the default rule set. Your rules are placed ahead of the defaults — first match wins, so yours take priority — and every default that does not collide with one of yours is kept.

So this, on its own:

[[rule]]
pattern = "cargo build"
class = "safe"

...allows cargo build --release, and leaves sudo gated and a fork bomb hard-blocked. Before rules were merged this way, that single entry would have replaced the entire default set — one line of convenience silently disarming every guard.

The property is pinned by a test named for it, user_rules_do_not_disarm_default_guards, which asserts all three outcomes together: the custom rule allows what it names, the fork bomb is still blocked, and sudo is still gated.

Deliberate overrides still work. Declaring the same pattern as a default replaces it — your classification wins and the duplicate is dropped. Declaring a broader one that downgrades a guard is honoured too, because it is an explicit choice on your own machine. What is prevented is the accidental case, not the intentional one.

How a decision is reached

In order:

  1. An operator-approved prefix from a previous "Project" or "User" answer → allow.
  2. The first rule whose pattern appears in the command:
    • safe → allow;
    • self_destructive → block;
    • privileged → block when escalation is off; resolve against the non-interactive default when there is nobody to ask; otherwise prompt.
  3. No rule matched → allow.

Step 1 short-circuits, which is why a persistent allow you granted earlier does not have to fight the rule set every time — and why it is worth granting at the narrowest scope that works.

The design position behind all of this

Snaga's stated contract is that users own their systems and accept the risks on them. That is why a broad override on your own machine is honoured rather than second-guessed. The guards exist to stop accidents and to make dangerous things visible — not to overrule you about your own computer.