---
title: "Run forking, self-update, and Docker-style fabro ps"
date: "2026-03-15"
---

## Non-destructive run forking

You can now branch a new run from any checkpoint in an existing run with `fabro fork`. Unlike `fabro rewind`, which rewinds the original run in place, `fabro fork` creates an independent copy — the original run stays intact. This is useful for exploring alternate paths from a checkpoint without losing the work that came after it.

```bash
fabro fork <run_id> plan        # fork from the "plan" node
fabro fork <run_id> review@2    # fork from the 2nd visit of "review"
fabro fork <run_id> @3          # fork from checkpoint index 3
```

## Self-update with fabro upgrade

Fabro can now update itself. For self-managed installs, `fabro upgrade` downloads the latest release from GitHub, verifies its SHA256 checksum, and atomically replaces the binary. Downgrade protection prevents accidentally installing an older version (override with `--force`). On Homebrew installs, `fabro upgrade` leaves the Homebrew-managed binary alone and prints the matching `brew upgrade fabro` or `brew upgrade fabro-nightly` command instead. A daily background check notifies you when a new version is available — disable it with `upgrade_check = false` in `~/.fabro/cli.toml` or `--no-upgrade-check`.

```bash
fabro upgrade             # upgrade to latest
fabro upgrade --dry-run   # check without installing
```

## Docker-style process listing

`fabro ps` has been rebuilt to behave like `docker ps`. It now shows a table with run ID, status, workflow name, goal, and timing — making it easy to see what's running at a glance. Run status is tracked via a proper state machine, so status transitions are reliable and `fabro ps` always reflects the current state.

```bash
fabro ps        # active runs
fabro ps -a     # all runs including completed
```

<Warning>
**`[feature_flags]` renamed to `[features]`.** If your `fabro.toml` uses `[feature_flags]`, rename the section to `[features]`.
</Warning>

<Warning>
**Retros are now experimental and disabled by default.** If you use retros, enable them explicitly with `retros = true` under `[features]` in your `fabro.toml`.
</Warning>

## More

<Accordion title="CLI">
- Added `fabro artifact list` to view run artifacts and `fabro artifact cp` to copy them locally with optional `--tree` directory structure
- Added `fabro rm` command to remove runs by ID with sandbox cleanup
- Added `--direction` (`-d`) flag to `fabro graph` for overriding layout direction (`lr` or `tb`)
- Added `-p` short alias for `--pretty` in `fabro logs`
- Added progress spinner during `run --preflight`
</Accordion>

<Accordion title="Workflows">
- Added `auto_merge = true` in `[pull_request]` config to enable GitHub auto-merge on created PRs, with configurable `merge_strategy` (squash/merge/rebase)
- `fabro init` now generates `[pull_request]` with `enabled = true` and `draft = true` by default
- Added `selection="random"` node attribute for weighted-random edge selection in workflow graphs
- GitHub App installation tokens are now automatically injected into sandboxes as `GITHUB_TOKEN`
- Workflow PRs now open as ready-for-review by default (control with `[pull_request] draft = false`)
- Metadata branch renamed from `refs/fabro/{run_id}` to `fabro/meta/{run_id}` for cleaner ref namespace
- Added granular git checkpoint events and retro lifecycle events (`RetroStarted`, `RetroCompleted`, `RetroFailed`)
- `goal` field now included in `WorkflowRunStarted` event and rendered in `fabro logs --pretty`
- Run completion events now include final status and usage totals
</Accordion>

<Accordion title="Improvements">
- Command output in stage preambles now truncated to the last 25-50 lines, reducing token waste from verbose build logs
- Artifact collection now enforces a 100-file limit and excludes `.venv`, `venv`, `.cache`, `.tox`, `.pytest_cache`, `.mypy_cache`, and `dist` directories
- Unified dry-run behavior across all handler types — wait and human-in-the-loop nodes now properly simulate without side effects
</Accordion>

<Accordion title="Fixes">
- Fixed sub-agent file writes not being tracked in the API backend, causing downstream stages to receive incomplete file lists
- Fixed `--dry-run` executing command/script nodes instead of simulating them
- Fixed `--dry-run` pushing branches to remote
- Fixed `--goal-file` not expanding `~` to the home directory
- Fixed race condition between `fabro run --detach` and `fabro logs -f`
- Fixed dry-run runs cluttering `fabro ps -a` output (now uses temp directory)
</Accordion>
