Sessions Layout¶
Every devloop run writes a session directory under .devloop/sessions/. Sessions are append-only and safe to read concurrently from a TUI or external monitor.
Directory structure¶
.devloop/
├── events.ndjson ← project-wide event stream
├── permissions.yaml ← allow/deny rules
├── permission-queue/<UUID>.json ← pending permission escalations
├── permissions.log ← audit log
├── provider-health.sh ← failover state (sourced as bash)
├── daemon.pid, daemon.log ← daemon liveness
├── agent-docs/ ← cached provider docs (24h TTL)
├── specs/
│ ├── <TASK-ID>.md ← architect spec
│ ├── <TASK-ID>.review.md ← reviewer verdict
│ └── <TASK-ID>.pre-commit ← git hash captured before worker
└── sessions/
└── <TASK-ID>/
├── status ← single-line status (running / done / failed)
├── events.ndjson ← per-session event stream
├── architect.log ← phase log
├── worker.log
├── reviewer.log
├── fix-1.log, fix-2.log, …
├── respec.log ← if re-architect ran
└── approvals/
├── plan.json
└── diff.json
TASK-ID format¶
UTC, second precision. The CLI prints the assigned ID at the start of every devloop run. Use it with devloop session, devloop replay, devloop resume.
Reading sessions safely¶
The bash engine writes; the TUI and other consumers only read. To follow a session live:
Events are emitted with unbuffered printf >> ..., so a tailer sees each JSON line atomically. See Events Stream for the kind catalog.
Status file¶
.devloop/sessions/<TASK-ID>/status contains a single short string:
| Value | Meaning |
|---|---|
running | Pipeline is active |
done | Pipeline completed (look at the final session.end event for approved/rejected/needs-work) |
failed | Pipeline aborted due to error |
The TUI uses this for stuck-task detection alongside the DEVLOOP_STUCK_THRESHOLD_MIN heuristic.
Approvals¶
Each pre-flight gate ("approve this plan?", "approve this diff?") writes a JSON decision into approvals/:
You can settle a gate non-interactively by writing the file before the gate runs:
mkdir -p .devloop/sessions/$TASK_ID/approvals
echo '{"decision":"approve"}' > .devloop/sessions/$TASK_ID/approvals/plan.json
See Events Stream — approval.request for the gate kinds.
Retention¶
DEVLOOP_SESSION_KEEP_DAYS=30 # default — sessions older than this are auto-pruned
DEVLOOP_SESSION_KEEP_DAYS=0 # disable pruning (keep all)
devloop clean removes finalized (approved/rejected) specs older than --days N (default 30).