---
title: "Run Directory"
description: "Structure of Fabro's per-run directory"
---

<Warning>
  The run directory structure and file formats described here are internal implementation details and subject to change without notice. Do not build tooling that relies on them.
</Warning>

Each `fabro run` invocation creates a timestamped directory under `~/.fabro/runs/`:

```
~/.fabro/runs/20260307-01JQXYZ123ABC456DEF789/
```

The naming format is `YYYYMMDD-{run_id}`, where `run_id` is the ULID assigned to the run. You can override the location with `--run-dir`.

## Root-level files

| File | Format | When written | Description |
|---|---|---|---|
| `manifest.json` | JSON | Run start | Run metadata — `run_id`, `workflow_name`, `goal`, `start_time`, `node_count`, `edge_count`, `run_branch`, `base_sha`, `labels` |
| `graph.fabro` | Graphviz | Run start | Copy of the workflow graph |
| `run.pid` | Text | Run start | Process ID of the running CLI process. Presence indicates the run is active; an orphaned file indicates a crash. |
| `run.toml` | TOML | Run start | Copy of the original workflow file (only when the workflow is defined in TOML) |
| `progress.jsonl` | JSONL | Continuous | Event stream — one JSON object per line for every significant event (stage starts, completions, tool calls, retries, etc.). See [Observability](/execution/observability) for the full event catalog. |
| `live.json` | JSON | Continuous | Current execution state snapshot, overwritten on each event. Used for live monitoring. |
| `checkpoint.json` | JSON | After each node | Crash recovery state — `current_node`, `completed_nodes`, `node_retries`, `context_values`, `node_outcomes`, `next_node_id`, `git_commit_sha`, failure signatures. See [Checkpoints](/execution/checkpoints). |
| `conclusion.json` | JSON | Run end | Final result — `status`, `duration_ms`, `failure_reason`, `final_git_commit_sha`. Only present when the run completes (not for crashed or interrupted runs). |
| `final.patch` | Diff | Run end | Git diff from `base_sha` to final HEAD. Only present in git checkpoint mode. |
| `retro.json` | JSON | Run end | Post-run retrospective analysis — `smoothness_rating`, `learnings`, `friction_points`, `stages`. Omitted if `--no-retro` is passed. See [Retros](/execution/retros). |
| `cli.log` | Text | Continuous | Per-run tracing log. Contains the same tracing output as the daily log file, scoped to this run. |

## `nodes/` subdirectory

Each node execution writes artifacts into `nodes/{node_id}/`. When a node is retried, subsequent visits use `nodes/{node_id}-visit_{N}/` (where N starts at 2).

Every node gets a `status.json` after completion containing `status`, `notes`, `failure_reason`, and `timestamp`. The remaining files depend on the handler type:

**Agent and prompt nodes:**

| File | Description |
|---|---|
| `prompt.md` | The full prompt sent to the LLM |
| `response.md` | The LLM's response text |
| `status.json` | Execution status with routing outcome |

**Command nodes:**

| File | Description |
|---|---|
| `script_invocation.json` | Command metadata — `command`, `language`, `timeout_ms` |
| `stdout.log` | Standard output |
| `stderr.log` | Standard error |
| `script_timing.json` | Timing info — `duration_ms`, `exit_code`, `timed_out` |

**Nodes with git checkpointing:**

| File | Description |
|---|---|
| `diff.patch` | Git diff of changes made during this stage |

**Manager loop nodes:**

Manager nodes that run sub-workflows write a nested `child/` directory containing a full run structure (manifest, checkpoint, nodes, etc.).

## Other directories

**`worktree/`** — When running in git checkpoint mode, Fabro creates a Git worktree here as the working directory for agents and commands.

**`assets/`** — Test artifacts collected from the execution environment (Playwright reports, JUnit XML, Cypress screenshots/videos). Located at `worktree/assets/` for local runs or within node directories for remote sandbox runs.

## Browsing runs

Use `fabro ps` to scan the runs directory and display a table of all runs with their status, workflow name, and timestamps. Pass `--json` for machine-readable output.

```bash
fabro ps
fabro ps --json
fabro ps --filter workflow=my-workflow
```

## Full directory tree

```
~/.fabro/runs/
├── 20260307-01JQXYZ123ABC456DEF789/  # One directory per run
│   ├── manifest.json
│   ├── graph.fabro
│   ├── run.pid
│   ├── run.toml
│   ├── progress.jsonl
│   ├── live.json
│   ├── checkpoint.json
│   ├── conclusion.json
│   ├── final.patch
│   ├── retro.json
│   ├── cli.log
│   ├── nodes/
│   │   ├── plan/
│   │   │   ├── prompt.md
│   │   │   ├── response.md
│   │   │   └── status.json
│   │   ├── work/
│   │   │   ├── prompt.md
│   │   │   ├── response.md
│   │   │   ├── status.json
│   │   │   └── diff.patch
│   │   ├── work-visit_2/             # Retry of "work" node
│   │   │   ├── prompt.md
│   │   │   ├── response.md
│   │   │   ├── status.json
│   │   │   └── diff.patch
│   │   ├── test/
│   │   │   ├── script_invocation.json
│   │   │   ├── stdout.log
│   │   │   ├── stderr.log
│   │   │   ├── script_timing.json
│   │   │   └── status.json
│   │   └── manager/
│   │       ├── status.json
│   │       └── child/
│   │           ├── manifest.json
│   │           ├── checkpoint.json
│   │           └── nodes/
│   ├── worktree/                     # Git worktree (git checkpoint mode)
│   │   └── assets/                   # Test artifacts
│   └── assets/                       # Or here for remote sandboxes
```
