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.
| Tier | Example tools | Auto-approved? |
|---|---|---|
| Read | read_file, grep, git_log, web_search, memory_recall | Yes — always |
| Write | write_file, edit_file, git_commit, gh_pr_create, memory_write | No — pauses for approval |
| Exec | bash, run_tests | No — 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:
| Key | Action | When to use it |
|---|---|---|
a or y | Allow once — this call proceeds; the next call to the same tool prompts again | Most of the time |
A | Allow all — this call and all future calls to this tool in this session proceed without prompting | You’re in a long session and tired of approving the same tool repeatedly |
d, c, or n | Deny — the call is blocked; the agent gets a permission error and tries a different approach | You don’t like what’s about to happen |
Allow All is per-tool, not global. Pressing
Aforedit_fileapproves all futureedit_filecalls. It does not approvebash. 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.
| Key | Action |
|---|---|
a or y | Approve the write |
d | Deny the write |
The diff_review_mode config setting
This setting controls when the diff prompt appears. Set it in ~/.huginn/config.json.
| Value | Behavior | When to use it |
|---|---|---|
"always" | Show a diff before every write, even in auto-run mode | When you want maximum visibility |
"auto" | Show diffs during normal interactive use; skip them when auto-run is active | Default — good for most workflows |
"never" | Never show diffs; writes go straight through | Only 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:
| Button | Equivalent to |
|---|---|
| Approve | Allow once (a / y in TUI) |
| Always Approve | Allow all (A in TUI) |
| Deny | Deny (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:
| Button | What it does |
|---|---|
| Accept | Sets the artifact status to accepted |
| Reject | Sets the artifact status to rejected (you can add a reason; the agent can revise) |
| Download | Saves 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
| Situation | What to do |
|---|---|
| Normal interactive work | Use the defaults. Approve or deny each prompt as it appears. |
| Long refactor session, tired of repeated prompts | Press A on the tool you trust for the rest of the session |
| You want to see diffs even in auto-run | Set diff_review_mode: "always" in config |
| CI pipeline, no human present | Use --dangerously-skip-permissions inside an isolated container |
| Agent paused and appears stuck | Look for a pending approval card in the TUI or web UI |
| Repeated stale file errors | Another process may be editing the same file; the agent will re-read and retry automatically |