Skip to main content
ClaudeWave
Skill606 estrellas del repoactualizado today

daemon

The daemon skill orchestrates unattended multi-session autonomous campaigns by chaining Claude interactions until reaching a specified budget or ceiling. Use it to run extended operations overnight or without manual intervention. By default, it uses a local runner (npm run daemon:local) that respects the daemon.json state file without consuming Anthropic's 15-routine-per-day quota; pass --remote only with explicit user confirmation to enable RemoteTrigger-based scheduling.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/SethGammon/Citadel /tmp/daemon && cp -r /tmp/daemon/skills/daemon ~/.claude/skills/daemon
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# /daemon -- Continuous Autonomous Operation

Architecture, daemon.json field reference, and rationale: docs/DAEMON.md.

## Orientation

**Use when:** running campaigns overnight or unattended -- chains sessions automatically until a ceiling or budget is hit.
**Don't use when:** a single autonomous session is enough (use /archon); you want manual control between cycles (use /loop).

## Default execution path (READ FIRST)

**`/daemon start` does NOT call `RemoteTrigger` by default.** The local runner is the default. Only pass `--remote` to use Anthropic's routine system, and only after explicit user confirmation.

**Why:** `RemoteTrigger` counts against the account-wide **15 routine runs / 24h** cap. A single overnight run can exhaust the quota and pause every other routine on the account (including unrelated ones). See [docs/ROUTINE-QUOTA.md](../../docs/ROUTINE-QUOTA.md).

### Default flow — `/daemon start` (no `--remote` flag)

1. Do Steps 1, 2, and 4 below (validate, check existing, write `daemon.json`).
2. **Skip Step 3** — do NOT create any `RemoteTrigger`. Leave `chainTriggerId` and `watchdogTriggerId` as `null` in the state file.
3. Instead of Step 5's trigger-confirmation, output the local-runner instructions (full text: docs/DAEMON.md#local-runner-default): the state file path, campaign, and budget, then:
   ```
   To start the tick loop, run in a separate terminal:
     npm run daemon:local

   Leave that terminal open. It spawns `claude -p "/do continue"` each
   session, respects daemon.json status, and consumes zero Anthropic
   routine quota. Stop with Ctrl+C or `/daemon stop`.

   For true unattended background operation (machine sleeps, user away):
     /daemon start --remote    (uses RemoteTrigger, counts against 15/day cap)
   ```

### Codex automation lane

In Codex, prefer a Codex Automation for durable unattended daemon ticks when available: `node scripts/codex-automation.js plan --type daemon --command "/daemon tick" --cadence "<interval>" --target background-worktree --write`. Use the returned prompt in the Codex app automation surface. Each run must still read and update `.planning/daemon.json`; Codex owns the scheduling, Citadel owns the budget/status gates and run log.

### Opt-in routine flow — `/daemon start --remote`

Only when the user has explicitly passed `--remote`:
1. Before proceeding, confirm: "This will use Anthropic's `RemoteTrigger`, which counts against your 15 routine runs / 24h quota. A single overnight daemon can exhaust it. Continue? (y/N)"
2. If the user confirms, run the full Step 1-5 protocol below (including Step 3's trigger creation).

## Commands

| Command | Behavior |
|---|---|
| `/daemon start` | Default: create state file, prompt user to run `npm run daemon:local` (zero routine cost) |
| `/daemon start --remote` | Use `RemoteTrigger` instead (counts against 15/day routine quota — requires confirmation) |
| `/daemon start --campaign {slug}` | Target a specific campaign |
| `/daemon start --budget {N}` | Set budget cap in dollars (default: $50) |
| `/daemon start --budget unlimited` | Explicitly disable budget cap |
| `/daemon start --interval {N}m` | Set watchdog interval (default: 30m) |
| `/daemon start --cooldown {N}s` | Set delay between sessions (default: 60s) |
| `/daemon start --cost-per-session {N}` | Override per-session cost estimate (default: $3) |
| `/daemon stop` | Stop the daemon, tear down triggers |
| `/daemon status` | Show daemon state, session count, budget remaining |
| `/daemon log` | Show recent daemon session history |
| `/daemon tick` | Internal: heartbeat handler fired by triggers. Not user-facing. |

## Protocol

### /daemon start

**Step 1: Validate prerequisites**

1. Check `.planning/` exists. If not: "No planning directory found. Run `/do setup` first."
2. Find the target campaign: if `--campaign {slug}` provided, read `.planning/campaigns/{slug}.md`; otherwise scan `.planning/campaigns/` (excluding `completed/`) for files with `status: active` in frontmatter. No active campaign → "No active campaign. Start one with `/archon` first." Multiple active and no flag → list them, ask user to specify.
3. Verify the campaign has a Continuation State section (Archon knows where to resume)
4. Parse budget: default `$50`. `--budget unlimited` → set budget to `Infinity`, warn: "No budget cap. You will not be protected from runaway costs. Monitor usage at your Anthropic dashboard." `--budget {N}` → parse as number, must be > 0.
5. Parse cost-per-session: `--cost-per-session {N}` if provided; else the campaign's `estimated_cost_per_loop` frontmatter field if present (improve campaigns set this to 12); otherwise default `$3`. The auto-read prevents running an improve campaign on the $3 default designed for simple archon sessions (rationale: docs/DAEMON.md#cost-estimation).

**Step 2: Check for existing daemon**

Read `.planning/daemon.json` if it exists. If a daemon is already running (`status: "running"`): show its state (campaign, sessions completed, budget remaining) and ask "A daemon is already running. Stop it and start a new one?" Yes → run `/daemon stop` first, then continue. No → abort.

**Step 3: Create triggers** (remote flow only)

**A. Chain trigger** — one-shot, fires after cooldown, `command: "/daemon tick"`. Save ID as `chainTriggerId`.
**B. Watchdog trigger** — recurring, fires every `--interval`, `command: "/daemon tick --watchdog"`. Save ID as `watchdogTriggerId`.
Both use `type: scheduled/recurring`, `project_path: {absolute project root}`, `description: "Daemon: {slug} tick/watchdog"`.

**Step 4: Write state file**

Write `.planning/daemon.json`:

```json
{
  "status": "running",
  "campaignSlug": "{slug}",
  "budget": 50,
  "costPerSession": 3,
  "estimatedSpend": 0,
  "sessionCount": 0,
  "interval": "30m",
  "cooldown": "60s",
  "chainTriggerId": "{id from step 3A}",
  "watchdogTriggerId": "{id from step 3B}",
  "startedAt": "{ISO timestamp}",
  "lastTickAt": null,
  "lastTickStatus": null,
  "stop