--- name: setup-dashclaw description: Set up a DashClaw instance, install the CLI tool, and configure Claude Code hooks license: MIT metadata: author: ucsandman version: "1.0.0" category: setup --- # Set Up DashClaw Three ways to get DashClaw running, plus CLI and Claude Code hook setup. --- ## Instance Setup ### Option 1: Local Development ```bash # Clone the repo git clone git@github.com:ucsandman/DashClaw.git cd DashClaw # Install dependencies npm install # Run interactive setup (creates .env, initializes database) node scripts/setup.mjs # Start dev server npm run dev # → http://localhost:3000 ``` **Required environment variables (.env):** ```bash DATABASE_URL=postgresql://user:pass@localhost:5432/dashclaw ENCRYPTION_KEY=<32-char-random-string> NEXTAUTH_URL=http://localhost:3000 NEXTAUTH_SECRET=<32-char-random-string> DASHCLAW_API_KEY= DASHCLAW_MODE=self_host ``` ### Option 2: Cloud (Vercel + Neon) 1. Fork the DashClaw repo on GitHub 2. Deploy to Vercel (connect the fork) 3. Create a free Neon Postgres database 4. Set `DATABASE_URL` in Vercel environment variables 5. Run `node scripts/setup.mjs` locally pointing to your cloud instance 6. Grab your API key from the dashboard ### Option 3: Demo Mode ```bash npx dashclaw-demo # Runs a local demo instance with fixture data # Opens Decision Replay automatically # Agent attempts risky deployment, DashClaw blocks it ``` Demo mode is read-only — no writes allowed. Good for exploring the UI. ### Verify Setup ```bash # Health check curl http://localhost:3000/api/health # Expected response: # { "status": "ok", "database": "connected", "version": "2.x.x" } ``` Visit `http://localhost:3000/setup` for the instance readiness verification page. --- ## CLI Installation The `@dashclaw/cli` provides terminal-based approval workflows. ### Install ```bash npm install -g @dashclaw/cli ``` ### Configure ```bash export DASHCLAW_BASE_URL=http://localhost:3000 export DASHCLAW_API_KEY=your-api-key # Optional: export DASHCLAW_AGENT_ID=cli-operator ``` ### Commands ```bash # Interactive approval inbox (TUI with live updates) dashclaw approvals # Approve a specific action dashclaw approve act_abc123 --reason "Reviewed and safe" # Deny a specific action dashclaw deny act_abc123 --reason "Risk too high for current sprint" # Help dashclaw help ``` ### Interactive Mode Keyboard Shortcuts | Key | Action | |-----|--------| | `↑/↓` | Navigate approvals | | `A` | Approve selected | | `D` | Deny selected | | `R` | Refresh list | | `O` | Open replay link in browser | | `Q` | Quit | Risk scores are color-coded: green (<40), yellow (40-70), red (70+). --- ## Claude Code Hooks DashClaw provides pre/post tool hooks for Claude Code that create a policy-enforced execution pipeline. Hooks v2 govern 40+ tool types (not just Bash/Edit/Write/MultiEdit) with semantic classification via the bundled `dashclaw_agent_intel` module. ### How It Works ``` Claude Code Tool Call (Bash/Edit/Write/MultiEdit) ↓ [PreToolUse: dashclaw_pretool.py] → Classify action (type, risk, systems) → POST to /api/guard → Allow / Warn / Block / Require Approval → Store action_id in temp file ↓ [Tool Executes] (unless blocked) ↓ [PostToolUse: dashclaw_posttool.py] → Read action_id from temp file → Determine outcome (completed/failed) → PATCH /api/actions/:id with result ↓ Full audit trail in DashClaw dashboard ``` ### Install Hooks **Recommended:** use the one-command installer from your DashClaw checkout: ```bash node /path/to/DashClaw/scripts/install-hooks.mjs --target=. ``` This copies all three governance hooks (`dashclaw_pretool.py`, `dashclaw_posttool.py`, `dashclaw_stop.py`) and the `dashclaw_agent_intel/` Python module into `.claude/hooks/`, then merges the `PreToolUse` / `PostToolUse` / `Stop` blocks into `.claude/settings.json`. Idempotent — safe to re-run after each `git pull`. **Manual install** (if you need to control file placement): 1. Copy hook files into your project's `.claude/hooks/` directory: ```bash mkdir -p .claude/hooks cp /path/to/DashClaw/hooks/dashclaw_pretool.py .claude/hooks/ cp /path/to/DashClaw/hooks/dashclaw_posttool.py .claude/hooks/ cp /path/to/DashClaw/hooks/dashclaw_stop.py .claude/hooks/ cp -r /path/to/DashClaw/hooks/dashclaw_agent_intel .claude/hooks/ ``` The `dashclaw_agent_intel/` module is required — `dashclaw_pretool.py` imports it for semantic tool classification, so omitting it raises `ImportError` on the first governed tool call. 2. Add hook configuration to `.claude/settings.json` — three entries are needed: `PreToolUse` (governance gate), `PostToolUse` (outcome recorder), and `Stop` (LLM token + cost capture, plus auto-close fallback for any actions that PostToolUse missed): ```json { "hooks": { "PreToolUse": [ { "matcher": "Bash|Edit|Write|MultiEdit", "hooks": [ { "type": "command", "command": "python .claude/hooks/dashclaw_pretool.py", "timeout": 3660 } ] } ], "PostToolUse": [ { "matcher": "Bash|Edit|Write|MultiEdit", "hooks": [ { "type": "command", "command": "python .claude/hooks/dashclaw_posttool.py" } ] } ], "Stop": [ { "hooks": [ { "type": "command", "command": "python .claude/hooks/dashclaw_stop.py" } ] } ] } } ``` 3. Set environment variables: ```bash export DASHCLAW_BASE_URL=http://localhost:3000 export DASHCLAW_API_KEY=your-api-key export DASHCLAW_AGENT_ID=claude-code export DASHCLAW_HOOK_MODE=observe # Start with observe, switch to enforce later export DASHCLAW_RISK_THRESHOLD=60 # Default risk threshold export DASHCLAW_GOVERNED_CATEGORIES=all # Comma-separated tool categories or "all" (see below before narrowing) export DASHCLAW_PERMISSION_MODE=standard # standard | elevated | admin ``` ### Hook Modes - **`observe`** — Logs all decisions but never blocks. Use this first to understand what would be caught. - **`enforce`** — Blocks tool execution when guard returns `block` or approval is denied/times out. ### Action Type Mapping (Pretool) The pretool automatically classifies tool calls: **Bash commands:** | Pattern | Action Type | Risk | Reversible | |---------|------------|------|------------| | `git push`, `git merge`, `git rebase` | deploy | 80 | false | | `npm run deploy`, `vercel deploy` | deploy | 75-85 | false | | `terraform apply` | deploy | 85 | false | | `rm -rf`, `DROP TABLE` | security | 90 | false | | `.env`, `secret`, `key` file access | security | 85 | false | | `npm install`, `pip install` | build | 30 | true | | `curl`, `wget` | api | 40 | true | **File operations (Edit/Write/MultiEdit):** | File Pattern | Action Type | Risk | |-------------|------------|------| | `.env`, `secrets`, `credentials` | security | 85 | | `migration`, `schema` | migrate | 70 | | `auth`, `middleware` | security | 75 | | Other files | file_write | 15 | ### Approval Timeout When the guard returns `require_approval`, the pretool polls for 30 seconds. If no decision is made, the tool is blocked (enforce mode) or allowed (observe mode). Use `dashclaw approvals` in another terminal to approve in real-time. ### Graceful Degradation If the hook is **unconfigured** (no `DASHCLAW_BASE_URL`/`DASHCLAW_API_KEY`), it exits 0 and the tool runs ungoverned; half-configured warns on stderr and still exits 0. But a **server down or network error is not the same case**: in enforce mode the hook fails *closed* and blocks (exit 2), because an action that could not be governed must not proceed. Override with `DASHCLAW_GUARD_UNAVAILABLE_POLICY=warn|allow` (not recommended). Observe mode never blocks either way, and every outage is written to `~/.dashclaw/orphan-actions.jsonl` for backfill on recovery. ### Governed categories — narrowing the scope is visible `DASHCLAW_GOVERNED_CATEGORIES` decides which tool categories call the guard at all. This is a **scope** knob, not a mode knob, and it is sharper than it looks: for a category it excludes, the hook exits **before** the network call, so those tool calls produce no decision row, no witness and no signal. Their absence from `/decisions` is indistinguishable from an agent that simply did nothing. Default governed set: `execution,orchestration,file_io,interactive,mcp`. `search` and `system` are ungoverned out of the box by design. Unknown tools that match no category fail safe to governed. Since v5.20 the hook declares the categories it is *not* governing on the calls it does still make, and any category dropped below that default set raises the red **Governance scope narrowed** (`ungoverned_scope`) signal naming what is unwatched. A healthy default install declares nothing and raises nothing. This is a visibility guarantee, not an enforcement one — the variable lives on the agent's own machine — but it catches the case that actually happens: a misconfigured agent, or a typo that silently dropped a real category (`file-io` is not `file_io`). ### Related policy types Hooks v2 enrichment feeds three guard **policy** types (these are policies you configure, not signals the dashboard emits): - **`permission_escalation`** — matches when the action requires elevated permissions - **`green_contract`** — requires a test-verification level before deploys - **`branch_freshness`** — matches deploys from a stale or diverged branch Blocked decisions may also carry a **recovery recipe**: actionable remediation steps returned alongside the verdict. Monitor the resulting risk signals in the dashboard or via `/api/signals`. ### Session Setup (Recommended) For long-running Claude Code sessions, create a session to enable lifecycle tracking and recovery: ```bash # Sessions are created automatically by hooks when DASHCLAW_SESSION_TRACKING=true export DASHCLAW_SESSION_TRACKING=true ``` Session tracking is optional. When enabled, the pretool hook creates a session on first invocation and reports status updates throughout the session. If a session is interrupted, DashClaw records the last checkpoint for recovery.