Status: Living document — update after every AlphaClaw upstream merge
Version: 0.9.9.9 (aligned with Perpetua-Tools)
Last verified: 2026-04-20 against AlphaClaw feature/MacOS-post-install
Cross-repo context:
- Architecture authority:
orama-system/docs/2026-05-14--UNIFIED-ABSORPTION-PLAN.md - Shared types (PT-owned):
orchestrator/contracts.py(OrchestrationSession,TaskEnvelope,WorkerAssignment,WorkerResult,VerificationResult) - AlphaClaw is L1 (infra) — referenced here but never imported as a module
This is the invariant that Perpetua-Tools tests against. When AlphaClaw's surface changes, update this document first, then update PT adapter code.
AlphaClaw requires:
- Node.js ≥ 22.14.0
.envfile withSETUP_PASSWORDsetnpm installcompletednpm run build:uicompleted (required for UI assets)
# Start server on default port (reads PORT from .env, default 3000)
node bin/alphaclaw.js start
# Start on custom port
node bin/alphaclaw.js start --port 3001
# Version string
node bin/alphaclaw.js --version
# Build UI assets (required before first run)
npm run build:ui
# Run full test suite (440 tests)
npm test
# Run watchdog suite only (14 tests, faster)
npm run test:watchdog
# Run with coverage
npm run test:coverageEnvironment variable overrides:
| Variable | Default | Purpose |
|---|---|---|
PORT |
3000 |
HTTP server port |
SETUP_PASSWORD |
(required) | Auth gate for setup and session login |
PT sets these via:
const ALPHACLAW_ROOT = process.env.ALPHACLAW_ROOT || '../AlphaClaw';
const env = { ...process.env, PORT: String(port), ALPHACLAW_ROOT };
spawnSync('node', ['bin/alphaclaw.js', 'start'], { cwd: ALPHACLAW_ROOT, env });Base URL: http://127.0.0.1:{PORT} (default port 3000)
| Method | Path | Auth | Source file | Response shape |
|---|---|---|---|---|
GET |
/health |
none | routes/pages.js:4 |
{status:"ok"} or {status:"error"} |
GET |
/api/status |
setup¹ | routes/system.js:530 |
server state + uptime |
GET |
/api/gateway-status |
setup¹ | routes/system.js:657 |
gateway process health |
GET |
/api/gateway/dashboard |
setup¹ | routes/system.js:718 |
full dashboard data |
POST |
/api/gateway/restart |
setup¹ | routes/system.js:760 |
{ok:true} or error |
GET |
/api/restart-status |
setup¹ | routes/system.js:730 |
restart state |
POST |
/api/restart-status/dismiss |
setup¹ | routes/system.js:744 |
dismisses banner |
GET |
/api/onboard/status |
none | routes/onboarding.js:161 |
{onboarded:bool,...} |
GET |
/api/alphaclaw/version |
setup¹ | routes/system.js:604 |
version string |
GET |
/api/models |
session² | routes/models.js:164 |
model list |
GET |
/api/models/config |
session² | routes/models.js:211 |
routing config |
PUT |
/api/models/config |
session² | routes/models.js:234 |
update routing config |
GET |
/api/env |
session² | routes/system.js:369 |
env vars (PT must redact) |
PUT |
/api/env |
session² | routes/system.js:416 |
write env vars |
¹ setup-allowlisted — accessible during setup phase via SETUP_API_PREFIXES in lib/server/constants.js:380. Includes /api/status, /api/gateway, /api/restart-status.
² session auth — requires active login session (cookie from /api/auth/login).
| Method | Path | Auth | Purpose |
|---|---|---|---|
POST |
/api/auth/login |
none | Body: {password: SETUP_PASSWORD} → sets session cookie |
GET |
/api/auth/status |
none | {authenticated: bool} |
POST |
/api/auth/logout |
none | Invalidates session |
PT login flow:
// 1. POST /api/auth/login with SETUP_PASSWORD
// 2. Store session cookie from response headers
// 3. Include cookie in all subsequent session² requests
// 4. On 401, re-login and retry once| Method | Path | Auth | Purpose |
|---|---|---|---|
GET |
/api/watchdog/status |
session² | Watchdog health state |
GET |
/api/watchdog/events |
session² | Recent watchdog events |
GET |
/api/watchdog/logs |
session² | Log tail (last N lines) |
POST |
/api/watchdog/repair |
session² | Trigger self-repair |
SETUP_PASSWORD=<required>
PORT=3000 # optional, default 3000
PT reads this to know the password for auth. Never log or expose SETUP_PASSWORD.
{
"gateway": {
"providers": {
"<provider-name>": {
"enabled": true,
"models": ["<model-id>", ...],
"apiKey": "<redact-in-PT>"
}
}
},
"channels": { ... },
"version": "..."
}PT reads this via GET /api/models/config (authenticated) or via the MCP tool alphaclaw_read_config (which redacts secrets automatically).
Redaction rule: PT must strip any key matching /token|secret|password|key|auth|credential/i before logging, storing, or passing to orama-system.
~/Library/LaunchAgents/com.alphaclaw.hourly-sync.plist
PT does not manage LaunchAgents directly. AlphaClaw manages its own LaunchAgent on macOS.
AlphaClaw currently logs unstructured stdout. PT's process wrapper will parse and forward as OTel spans.
Current stdout pattern (examples):
[alphaclaw] git auth shim installed
[alphaclaw] Setup complete -- starting server
[alphaclaw] gateway started on port 3001
[watchdog] gateway health: ok
Target format after PT wrapping:
{"ts":"2026-04-20T00:00:00Z","level":"info","service":"alphaclaw","component":"gateway","msg":"gateway started","port":3001,"traceId":"...","spanId":"..."}The OTel emitter lives in orama-system: plugins/alphaclaw_otel_emitter.py. It reads PT's structured output via OTLP gRPC → otel-collector → Tempo + Prometheus.
Run this in the AlphaClaw repo root to re-enumerate all HTTP routes:
grep -rn "app\.\(get\|post\|put\|delete\|patch\)" lib/server/routes/ \
| grep -v "node_modules" \
| sortThen diff against §3 above and update this document. Any change to the control-plane endpoints in §3.1 requires a corresponding update to packages/alphaclaw-adapter/src/index.js.
This contract tracks AlphaClaw version. Breaking changes require a semver bump in PT.
| AlphaClaw version | Contract version | Breaking changes |
|---|---|---|
0.9.9 (upstream) |
0.9.9.9 |
Initial enumeration |
- System design:
../../../AlphaClaw/docs/system-design-three-repo-architecture.md§3 - AlphaClaw routes:
lib/server/routes/(18 route files) - Auth allowlist:
lib/server/constants.js:380(SETUP_API_PREFIXES) - MCP server:
packages/alphaclaw-adapter/src/mcp/server.js