# Quick Start Guide
**Get started with APort Repository Guard and runtime guardrails in one command**

---

## 1. Protect a GitHub repository

```bash
npx @aporthq/aport-agent-guardrails github
```

This creates `.github/workflows/aport-guard.yml` using the public
[APort Repository Guard](https://github.com/marketplace/actions/aport-repository-guard)
Action (`aporthq/policy-verify-action@v1`).

Default `mode: auto` uses GitHub OIDC, creates or reuses a repository-scoped
hosted OAP passport, and starts with report-only evidence. Pair hosted
enforcement with branch protection when you are ready to block merges or
protected-branch pushes.

Blocking hosted setup:

```bash
npx @aporthq/aport-agent-guardrails github --mode hosted --branches main,staging --block-protected-paths
```

Guide: [GITHUB_PROTECTION.md](GITHUB_PROTECTION.md)

## 2. Install runtime guardrails

Use this on the machine where the agent or coding tool runs:

```bash
npx @aporthq/aport-agent-guardrails
```

Choose a runtime target when prompted: `cursor`, `claude`/`claude-code`,
`openclaw`, `langchain`, `crewai`, `deerflow`, or beta command-hook targets:
`codex`, `gemini`, and `goose`. `n8n` is setup-only today; runtime node
enforcement ships separately.

Alias note: Claude Code users run Anthropic's `claude` CLI, so both `claude`
and `claude-code` are accepted. Gemini CLI users can use `gemini`; `gemini-cli`
is kept as a compatibility alias. opencode is intentionally gated until an
installed-version plugin smoke test validates enforcement.

Direct examples:

```bash
npx @aporthq/aport-agent-guardrails cursor
npx @aporthq/aport-agent-guardrails claude
npx @aporthq/aport-agent-guardrails openclaw

# beta command-hook harnesses
npx @aporthq/aport-agent-guardrails codex
npx @aporthq/aport-agent-guardrails gemini
npx @aporthq/aport-agent-guardrails goose
```

When prompted for passport setup:

1. `Create hosted APort passport now` — recommended; creates a hosted passport and narrow setup key.
2. `Use existing hosted passport ID` — paste an existing `agent_id`.
3. `Create local passport file` — offline/local JSON passport.

Hosted mode is the default public path because it gives you centralized audit,
remote suspend/status, and signed hosted decisions. Local JSON remains available
for offline or privacy-sensitive deployments.

All runtime hooks need `jq` on the PATH the host uses; without it the hook
denies every tool call in enforce, warn and observe modes because it cannot
safely parse or evaluate the payload. Install `jq` before setup.

### Non-interactive installs

Two flag-driven paths exist. Both skip every prompt; `CI=1` in the environment
has the same effect as `--non-interactive`.

Hosted passport (creates the passport and a setup key, writes API mode):

```bash
npx --yes @aporthq/aport-agent-guardrails claude-code \
  --quick-hosted --email you@example.com --non-interactive
# or: APORT_OWNER_EMAIL=you@example.com APORT_QUICK_HOSTED=1 \
#     npx --yes @aporthq/aport-agent-guardrails claude-code --non-interactive
```

Local passport file (framework defaults, no network):

```bash
npx --yes @aporthq/aport-agent-guardrails claude-code --mode=local --non-interactive \
  --output ~/.claude/aport/passport.json
```

`--output` is optional. `--non-interactive` with none of the hosted flags and
no `--mode` also takes the local path. The defaults are permissive
(`allowed_commands: ["*"]`, `allowed_paths: ["*"]`, `allowed_domains: ["*"]`,
blocked patterns `rm -rf`, `sudo`, `chmod 777`, `dd if=`, `mkfs`), so edit
`limits` in the passport file before trusting it for an unattended agent.

### Interactive local passport, step by step

1. Run `npx @aporthq/aport-agent-guardrails <framework>` (for example `claude-code`).
2. At `Passport setup:` choose `3. Create local passport file`.
3. `Passport file path [<framework default>]:` press Enter, or type another path.
4. `Your email or ID`, `Owner type (user/org)`, `Agent name`, `Agent description`: accept the defaults or fill in.
5. Capability questions: `Create and merge pull requests?`, `Execute system commands?`, `Send messages?`, `Read files from disk?`, `Write/edit files on disk?`, `Fetch data from web?`, `Automate web browser?`, `Export data?`, `Spawn sub-agents and tasks?`, `Use MCP tools?`. Answer `Y` to `Spawn sub-agents and tasks?` for Claude Code, Cursor, Codex, Goose and OpenClaw; every subagent, task and team tool is denied without the `agent.session.create` capability.
6. Limits: allowed repos, allowed commands (`Enter or *=allow any / list=fixed list`; a fixed list is a prefix allowlist and chained commands are then denied), allowed paths, allowed domains. Press Enter for `*` and tighten later in the JSON file.
7. `Should this passport expire?` and, if yes, the number of days.
8. Back in the installer: `Mode [1=local, 2=api]:` choose `1`. Enforcement is `enforce` unless you passed `--enforcement=warn` or `--enforcement=observe`.

### Custom install directory

Set `APORT_<FRAMEWORK>_CONFIG_DIR` (for example `APORT_CLAUDE_CODE_CONFIG_DIR`
or `APORT_CODEX_CONFIG_DIR`) before running the installer to move the passport,
mode file, runtime copy and audit log. The full table, and the note on when the
variable must also be exported at run time, is in the README under "Install
into a custom directory".

Install URL alternative for runtime hooks:

```bash
curl -fsSL https://aport.io/install.sh | bash -s -- claude-code
```

This thin shim uses the
[npm package](https://www.npmjs.com/package/@aporthq/aport-agent-guardrails).

## 3. Change enforcement without recreating passports

APort is fail-closed by default. Use `warn` for conservative report-only rollout:
completed policy denials allow with warnings, while unknown tools and APort
runtime/API failures still block. Use `observe` for adoption-first rollout:
policy denials, mapping gaps, and non-mandatory APort verifier/runtime failures
allow with warnings so developers are not blocked while you tune passports and
mappings. Mandatory prerequisites such as missing `jq` still block. Audit
entries require `python3`; unsafe or unavailable audit paths still
block with `oap.audit_unavailable` because APort will not allow a tool call
without its audit record.

```bash
npx @aporthq/aport-agent-guardrails mode claude-code --enforcement=warn
npx @aporthq/aport-agent-guardrails mode codex --enforcement=observe
npx @aporthq/aport-agent-guardrails mode cursor --enforcement=enforce
npx @aporthq/aport-agent-guardrails mode gemini --enforcement=enforce
npx @aporthq/aport-agent-guardrails mode goose --enforcement=enforce
```

The `mode` command preserves the existing hosted passport, setup key, API URL,
and local passport path. It only changes mode/enforcement settings.

Warn mode downgrades completed policy denials only. Malformed hook input, missing
dependencies, invalid mode files, unmapped effectful tools, and evaluator integrity
failures still fail closed because APort cannot prove what would have been
authorized. Warn-mode visibility depends on the host. Claude Code shows an APort
`systemMessage` warning. Cursor returns warning fields as best-effort context but
may not display allow warnings in the UI, so check `bin/aport-status.sh` or the
audit log for the recorded report-only decision.

## 4. Enterprise device rollout

For IT-managed fleets, use the bundled deploy/enforce/uninstall scripts:

```bash
curl -fsSL "https://api.aport.io/enterprise/scripts/deploy" | sudo -E bash
```

Docs: [ENTERPRISE_DEVICE_DEPLOYMENT.md](ENTERPRISE_DEVICE_DEPLOYMENT.md)

## Manual OpenClaw local walkthrough

The remaining steps are retained for lower-level OpenClaw/local testing. Most
users should prefer `npx @aporthq/aport-agent-guardrails github` for repository
protection or `npx @aporthq/aport-agent-guardrails <framework>` for runtime
hooks.

**From the repo** (if you cloned the repo):

```bash
./bin/openclaw
```

The script will:

1. **Prompt for your OpenClaw config directory** — default `~/.openclaw`; you can use a different path (e.g. your project’s `.openclaw`).
2. **Create or select a passport** — use hosted setup for a passport and setup key, or local setup for an on-disk OAP passport.
3. **Install wrappers** in your config dir (`.skills/`) so OpenClaw can call the guardrail with the correct passport/decision paths.
4. **Update your passport** — the installer sets `allowed_commands: ["*"]` automatically (no manual editing needed); then runs a self-check and exits with a clear error if the check is denied.
5. **Install the APort skill** in `~/.openclaw/skills/aport-guardrail/` so OpenClaw loads it; the agent knows to call the guardrail before effectful actions.
6. **Print the tool → policy mapping** so you see how tool names map to policy packs in `external/aport-policies`. Full table: [TOOL_POLICY_MAPPING.md](TOOL_POLICY_MAPPING.md). If you have a workspace, the script saves an AGENTS.md snippet you can merge.

Then test with the path it showed (e.g. `~/.openclaw/.skills/aport-guardrail.sh system.command.execute '{"command":"ls"}'`).

For **OpenClaw + API** (self-hosted or cloud), see [OpenClaw Local Integration](OPENCLAW_LOCAL_INTEGRATION.md).

---

## Copy-paste (no wizard)

If you prefer a single block with no prompts (e.g. for automation or a different config dir):

```bash
git clone https://github.com/aporthq/aport-agent-guardrails.git && cd aport-agent-guardrails
mkdir -p ~/.openclaw
# Create minimal passport (see README for full JSON)
make install
~/.openclaw/.skills/aport-guardrail.sh system.command.execute '{"command":"ls"}'
```

Note: `make install` copies scripts to `~/.openclaw/.skills`; the guardrail will look for policies in the **repo** (so run from repo or use `./bin/openclaw` for path-aware wrappers that point to the repo).

---

## Prerequisites

- `jq` (`brew install jq` on macOS)
- Bash shell

---

## Step 1: Install (if not using openclaw script)

From the repo root:

```bash
make install
```

This copies scripts to `~/.openclaw/.skills/`. For a **configurable path** and wrappers that always use this repo’s policies, use `./bin/openclaw` instead.

---

## Step 2: Create Your First Passport (1 minute)

```bash
~/.openclaw/.skills/aport-create-passport.sh
```

**Interactive prompts will guide you through:**
1. Your email/ID (e.g., `uchi@aport.io`)
2. Owner type (user/team/org) - Choose `user`
3. Capabilities:
   - Create and merge PRs? → `y`
   - Execute system commands? → `y`
   - Send messages? → `n` (for now)
   - Export data? → `n` (for now)
4. Limits:
   - Max PR size: `500` (files)
   - Max PRs per day: `10`
   - Allowed repos: `*` (all repos)

**Result:** Passport created at `~/.openclaw/aport/passport.json`

**Verify:**
```bash
cat ~/.openclaw/aport/passport.json | jq '.passport_id, .status, .expires_at'
```

You should see:
```json
"550e8400-e29b-41d4-a716-446655440000"
"active"
"2026-03-16T00:00:00Z"
```

---

## Step 3: Check Status (10 seconds)

```bash
~/.openclaw/.skills/aport-status.sh
```

**You'll see:**
```
🛂 APort Status Dashboard
=========================

🟢 Kill Switch: inactive

📋 Passport Information
   Location: /Users/uchi/.openclaw/passport.json
   ID: 550e8400-e29b-41d4-a716-446655440000
   Owner: uchi@aport.io
   Type: user
   Status: ✅ active
   Expires: 2026-03-16T00:00:00Z
   ✅ 30 days until expiration

🔐 Capabilities
  • repo.pr.create
  • repo.merge
  • system.command.execute

⚙️  Limits
  • code.repository.merge:
    - Max PRs/day: 10
    - Max PR size: 500 files

📊 Recent Activity (last 10)
  (no activity yet)

💡 Useful Commands
  • View full audit log: tail -f /Users/uchi/.openclaw/audit.log
  • Edit passport: vim /Users/uchi/.openclaw/passport.json
  • Verify passport: aport-verify-passport.sh
  • Suspend agent (local): set passport status to "suspended" in passport.json (e.g. jq '.status = "suspended"')
```

---

## Step 4: Test Policy Evaluation (1 minute)

Scripts exit **0** = allow, **1** = deny. The decision is written to `~/.openclaw/aport/decision.json` (not printed to stdout).

### Test 1: Allow a small PR (should PASS)

```bash
~/.openclaw/.skills/aport-guardrail.sh git.create_pr '{
  "repo": "aport-agent-guardrails",
  "branch": "feature/test",
  "base_branch": "main",
  "files_changed": 10
}'
echo "Exit: $? (0 = ALLOW)"
```

**Check decision:**
```bash
cat ~/.openclaw/aport/decision.json | jq .
```

**Check audit log:**
```bash
tail -1 ~/.openclaw/aport/audit.log
```

---

### Test 2: Deny a large PR (should FAIL)

```bash
~/.openclaw/.skills/aport-guardrail.sh git.create_pr '{
  "repo": "aport-agent-guardrails",
  "branch": "feature/large",
  "files_changed": 1000
}'
echo "Exit: $? (1 = DENY)"
cat ~/.openclaw/aport/decision.json | jq '.allow, .reasons'
```

You should see `"allow": false` and a deny reason.

---

### Test 3: Block dangerous command (should FAIL)

```bash
~/.openclaw/.skills/aport-guardrail.sh system.command.execute '{"command":"rm -rf /tmp/test"}'
echo "Exit: $? (1 = DENY)"
cat ~/.openclaw/aport/decision.json | jq '.allow, .reasons[0].message'
```

---

## Step 5: Test suspend (kill switch = passport status) (30 seconds)

The passport is the source of truth. To suspend the agent, set passport `status` to `suspended`.

### Suspend the agent:
```bash
# Set passport status to suspended (e.g. edit ~/.openclaw/aport/passport.json or:)
jq '.status = "suspended"' ~/.openclaw/aport/passport.json > /tmp/passport.tmp && mv /tmp/passport.tmp ~/.openclaw/aport/passport.json
```

### Try any action (should be blocked):
```bash
~/.openclaw/.skills/aport-guardrail.sh git.create_pr '{"repo": "test", "files_changed": 1}'
cat ~/.openclaw/aport/decision.json | jq '.allow, .reasons[0].code'
```
You should see `allow: false` and `oap.passport_suspended`.

### Resume the agent:
```bash
jq '.status = "active"' ~/.openclaw/aport/passport.json > /tmp/passport.tmp && mv /tmp/passport.tmp ~/.openclaw/aport/passport.json
```

### Verify it works again:
```bash
~/.openclaw/.skills/aport-guardrail.sh git.create_pr '{"repo": "test", "files_changed": 1}'
```

Should see `"allow": true` now.

---

## Step 6: View Activity Dashboard (10 seconds)

```bash
~/.openclaw/.skills/aport-status.sh
```

**You'll now see:**
```
📊 Recent Activity (last 10)
  ✅ 2026-02-14 17:00:00 | git.create_pr
  ❌ 2026-02-14 17:01:00 | git.create_pr
  ❌ 2026-02-14 17:02:00 | exec.run
  ❌ 2026-02-14 17:03:00 | git.create_pr

📈 Statistics (all time)
  Total actions: 4
  Allowed: 1
  Denied: 3
  Allow rate: 25%
```

---

## 🎉 Success! You've tested all core features

**What you've verified:**
- ✅ Passport creation (interactive wizard)
- ✅ Status dashboard (health checks)
- ✅ Policy evaluation (allow/deny based on rules)
- ✅ Kill switch (global emergency stop)
- ✅ Audit logging (tamper-evident trail)

---

## Step 7: Integrate with Your OpenClaw Instance (5 minutes)

### Option A: Add to AGENTS.md (Best-effort)

**1. Locate your OpenClaw AGENTS.md:**
```bash
# Find your OpenClaw installation
find ~ -name "AGENTS.md" -path "*/.openclaw/*" | head -1
```

**2. Add APort section:** From the repo root:
```bash
cat docs/AGENTS.md.example >> ~/.openclaw/AGENTS.md
```

**3. Verify:**
```bash
cat ~/.openclaw/AGENTS.md | grep "Pre-Action Authorization"
```

AGENTS.md is repository-controlled instruction text, not the trusted runtime identity source. Runtime hooks use machine-scoped config by default. Set `APORT_TRUST_REPO_POLICY=1` only if you intentionally want a trusted repository to select its own APort passport.

---

### Option B: Manual Integration (Advanced)

**In your OpenClaw agent code, before any tool execution:**

```python
import subprocess
import json

def execute_tool(tool_name, params):
    # 1. Pre-action verification
    result = subprocess.run([
        '~/.openclaw/.skills/aport-guardrail.sh',
        tool_name,
        json.dumps(params)
    ], capture_output=True, text=True)

    # 2. Read decision
    with open(os.path.expanduser('~/.openclaw/aport/decision.json')) as f:
        decision = json.load(f)

    # 3. Check if allowed
    if not decision.get('allow'):
        raise PermissionError(f"Policy denied: {decision.get('message')}")

    # 4. Execute tool (if allowed)
    return actual_tool_execution(tool_name, params)
```

---

## Step 8: Customize Your Passport (Optional)

### Edit passport directly:
```bash
vim ~/.openclaw/aport/passport.json
```

### Common customizations:

**1. Change PR size limit:**
```json
{
  "limits": {
    "code.repository.merge": {
      "max_pr_size_kb": 1000  // Increase from 500 to 1000
    }
  }
}
```

**2. Add allowed repos (restrict to specific repos):**
```json
{
  "limits": {
    "code.repository.merge": {
      "allowed_repos": ["aporthq/*", "my-org/*"]  // Only these repos
    }
  }
}
```

**3. Add blocked commands:**
```json
{
  "limits": {
    "system.command.execute": {
      "blocked_patterns": ["rm -rf", "sudo", "curl | bash", "dd if="]
    }
  }
}
```

**After editing, verify:**
```bash
jq . ~/.openclaw/aport/passport.json > /dev/null && echo "✅ Valid JSON" || echo "❌ Invalid JSON"
```

---

## Troubleshooting

### Problem: "jq not found"
```bash
brew install jq  # macOS
apt-get install jq  # Linux
```

### Problem: "Permission denied"
```bash
chmod +x ~/.openclaw/.skills/aport-*.sh
```

### Problem: "Passport not found"
```bash
# Recreate passport
~/.openclaw/.skills/aport-create-passport.sh
```

### Problem: "Command must be in allowed list" (oap.command_not_allowed)
The guardrail is blocking **exec** because the command (e.g. `mkdir`, `ls`) is not in your passport’s **allowed_commands**. OpenClaw uses **exec** for both guardrail invocations and real shell commands; we check real commands against the passport.

**Fix:** The installer sets `allowed_commands: ["*"]` by default; this usually appears only if you intentionally tightened the allowlist. Re-add the commands you need to `limits.system.command.execute.allowed_commands`, or set `["*"]` (blocked patterns still apply). Alternatively, set **mapExecToPolicy: false** in the plugin config so exec is never checked (no command allowlist; use only if you rely on other controls). See [OPENCLAW_TOOLS_AND_POLICIES.md](OPENCLAW_TOOLS_AND_POLICIES.md).

### Problem: "Missing required capabilities: messaging.send"
If you see `oap.unknown_capability: Missing required capabilities: messaging.send`, your passport was created with the old capability/limits keys. Align with APort:

- In `capabilities`, use `"id": "messaging.send"` (not `messaging.message.send`).
- In `limits`, use the key `"messaging"` (not `messaging.message.send`) for `msgs_per_min`, `msgs_per_day`, etc.

Re-run the passport wizard to create a new passport, or edit `~/.openclaw/aport/passport.json` and fix those two places.

### Problem: "All actions denied"
```bash
# Check passport status (source of truth for suspend)
jq '.status' ~/.openclaw/aport/passport.json
# Should be "active"; if "suspended" or "revoked", set back to "active" to resume

# Check expiration
jq '.expires_at' ~/.openclaw/aport/passport.json
# If expired, update it
```

### Problem: "Decision file not created"
```bash
# Check script permissions
ls -la ~/.openclaw/.skills/aport-guardrail.sh
# Should be -rwxr-xr-x (executable)

# Make executable
chmod +x ~/.openclaw/.skills/aport-guardrail.sh
```

---

## Next Steps

### For Testing:
1. ✅ **Create more test scenarios** - Try different policy violations
2. ✅ **Test rate limiting** - Create 11 PRs in a day (should deny 11th)
3. ✅ **Test expiration** - Set expiration to past date, verify it denies

### For Integration:
1. ✅ **Add to OpenClaw AGENTS.md** - Make it automatic
2. ✅ **Create custom policy packs** - Add policies for your use case
3. ✅ **Set up recurring passport renewal** - Cron job to renew every 30 days

### For Production:
1. ✅ **Upgrade to APort Cloud** - Get global kill switch, Ed25519 signatures
2. ✅ **Set up team passports** - Share policies across team
3. ✅ **Enable audit log monitoring** - Alert on policy violations

---

## Resources

- [GitHub Protection](GITHUB_PROTECTION.md) — Repository Guard setup for PR, merge, and push evidence
- [Claude Code](frameworks/claude-code.md), [Cursor](frameworks/cursor.md), [Codex](frameworks/codex.md), [Gemini CLI](frameworks/gemini-cli.md), and [Goose](frameworks/goose.md) — runtime hook setup
- [OpenClaw Local Integration](OPENCLAW_LOCAL_INTEGRATION.md) — Full OpenClaw + API setup
- [QuickStart: OpenClaw Plugin](QUICKSTART_OPENCLAW_PLUGIN.md) — Plugin setup
- [Tool / Policy Mapping](TOOL_POLICY_MAPPING.md)
- [Contributing](../CONTRIBUTING.md)

---

## Get Help

- **GitHub Issues:** https://github.com/aporthq/aport-agent-guardrails/issues
- **Discussions:** https://github.com/aporthq/aport-agent-guardrails/discussions
- **Security reports:** security@aport.io

---

**Total Time:** ~5 minutes to get started, 30 minutes to fully integrate

**You're now running policy-enforced AI agents! 🎉**
