Session & History
Every superclaw run is recorded to a JSONL file. Sessions are inspectable, auditable, and queryable with standard tools like jq.
Where sessions are stored
Sessions are appended to .superclaw/runs.jsonl in the working directory (or /data/.superclaw/runs.jsonl in Docker). One JSON object per line, one line per run.
The .superclaw/ directory is created automatically on the first run. Add it to .gitignore if you do not want session history committed.
Session schema
Each line in runs.jsonl is a complete JSON object with the following structure:
1{2 "id": "01HZ3K8XQVN5YWBR4PSTJ7MEA",3 "version": "0.3.0",4 "started_at": "2025-11-14T09:31:02Z",5 "finished_at": "2025-11-14T09:31:09Z",6 "duration_ms": 7142,7 "status": "done",8 "task": "read the README and write a summary to summary.md",9 "model": "claude-opus-4-5",10 "skills": ["summarize"],11 "steps": 2,12 "steps_limit": 20,13 "tokens_used": 1284,14 "tool_calls": [15 {16 "step": 1,17 "tool": "read_file",18 "input": { "path": "README.md" },19 "output_bytes": 2142,20 "duration_ms": 3,21 "error": null22 },23 {24 "step": 2,25 "tool": "write_file",26 "input": { "path": "summary.md" },27 "output_bytes": 847,28 "duration_ms": 2,29 "error": null30 }31 ],32 "result": "Summary written to summary.md (847 bytes, 3 sections).",33 "error": null34}| Field | Type | Description |
|---|---|---|
| id | string | ULID — lexicographically sortable by creation time. |
| version | string | superclaw version that produced this run. |
| started_at | RFC3339 | Run start time (UTC). |
| finished_at | RFC3339 | Run end time (UTC). |
| duration_ms | integer | Total wall-clock duration in milliseconds. |
| status | string | One of: done, error, timeout, budget_exceeded. |
| task | string | The task string passed at invocation. |
| model | string | The model ID used. |
| skills | []string | Skills that were active during the run. |
| steps | integer | Number of tool-call rounds executed. |
| steps_limit | integer | The max_steps value in effect. |
| tokens_used | integer | Total output tokens consumed. |
| tool_calls | []object | Ordered list of tool calls with input, output size, duration, and error. |
| result | string|null | The final text response from the model, or null if aborted. |
| error | string|null | Error message if status != done, otherwise null. |
Status values
The model returned a final response with no pending tool calls. The task completed normally.
The run terminated due to an unrecoverable error — API failure after retries, filesystem permission error, or invalid tool call.
The run exceeded timeout_seconds. The current tool call was interrupted and the session was closed.
The run hit max_steps or max_fetch_calls before the model returned a final response.
Timeout run example
{
"id": "01HZ3K9YQVN5YWBR4PSTJ8MEA",
"version": "0.3.0",
"started_at": "2025-11-14T10:02:11Z",
"finished_at": "2025-11-14T10:04:11Z",
"duration_ms": 120003,
"status": "timeout",
"task": "scan all files and generate a full test suite",
"model": "claude-opus-4-5",
"skills": ["coding"],
"steps": 14,
"steps_limit": 20,
"tokens_used": 18432,
"tool_calls": [...],
"result": null,
"error": "run exceeded timeout of 120s"
}Querying history with jq
Because runs.jsonl is standard JSONL, you can use jq to slice and inspect it:
# Show all run IDs and statuses
jq -r '[.id, .status] | @tsv' .superclaw/runs.jsonl
# Count runs by status
jq -r '.status' .superclaw/runs.jsonl | sort | uniq -c
# Show only failed runs
jq 'select(.status != "done")' .superclaw/runs.jsonl
# Show tool usage frequency across all runs
jq -r '.tool_calls[].tool' .superclaw/runs.jsonl | sort | uniq -c | sort -rn
# Show average steps per run
jq '.steps' .superclaw/runs.jsonl | awk '{s+=$1; n++} END {print s/n " avg steps"}'
# Get the last 5 runs
tail -n 5 .superclaw/runs.jsonl | jq '{id, status, task, steps, duration_ms}'Retention policy
By default, superclaw retains all runs indefinitely. You can configure automatic pruning in superclaw.json:
{
"history": {
"max_runs": 500,
"max_age_days": 30
}
}| Field | Default | Description |
|---|---|---|
| history.max_runs | unlimited | Prune oldest runs when this count is exceeded. |
| history.max_age_days | unlimited | Remove runs older than this many days. |
Pruning runs at the start of each new run. It compacts the runs.jsonl file in-place, so the file size stays bounded over long-running deployments.