Getting Started

INTRO­DUCTION

Guardrail is a local-first control layer for trusted CLI and agent-assisted automation. It records an execution boundary, reuses it while unchanged, and stops drift before process spawn.

⬡
What Guardrail is
An execution-contract layer for commands, workflows, templates, recipes, resident lanes, and delegated MCP tools. A matching acknowledged manifest can be reused; a changed contract requires review.

THE PROBLEM

You approve npm test. A later automation run adds --silent. Nobody reviewed the extra argument. The command surface changed, and ordinary shell execution would not tell you that the approved contract no longer matches.

This is scope drift. It happens in build scripts, CI pipelines, AI-assisted workflows, and iterative repair loops. It's rarely malicious. It's almost always invisible.

terminal — drift blocked
# what the agent tried to run guardrail run --non-interactive --approved-manifest .guardrail/approved.json -- npm test --silent # guardrail output ▶ Execution paused. Drift detected. approved args: ["test"] current args: ["test", "--silent"] DRIFT Exit 12. Re-run with explicit approval to widen scope.

WHAT GUARDRAIL IS NOT

  • Not a sandbox. It does not isolate processes or restrict syscalls.
  • Not a container replacement. It does not limit filesystem or network access.
  • Not safe for untrusted binaries. It verifies what runs, not what it does once running.
  • Not a security boundary. It's a contract layer. The host environment handles containment.

HOW IT WORKS IN 30 SECONDS

1
Build the contract
Normalize the command, arguments, paths, environment policy, and other bound execution fields.
2
Review
The first interactive run shows the candidate contract and risk. Type APPROVE to acknowledge it.
3
Reuse or stop
An exact contract match runs. Any manifest difference is drift; non-interactive drift exits 12.
Getting Started

INSTALL­ATION

Guardrail 1.0.0 requires Node.js 20 or newer. Until a verified package name is published, install from the source checkout.

SOURCE INSTALL

bash
git clone https://github.com/justguy/guardrail.git cd guardrail npm install npm link

Verify the install:

bash
guardrail --version 1.0.0

WITHOUT LINKING

bash — from the checkout
node src/cli.js --help node src/cli.js run -- npm test
⚠
Package-name check
The public npm package currently named guardrail is unrelated. Do not use npm install -g guardrail until this project publishes a verified distribution name.

SYSTEM REQUIREMENTS

PlatformStatusNotes
RuntimeNode.js 20+Uses ESM and Node's built-in test/runtime APIs.
Interactive approvalReal TTYThe first run prompts for the literal word APPROVE.
CINon-interactivePass an acknowledged manifest explicitly; missing or changed state fails closed.
Getting Started

QUICK START

Run one command interactively, acknowledge its contract, then reuse that exact manifest in CI.

YOUR FIRST APPROVED COMMAND

Step 1 — Run and review

bash — interactive TTY
guardrail run -- npm test Review the candidate contract and risk assessment. Type APPROVE to continue: APPROVE ✓ Acknowledged manifest stored. Executing.

Step 2 — Reuse the acknowledged manifest in CI

bash — non-interactive
guardrail run \ --non-interactive \ --approved-manifest .guardrail/approved.json \ -- npm test

Step 3 — Watch drift get caught

bash
guardrail run -- npm test --silent ✕ Drift detected. Exit 12. Changes from approved manifest: + args[1]: --silent BLOCKED — not in approved scope Re-run interactively to review and acknowledge the changed contract.
✓
You're set
That's the core loop. Normalize → Approve → Enforce. Everything else in Guardrail is built on top of this.
Getting Started

CORE CONCEPTS

Five things to understand before everything else clicks.

THE MANIFEST

A manifest is the stored record of an acknowledged contract. It contains the normalized contract, contract hash, project root, risk assessment, acknowledgement fields, and workflow settings.

Command manifests use .guardrail/approved.json by default. Decide deliberately whether to version-control them; they include absolute project context and are not a cryptographic identity signature.

THE CONTRACT FIELDS

The contract is structured data: command, args, working directory, mode, readable/writable paths, environment policy, child-process policy, network policy, timeout, retry policy, and update policy. The hash binds those normalized fields.

RISK CLASSIFICATION

Every command gets a risk level computed by the engine:

● GREEN — read-only, local ● YELLOW — local writes or installs ● RED — system, production, destructive, or elevated

Risk is computed from the contract and provenance. RED requires strong confirmation; all interactive approvals currently require typing APPROVE.

TRUST CLASSES

ClassMeaning
reviewed_internalFirst-party, committed to version control, manually reviewed
pinned_externalExternal source, pinned to an immutable commit SHA
generatedProduced by an LLM, script, or automated process
unknownProvenance cannot be determined
⚠
Generated and unknown sources
generated and unknown trust classes evaluate to RED. Reviewed or hash-pinned provenance is required before a contract can qualify for GREEN.

FAIL CLOSED

When an approved contract is required but missing, changed, or unreadable, Guardrail does not silently execute. Non-interactive mode returns a distinct failure status instead of prompting or guessing.

The Engine

MANIFESTS

The locally stored record of the contract and risk you acknowledged.

MANIFEST STRUCTURE

.guardrail/approved.json
{ "version": 1, "tool": "guardrail", "approvedAt": "2026-08-24T14:01:22Z", "projectRoot": "/absolute/path/to/project", "contractHash": "a3f9c12e...", "contract": { "command": "npm", "args": ["test"], "mode": "structured", "cwd": "/absolute/path/to/project", "envPolicy": { "inherit": false, "allow": ["PATH"] } }, "riskAssessment": { "trustClass": "reviewed_internal", "riskLevel": "green", "requiresStrongConfirmation": false, "acknowledgedBy": "interactive_user" }, "workflow": { "validator": "exit_code", "updateSource": "none" } }

MANIFEST PATHS

TypeDefault path
Command manifest.guardrail/approved.json
Workflow manifest.guardrail/workflows/default.approved.json
Audit log.guardrail/audit.jsonl (repo-local by default)
⚠
Manifest isolation
A command manifest does not also approve a workflow, and a workflow manifest does not implicitly approve ad hoc commands. Each manifest path stores exactly one approval unit.
The Engine

RISK CLASSIFI­CATION

Computed by the engine. Never trusted from the manifest alone.

THE THREE LEVELS

LevelTriggersExamples
GREENReviewed or pinned source, structured argv, safe binaries, local/temp writes, no env inheritance, and no destructive traitsBounded local checks and status commands
YELLOWFallback when work is not RED but misses at least one GREEN conditionPackage installs, scoped local writes, or shell mode without RED traits
REDGenerated/unknown source, production/system targets, outside-repo writes, sudo/admin commands, or destructive system-path workProduction deploys, system mutation, database/cloud administration

RED ESCALATION TRIGGERS

  • generated or unknown workflow provenance
  • System paths, production-like targets, or writes outside the project boundary
  • Elevated privileges, admin binaries, or database administration
  • Destructive behavior aimed at system paths
  • Secret-shaped env var with a production-like target
  • Shell mode combined with install, download, or destructive behavior
🔴
RED requires strong confirmation
RED sets requiresStrongConfirmation. In interactive mode, the operator must type APPROVE; delegated tools cannot self-approve through normal arguments.
The Engine

DRIFT DETECTION

Every execution is re-hashed and compared against the approved manifest. No silent pass-through.

WHAT COUNTS AS DRIFT

ChangeResultSelf-resolvable
New flag addedBLOCKED — Exit 12No
New env var accessedBLOCKED — Exit 12No
Binary name changedBLOCKED — Exit 12No
New target or hostBLOCKED — Exit 12No
Mode changed to shellBLOCKED — Exit 12No
Risk escalationBLOCKED — human requiredNo
Argument removedDRIFT — Exit 12No
Exact normalized contractALLOWEDN/A

STRUCTURED DRIFT OUTPUT

bash — CI-safe JSON
guardrail run \ --json \ --non-interactive \ --approved-manifest .guardrail/approved.json \ -- npm test --silent # status: drift_detected · exitCode: 12 # drift.diffs contains the changed manifest fields
The Engine

APPROVAL FLOW

Interactive acknowledgement, reusable manifests, and a fail-closed delegated approval path.

INTERACTIVE COMMANDS

The first guardrail run shows the candidate contract and risk in a real TTY. Typing APPROVE acknowledges and stores the manifest. Exact later runs can reuse it; changed bound fields require a fresh review.

PENDING DELEGATED REQUESTS

bash — compatibility queue
guardrail approve list guardrail approve <request-id>

These commands handle queued MCP approval requests. They do not approve an arbitrary command line or attach a signature to a manifest.

MCP HOST APPROVAL

Unpinned delegated recipe/template runs require MCP host form elicitation or an already approved approval_request_id. Hosts without elicitation support return host_approval_unavailable. Normal tool arguments cannot self-approve.

REPLACING AN APPROVAL

There is no generic revoke command. To change command scope, run the desired contract interactively and acknowledge the replacement manifest, or use a different explicit manifest path.

Workflows

WORKFLOW DEFINITIONS

Multi-step execution contracts with explicit transitions, validators, and a bounded iteration count.

FORMAT

workflows/deploy-staging.json
{ "version": 1, "kind": "workflow_definition", "name": "test-and-build", "projectRoot": ".", "entryStep": "test", "maxIterations": 2, "services": [], "steps": [ { "id": "test", "type": "task", "run": { "command": "npm", "args": ["test"], "cwd": ".", "mode": "structured", "envPolicy": { "inherit": true } }, "validator": "exit_code", "on": { "success": "build", "validation_failed": "abort" } }, { "id": "build", "type": "task", "run": { "command": "npm", "args": ["run", "build"], "cwd": ".", "mode": "structured", "envPolicy": { "inherit": true } }, "validator": "exit_code", "on": { "success": "done", "validation_failed": "abort" } } ] }

LINT BEFORE APPROVING

bash
guardrail workflow lint --definition workflows/deploy-staging.json ✓ No issues found.
⬡
Run after linting
guardrail workflow run --definition workflows/deploy-staging.json reviews and stores a workflow-specific approved manifest before execution.
Reference

EXIT CODES

Every Guardrail exit is deterministic and machine-readable.

0
Success — command ran and all validators passed
10
Approval required — no reusable approved contract is available
11
Denied — the requested approval was declined
12
Drift detected — proposed execution does not match approved manifest
13
Validation failed — the command ran but its validator did not pass
14
Update denied
15
Timeout
16
Policy violation
17
Unsupported operation
18
Protocol error
19
Internal error
20
Time policy violated
21
Concurrent execution blocked
22
Audit chain broken

USING EXIT CODES IN CI

.github/workflows/guardrail.yml
- name: Run with Guardrail run: | guardrail run \ --non-interactive \ --approved-manifest .guardrail/approved.json \ -- npm test # Exit 12 = drift = build failure. No special handling needed.
Integrations

CI / GITHUB ACTIONS

Create the approved manifest interactively, then reuse that exact contract non-interactively in CI.

THE CI PATTERN

1
Approve locally
Run the command in an interactive terminal, inspect the contract, and type APPROVE.
2
Handle the manifest deliberately
If your policy allows it, version the manifest with the code that consumes it. It can contain absolute project context.
3
Run non-interactively
The CI job cannot prompt. Approval, drift, validation, and policy failures remain distinct non-zero exit codes.

GITHUB ACTIONS EXAMPLE

.github/workflows/guardrail.yml
name: Guardrail CI on: [push, pull_request] jobs: guardrail: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Use Node.js 20 uses: actions/setup-node@v4 with: node-version: 20 - name: Install this source checkout run: npm install && npm link - name: Lint workflow definitions run: | for f in workflows/*.json; do guardrail workflow lint --definition "$f" || exit 1 done - name: Run tests (contract-locked) run: | guardrail run \ --non-interactive \ --approved-manifest .guardrail/approved.json \ -- npm test - name: JSON output for structured logging run: | guardrail run \ --json \ --non-interactive \ --approved-manifest .guardrail/approved.json \ -- npm test
⬡
Exit codes are build signals
Exit 10 means approval is required, 12 means drift, 13 means validation failed, and 16 means a policy violation. Each fails the job without an interactive bypass.
Integrations

OPENCLAW RECIPES

Run the bundled, fixed OpenClaw workflows through the same contract review and drift checks as other recipes.

⚠
Integration boundary
These recipes wrap the repository's fixed OpenClaw flows. Guardrail does not claim to intercept every OpenClaw shell call or replace operating-system sandboxing.

RUN A BUNDLED FLOW

bash
guardrail run --recipe openclaw-fix-tests --dry-run guardrail run --recipe openclaw-debug-ci --dry-run

WHAT CHANGES

Without GuardrailWith Guardrail adapter
Ad hoc commandNamed recipe with an inspectable manifest
Implicit working scopeDeclared read/write paths and environment policy
Silent recipe changeContract drift and a new review
Unstructured historyRepo-local structured audit events

OPENCLAW RECIPES

The bundled catalog currently includes:

openclaw-fix-tests openclaw-debug-ci openclaw-deploy openclaw-wrapper
Security

INVARIANTS

The behavioral boundaries implemented by the current local-first runtime.

CURRENT GUARANTEES

I-1 — Explicit approval records

An interactive command run stores the normalized contract and its hash after the operator types APPROVE. A manifest is an acknowledgement record, not a cryptographic identity signature.

I-2 — Risk-aware confirmation

Generated or unknown provenance, system paths, production targets, destructive operations, and sensitive combinations can raise a contract to RED and require strong interactive confirmation.

I-3 — State Machine Default-Deny

A failed validation must not result in a success state. validation_failed → done is fatally rejected at lint time. Steps default to idempotent: false.

I-4 — Normalized paths

Working, readable, and writable paths are resolved into normalized absolute contract fields before hashing and comparison.

I-5 — Bounded workflow execution

Workflow definitions declare an entry step, transitions, validators, and a positive maxIterations limit.

I-6 — Deterministic status codes

Approval, denial, drift, validation, timeout, policy, protocol, and audit-chain failures have distinct machine-readable statuses.

I-7 — Delegated work is grant-owned

The MCP server uses an operator-owned grant and fail-closed describe, prepare, and approval stages. A missing capability is not silently replaced with broader shell access.

⚠
Trust boundary
Guardrail is not a sandbox, container boundary, or containment system for untrusted binaries. It makes intended command scope inspectable and rejects unapproved contract changes.
Workflows

ROLLBACK

Model failure paths explicitly with workflow transitions and validators.

A workflow step maps outcomes through its on object—for example, success to the next step and validation_failed to abort or a declared cleanup step. Lint the full definition before running it.

bash
guardrail workflow lint --definition workflows/release.json guardrail workflow run --definition workflows/release.json
⚠
Keep cleanup bounded
A cleanup command still belongs to the reviewed workflow contract; workflow support is not a general transaction or filesystem rollback system.
Workflows

NEGOTIATION LOOP

Worker proposals can suggest bounded workflow updates; Guardrail evaluates the resulting contract before reuse.

Set --update-source worker_proposal only for a workflow designed to accept structured proposals. Scope widening, higher risk, invalid transitions, and exhausted iteration limits remain explicit failure states.

⬡
Delegated tools
For MCP work, call grant status first, then use describe or prepare. Unpinned execution needs host approval or an existing approval request; ordinary arguments cannot self-approve.
Recipes

USING RECIPES

Bundled parameterized contracts for common Git, package, infrastructure, agent, and OpenClaw workflows.

bash
guardrail list --category infra guardrail run --recipe terraform-plan-only --input config_path=infra --dry-run

Bundled recipes run directly by ID. Browse all 25 recipes and check the current input names before execution.

Recipes

AUTHORING RECIPES

Start with a generated skeleton, validate it, then package the exact artifact you intend to distribute.

bash
guardrail create --name safe-task --category local --output safe-task.recipe.json guardrail recipe validate safe-task.recipe.json guardrail pack safe-task.recipe.json --output safe-task.packed.json
Recipes

REMOTE RECIPES

Install a recipe from a local path, URL, pinned GitHub source, or an exact registry coordinate.

bash
guardrail recipe install ./safe-task.recipe.json guardrail recipe install github://owner/repo/path/to/recipe.json@<commit-sha> guardrail recipe install local/safe-task@1.0.0 --registry ./registry
⚠
Bare IDs are not install sources
Use guardrail run --recipe <id> for a bundled recipe. Installation requires one of the explicit sources above.
CLI Reference

guardrail run

Review and execute a command, recipe, template, or shell script as a normalized contract.

usage
guardrail run [options] -- <command> [args...] Options: --shell <text> Run shell-mode script text --recipe <id[@version]> Run a bundled or installed recipe --template <path> Run a template file --input <key=value> Supply a recipe/template input; repeatable --env-allow <name> Allow an environment variable; repeatable --manifest <path> Use a custom manifest path --approved-manifest <path> Reuse an approved manifest --non-interactive Never prompt; fail if approval is needed --json Emit a structured result --json-stream Emit progress events plus the result
⬡
First run
Use an interactive TTY for the initial review. CI should use --non-interactive with the exact approved manifest.
CLI Reference

guardrail approve

Inspect and resolve queued MCP compatibility approvals.

bash
guardrail approve list guardrail approve <request-id>

This does not approve an arbitrary command line. Direct command approval happens during an interactive guardrail run.

CLI Reference

template diff

Compare a rendered template contract with its approved hash.

bash
guardrail template diff --template ./templates/npm-publish.json --input package_dir=packages/lib --input tag=beta

There is no generic guardrail diff command. Command drift is reported by guardrail run.

CLI Reference

guardrail audit

Verify or query the repo-local hash-linked audit log.

bash
guardrail audit verify --path .guardrail/audit.jsonl guardrail audit query --status drift_detected guardrail export --format csv
CLI Reference

guardrail recipe

Validate, inspect, install, compose, publish, and version recipes.

bash
guardrail list --search git guardrail recipe validate ./safe-task.recipe.json guardrail recipe inspect ./safe-task.packed.json
CLI Reference

guardrail workflow

Lint or run a workflow definition.

bash
guardrail workflow lint --definition workflows/ci.json guardrail workflow run --definition workflows/ci.json --non-interactive
Audit & Observability

AUDIT LOG

Command and workflow events are stored as structured JSONL in .guardrail/audit.jsonl by default.

Each entry carries previous, payload, and entry hashes. Use guardrail audit query for filters, guardrail audit verify for chain integrity, and the top-level guardrail export command for JSON or CSV output.

Audit & Observability

TAMPER EVIDENCE

Hash linking makes local log edits detectable when the chain is verified.

⚠
Local evidence, not an external ledger
The log remains a local file. Copy it to operator-controlled storage if your threat model includes deletion or replacement of repository state.
Integrations

AGENT INTEGRATION

Expose only the delegated capabilities in an operator-owned MCP grant.

bash
guardrail mcp serve --grant ~/.guardrail/mcp-grants/codex.json --agent codex

The server uses stdio. Agents call grant status, then describe or prepare an action; execution requiring approval fails closed if host elicitation or an approved request is unavailable.

Security

TRUST MODEL

Guardrail trusts the local operator and the tools the operating system allows it to launch.

  • It is a command-scope and approval layer, not a security sandbox.
  • It does not isolate processes, restrict syscalls, or contain an untrusted binary.
  • Approved manifests are local acknowledgement records, not identity signatures.
  • Delegated MCP capabilities are bounded by an operator-owned grant.
  • Audit-chain verification detects edits; external retention is your responsibility.