Adds internal/safety/ — the in-repo source of truth for the PreToolUse hook
deployed into every project before a Claude Code agent is launched. The hook
blocks destructive Bash/Edit/Write patterns on sessions running with
--dangerously-skip-permissions, closing the exploitation path where a prompt
injection via MCP sessions.send could otherwise trigger arbitrary destruction
without interactive confirmation.
Wire-up:
- internal/dispatcher/dispatcher.go launchAgent: deploys hook before claude
launch; fail-closed if deployment fails.
- internal/switcher/account_switcher.go relaunchDedicatedSessions: redeploys
hook before --resume after account failover; fail-open (log + continue)
since the initial deployment is still in place.
Blocks (exit 2, stderr shown to model):
- rm -rf targeting /, ~, $HOME, /etc, /var, /usr, /boot
- dd of=/dev/{sd,nvme,disk,hd,mmcblk}*, mkfs*
- git push --force (but allows --force-with-lease)
- git reset --hard on main|master|production
- sudo outside short allowlist (systemctl, journalctl, cp, install, apt*)
- curl|sh, bash <(curl ...), eval "$(curl ...)", fork bomb, crontab -e
- chmod 777 on system paths / home
- Writes to .claude/settings*.json, .claude/hooks/, ~/.ssh/authorized_keys,
shell rc files, /etc/sudoers*, /etc/systemd/*
Warn-only (logged, not blocked):
- kubectl delete, helm uninstall, terraform destroy
- DROP TABLE, TRUNCATE TABLE, DELETE FROM ... WHERE 1=1
Hook script is embedded via //go:embed so a single binary release carries
the authoritative copy. Every launch rewrites the deployed file with mode
0555 (anti-tamper); the hook itself also blocks writes to .claude/hooks/
for defense in depth.
Decision: Olivier, 2026-04-19 — Option A now, Option C (two pools) tracked
separately. Complements FNDG-04 input sanitization in secuaas-mcp.
Tests: 8 unit/integration tests in internal/safety/, plus a dispatcher-level
test verifying the hook is written before launch. go vet clean, go test ./...
all pass.
Refs: FNDG-04 audit (secuaas-mcp branch audit/mcp-stdio-2026-04-18)
Task: .agent-queue/inbox/20260418-211102-fndg-04b-*.md
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|---|---|---|
| cmd/claude-failover | ||
| docs | ||
| internal | ||
| scripts | ||
| .gitignore | ||
| CLAUDE.md | ||
| config.example.yaml | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| README.md | ||
| VERSION.md | ||
| WORK_IN_PROGRESS.md | ||
claude-failover
Go daemon for Claude Code multi-account session orchestration with automatic quota-based failover.
Overview
claude-failover orchestrates a pool of Claude Code sessions running under
multiple Anthropic accounts. When the active account reaches its quota
threshold (5-hour usage window or weekly cap), the daemon transparently fails
over the workload to a backup account without losing in-flight session state.
It is the runtime glue behind the SecuAAS agent pool (ccl-0..ccl-9,
ccl-auto-11..ccl-auto-20) and is engineered to hold sessions warm across
account swaps by sharing the ~/.claude/projects/ transcript tree via
symlinks.
Architecture (goroutines)
The daemon is a single Go binary composed of cooperating goroutines:
- dispatcher — reads
.agent-queue/inbox/*.mdacross registered projects and assigns tasks to idle sessions. - quota-monitor — polls each configured Anthropic account's usage window and triggers a failover when the active account crosses its threshold.
- session-watcher — tracks tmux session liveness (
ccl-*), heartbeats, and.agent-queue/status.jsontransitions (idle / working). - checkpoint — periodically snapshots session context (current task, last tool call, working dir) so an interrupted session can resume on a different account.
- janitor — cleans stale
.dispatchedmarkers, archives olddone/tasks, prunes expired checkpoints. - notifier — pushes state changes (failover fired, session degraded, task failed) to Telegram / MCP dashboard / log aggregator.
- account-switcher — performs the actual swap: stop sessions on account A, rehome symlinks, relaunch sessions on account B, replay last checkpoint. Serialized via a single mutex so only one swap can happen at a time.
All goroutines communicate through typed channels plus a shared state struct
behind a sync.RWMutex. The daemon exposes an HTTP control plane for the
MCP server to query status and force-trigger operations.
Relationship to SecuAAS agent-orchestrator
This project extracts the session-management and failover logic that
currently lives in dev-management/agent-orchestrator/ (shell scripts:
launch-agent.sh, graceful-switch.sh, watchdog.sh,
checkpoint-daemon.sh, start-dedicated-agents.sh) and reimplements it
as a single Go service. See the orchestrator docs for the operational
context this daemon is designed to replace.
Repository layout
cmd/claude-failover/ Main entrypoint
docs/ Architecture, configuration, analysis notes
scripts/ Setup helpers (shared-projects symlink, etc.)
config.example.yaml Annotated example config
Status
Pre-alpha. Design and scaffolding only — no working binary yet.
License
MIT — see LICENSE.