---
title: "CLI Reference"
description: "Fabro command-line interface reference"
---

## Global options

These flags apply to all subcommands:

| Flag | Description |
|---|---|
| `--debug` | Enable DEBUG-level logging (default is INFO) |
| `--no-upgrade-check` | Skip the automatic background upgrade check |
| `-h, --help` | Print help |
| `-V, --version` | Print version |

Fabro loads environment variables from `~/.fabro/.env`.

## Configuration

CLI defaults can be set in `~/.fabro/cli.toml` so you don't have to pass common flags every time:

```toml title="cli.toml"
[exec]
provider = "anthropic"
model = "claude-opus-4-6"
permissions = "read-write"
output_format = "text"

[llm]
model = "claude-sonnet-4-5"
```

CLI flags always override `cli.toml` values, which override hardcoded defaults.

---

## `fabro run`

Launch a workflow from a `.fabro` workflow file or `.toml` task config.

```bash
fabro run <WORKFLOW>
fabro run run.toml
fabro run --run-branch fabro/run/abc123
```

| Argument / Flag | Description |
|---|---|
| `<WORKFLOW>` | Path to a `.fabro` workflow file, `.toml` task config, or workflow name (resolved from `fabro/workflows/` in the project, then `~/.fabro/workflows/`). Not required when using `--run-branch`. |
| `--run-dir <DIR>` | Run output directory |
| `--dry-run` | Execute with a simulated LLM backend |
| `--preflight` | Validate run configuration without executing |
| `--auto-approve` | Auto-approve all human gates |
| `--resume <FILE>` | Resume from a checkpoint file |
| `--run-branch <BRANCH>` | Resume from a git run branch (reads checkpoint and graph from metadata branch) |
| `--model <MODEL>` | Override default LLM model |
| `--provider <PROVIDER>` | Override default LLM provider |
| `-v, --verbose` | Enable verbose output |
| `--sandbox <SANDBOX>` | Sandbox for agent tools: `local`, `docker`, `daytona`, `ssh`, or `exe` |
| `--label <KEY=VALUE>` | Attach a label to this run (repeatable) |
| `--goal <GOAL>` | Override the workflow goal (exposed as `$goal` in prompts) |
| `--goal-file <FILE>` | Read the goal from a file instead of inline text |
| `--no-retro` | Skip retro generation after the run |
| `--ssh` | Create SSH access to the sandbox (Daytona or exe.dev) and print the connection command |
| `--preserve-sandbox` | Keep the sandbox alive after the run finishes (for debugging) |
| `-d, --detach` | Fork the workflow as a background process and print the run ID. Reconnect later with `fabro logs -f`. |

<Note>
`--preflight` conflicts with `--resume`, `--run-branch`, `--dry-run`, and `--detach`. `--run-branch` conflicts with `--resume`.
</Note>

## `fabro ps`

List workflow runs. By default, shows only active (running) runs — similar to `docker ps`. Use `-a` to include completed runs.

```bash
fabro ps            # active runs only
fabro ps -a         # all runs including completed
fabro ps --workflow deploy --label env=prod
fabro ps --json
```

The table shows run ID, status, workflow name, goal, and timing.

| Flag | Description |
|---|---|
| `-a, --all` | Show all runs, not just active ones |
| `--before <DATE>` | Only show runs started before this date (YYYY-MM-DD prefix match) |
| `--workflow <NAME>` | Filter by workflow name (substring match) |
| `--label <KEY=VALUE>` | Filter by label (repeatable, AND semantics) |
| `--orphans` | Include orphan directories (no `manifest.json`) |
| `--json` | Output as JSON |

## `fabro rm`

Remove one or more workflow runs by ID or workflow name. Cleans up both the run directory and any associated sandbox.

```bash
fabro rm <RUN>...
fabro rm abc123
fabro rm my-workflow --force
```

| Argument / Flag | Description |
|---|---|
| `<RUN>...` | Run IDs or workflow names to remove (required, repeatable) |
| `-f, --force` | Force removal of active runs |

## `fabro system prune`

Delete old workflow runs. Dry-run by default — pass `--yes` to actually delete.

```bash
fabro system prune --before 2026-01-01
fabro system prune --before 2026-01-01 --yes
fabro system prune --orphans --yes
```

| Flag | Description |
|---|---|
| `--before <DATE>` | Only prune runs started before this date (YYYY-MM-DD prefix match) |
| `--workflow <NAME>` | Filter by workflow name (substring match) |
| `--label <KEY=VALUE>` | Filter by label (repeatable, AND semantics) |
| `--orphans` | Include orphan directories (no `manifest.json`) |
| `--yes` | Actually delete (default is dry-run) |

---

## `fabro exec`

Run an agentic coding session. The agent operates in the current directory using file, search, and shell tools.

```bash
fabro exec "Add input validation to the signup form"
fabro exec "Fix the failing test" --provider openai --model gpt-5.2-codex
fabro exec "Refactor the auth module" --permissions full --auto-approve
```

| Argument / Flag | Description | Default |
|---|---|---|
| `<PROMPT>` | Task prompt (required) | — |
| `--provider <PROVIDER>` | LLM provider | `anthropic` |
| `--model <MODEL>` | Model name | Per provider (see below) |
| `--permissions <LEVEL>` | Permission level: `read-only`, `read-write`, or `full` | `read-write` |
| `--auto-approve` | Skip interactive prompts; deny tools outside permission level | — |
| `--debug` | Print LLM request/response debug info to stderr | — |
| `--verbose` | Print full LLM request/response JSON to stderr | — |
| `--skills-dir <DIR>` | Directory containing skill files (overrides default discovery) | — |
| `--output-format <FORMAT>` | Output format: `text` (human-readable) or `json` (NDJSON event stream) | `text` |
| `--mode <MODE>` | `standalone` (default) or `server` — in server mode, routes through the Fabro API's `/completions` endpoint | `standalone` |
| `--server-url <URL>` | Fabro API server URL (overrides `server.base_url` from `cli.toml`) | — |

Permission levels control which tools are auto-approved: `read-only` allows read tools (`read_file`, `grep`, `glob`, `list_dir`) and subagent tools; `read-write` adds write tools (`write_file`, `edit_file`, `apply_patch`); `full` allows all tools including shell commands. Tools outside the permission level are either interactively prompted (if a TTY is present) or denied (with `--auto-approve`). See [default models by provider](/core-concepts/models#default-models).

---

## `fabro llm prompt`

Send a one-shot prompt to an LLM. Accepts a prompt as an argument, via stdin, or both (stdin is prepended).

```bash
fabro llm prompt "Explain quicksort in one paragraph"
echo "Summarize this:" | fabro llm prompt
fabro llm prompt "Translate to French" -m claude-sonnet-4-5 -o temperature=0.3
fabro llm prompt -S '{"type":"object","properties":{"name":{"type":"string"}}}' "Extract the name from: John Smith"
```

| Argument / Flag | Description |
|---|---|
| `[PROMPT]` | The prompt text (also accepts stdin) |
| `-m, --model <MODEL>` | Model to use |
| `-s, --system <SYSTEM>` | System prompt |
| `--no-stream` | Do not stream output |
| `-u, --usage` | Show token usage |
| `-S, --schema <SCHEMA>` | JSON schema for structured output (inline JSON string) |
| `-o, --option <KEY=VALUE>` | Generation options: `temperature`, `max_tokens`, `top_p`, or provider-specific keys |

## `fabro llm chat`

Start an interactive multi-turn chat session. In server mode, the session is backed by the Fabro server's session endpoints.

```bash
fabro llm chat
fabro llm chat -m claude-opus-4-6 -s "You are a helpful coding assistant"
fabro llm chat --mode server
```

| Flag | Description |
|---|---|
| `-m, --model <MODEL>` | Model to use |
| `-s, --system <SYSTEM>` | System prompt |
| `--mode <MODE>` | `standalone` (default) or `server` — in server mode, routes through the Fabro API |

---

## `fabro model list`

List available LLM models from the built-in catalog. Running `fabro model` with no subcommand also lists models.

```bash
fabro model list
fabro model list -p anthropic
fabro model list -q sonnet
fabro model list --mode server
```

| Flag | Description |
|---|---|
| `-p, --provider <PROVIDER>` | Filter by provider |
| `-q, --query <QUERY>` | Search for models matching this string (checks ID, display name, and aliases) |
| `--mode <MODE>` | `standalone` (default) or `server` — in server mode, fetches the catalog from the Fabro API |

## `fabro model test`

Test model availability by sending a simple prompt to each model and reporting the result.

```bash
fabro model test
fabro model test -p anthropic
fabro model test -m claude-sonnet-4-5
```

| Flag | Description |
|---|---|
| `-p, --provider <PROVIDER>` | Filter by provider |
| `-m, --model <MODEL>` | Test a specific model |

---

## `fabro serve`

Start the HTTP API server that exposes the [REST API](/api-reference) for launching and managing workflow runs.

```bash
fabro serve
fabro serve --port 8080 --host 0.0.0.0
fabro serve --sandbox daytona --max-concurrent-runs 4
```

| Flag | Description | Default |
|---|---|---|
| `--port <PORT>` | Port to listen on | `3000` |
| `--host <HOST>` | Host address to bind to | `127.0.0.1` |
| `--model <MODEL>` | Override default LLM model | — |
| `--provider <PROVIDER>` | Override default LLM provider | — |
| `--dry-run` | Execute with simulated LLM backend | — |
| `--sandbox <SANDBOX>` | Sandbox for agent tools: `local`, `docker`, `daytona`, `ssh`, or `exe` | — |
| `--max-concurrent-runs <N>` | Maximum number of concurrent run executions | — |
| `--config <PATH>` | Path to server config file | `~/.fabro/server.toml` |

Demo mode is per-request: send the `X-Fabro-Demo: 1` header to get static demo data with auth disabled.

If no LLM provider API keys are configured, the server automatically falls back to dry-run mode.

---

## `fabro cp`

Copy files between a run's sandbox and the local filesystem. The run must have a persisted sandbox record (Daytona, exe.dev, or a preserved local/Docker sandbox).

```bash
fabro cp <run-id>:/path/in/sandbox ./local-dir     # download
fabro cp ./local-file <run-id>:/path/in/sandbox     # upload
fabro cp -r <run-id>:/output ./results              # recursive download
```

| Argument / Flag | Description |
|---|---|
| `<SRC>` | Source: `<run-id>:<path>` for sandbox, or a local path |
| `<DST>` | Destination: `<run-id>:<path>` for sandbox, or a local path |
| `-r, --recursive` | Recurse into directories |

Run IDs support prefix matching — you can use the first few characters instead of the full ID.

## `fabro pr`

Manage GitHub pull requests created by workflow runs. Requires a [GitHub App](/integrations/github) to be configured.

### `fabro pr create`

Create a GitHub pull request from a completed workflow run. Uses the run's persisted manifest, conclusion, and diff.

```bash
fabro pr create <run-id>
fabro pr create <run-id> --model claude-opus-4-6
```

| Argument / Flag | Description |
|---|---|
| `<RUN_ID>` | Run ID or prefix (required) |
| `--model <MODEL>` | LLM model for generating the PR description |

The run must have completed successfully (or with partial success) and have a `final.patch` with changes.

### `fabro pr list`

List all pull requests created by workflow runs. Shows PR number, title, status, and the associated run ID.

```bash
fabro pr list
fabro pr list --all
```

| Flag | Description |
|---|---|
| `--all` | Include closed and merged PRs (default: open only) |

### `fabro pr view`

Show details of a pull request from a specific run.

```bash
fabro pr view <run-id>
```

| Argument | Description |
|---|---|
| `<RUN_ID>` | Run ID or prefix (required) |

### `fabro pr merge`

Merge a pull request from a specific run.

```bash
fabro pr merge <run-id>
fabro pr merge <run-id> --method rebase
```

| Argument / Flag | Description |
|---|---|
| `<RUN_ID>` | Run ID or prefix (required) |
| `--method <METHOD>` | Merge method: `squash` (default), `merge`, or `rebase` |

### `fabro pr close`

Close a pull request from a specific run without merging.

```bash
fabro pr close <run-id>
```

| Argument | Description |
|---|---|
| `<RUN_ID>` | Run ID or prefix (required) |

---

## `fabro system df`

Show disk usage of Fabro's data directory, including run logs, worktrees, server logs, and databases.

```bash
fabro system df
fabro system df -v
```

| Flag | Description |
|---|---|
| `-v, --verbose` | Show per-run breakdown |

## `fabro graph`

Render a workflow DOT graph as SVG or PNG. Requires [Graphviz](https://graphviz.org) (`dot`) to be installed.

```bash
fabro graph workflow.fabro
fabro graph workflow.fabro --format png -o diagram.png
fabro graph run.toml --format svg
```

| Argument / Flag | Description |
|---|---|
| `<WORKFLOW>` | Path to a `.fabro` workflow file or `.toml` run config (required) |
| `--format <FORMAT>` | Output format: `svg` (default) or `png` |
| `-o, --output <FILE>` | Output file path. Defaults to stdout. |
| `-d, --direction <DIR>` | Graph direction: `lr` or `tb`. If omitted, uses the DOT file's own `rankdir`. |

## `fabro skill install`

Install the built-in `fabro-create-workflow` skill for AI assistants (Claude Code, Codex). The skill teaches AI assistants Fabro's DOT syntax, node types, and run configuration format.

```bash
# Install into the current project (.claude/skills/ or .agents/skills/)
fabro skill install --for project --dir claude

# Install for all projects (user-level, ~/.claude/skills/)
fabro skill install --for user --dir claude
```

| Flag | Description |
|---|---|
| `--for <SCOPE>` | `user` (default) — installs to `~/<dir>/skills/`. `project` — installs to `./<dir>/skills/`. |
| `--dir <DIR>` | Directory convention: `claude` (`.claude/skills/`) or `agents` (`.agents/skills/`). Required. |
| `--force` | Overwrite an existing installation without prompting. |

## `fabro rewind`

Rewind a workflow run to an earlier checkpoint. This resets both the run branch and metadata branch refs so that `fabro run --run-branch` resumes from the target checkpoint.

```bash
fabro rewind <RUN_ID> [TARGET]
fabro rewind <RUN_ID> --list
```

| Argument / Flag | Description |
|---|---|
| `<RUN_ID>` | Run ID or unambiguous prefix (required) |
| `[TARGET]` | Checkpoint to rewind to: node name, `node@visit`, or `@ordinal` (1-based). Omit to show the timeline. |
| `--list` | Show the checkpoint timeline instead of rewinding |
| `--no-push` | Skip force-pushing rewound refs to the remote |

Target formats:

| Format | Example | Meaning |
|---|---|---|
| `node` | `plan` | Most recent visit of the named node |
| `node@N` | `plan@2` | The 2nd visit of the named node |
| `@N` | `@3` | The 3rd checkpoint in sequence |

After rewinding, resume from the earlier point:

```bash
fabro run --run-branch fabro/run/<RUN_ID>
```

See [Checkpoints](/execution/checkpoints#rewinding-to-an-earlier-checkpoint) for background on how checkpointing works.

## `fabro fork`

Fork a new run from an existing run's checkpoint. Unlike `fabro rewind`, which resets the original run in place, `fabro fork` creates an independent copy — the original run stays intact.

```bash
fabro fork <RUN_ID> [TARGET]
fabro fork <RUN_ID> --list
```

| Argument / Flag | Description |
|---|---|
| `<RUN_ID>` | Run ID or unambiguous prefix (required) |
| `[TARGET]` | Checkpoint to fork from: node name, `node@visit`, or `@ordinal` (1-based). Omit to fork from the latest checkpoint. |
| `--list` | Show the checkpoint timeline instead of forking |
| `--no-push` | Skip pushing new branches to the remote |

Target formats are the same as [`fabro rewind`](#fabro-rewind). After forking, resume the new run:

```bash
fabro run --run-branch fabro/run/<NEW_RUN_ID>
```

See [Checkpoints — Forking a run](/execution/checkpoints#forking-a-run) for when to use fork vs. rewind.

## `fabro logs`

View the event log of a workflow run. Runs can be referenced by ID prefix or workflow name (uses the most recent run).

```bash
fabro logs my-workflow
fabro logs abc123 --pretty
fabro logs -f my-workflow -p
```

| Argument / Flag | Description |
|---|---|
| `<RUN>` | Run ID prefix or workflow name (required) |
| `-f, --follow` | Follow log output in real time |
| `-p, --pretty` | Formatted colored output with rendered assistant messages and tool calls |
| `--since <TIMESTAMP>` | Show logs since a timestamp or relative duration (e.g. `42m`, `2h`, `2026-01-02T13:00:00Z`) |
| `-n, --tail <N>` | Show only the last N lines |

## `fabro inspect`

Show detailed JSON data for a workflow run, including its manifest, conclusion, checkpoint, and sandbox record.

```bash
fabro inspect <RUN>
fabro inspect abc123
```

| Argument | Description |
|---|---|
| `<RUN>` | Run ID prefix or workflow name (required) |

## `fabro workflow list`

List all available workflows in the current project. Shows workflows from both the project directory and user-level `~/.fabro/workflows/`, grouped by source with descriptions pulled from each workflow's goal.

```bash
fabro workflow list
```

## `fabro workflow create`

Scaffold a new workflow in the project's workflows directory. Creates a `workflow.fabro` graph file and a `workflow.toml` run config.

```bash
fabro workflow create my-workflow
fabro workflow create my-workflow --goal "Run the CI pipeline"
```

| Argument / Flag | Description |
|---|---|
| `<NAME>` | Name of the workflow (required) |
| `-g, --goal <GOAL>` | Goal description for the workflow |

Requires a `fabro.toml` project config in the current directory or a parent.

---

## `fabro validate`

Validate a workflow file without executing it. Reports errors and warnings. Accepts both `.fabro` workflow files and `.toml` run configs.

```bash
fabro validate workflow.fabro
fabro validate run.toml
```

| Argument | Description |
|---|---|
| `<WORKFLOW>` | Path to a `.fabro` workflow file or `.toml` run config (required) |

## `fabro parse`

Parse a DOT file and print its AST as JSON. Useful for debugging workflow definitions.

```bash
fabro parse workflow.fabro
```

| Argument | Description |
|---|---|
| `<WORKFLOW>` | Path to the `.fabro` workflow file (required) |

---

## `fabro init`

Initialize a new Fabro project in the current git repository. Creates an `fabro.toml` project config and a sample `hello` workflow.

```bash
fabro init
```

The command must be run inside a git repository. It creates:
- `fabro.toml` — project configuration with comments and a link to docs
- `fabro/workflows/hello/workflow.fabro` — a simple greeting workflow
- `fabro/workflows/hello/workflow.toml` — run config for the hello workflow

## `fabro diff`

Show the diff from a workflow run. Displays the `final.patch` for completed runs, or connects to the sandbox for a live diff from in-progress runs.

```bash
fabro diff <run-id>
fabro diff <run-id> --node work
fabro diff <run-id> --stat
```

| Argument / Flag | Description |
|---|---|
| `<RUN>` | Run ID or prefix (required) |
| `--node <NODE>` | Show diff for a specific node instead of the full run |
| `--stat` | Show diffstat instead of full patch (live diffs only) |
| `--shortstat` | Show only files-changed/insertions/deletions summary (live diffs only) |

Output is colorized when writing to a terminal.

## `fabro ssh`

SSH into a Daytona sandbox from a completed or in-progress run. Creates temporary SSH credentials and connects directly, or prints the command with `--print`.

```bash
fabro ssh <run-id>
fabro ssh <run-id> --print
fabro ssh <run-id> --ttl 120
```

| Argument / Flag | Description |
|---|---|
| `<RUN>` | Run ID or prefix (required) |
| `--ttl <MINUTES>` | SSH credential expiry in minutes (default: 60) |
| `--print` | Print the SSH command instead of connecting |

See [SSH Access](/human-tools/ssh-access) for more details on SSH workflows.

## `fabro preview`

Generate a preview URL for a port exposed by a Daytona sandbox. Useful for accessing web servers, dev tools, or APIs running inside the sandbox.

```bash
fabro preview <run-id> <port>
fabro preview <run-id> 3000 --signed
fabro preview <run-id> 3000 --open
```

| Argument / Flag | Description |
|---|---|
| `<RUN>` | Run ID or prefix (required) |
| `<PORT>` | Port number to preview (required) |
| `--signed` | Generate a signed URL (self-contained, no headers needed) |
| `--ttl <SECONDS>` | Signed URL expiry in seconds (default: 3600, requires `--signed`) |
| `--open` | Open the URL in a browser (implies `--signed`) |

Without `--signed`, the command prints the URL, token, and a `curl` example. See [Preview](/human-tools/preview) for more details.

---

## `fabro doctor`

Check environment and integration health. Verifies system dependencies, API keys, and optional services. Probes live services (LLM providers, sandbox, GitHub App) by default.

```bash
fabro doctor
fabro doctor -v
fabro doctor --dry-run
```

| Flag | Description |
|---|---|
| `-v, --verbose` | Show detailed information for each check |
| `--dry-run` | Skip live service probes (LLM, sandbox, API, web, Brave Search) |

## `fabro upgrade`

Download and install a newer version of Fabro from GitHub releases. Verifies the download with SHA256 checksums and atomically replaces the binary.

```bash
fabro upgrade
fabro upgrade --dry-run
fabro upgrade --version 0.6.0
```

| Flag | Description |
|---|---|
| `--version <VERSION>` | Target version (e.g. `0.5.0` or `v0.5.0`). Defaults to the latest release. |
| `--force` | Upgrade even if already on the target version |
| `--dry-run` | Preview what would happen without making changes |

Fabro refuses to downgrade unless you specify an explicit `--version`. A daily background check notifies you when a new version is available — disable it with `upgrade_check = false` in [`cli.toml`](/reference/cli-configuration#upgrade_check) or the `--no-upgrade-check` global flag.

## `fabro asset list`

List assets (screenshots, test reports, traces) collected from a workflow run.

```bash
fabro asset list <RUN_ID>
fabro asset list <RUN_ID> --node verify --json
```

| Argument / Flag | Description |
|---|---|
| `<RUN_ID>` | Run ID or unambiguous prefix (required) |
| `--node <NODE>` | Filter to assets from a specific node |
| `--json` | Output as JSON |

## `fabro asset cp`

Copy assets from a workflow run to the local filesystem.

```bash
fabro asset cp <RUN_ID> ./output               # all assets, flat
fabro asset cp <RUN_ID> ./output --tree         # preserve directory structure
fabro asset cp <RUN_ID>:report.html ./output    # specific file
```

| Argument / Flag | Description |
|---|---|
| `<SOURCE>` | `RUN_ID` (all assets) or `RUN_ID:path` (specific file) |
| `[DEST]` | Destination directory (defaults to `.`) |
| `--node <NODE>` | Filter to assets from a specific node |
| `--tree` | Preserve `{node}/{retry}/` directory structure |

When copying all assets in flat mode, filenames must be unique across nodes. Use `--tree` or `--node` to disambiguate.

## `fabro install`

Interactive setup wizard that walks you through configuring API keys and validating your environment. Runs `fabro doctor` with live probes after setup to validate the configuration.

```bash
fabro install
```
