# shelbi zen

Toggle Zen Mode and run the exact-provenance merge primitives the orchestrator sequences.

```text
shelbi zen <SUBCOMMAND> [OPTIONS]
```

`shelbi zen` is the CLI face of [Zen Mode](/docs/concepts/zen-mode).
The toggle subcommands (`on`, `off`, `pause`, `status`) flip the
project's mode in `state.json` and write a `mode=zen <prev> -> <new>
reason=user:cli` line to `~/.shelbi/events.log`. The orchestrator
reads those events to know when to switch behavior.

The remaining subcommands are single-purpose primitives. The
orchestrator sequences them per the merge-conditions policy in the
project's [`zenmode.md`](/docs/concepts/zen-mode#the-zenmodemd-file)
file; each one does exactly one thing and prints a single line on
stdout. The same primitives are available to you at the shell when
you want to probe a branch or open a PR by hand without flipping the
global mode.

Every subcommand accepts the global `-p / --project <PROJECT>` flag, omitted
from the per-subcommand tables.

## on

```text
shelbi zen on
```

Turn Zen Mode on. The orchestrator may auto-promote and auto-merge finished
work through the exact-provenance PR flow. Idempotent. Mirrors
`Alt+Z` in the TUI.

## off

```text
shelbi zen off
```

Turn Zen Mode off. Every promotion goes through manual review.
In-flight workspaces keep going; nothing already running is cancelled.

## pause

```text
shelbi zen pause
```

Pause Zen Mode: no *new* auto-promotions, but tasks already on the
Zen track may still complete their merge flow. Use this to triage incoming
work yourself while preserving work already in motion.

## status

```text
shelbi zen status
```

Print the current mode, the project's configured local check
commands, the resolved danger-paths list (with detected project
shapes labeled inline), the last crash timestamp (if any), and the
count of in-flight tasks on the Zen track. Cheap and safe to call
repeatedly.

## scan

```text
shelbi zen scan
```

Print backlog task ids that are *mechanically* eligible for Zen
auto-promotion, one per line, in priority order. "Mechanical" means
not blocked on dependencies, not opted out via task frontmatter, and
no file overlap with anything currently in flight. The orchestrator's
prompt applies the judgment categories on top of this list. See
[the judgment layer](/docs/concepts/zen-mode#the-judgment-layer).

## dry-run

```text
shelbi zen dry-run [OPTIONS]
```

Preview what Zen Mode would do without changing task, board, PR, or branch
state. On every tick the backlog scan and merge-conditions bar are evaluated,
and each "would have …" decision is logged to stdout, the dedicated dry-run
log (`~/.shelbi/logs/zen-dryrun.log`), and the activity feed.
No PRs, merges, or board moves happen. Use it before flipping Zen on
for real to confirm the policy matches your intent.

| Flag | Type | Default | Description |
| --- | --- | --- | --- |
| `--for <DURATION>` | duration | run until Ctrl-C | Stop after this long. Accepts `30s`, `5m`, `2h`, `1d`, or a bare integer of seconds. |
| `--interval <DURATION>` | duration | `5s` | Override the per-tick interval. Same duration grammar as `--for`. |

## probe

```text
shelbi zen probe <ID>
```

Run every readiness probe for the task and print the full report as
pretty JSON. Covers the four pre-PR conditions the orchestrator
checks before opening a PR: local checks, merge-conflict probe, diff
size, and danger-path matches.

The task must be assigned to a workspace so the probe can locate the
repository that holds its named branch. Shelbi checks out that exact branch
commit in an isolated temporary worktree, so a newer task reusing the assigned
workspace is not modified or tested by mistake. A successful rebase advances
the durable task branch. The report freezes `repository`, `repository_id`,
`base_branch`, `base_sha`, `integration_sha`, and `head_sha`. Together those fields identify the
exact repository and workflow base used for every check and fact, plus the
reviewed task commit and exact squash candidate. Pass the same six values to
every later PR command.

| Argument | Type | Default | Description |
| --- | --- | --- | --- |
| `<ID>` | string | — | Task id to probe (required). |

## pr-create

```text
shelbi zen pr-create <ID> --match-repository <REPOSITORY> --match-repository-id <REPOSITORY_ID> --match-base-branch <BRANCH> --match-base-commit <BASE_SHA> --match-integration-commit <INTEGRATION_SHA> --match-head-commit <HEAD_SHA>
```

Push the task's named branch and open a PR. Idempotent. If an open PR for
the branch already exists, Shelbi updates the branch and returns its number
only after the PR head matches the exact task branch commit that was pushed.
Otherwise, it opens a new PR. Prints the PR number on stdout.

Reuse also requires the exact task branch, resolved workflow base branch and
commit, and `origin` repository identity. A same-named PR aimed at another
base or coming from another repository is rejected.

All six `--match-*` flags are required. Copy them from the immediately
preceding `probe` report without re-resolving configuration or `origin`.
Shelbi rejects the operation if any part of that identity moved after the
probe, so mutable workflow, remote, or branch state cannot silently replace
what was reviewed.

| Argument or flag | Type | Default | Description |
| --- | --- | --- | --- |
| `<ID>` | string | — | Task id whose branch to push and PR (required). |
| `--match-repository <REPOSITORY>` | string | required | Require the `origin` repository selector to equal probe `repository`. |
| `--match-repository-id <REPOSITORY_ID>` | string | required | Require the immutable GitHub repository id to equal probe `repository_id`. |
| `--match-base-branch <BRANCH>` | string | required | Require the PR target to equal probe `base_branch`. |
| `--match-base-commit <SHA>` | string | required | Require the resolved target commit to equal probe `base_sha`. |
| `--match-integration-commit <SHA>` | string | required | Require the published PR head to equal probe `integration_sha`. |
| `--match-head-commit <SHA>` | string | required | Require the durable task branch to match probe `head_sha`. |

## ci-watch

```text
shelbi zen ci-watch <PR_NUMBER> --match-repository <REPOSITORY> --match-repository-id <REPOSITORY_ID> --match-base-branch <BRANCH> --match-base-commit <BASE_SHA> --match-integration-commit <INTEGRATION_SHA> --match-head-commit <HEAD_SHA> [OPTIONS]
```

Watch the PR's checks until they settle or the timeout fires. Prints one of:

- `green` — every watched check passed; exit 0.
- `red:<check>:<summary>` — at least one check failed; exit 1.
- `timeout` — checks still pending when the deadline hit; exit 2.

Which checks it watches is auto-selected from the target branch: with
branch-protection required checks configured, it watches only those; on an
unprotected branch (or one with no required set) it falls back to every check
reported on the PR and requires GitHub's merge state to be clean. When required
rows exist, a blocked merge state keeps waiting for a required context that has
not reported, while an optional failed check does not override passing required
checks.

All six `--match-*` values must be the unchanged probe identity passed to
`pr-create`. Each poll verifies that original repository, base name and commit,
and head commit. Shelbi reads the PR identity and status rollup together,
including which contexts are required, and grades that one atomic snapshot.
There is no separate check-result read that a brief A-to-B-to-A head change
could confuse. Incomplete, paginated, or moved-head results fail closed and
the whole pinned flow must restart from a fresh probe.

| Flag | Type | Default | Description |
| --- | --- | --- | --- |
| `<PR_NUMBER>` | integer | — | The PR number returned by `pr-create` (required). |
| `--match-repository <REPOSITORY>` | string | required | Require probe `repository` on every snapshot. |
| `--match-repository-id <REPOSITORY_ID>` | string | required | Require probe `repository_id` on every snapshot. |
| `--match-base-branch <BRANCH>` | string | required | Require probe `base_branch` on every snapshot. |
| `--match-base-commit <SHA>` | string | required | Require probe `base_sha` on every snapshot. |
| `--match-integration-commit <SHA>` | string | required | Require the live PR head to stay at probe `integration_sha`. |
| `--match-head-commit <SHA>` | string | required | Bind the candidate back to probe `head_sha`. |
| `--timeout <DURATION>` | duration | project's `zen.ci_timeout` (default `15m`) | Override the wait. Accepts `30s`, `5m`, `2h`, `1d`, or a bare integer of seconds. |
| `--task <TASK_ID>` | string | — | Resolve the default timeout against the task's workflow's `zen.ci_timeout` (falling back to the project value). Without it, the project default is used directly. |

## pr-merge

```text
shelbi zen pr-merge <PR_NUMBER> --match-repository <REPOSITORY> --match-repository-id <REPOSITORY_ID> --match-base-branch <BRANCH> --match-base-commit <BASE_SHA> --match-integration-commit <INTEGRATION_SHA> --match-head-commit <HEAD_SHA>
```

Land the prebuilt squash candidate after `ci-watch` reports `green`. Shelbi
verifies that `integration_sha` has sole parent `base_sha` and exactly the tree
of `head_sha`, then advances only `refs/heads/<base_branch>` from `base_sha` to
`integration_sha` with Git's compare-and-swap lease. A concurrent same-head PR
retarget cannot redirect that update. This atomicity applies to the remote ref
update, not to GitHub PR metadata.

Repositories with branch protection, active rulesets, required-PR rules,
fork heads, merge queues, or a non-squash strategy cannot use this boundary.
Zen leaves the base unchanged and tells a human to review and merge through the
repository's required GitHub workflow. A landed candidate prints its SHA.

| Argument or flag | Type | Default | Description |
| --- | --- | --- | --- |
| `<PR_NUMBER>` | integer | — | The PR number to merge (required). |
| `--match-repository <REPOSITORY>` | string | required | Require probe `repository`. |
| `--match-repository-id <REPOSITORY_ID>` | string | required | Require probe `repository_id`. |
| `--match-base-branch <BRANCH>` | string | required | Require probe `base_branch`. |
| `--match-base-commit <SHA>` | string | required | Require probe `base_sha`. |
| `--match-integration-commit <SHA>` | string | required | Require probe `integration_sha`. |
| `--match-head-commit <SHA>` | string | required | Require probe `head_sha`. |

## Examples

Flip Zen on for the current project:

```bash
shelbi zen on
```

See the resolved danger-path list and configured local checks:

```bash
shelbi zen status
```

Inspect what Zen would consider promoting right now (without
promoting anything):

```bash
shelbi zen scan
```

Watch the policy in motion for ten minutes without committing to it:

```bash
shelbi zen dry-run --for 10m
```

Run the full pre-merge probe by hand on a finished branch and pipe it
through `jq`:

```bash
shelbi zen probe docs-write-cli-reference-pages | jq .
```

Drive the full merge flow manually, one primitive at a time,
exactly the sequence the orchestrator runs internally:

```bash
REPORT=$(shelbi zen probe docs-write-cli-reference-pages)
REPOSITORY=$(printf '%s\n' "$REPORT" | jq -r .repository)
REPOSITORY_ID=$(printf '%s\n' "$REPORT" | jq -r .repository_id)
BASE_BRANCH=$(printf '%s\n' "$REPORT" | jq -r .base_branch)
BASE_SHA=$(printf '%s\n' "$REPORT" | jq -r .base_sha)
INTEGRATION_SHA=$(printf '%s\n' "$REPORT" | jq -r .integration_sha)
HEAD_SHA=$(printf '%s\n' "$REPORT" | jq -r .head_sha)
PIN=(--match-repository "$REPOSITORY" --match-repository-id "$REPOSITORY_ID" --match-base-branch "$BASE_BRANCH" --match-base-commit "$BASE_SHA" --match-integration-commit "$INTEGRATION_SHA" --match-head-commit "$HEAD_SHA")
PR=$(shelbi zen pr-create docs-write-cli-reference-pages "${PIN[@]}")
shelbi zen ci-watch "$PR" "${PIN[@]}" --timeout 10m
shelbi zen pr-merge "$PR" "${PIN[@]}"
```

Pause Zen during a release window without aborting in-flight merges:

```bash
shelbi zen pause
```

## See also

- [Zen Mode](/docs/concepts/zen-mode) — the full mental model, the
  high-confidence bar, and how to tune the judgment categories per
  project.
- [Orchestrator](/docs/concepts/orchestrator) — how the prompt
  template that drives Zen's policy is loaded.
- [The events log](/docs/concepts/events-log) — the `mode=zen` and
  `orchestrator:zen-*` lines the toggles and primitives emit.
- [`shelbi merge`](/docs/cli/merge) — the user-driven counterpart
  that lands a single reviewed branch without the Zen bar.
