Skip to content

Consuming Repo Setup

This is the full walkthrough for onboarding a new repository to use vergil-tooling. For the one-screen quickstart, see Getting Started. For how the workflow unfolds once you're set up, see Git Workflow.

Mental model — what you're installing

Vergil-tooling is delivered through three coordinated surfaces. The setup steps below wire up each one:

Surface What it is How you consume it
Host tools vrg-container-run, vrg-commit, vrg-submit-pr, and other host-side CLI tools. uv tool install from the vergil-tooling git URL; scripts land in ~/.local/bin/.
Dev container ghcr.io/vergil-project/dev-<lang>:<version> — pre-baked images with language runtimes, validators, and every other vrg-* tool installed. Pulled automatically by vrg-container-run; nothing to install manually.
Claude Code plugin vergil-claude-plugin — hooks, skills, agents, and slash commands that enforce the workflow at the Claude-Code-tool level. Declared in .claude/settings.json; Claude Code loads on session start.

Plus two layers that aren't installed as packages but are expected to be present in every consuming repo:

  • Claude Code hook guard — a .claude/hooks/guard.sh shim checked into the repo, wired via .claude/settings.json as a PreToolUse hook.
  • CI workflow — the standards-compliance composite action from vergil-project/vergil-actions, invoked from your repo's .github/workflows/ci.yml.

Both of these validate the repo profile and enforce branching rules from two different entry points. See Git Workflow → Two enforcement layers for how they fit together.

Step 1: Host prerequisites

Install on your host (macOS or Linux):

Docker — the container engine. Docker Desktop on macOS is fine; Docker Engine on Linux works too.

uv — Python package manager. Used to install vergil-tooling on the host and (inside the container) to manage Python dependencies. Install via the official installer.

gh — GitHub CLI. Both the human and agent GitHub accounts must be logged into gh auth on the developer's machine. Credential selection is handled automatically by vrg-gh. See the credential management design (docs/specs/2026-05-14-credential-management-design.md) for the full setup details.

Git and Bash — ship with macOS by default and are standard on Linux.

You do not need to install language runtimes, linters, test frameworks, markdownlint, or shellcheck on the host. All of those live inside the container.

Step 2: Install vergil-tooling

uv tool install 'vergil-tooling @ git+https://github.com/vergil-project/vergil-tooling@v2.1'

This installs all vrg-* console scripts into ~/.local/bin/, which uv's official installer already configures on PATH. No sibling checkout, no custom PATH entries, no venv bootstrapping.

Verify:

which vrg-container-run    # should resolve to ~/.local/bin/vrg-container-run
vrg-container-run --help   # should print usage

Dev-tree override for vergil-tooling development

If you are developing vergil-tooling itself and want to test unreleased code on the host, use the single-.venv dev-tree override described in the vergil-tooling CLAUDE.md (uv sync --group dev, then prepend .venv/bin to PATH). A single .venv is safe because the dev container masks the host .venv with an anonymous volume, so host and container never clobber each other's environment. This does not apply to consuming repos.

Step 3: Claude Code hook guard

Every managed repo ships a .claude/hooks/guard.sh shim that blocks raw git and gh commands in Claude Code agent sessions. The shim delegates to vrg-hook-guard (when vergil-tooling is installed on the host) or falls back to a jq-based hard deny.

Create .claude/hooks/guard.sh in your repo (the vrg-github-repo-init wizard creates this automatically for new repos):

#!/usr/bin/env bash
set -euo pipefail
if command -v vrg-hook-guard >/dev/null 2>&1; then
  exec vrg-hook-guard
fi
# Fallback: hard-deny git/gh when vrg-hook-guard is not installed.
INPUT="$(cat)"
CMD="$(printf '%s' "$INPUT" | jq -r '.input.command // empty')"
case "$CMD" in
  git\ *|*/git\ *|gh\ *|*/gh\ *)
    printf '{"decision":"block","reason":"raw git/gh blocked (vrg-hook-guard not installed)"}\n'
    exit 0
    ;;
esac
exit 0

Save this as .claude/hooks/guard.sh, make it executable, and commit it:

mkdir -p .claude/hooks
chmod +x .claude/hooks/guard.sh

No per-clone configuration is required — the hook is wired via .claude/settings.json (see Step 5 below) and fires automatically in every Claude Code session.

All branch/context checks (detached HEAD, protected branches, branch prefix, issue number) live in vrg-commit itself.

Full reference: Git Hooks and Validation.

Step 4: Repository profile

Create docs/repository-standards.md at your repo root. This is the primary configuration surface for the validators:

# Repository Standards

## Table of Contents

- [AI co-authors](#ai-co-authors)
- [Repository profile](#repository-profile)

## AI co-authors

- Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

## Repository profile

- repository_type: library
- versioning_scheme: semver
- branching_model: library-release
- release_model: tagged-release
- supported_release_lines: 1
- primary_language: python

Required attributes and accepted values:

Attribute Values Notes
repository_type application, library, tooling, documentation Informational; some validators branch on this.
versioning_scheme semver, calver, none How releases are versioned.
branching_model library-release, application-promotion, docs-single-branch Determines which branch prefixes vrg-commit allows.
release_model tagged-release, continuous-deploy, none Affects release-flow tooling expectations.
supported_release_lines integer (commonly 1) How many concurrent major lines you support.
primary_language python, go, java, rust, ruby, cpp, typescript, shell, none Determines which per-language validators run.

The AI co-authors section defines which Co-Authored-By trailer values vrg-commit accepts for --agent. Add one line per accepted agent identity.

Values containing <, >, or | are rejected as placeholders by vrg-repo-profile.

Step 5: Enable the Claude Code plugin

Create .claude/settings.json in your repo. This file serves double duty: it wires the hook guard from Step 3, and it enables the Claude Code plugin:

{
  "permissions": {
    "allow": ["Bash(vrg-*)"]
  },
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/guard.sh"
          }
        ]
      }
    ]
  },
  "extraKnownMarketplaces": {
    "vergil-marketplace": {
      "source": {
        "source": "github",
        "repo": "vergil-project/vergil-claude-plugin"
      }
    }
  },
  "enabledPlugins": {
    "vergil@vergil-marketplace": true
  }
}

Commit this file. It's part of your repo's reproducible environment — any Claude Code session opened in this repo will load the hook guard and the plugin automatically.

What the plugin provides:

  • PreToolUse hooks on Bash that block heredoc syntax and (on repos that have adopted the worktree convention) commits originating outside .worktrees/<name>/.
  • PostToolUse hooks that remind you to run vrg-finalize-pr after vrg-submit-pr, and that surface deprecation warnings in test output.
  • Stop hooks that prevent session exit if a PR was submitted but never finalized.

See the plugin's own Hooks reference for the full list.

Plugin install is a known rough edge

The plugin itself has not yet been cut as a proper versioned release; Claude Code consumes it directly from the repo's default branch. Updates can be slow to propagate and the local ~/.claude/plugins/marketplaces/ and …/cache/ directories sometimes need manual refreshing. All tracked in vergil-claude-plugin#46. The settings above are enough to get going; plan on occasionally running git pull in ~/.claude/plugins/marketplaces/vergil-tooling-marketplace/ if a hook seems outdated.

Step 6: Worktree convention

Every managed repo adopts the worktree convention so multiple Claude Code agents can work in parallel without colliding. Two tiny changes:

Make sure .worktrees/ is in your .gitignore. It is one of the base fragment's entries (see Step 8: Managed .gitignore fence and config audit), so a repo that carries the managed fence already has it; the plugin's commit-block hook activates against its presence.

The managed fence already ignores your validation/build output

Validation and build artifacts (coverage reports, compiled output, cache dirs, temporary venvs) are part of the composed managed block in your .gitignore. Keeping them ignored matters: un-gitignored output dirties a worktree, and a merged worktree left dirty is one vrg-finalize-pr cannot auto-remove — it surfaces as needs-attention in vrg-worktree-status and requires the opt-in --clean-dirty (or a manual clean) to clear. Carrying the managed fence means merged worktrees sweep automatically.

Add a ## Parallel AI agent development section to your CLAUDE.md. Every managed repo has one you can copy — they differ only in the repo name and example issue number. The canonical text lives in the worktree convention spec at docs/specs/worktree-convention.md in vergil-tooling; a short local section in each repo's CLAUDE.md is the on-ramp, and the plugin's commit-block hook activates against the presence of .worktrees/ in .gitignore.

For how to actually use worktrees during development, see Git Workflow → Parallel work with worktrees.

Step 7: CI workflow

Use the standards-compliance composite action from vergil-project/vergil-actions. Minimal workflow (.github/workflows/ci.yml):

name: CI

on:
  pull_request:

permissions:
  contents: read

jobs:
  standards-compliance:
    name: "ci: standards-compliance"
    runs-on: ubuntu-latest
    container: ghcr.io/vergil-project/dev-base:latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Validate standards
        uses: vergil-project/vergil-actions/actions/standards-compliance@develop

What the composite action runs inside the dev-base container:

  • vrg-repo-profile — validates docs/repository-standards.md

The dev-base container already has vergil-tooling on PATH, so no further setup is needed in the workflow.

See the CI Architecture guide if you also want per-language test/lint/audit tiers.

Step 8: Managed .gitignore fence and config audit

Every managed repo owes two things to the fleet's self-policing config audit, and both are checked nightly:

  1. Your .gitignore must carry the vergil-managed fence. The fleet's ignore vocabulary is composed — a language-agnostic base fragment plus the fragment for your repo's [project].primary-language — into a fenced managed block: a # >>> vergil-managed: base + <language> … begin marker, the composed pattern lines (editors, OS, secrets, Vergil internals, all build/validation output, and your language's artifacts), and a # <<< vergil-managed <<< end marker. The audit requires that block to be present and to match the composed block for your language exactly, with no managed pattern left loose outside the fence. A language with no fragment of its own — or a repo that declares none — gets the base-only fence. Genuinely repo-local entries live outside the fence and are never touched; run vrg-gitignore-sync to write or refresh the block.

  2. Your repo must carry a scheduled ops.yml wired to the config audit. .github/workflows/ops.yml must call the reusable ops-github-config.yml workflow on a cron schedule. That scheduled job is what runs the audit each night.

Both are fatal in the nightly audit: any drift returns exit 1 and turns the scheduled ops.yml run red. A repo bootstrapped with vrg-github-repo-init is born conforming — it scaffolds the managed .gitignore fence and a staggered-cron ops.yml for you. For an existing repo, run vrg-gitignore-sync to install the fence and add ops.yml.

You never bump a pin to receive fragment changes: every repo tracks the rolling vergil-tooling@vX.Y tag, so an updated fragment released under that line is picked up on the next vrg-gitignore-sync run — and the nightly audit flags the drift until you run it.

Check your repo locally before relying on the nightly run:

vrg-github-repo-config audit   # exit 0 compliant, 1 drift, 2 could-not-complete

See the GitHub Config Audit reference for the full check list and the managed-fence propagation model.

Step 9: Verify end-to-end

Once the above is in place, sanity-check each layer:

# 1. Host tools — should print vrg-container-run help
vrg-container-run --help

# 2. Dev container — pulls an image on first run and runs a
#    tiny command inside it
vrg-container-run -- echo "container ok"

# 3. Repo profile — runs vrg-repo-profile inside the container
vrg-container-run -- uv run vrg-repo-profile

# 4. Hook guard shim is present and executable
ls -la .claude/hooks/guard.sh

# 5. Hook guard (requires Claude Code session) — in a Claude
#    Code session in this repo, have Claude try to run a raw
#    `git commit`. The hook guard should block it.

If any step fails, check the corresponding section above, then re-run. Common causes: uv tool install not run, .claude/settings.json not committed to the branch your Claude Code session loaded.

Keeping up to date

After each vergil-tooling release, upgrade the host tools:

uv tool upgrade vergil-tooling

uv tool upgrade re-resolves the git reference, pulls the current tip of the rolling minor tag, and rebuilds the isolated tool venv. No need to repeat the full git URL.

The dev container images auto-update on vrg-container-run pulls — the tag is a minor version (3.12, 1.26, etc.) that tracks upstream releases. If you need a fresh image, docker pull ghcr.io/vergil-project/dev-<lang>:<version> forces a refresh.

The Claude Code plugin can be stale after a release; manual refresh:

git -C ~/.claude/plugins/marketplaces/vergil-tooling-marketplace pull
# then restart Claude Code

Troubleshooting

  • vrg-container-run: command not found — uv tool install has not been run, or ~/.local/bin is not on PATH. Re-run the install command from Step 2 and confirm which vrg-container-run resolves.
  • manifest unknown when pulling a container image — the tag you're asking for doesn't exist on GHCR. Older docs referenced ghcr.io/vergil-project/dev-docs:latest (renamed to dev-base in vergil-tooling#252); make sure your workflow files use the new name.
  • Plugin hooks don't fire — check that .claude/settings.json is present, committed, and syntactically valid JSON. Restart Claude Code; the plugin is loaded at session start. If still stuck, refresh the local plugin marketplace clone per "Keeping up to date" above.
  • Commits blocked with "originate from inside .worktrees/" — intentional. This repo has adopted the worktree convention. Create a worktree for your work; see Git Workflow → Parallel work with worktrees.
  • vrg-submit-pr threw a CalledProcessError on auto-merge — expected since 2026-04-22. Auto-merge is disabled org-wide; the PR itself was created successfully. Tracked in vergil-tooling#268.
  • "raw git/gh blocked" — the Claude Code hook guard is working as intended. Use vrg-commit instead of raw git commit, and vrg-gh instead of raw gh.

For a broader troubleshooting index see Git Workflow → Troubleshooting.