CLI Tools Overview¶
Every CLI command provided by this package, organized by runtime context. Each entry documents the tool's purpose, where it runs, what it assumes, and how it fails when those assumptions are violated.
Host tools¶
Host tools run on the developer's machine (outside any container).
They drive git, gh, SSH, and Docker operations. Installed via
uv tool install or the dev-tree override venv.
vrg-commit¶
Construct standards-compliant conventional commits with co-author resolution. Performs five branch/context checks before committing (detached HEAD, protected branch, branch prefix, issue number, worktree convention).
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_commit |
| Args | --type (required), --scope, --message (required), --body, --agent (required) |
| Preconditions | Git repo, staged changes, not detached HEAD, not on protected branch, branch prefix matches branching model, issue number in branch name, not main worktree when .worktrees/ present |
| Failure mode | SystemExit with diagnostic on stderr for each check |
| Exit codes | 0 success, 1 rejection or error |
| Status | Active |
vrg-submit-pr¶
Create standards-compliant pull requests. Template mode pushes the
current branch and opens a PR from .vergil/pr-workflow.json. Relay
branch mode (positional <branch> [<branch> …]) opens PRs
worktree-free for branches already on origin — the Mac side of the
cloud→Mac handoff: each branch's ready-state comes from a local
worktree's pr-workflow.json when present, else the relay ref
refs/vergil/pr-workflow/<branch>; origin's tip is checked against the
recorded head_sha and the PR opens with --head without pushing.
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_submit_pr |
| Args | positional branches (relay mode); or --issue (required), --summary (required), --linkage (default: Ref; vrg-submit-pr auto-selects Closes for a managed task — Fixes/Resolves are banned), --notes, --title, --dry-run |
| Preconditions | Git repo, gh CLI on PATH; relay mode: named branches on origin with a resolvable ready-state and matching head_sha |
| Failure mode | Subprocess error from git push or gh pr create; relay mode: loud failure on a missing ready-state or head_sha drift |
| Exit codes | 0 success |
| Status | Active |
vrg-pr-fix-body¶
Repair a PR's body by regenerating it from corrected fields through
the same validated builder as vrg-submit-pr, then push an empty
commit to re-trigger CI. The agent-safe fix path for body-level
standards failures during the pr-watch reconcile loop (denied to the
audit identity; the user identity may only fix its own PR).
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_pr_fix_body |
| Args | pr (positional, required), --issue (required), --summary (required), --linkage (default: Ref), --notes, --dry-run, --no-retrigger |
| Preconditions | Git repo, gh CLI on PATH, PR open, agent identities on the PR's head branch |
| Failure mode | SystemExit/diagnostic on identity, scope, or state rejection |
| Exit codes | 0 success, 1 rejection or error |
| Status | Active |
vrg-pr-workflow¶
Record and manage the PR handoff state in .vergil/pr-workflow.json —
the oracle vrg-submit-pr reads. report-ready writes the PR metadata
(--issue/--title/--summary/--notes, optional --linkage) and marks the
branch ready; it is idempotent — re-running overwrites the recorded
prose (correcting the title/summary/notes is always allowed).
report-ready always also mirrors the ready-state onto the reserved
relay ref refs/vergil/pr-workflow/<branch> (unconditional — no config,
no off-platform detection), so a cloud VM's report-ready reaches the Mac
that later runs vrg-submit-pr <branch> even though the two never share a
disk. The relay push is a pure ref write built with git plumbing; it never
advances the branch, so it stays freeze-neutral. A push failure is
loud on stderr but never rolls back the durable local file. Because the
ref is world-readable on a public repo, keep secrets out of
--title/--summary/--notes. Reaching ready freezes the branch:
vrg-commit and the vrg-git push path then refuse further
commits/pushes, because a task is exactly one PR and more work is a new
follow-up issue (epic #146). unfreeze is the only sanctioned way to
reopen a still-unsubmitted branch — it drops the state back to
implementing while keeping the metadata; an already-submitted branch
cannot be unfrozen. status prints the current state.
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_pr_workflow |
| Args | report-ready (--issue, --title, --summary, --notes required; --linkage default Ref), unfreeze, status; global --base (default: origin/develop) |
| Preconditions | Git repo; run from the worktree whose branch is being staged |
| Failure mode | WorkflowError on stderr (e.g. unfreeze after submit, or nothing to unfreeze) |
| Exit codes | 0 success, 1 error |
| Status | Active |
vrg-merge-when-green¶
Poll a PR's CI checks, then merge when they all pass. Designed for release-workflow PRs where the agent is both author and reviewer.
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_merge_when_green |
| Args | pr (positional, required), --strategy (merge/squash/rebase), --no-delete-branch |
| Preconditions | gh CLI on PATH, worktree-aware (skips --delete-branch in secondary worktrees) |
| Failure mode | subprocess.CalledProcessError from gh pr checks --fail-fast on first red check |
| Exit codes | 0 success, non-zero on check failure or merge failure |
| Status | Active |
vrg-prepare-release¶
Automate release preparation: create release branch from develop, merge main, generate changelog and release notes, push, and open PR. Auto-detects the ecosystem (Python, Maven, Go, Ruby, Cargo, Claude plugin, VERSION file) to find the version.
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_prepare_release |
| Args | --issue (required) |
| Preconditions | On develop branch, clean working tree, local develop matches origin/develop, gh and git-cliff on PATH |
| Failure mode | SystemExit with clear message for each precondition |
| Exit codes | 0 success, 1 error |
| Status | Active |
vrg-finalize-pr¶
Finalize a pull request. Given a PR, runs the provenance check, merges
it, then cleans up; with no PR, runs cleanup only. Cleanup switches to
the target branch, fast-forward pulls, deletes merged local branches
(auto-removing worktrees inside .worktrees/ when necessary), deletes
each merged branch's PR-workflow relay ref
(refs/vergil/pr-workflow/<branch>) and sweeps any orphaned relay ref
whose branch is gone (issue #2369), prunes remotes, runs validation, and
checks the CD workflow status. A
merged/closed worktree the sweep cannot remove — a dirty tree, or a
reused branch name with unmerged commits (issue #1719) — is surfaced
prominently after the pipeline rather than buried in the stage log;
--clean-dirty opt-in clears one whose only dirt is untracked
build/validation output, after showing the paths and confirming
(issue #2348).
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_finalize_pr |
| Args | PR (optional), --target-branch (default: develop), --strategy (default: squash), --allow-provenance-violation, --clean-dirty, --dry-run |
| Preconditions | Must run from the main worktree, vrg-container-run on PATH |
| Failure mode | Provenance violations, a dirty working tree, validation failures, or a failed CD run all return exit 1 |
| Exit codes | 0 success, 1 provenance/worktree/validation/CD failure or unrecognized branching model |
| Status | Active |
vrg-worktree-status¶
List canonical .worktrees/ worktrees with their derived lifecycle
state, so removable cruft (merged/closed PRs whose worktree was never
cleaned up) is distinguishable from in-flight work at a glance.
Read-only — cleanup stays vrg-finalize-pr's job. PR state is queried
from GitHub per worktree; a failed lookup shows as unknown with the
reason rather than being silently downgraded. The summary counts fall
into disjoint buckets — active, needs-attention, stalled
(no-pr), and cruft (removable). A finished-but-stuck worktree
(merged/closed but not removable: dirty, or a reused branch name whose
merged verdict was withheld, issue #1719) is counted under
needs-attention with an actionable note, never miscounted as active
behind a "0 cruft" message (issue #2347).
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_worktree_status |
| Args | --target-branch (default: develop) |
| Preconditions | Git repo; gh CLI on PATH for PR state |
| Failure mode | None for classification — a failed PR lookup is reported as an unknown row, never a crash |
| Exit codes | 0 always (read-only) |
| Status | Active |
vrg-ensure-label¶
Ensure GitHub labels exist. Three modes: single-label (create/update one label), sync (provision all labels from the canonical registry), and project (discover repos via a GitHub Project and sync each).
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_ensure_label |
| Args | --repo, --label, --color, --description, --sync, --owner, --project |
| Preconditions | gh CLI on PATH |
| Failure mode | argparse validation for incompatible flag combinations; subprocess error from gh |
| Exit codes | 0 success |
| Status | Active |
vrg-github-repo-config¶
Audit a managed repo against the canonical Vergil configuration, and
in apply mode reconcile the GitHub half. Combines local filesystem
checks (vergil.toml, CLAUDE.md, .claude/settings.json, hook-guard
shim, workflow pins, .gitignore managed fence, ops.yml wiring)
with GitHub-API checks (repo settings, rulesets, required-check set).
Runs nightly from each repo's ops.yml via the reusable
ops-github-config.yml workflow, where drift is fatal. See the
GitHub Config Audit reference.
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_github_repo_config |
| Args | audit | diff | apply; --repo OWNER/REPO, --config PATH |
| Preconditions | Local checks require the repo's own checkout as CWD; GitHub checks require gh credentials |
| Failure mode | DiffItem list on drift; clean diagnostic on unreachable GitHub state |
| Exit codes | 0 compliant, 1 non-compliant (drift), 2 audit could not complete |
| Status | Active |
vrg-github-repo-init¶
Interactive (or --non-interactive) wizard that bootstraps a new
managed repository: creates and clones the repo, generates
vergil.toml, scaffolds config files (CLAUDE.md, hook-guard shim,
the managed .gitignore fence), scaffolds the language skeleton
(born-green — see below), generates
CI/CD/epic-rollup/ops.yml workflows, the docs site, branch structure,
GitHub config, and Pages. The scaffolded base + <language>
.gitignore fence and staggered-cron ops.yml make a new repo pass the
config audit's two local checks from day one.
Born-green language skeleton. A dedicated scaffolding step (step 5,
lib/lang_scaffold.py) renders the language's packaged skeleton
templates (src/vergil_tooling/data/skeletons/<lang>/) into the fresh
checkout, stamping only files that are missing so it never clobbers
existing content. For a language that resolves a committed lockfile
(cpp), it then runs that language's lock command
(conan lock create . -s build_type=Debug) and one full vrg-validate
inside the dev container, so the new repo is born green — it passes
validation from its first commit. The container is a fail-fast
precondition for a lock-resolving language: if no runtime is available
the step refuses before writing anything, so such a repo is born
green or not born at all, never half-created. The step writes no commit
of its own; its host-rendered skeleton and container-resolved lock ride
into the next step's commit. Because the container warmup for cpp
requires a conan.lock and one does not yet exist during this window,
the warmup deliberately skips until the scaffold's
conan lock create produces the lock — the skeleton resolves in an
unwarmed-but-usable container, and the warmup runs normally on every
later build once the lock is committed
(epic vergil-project/.github#342).
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_github_repo_init |
| Args | org/name positional; --adopt, --non-interactive, --target-dir, and per-field overrides (--primary-language, --repository-type, …) |
| Preconditions | gh and git on PATH; run from the org-layout parent (or pass --target-dir) |
| Failure mode | Loud refusal on a foreign-repo CWD, an occupied clone path, or missing required non-interactive values |
| Exit codes | 0 success, 1 error |
| Status | Active |
vrg-gitignore-sync¶
Single-repo applicator for the vergil-managed .gitignore block. Reads
<repo>/.gitignore, resolves the fence language from
[project].primary-language (normalized to base-only for any language
without a managed fragment), and either checks (default) or writes the
composed base + <language> managed block through lib/gitignore.py —
the same module the config audit renders through, so applicator and
audit cannot diverge. It owns only the file change: it has no git or
PR knowledge, and --write rewrites the fenced block in place while
leaving genuinely repo-local lines outside the fence untouched. See the
GitHub Config Audit reference.
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_gitignore_sync |
| Args | --repo PATH (default: CWD); mutually exclusive --check (default) | --write |
| Preconditions | A repo whose language resolves from [project].primary-language (absent/unreadable config → base-only) |
| Failure mode | --check prints each drift reason to stderr; --write always succeeds (prints already in sync or the synced path) |
| Exit codes | 0 ok, 1 --check drift, 2 usage error |
| Status | Active |
vrg-fleet-sync¶
Propagate the vergil-managed .gitignore block across a fleet of
repositories, opening one PR per repo whose .gitignore drifts. It
drives the generic fleet-sweep driver (lib/fleet_sweep.py): per repo it
creates a worktree, shells out to vrg-gitignore-sync --write, commits,
and runs report-ready. Like every agent-run task it never submits or
merges — it stops at report-ready, leaving submission and merge to the
human. --dry-run reports the intended per-repo action without touching
any git or GitHub state.
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_fleet_sync |
| Args | --repos PATH [PATH …] (required, local clone paths); --dry-run |
| Preconditions | vrg-gitignore-sync on PATH; each --repos path a local clone; git/gh credentials for the sweep |
| Failure mode | Any repo that errors is recorded and reported in the per-repo status lines |
| Exit codes | 0 all repos ok, 1 one or more repos errored |
| Status | Active |
vrg-container-run¶
Run arbitrary commands inside a dev container. Auto-detects the
project language to select the Docker image; falls back to
dev-base:latest. Uses execvp to replace the process.
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_container_run |
| Args | [--prefix <dev\|prod>] [--] <command> [args...] (manual parsing, -- separator) |
| Preconditions | Git repo, GH_TOKEN set, Docker daemon running |
| Failure mode | Explicit error message for missing GH_TOKEN; assert_docker_available() exits with message for Docker; git.repo_root() raises on non-git directory |
| Exit codes | 0 (help), 1 error; command exit code after execvp |
| Status | Active |
vrg-container-test¶
Run a repository's test suite inside a dev container. Auto-detects language and selects appropriate image and test command.
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_container_test |
| Args | None |
| Preconditions | Git repo, Docker daemon running, language detection or DOCKER_DEV_IMAGE + DOCKER_TEST_CMD |
| Failure mode | Explicit error for undetected language and unavailable Docker; git.repo_root() raises on non-git directory |
| Exit codes | 0 (help), 1 error; command exit code after execvp |
| Status | Active |
vrg-container-docs¶
Preview or build MkDocs documentation inside a dev container.
Supports serve (live-reload) and build subcommands. For Python
repos, wraps with uv sync --group docs.
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_container_docs |
| Args | <serve\|build> [mkdocs args...] (manual parsing) |
| Preconditions | Git repo, Docker daemon |
| Failure mode | Usage message on missing/unknown subcommand |
| Exit codes | 0 (help), 1 error; command exit code after execvp |
| Status | Active |
vrg-container-build-command¶
Print a repo's declared [container].build-command verbatim, for CI
consumption. The CI test jobs call --script to obtain the exact
provisioning command to run per job — the same command the local cache
build bakes into the per-branch image — so the two paths run one
declaration. Prints nothing when the repo declares no build-command.
See Container Config Reference → build-command.
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_container_build_command |
| Args | --script (explicit CI intent; identical output), --repo-root (default: CWD) |
| Preconditions | A readable vergil.toml at the repo root (absent/empty key prints nothing) |
| Failure mode | argparse error on unknown flags; no failure for an unset key |
| Exit codes | 0 always |
| Status | Active |
vrg-container-system-packages¶
Print a repo's declared [container].system-packages, for CI
consumption. Default mode prints the package names one per line;
--install-script prints the exact apt install snippet — the single
speller shared with the local cache build — which the CI test jobs run.
See Container Config Reference → system-packages.
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_container_system_packages |
| Args | --install-script (apt snippet instead of the name list), --repo-root (default: CWD) |
| Preconditions | A readable vergil.toml at the repo root (absent/empty key prints nothing) |
| Failure mode | argparse error on unknown flags; no failure for an unset key |
| Exit codes | 0 always |
| Status | Active |
vrg-container-cache¶
Manage the per-branch cached container image (base image plus
vergil-tooling, system-packages, and the build-command artifact) that
vrg-container-run builds over. Subcommands: build (build/refresh the
cached image for the current branch), clean (remove it), status (show
cache state and the expected tag), and clean-all (remove every image it
manages).
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_container_cache |
| Args | build | clean | status | clean-all |
| Preconditions | Git repo; a container runtime (docker/nerdctl) available for build/clean/clean-all |
| Failure mode | Runtime-unavailable error; propagates the runtime's build/remove failures |
| Exit codes | 0 success, non-zero on runtime or build failure |
| Status | Active |
vrg-generate-commands¶
Generate MQSC command methods for all language ports (Python, Ruby,
Java, Go, Rust) from mapping-data.json. Updates target files
between BEGIN/END GENERATED MQSC METHODS markers.
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_generate_commands |
| Args | --language (required), --mapping-data (required), --target, --mapping-pages-dir, --check |
| Preconditions | mapping-data.json file exists at the given path |
| Failure mode | Explicit error for missing mapping data file |
| Exit codes | 0 success, 1 error or --check mismatch |
| Status | Active |
Container tools¶
Container tools run inside dev containers launched by vrg-container-run.
They assume language toolchain dependencies (ruff, mypy, shellcheck,
markdownlint, yamllint) are available on PATH.
vrg-validate-common¶
Shared validation checks for all repos: repository profile
validation, markdownlint on published markdown (docs/site/**/*.md
and README.md) using the bundled canonical config, shellcheck on
scripts/, yamllint on .github/ and docs/ YAML files, hadolint
on Dockerfile*, actionlint on .github/workflows/, and
ansible-lint (using the bundled canonical config) when the repo
carries Ansible content.
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.validate_common |
| Args | None |
| Preconditions | Git repo, shellcheck and yamllint on PATH |
| Failure mode | Propagates exit codes from each tool |
| Exit codes | 0 all passed, non-zero on first failure |
| Status | Active (called internally by vrg-validate) |
vrg-repo-profile¶
Validate the repository profile in docs/repository-standards.md.
Checks that all required attributes are present and none contain
placeholder values.
| Attribute | Value |
|---|---|
| Source | vergil_tooling.bin.vrg_repo_profile |
| Args | None |
| Preconditions | docs/repository-standards.md exists |
| Failure mode | Exit 2 if profile file not found; exit 1 for missing or placeholder attributes |
| Exit codes | 0 valid, 1 invalid, 2 file not found |
| Status | Active |
Removed in this audit¶
st-list-project-repos (removed)¶
Entry point declared in pyproject.toml but the source module
vergil_tooling.bin.list_project_repos did not exist. Would crash
on import with ModuleNotFoundError. The underlying function
(list_project_repos) lives in vergil_tooling.lib.github and is
consumed by vrg-ensure-label --owner/--project mode.
st-set-project-field (removed)¶
Entry point declared in pyproject.toml but the source module
vergil_tooling.bin.set_project_field did not exist. Would crash
on import with ModuleNotFoundError.
Audit notes¶
Precondition consistency¶
Most tools check preconditions explicitly and fail with clear messages. Notable gaps:
vrg-submit-prdoes not validate thatghis on PATH before attemptinggit pushandgh pr create. Failure surfaces as a subprocess error rather than a clear precondition message.vrg-container-runchecksGH_TOKENexplicitly;vrg-container-testdoes not (it will fail inside the container whenghcommands run without a token, but the error is less clear).
Args style¶
Most tools use argparse. Two exceptions:
vrg-container-runparsessys.argvmanually with a--separator.vrg-container-docsparsessys.argvmanually with subcommands.
Both are intentional: vrg-container-run passes everything after --
through to docker run, and vrg-container-docs has a simpler
interface than argparse would provide. No alignment needed.
Exit code contract¶
- 0: success
- 1: check failure, validation error, or precondition violation
- 2: infrastructure error (used by
vrg-repo-profile)
The 1-vs-2 distinction is not universal. Tools added before the convention was established use 1 for all errors.