> ## Documentation Index
> Fetch the complete documentation index at: https://docs.prbe.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI overview

> Grammar, how to address an entity, and why most writes return before the server answers.

```bash theme={null}
probe --help
```

The CLI is a thin shell over [the SDK](/sdk/quickstart.md) — same implementation, different ergonomics, so the two have capability parity.

> [!NOTE]
>
> **Setting the device up is the wizard's job, not the CLI's.** Installing, updating, uninstalling, signing in, switching accounts, turning capture or tracking on or off, and importing existing work all have a screen in [the wizard](/wizard/overview.md) that shows you the current state before it changes anything.
>
> The commands below are the scriptable half of those screens. Throughout these docs a **Wizard / Command** toggle marks a feature that has both — use whichever suits where you are.

## Grammar

Connection flags are **global** and go *before* the command:

```bash theme={null}
probe --base-url https://api.example.internal log $RUN loss=0.1
probe --spool-dir /shared/probe/spool log $RUN loss=0.1
```

Signing in to another endpoint takes it as a flag: `probe wizard --action login --base-url <url>`.

| Global flag | Effect |
| - | - |
| `--base-url` | Override the endpoint |
| `--spool-dir` | The outbox journal directory (or `PROBE_OUTBOX_DIR`) |
| `--async` / `--sync` | Queue writes, or block until the server answers |
| `--version` | Print the version |

## Addressing an entity

> [!WARNING]
>
> **A bare ref is the slug. An id is written `id:<uuid>`.**
>
> ```bash theme={null}
> probe project delete folding                    # the slug
> probe project delete id:6fa49e87-...            # the id
> ```
>
> Nothing is ever tried two ways, so a ref cannot mean two things. A bare UUID is refused as an unknown slug rather than resolved as an id.

The rule exists because the clever version was worse. With a resolver that tried a UUID first, a project whose *slug* happened to be another project's *id* meant `probe project delete <that string>` deleted the wrong project — exit 0, a `deleted` line echoing the ref, nothing to restore. Refusing an ambiguous question is a good answer; not being able to ask one is better.

## Async by default

Some writes queue locally and return immediately. Some do not. The split is deliberate.

| Command | Default |
| - | - |
| `probe log` | **Queued** — a training loop must not wait on the network |
| `probe span add` | **Queued** |
| `probe artifact add` (run anchor) | **Queued** |
| `probe run end` | **Blocks** — it is the delivery barrier |
| Everything else | Synchronous |

`PROBE_ASYNC=0` turns queueing off for the three that have it. `--async` on `run end` skips the barrier. Both flags are also accepted *after* the subcommand, where they win.

> [!NOTE]
>
> Queued writes are fsynced and atomic, and survive a crash. `probe flush` (an alias of `probe outbox drain`) delivers everything and waits. See [the outbox](/cli/outbox.md).

## Scoping

Most commands default to the active workspace and project of the current context:

```bash theme={null}
probe workspace use engineering
probe project use folding

probe run start --experiment dockq        # no --project needed
```

`probe workspace use` sets **this computer's workspace**: every new project made on this computer, by the CLI, the Probe daemon or an SDK run, is filed there. The install asks for it when your team has more than one workspace. On such a team with none set, creating a project is refused rather than guessed.

The active account is the wizard's to switch (`probe wizard --action account`); `probe context list` shows which one is answering.

Override per call with `--workspace-id`, `--workspace`, or `--project`.

## Reading output

Every read command prints JSON, so `jq` works everywhere:

```bash theme={null}
probe get $RUN | jq -r '.status'
probe project get folding | jq -r '.description'
probe run list --experiment dockq | jq -r '.items[].name'
```

A project's or experiment's summary (its Overview page) is not part of `get`. Whoever records the work keeps it, and `probe summary checkout --project folding` writes it to a file you can read or edit. See [Summaries](/tracking/summaries.md).

## Exit codes

| Code | Meaning |
| - | - |
| `0` | Success |
| `1` | Failure — the reason is printed |
| `2` | Unknown command or bad arguments — and the specific verdict of `probe run check` (incomplete) and `probe outbox status` (undelivered) |

Those two commands use exit 2 as an *answer*, not an error, so they compose into scripts:

```bash theme={null}
probe outbox status || echo "still undelivered"
probe run check $RUN --verify || echo "not reproducible yet"
```

> **[Every command](/cli/commands.md)**
>
> Every command group, with what each one is for.

> **[Authentication](/cli/auth.md)**
>
> Device flow, tokens, contexts, and the read-only MCP credential.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.