Command-line interface for the ClawForge audit & governance platform.
clawctl is a thin wrapper around the ClawForge library modules. It contains
no business logic — every command delegates to the same functions available to
programmatic consumers.
# Build the project
pnpm build
# Initialize data directory (~/.clawforge/)
pnpm clawctl init
# Create a run (generates UUID, emits RunStarted event)
pnpm clawctl new-run --json
# → {"createdAt":"2026-02-09T...","eventId":"...","runId":"abc123..."}
# Validate a contract file
pnpm clawctl validate-contract intent.json
# Attach an artifact
pnpm clawctl put-artifact --run <runId> --file report.pdf --mime application/pdf --label "Final report"
# Append a custom event
pnpm clawctl append-event --run <runId> --event step-completed.json
# Verify hash chain integrity
pnpm clawctl verify-run --run <runId>
# Export evidence bundle
pnpm clawctl export-evidence --run <runId> --out evidence.zip| Setting | Default | Environment Variable |
|---|---|---|
| SQLite database | ~/.clawforge/db.sqlite |
CLAWFORGE_DB_PATH |
| Artifact root | ~/.clawforge/artifacts/ |
CLAWFORGE_ARTIFACT_ROOT |
View resolved configuration:
pnpm clawctl config show
pnpm clawctl config show --jsonCreates the data directory, artifact root, and SQLite database (with schema).
pnpm clawctl initPrints the resolved configuration paths.
pnpm clawctl config show # human-readable
pnpm clawctl config show --json # canonical JSONReads a JSON file and validates it against the appropriate contract schema. Detects the contract type automatically:
- IntentContract — identified by
intentIdfield - StepContract — identified by
stepId+toolNamefields - WorkerTaskContract — identified by
taskId+workerTypefields
pnpm clawctl validate-contract intent.json
pnpm clawctl validate-contract intent.json --jsonExit code 0 = valid, 1 = invalid (errors printed to stderr or JSON to stdout).
Creates a new run row and emits a RunStarted audit event.
pnpm clawctl new-run
pnpm clawctl new-run --run <uuid> # explicit run ID
pnpm clawctl new-run --actor operator-1 # actor ID (default: "cli")
pnpm clawctl new-run --host prod-server-02 # host ID (default: hostname)
pnpm clawctl new-run --correlation req-456 # optional correlation ID
pnpm clawctl new-run --meta '{"env":"staging"}' # arbitrary metadata JSON
pnpm clawctl new-run --json # structured output| Flag | Required | Default | Description |
|---|---|---|---|
--run |
No | generated UUID | Run ID |
--actor |
No | "cli" |
Actor ID for RunStarted event |
--host |
No | os.hostname() |
Host ID stored in metadata |
--correlation |
No | — | Correlation ID in metadata |
--meta |
No | {} |
Additional metadata (JSON) |
--json |
No | — | Output as canonical JSON |
Appends an event to a run from a JSON file. The store computes seq,
prevHash, and hash — the caller must not supply these fields.
Required fields in the event JSON file:
{
"eventId": "uuid-v4",
"type": "StepCompleted",
"schemaVersion": "1.0.0",
"actor": { "actorId": "agent-1", "actorType": "worker" },
"payload": { "stepId": "step-1", "status": "success" }
}pnpm clawctl append-event --run <runId> --event event.json
pnpm clawctl append-event --run <runId> --event event.json --jsonLists all events for a run, ordered by sequence number.
pnpm clawctl list-events --run <runId>
pnpm clawctl list-events --run <runId> --jsonVerifies the hash chain integrity for a run. Exit code 0 = valid, 1 = invalid.
pnpm clawctl verify-run --run <runId>
pnpm clawctl verify-run --run <runId> --jsonStores a file in the content-addressable artifact store and records an
ArtifactRecorded audit event.
pnpm clawctl put-artifact --run <runId> --file report.pdf
pnpm clawctl put-artifact --run <runId> --file data.json --mime application/json --label "API response"
pnpm clawctl put-artifact --run <runId> --file data.json --json| Flag | Required | Default | Description |
|---|---|---|---|
--run |
Yes | — | Run ID |
--file |
Yes | — | Path to artifact |
--mime |
No | guessed from extension | MIME type |
--label |
No | file path | Human-readable label |
--json |
No | — | Structured output |
Exports a complete evidence bundle as a zip file. Pre-verifies hash chain integrity and included artifact hashes before writing.
pnpm clawctl export-evidence --run <runId> --out evidence.zip
pnpm clawctl export-evidence --run <runId> --out evidence.zip --max-include-bytes 5242880
pnpm clawctl export-evidence --run <runId> --out evidence.zip --no-artifacts| Flag | Required | Default | Description |
|---|---|---|---|
--run |
Yes | — | Run ID |
--out |
Yes | — | Output zip file path |
--max-include-bytes |
No | 10 MB | Max artifact size to include inline |
--no-artifacts |
No | — | Skip including artifact bytes |
# 1. Initialize
pnpm clawctl init
# 2. Create a run
RUN_ID=$(pnpm clawctl new-run --json | node -pe "JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')).runId")
echo "Run: $RUN_ID"
# 3. Validate and record an intent contract
cat > /tmp/intent.json << 'EOF'
{
"schemaVersion": "1.0.0",
"intentId": "550e8400-e29b-41d4-a716-446655440001",
"title": "Summarize repository",
"description": "Analyze and summarize the code repository structure",
"actor": { "actorId": "user-1", "actorType": "human" },
"constraints": { "maxSteps": 10, "timeoutMs": 300000, "providers": ["openai", "anthropic"] },
"inputParams": { "repoUrl": "https://github.com/example/repo" },
"tags": ["summarization", "code-analysis"],
"createdAt": "2026-02-09T00:00:00.000Z"
}
EOF
pnpm clawctl validate-contract /tmp/intent.json
# 4. Record the contract as an event
cat > /tmp/contract-event.json << EOF
{
"eventId": "$(uuidgen | tr '[:upper:]' '[:lower:]')",
"type": "ContractRecorded",
"schemaVersion": "1.0.0",
"actor": { "actorId": "user-1", "actorType": "human" },
"payload": { "contractType": "IntentContract", "contractId": "550e8400-e29b-41d4-a716-446655440001" }
}
EOF
pnpm clawctl append-event --run "$RUN_ID" --event /tmp/contract-event.json
# 5. Attach an artifact
echo '{"summary": "This repo contains 42 modules."}' > /tmp/summary.json
pnpm clawctl put-artifact --run "$RUN_ID" --file /tmp/summary.json --mime application/json --label "Repo summary"
# 6. Verify chain integrity
pnpm clawctl verify-run --run "$RUN_ID"
# 7. Export evidence bundle
pnpm clawctl export-evidence --run "$RUN_ID" --out /tmp/evidence.zip
unzip -l /tmp/evidence.zip| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | User error (bad input, validation failure, integrity failure) |
| 2 | Fatal / unexpected error (unhandled exception) |
All errors are written to stderr with the prefix error: . When --json is
available and used, structured errors are written to stdout instead.
| Error Message Pattern | Command(s) | Cause |
|---|---|---|
Unknown command: <name> |
(any) | Unrecognized command name |
missing required flag: --<name> |
append-event, list-events, verify-run, put-artifact, export-evidence | Required flag not provided |
Invalid run ID (must be UUID): <value> |
new-run, append-event, put-artifact | --run value is not a valid UUID |
File not found: <path> |
validate-contract, put-artifact | Input file does not exist |
--meta must be valid JSON object |
new-run | --meta value is not parseable JSON |
--max-include-bytes must be a non-negative integer |
export-evidence | Invalid byte limit value |
Contract file must contain a JSON object |
validate-contract | File contents are not a JSON object |
Cannot detect contract type... |
validate-contract | File missing discriminator fields |
Invalid <ContractType>: |
validate-contract | Schema validation failed (details follow) |
Event draft must contain: eventId, type, schemaVersion, actor, payload |
append-event | Missing required fields in event JSON |
Failed to read event file: <detail> |
append-event | File unreadable or invalid JSON |
These originate from the library modules and are surfaced by the CLI.
| Code | Cause |
|---|---|
RUN_NOT_FOUND |
--run references a run ID not in the database |
RUN_ALREADY_EXISTS |
Attempted to create a run with a duplicate ID |
FIRST_EVENT_NOT_RUN_STARTED |
First event in a run must have type RunStarted |
EVENT_ID_CONFLICT |
Attempted to append an event with a duplicate eventId |
| Code | Cause |
|---|---|
ARTIFACT_TOO_LARGE |
Artifact exceeds the maximum size limit (default: 100 MB) |
PATH_TRAVERSAL |
Resolved artifact path escapes the artifact root directory |
ARTIFACT_NOT_FOUND |
Requested artifact hash not found on disk |
HASH_MISMATCH |
Artifact bytes on disk do not match the expected hash |
INVALID_HASH |
Provided hash is not a valid 64-character hex string |
| Code | Cause |
|---|---|
CHAIN_VERIFICATION_FAILED |
Run's hash chain is invalid; export aborted |
RUN_NOT_FOUND |
Run ID not found in the database |
ARTIFACT_VERIFICATION_FAILED |
Included artifact's on-disk hash does not match |
Exit code 2 indicates an unexpected error that was not caught by normal error
handling (e.g., permission denied on the database file, out of disk space).
The error message is printed to stderr with prefix Fatal: .
- No business logic in CLI. Every command calls library functions directly.
- No interactive prompts. Fail fast with clear messages and non-zero exit codes.
- No new dependencies. Uses only Node built-ins and the existing project dependencies.
- Human-readable by default. Add
--jsonfor machine-parseable canonical JSON output. - Strict input validation. UUIDs are validated, files are checked for existence, JSON is parsed safely.
- Contract Schemas — field definitions and validation rules
- Audit Event Model — event envelope, hash chain, SQLite schema
- Architecture — module boundaries and data flow
- Threat Model — security analysis and mitigations