shelbi zen <SUBCOMMAND> [OPTIONS]

shelbi zen is the CLI face of 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 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

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

shelbi zen off

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

pause

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

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

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.

dry-run

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.

FlagTypeDefaultDescription
--for <DURATION>durationrun until Ctrl-CStop after this long. Accepts 30s, 5m, 2h, 1d, or a bare integer of seconds.
--interval <DURATION>duration5sOverride the per-tick interval. Same duration grammar as --for.

probe

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.

ArgumentTypeDefaultDescription
<ID>stringTask id to probe (required).

pr-create

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 flagTypeDefaultDescription
<ID>stringTask id whose branch to push and PR (required).
--match-repository <REPOSITORY>stringrequiredRequire the origin repository selector to equal probe repository.
--match-repository-id <REPOSITORY_ID>stringrequiredRequire the immutable GitHub repository id to equal probe repository_id.
--match-base-branch <BRANCH>stringrequiredRequire the PR target to equal probe base_branch.
--match-base-commit <SHA>stringrequiredRequire the resolved target commit to equal probe base_sha.
--match-integration-commit <SHA>stringrequiredRequire the published PR head to equal probe integration_sha.
--match-head-commit <SHA>stringrequiredRequire the durable task branch to match probe head_sha.

ci-watch

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.

FlagTypeDefaultDescription
<PR_NUMBER>integerThe PR number returned by pr-create (required).
--match-repository <REPOSITORY>stringrequiredRequire probe repository on every snapshot.
--match-repository-id <REPOSITORY_ID>stringrequiredRequire probe repository_id on every snapshot.
--match-base-branch <BRANCH>stringrequiredRequire probe base_branch on every snapshot.
--match-base-commit <SHA>stringrequiredRequire probe base_sha on every snapshot.
--match-integration-commit <SHA>stringrequiredRequire the live PR head to stay at probe integration_sha.
--match-head-commit <SHA>stringrequiredBind the candidate back to probe head_sha.
--timeout <DURATION>durationproject's zen.ci_timeout (default 15m)Override the wait. Accepts 30s, 5m, 2h, 1d, or a bare integer of seconds.
--task <TASK_ID>stringResolve 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

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 flagTypeDefaultDescription
<PR_NUMBER>integerThe PR number to merge (required).
--match-repository <REPOSITORY>stringrequiredRequire probe repository.
--match-repository-id <REPOSITORY_ID>stringrequiredRequire probe repository_id.
--match-base-branch <BRANCH>stringrequiredRequire probe base_branch.
--match-base-commit <SHA>stringrequiredRequire probe base_sha.
--match-integration-commit <SHA>stringrequiredRequire probe integration_sha.
--match-head-commit <SHA>stringrequiredRequire probe head_sha.

Examples

Flip Zen on for the current project:

shelbi zen on

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

shelbi zen status

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

shelbi zen scan

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

shelbi zen dry-run --for 10m

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

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:

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:

shelbi zen pause

See also

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