Beta — for evaluation and testing only. AIGuard is a guardrail, not a security boundary. Read the risk disclosures

Architecture

A local, file-based system with no network component. All state lives in ~/.aiguard/.

System overview

The assistant's PreToolUse hook pipes each command, as JSON on stdin, to aiguard-evaluate. The policy engine returns a Decision; the exit code tells the assistant whether to run the command.

┌─────────────────┐   PreToolUse hook (JSON on stdin)
│  AI assistant   │──────────────────────────────┐
│ (Kimi / Claude) │                              ▼
└─────────────────┘                    ┌───────────────────┐
        ▲                              │ aiguard-evaluate  │
        │ exit 0: run                  └─────────┬─────────┘
        │ exit 2: blocked,                       │ Decision
        │   relay challenge token                ▼
        ▼                              ┌───────────────────┐
┌─────────────────┐  approve <token>   │  policy engine    │
│  user terminal  │───────────────────▶│ allow / ask /     │
│  aiguard approve│                    │ block (+ risk)    │
└─────────────────┘                    └───────────────────┘
   Touch ID (macOS) / TOTP (Linux)           │
                                             ▼
                        ~/.aiguard/: challenges/  approved/  audit.jsonl

The Decision contract

FieldValuesMeaning
action allow ask block What happens to the command
risk low medium high critical Informational severity — never changes the action on its own
warningstring Plain-English explanation of what the command does

Evaluation flow

  1. Prune expired challenges and approvals (opportunistic GC).
  2. Parse the hook payload (tool_input.command) from stdin.
  3. The policy engine returns a Decision.
  4. allow → audit, exit 0. block → audit, exit 2 with the warning.
  5. ask → if a matching approval exists for the exact command hash, consume it (single-use), audit, exit 0. Otherwise create a challenge file, audit, exit 2 with AIGUARD_CHALLENGE:<token> on stderr.
  6. Any internal error → exit 2. AIGuard fails closed.

But the platforms fail open

Per Kimi Code CLI and Claude Code documentation, a hook that times out or crashes allows the command to run. AIGuard cannot be a hard gate — do not use it as your sole security barrier.

Policy engine: order of evaluation

First match wins:

  1. Absolute Block — recursive+force delete of protected targets (/, ~, $HOME, …) and any write/delete/cp/mv/ln into ~/.aiguard/. Cannot be overridden by anything.
  2. User Policy — your block, ask, allow regex patterns in ~/.aiguard/policy.toml.
  3. Built-in high-risk patterns — curl|bash, sudo, dd of=/dev/, git push --force, … → ask.
  4. Shell metacharacters (;|&<>`$() and newlines) → ask.
  5. Safe prefixes (ls, pwd, git status, …) → allow.
  6. Default → ask.

An example user policy:

block = ["npm publish", "kubectl delete"]
ask = ["^docker "]
allow = ["^make test$"]

User policy can restrict, never unblock

Your rules can add restrictions and widen auto-allow, but no user rule — and no approval — can override an Absolute Block.

Challenge & approval flow

TOTP

RFC 6238, SHA-1, 6 digits, 30-second period, verification window ±1 step. Three failed verification attempts trigger a 5-minute lockout. Secrets live in the system keyring where available, with a 0600-file fallback (~/.aiguard/totp-secret) on headless systems.

State layout

PathModeContents
~/.aiguard/0700 All AIGuard state
challenges/, approved/0600 files Pending challenges and single-use approvals
audit.jsonl0600 Append-only log of every command, verbatim
policy.toml— Your user policy
totp-secret0600 TOTP fallback when no keyring is available

Do not weaken these permissions

The 0700/0600 modes are part of the security model. The audit log may contain secrets passed as CLI arguments — handle it as sensitive.

Design records

Significant decisions are recorded as ADRs in the repository (docs/adr/) — including PreToolUse hooks over native instrumentation and out-of-band challenge-response. The vocabulary used here (Decision, Action, Absolute Block, Challenge, Approval, Fail-Open) is defined in the repository's GLOSSARY.md.