Permissions & Write Approval

Huginn shows you exactly what it’s about to change before it changes anything — reads run freely, writes stop and wait for your go-ahead.


The core idea

The agent can read files, search code, browse git history, and fetch URLs without interruption. All of that is safe. None of it destroys state.

The moment the agent wants to write a file, run a shell command, or create a commit, it stops and shows you what it’s about to do. You approve or reject before anything lands on disk.

This isn’t about slowing you down. It’s about making irreversible actions visible. One bad write can corrupt a file. One misguided bash call can do a lot more. The approval gate catches those before they happen.

Session approvals are in-memory only. If you approve a tool and then restart Huginn, the approval is gone. Each new process starts clean.


Three permission tiers

Every tool has a tier that reflects its maximum risk.

TierExample toolsAuto-approved?
Readread_file, grep, git_log, web_search, memory_recallYes — always
Writewrite_file, edit_file, git_commit, gh_pr_create, memory_writeNo — pauses for approval
Execbash, run_testsNo — pauses for approval

Read-only tools never show a prompt. Requiring approval for every grep would make the agent unusable — and reads can’t destroy anything.


The TUI approval prompt

When the agent tries a Write or Exec tool, the TUI pauses and shows a prompt. The prompt displays the tool name, its arguments, and a plain-English summary of what is about to happen.

You have four choices:

KeyActionWhen to use it
a or yAllow once — this call proceeds; the next call to the same tool prompts againMost of the time
AAllow all — this call and all future calls to this tool in this session proceed without promptingYou’re in a long session and tired of approving the same tool repeatedly
d, c, or nDeny — the call is blocked; the agent gets a permission error and tries a different approachYou don’t like what’s about to happen

Allow All is per-tool, not global. Pressing A for edit_file approves all future edit_file calls. It does not approve bash. Each tool tracks its own approval state independently.

If you don’t respond within 30 seconds, the call is denied automatically. The agent receives a timeout error and can try again.


What the write-approval diff looks like

When the agent wants to write or modify a file, you’re shown a write-approval prompt specific to that file. For a patch, it looks like this:

--- a/internal/auth/session.go
+++ b/internal/auth/session.go
@@ -42,6 +42,10 @@ func validateSession(ctx context.Context, id string) error {
        if id == "" {
                return errors.New("session id required")
        }
+
+       if len(id) > maxSessionIDLength {
+               return fmt.Errorf("session id exceeds max length %d", maxSessionIDLength)
+       }
+
        return store.Get(ctx, id)
 }

Lines prefixed with + are being added. Lines prefixed with - are being removed. Context lines (no prefix) show surrounding code so you know where the change lands.

KeyAction
a or yApprove the write
dDeny the write

The diff_review_mode config setting

This setting controls when the diff prompt appears. Set it in ~/.huginn/config.json.

ValueBehaviorWhen to use it
"always"Show a diff before every write, even in auto-run modeWhen you want maximum visibility
"auto"Show diffs during normal interactive use; skip them when auto-run is activeDefault — good for most workflows
"never"Never show diffs; writes go straight throughOnly if you’ve already reviewed the code and just want speed
{
  "diff_review_mode": "always"
}

Setting diff_review_mode: "always" means diffs appear even when auto-run mode is on. It’s the safest option when you want a hard guarantee that nothing writes without you seeing it.


Auto-run mode (Shift+Tab)

Press Shift+Tab in the TUI to toggle auto-run mode. The current state is shown in the footer.

When auto-run is on, all tool calls at any tier are approved automatically — the equivalent of pressing A for every tool at once.

Use auto-run when:

  • You trust the agent completely for the current task
  • You’re doing a long refactor and don’t want to approve every individual file edit
  • The diff review mode is set to "always" so you still see what’s being written

Auto-run is not persisted. Restarting Huginn turns it off.


--dangerously-skip-permissions

huginn --dangerously-skip-permissions

This flag bypasses all approval prompts for all tools. Reads, writes, and exec calls all go through without any user interaction.

Use this in CI pipelines, Docker containers, and automation environments where no human is present to respond to prompts. The container or CI environment itself is your safety boundary.

The word “dangerously” is intentional. An agent running with this flag can write to any file, run any shell command, and create commits with no checkpoint. Only use it when you’ve accepted that risk and the environment is isolated.

AllowAll vs this flag: Session-level AllowAll (the A key) approves a specific tool for the session. The flag approves everything. If you only want to skip prompts for bash but still review write_file, use AllowAll during the session instead of the flag.


Stale file protection

The agent reads a file, plans a change, then later tries to write it. What if you edited the file in your editor between those two steps?

Huginn captures a SHA-256 hash of the file at read time. When the agent goes to write, it re-checks the hash. If the file changed, the write is rejected with a stale file error.

The agent re-reads the file automatically and replans the change using the current content. If you see an agent pause and re-read a file it already looked at, this is usually why.

This prevents silent data loss. Without this check, your in-progress edits could be overwritten by a version based on stale state — and you might not notice until much later.


Web UI artifact cards

In the web UI, the same approval logic appears as inline cards in the chat area. When a tool call needs approval, a card shows the tool name, arguments, and a summary. Click one of three buttons:

ButtonEquivalent to
ApproveAllow once (a / y in TUI)
Always ApproveAllow all (A in TUI)
DenyDeny (d in TUI)

The chat stream resumes immediately after you click.

When an agent produces a structured artifact — a code patch, a generated document, a data export — it appears as a card with its own review controls:

ButtonWhat it does
AcceptSets the artifact status to accepted
RejectSets the artifact status to rejected (you can add a reason; the agent can revise)
DownloadSaves the artifact to your machine as a file

For code_patch artifacts, download and apply with:

git apply patch.diff

Headless mode and Routines

Routines run in headless sessions — no terminal, no user. The permission gate detects this and denies all Write and Exec calls by default. There is no prompt function registered, so non-read calls fail immediately.

Design Routines to use only Read-tier tools. A Routine that reads files, searches code, checks git history, and produces a report works perfectly. A Routine that writes files or runs commands will stall.

To run write-capable Routines unattended, start Huginn with --dangerously-skip-permissions in an isolated environment.


Quick reference

SituationWhat to do
Normal interactive workUse the defaults. Approve or deny each prompt as it appears.
Long refactor session, tired of repeated promptsPress A on the tool you trust for the rest of the session
You want to see diffs even in auto-runSet diff_review_mode: "always" in config
CI pipeline, no human presentUse --dangerously-skip-permissions inside an isolated container
Agent paused and appears stuckLook for a pending approval card in the TUI or web UI
Repeated stale file errorsAnother process may be editing the same file; the agent will re-read and retry automatically