Skip to content

Repository setup for agents

Use this guide when you need to configure a repository for Shipper without running shipper setup --assist.

The assisted setup prompt receives a CLI-supplied target contract with linkage=github|unlinked|fully-local. target=user writes only the exact supplied personal settings path and leaves no committed repository footprint by default. With linkage=github, the contract also supplies repository name-with-owner, conventions posture, and mirror mode. With linkage=unlinked, those GitHub policy fields are intentionally absent: do not infer or request them, create a remote, or derive a different path from the session key. This is an identity-keyed personal settings contract, not committed repository setup.

With target=repo and linkage=fully-local, the contract supplies the stable commit-lineage repository identity, CLI version fingerprint, and resolved transport=none. It supplies no GitHub repository name, conventions posture, or mirror mode. Write the standard committed repository artifacts, but perform no GitHub inspection or mutation, remote creation, workflow, ruleset, or label work. Do not create a branch, commit, rewrite history, open or adopt a pull request, or invoke setup PR finalization. Leave all changes in the working tree for operator review and commit. GitHub-backed target=repo setup retains its setup PR finalizer. If you are following this guide manually, choose the same target and linkage before making changes.

Exactly five settings are repository-only: cliVersion, mirrorMode, transport, pullRequests, and reviewDelivery. Setup never prompts for the three policy axes. Fully local repository setup is the intentional carve-out that writes explicit "transport": "none" so adding an origin later cannot silently change posture. It does not write pullRequests or reviewDelivery; pullRequests remains inferred and reviewDelivery is always "local". Other setup paths leave all three axes absent. When absent, transport follows exact origin remote presence without probing reachability, and pull requests follow effective transport.

A fresh fully local repository settings file starts with exactly:

{
"cliVersion": "<contract-supplied fingerprint>",
"transport": "none"
}

Aside from a discovered or deliberately empty installCommand, preserve unrelated existing settings and do not materialize conventions, mirror mode, agent settings, derived axes, or built-in defaults.

Inspect the full repository layout and configure the dependency bootstrap Shipper should run in new worktrees.

  1. Build a bootstrap inventory.

    Read the target settings file first. For target=user, this is the supplied personal settings path; you may read .shipper/settings.json for context, but do not write it. For target=repo, this is .shipper/settings.json. Then inspect root and nested manifests/lockfiles such as package.json, package-lock.json, pnpm-lock.yaml, yarn.lock, bun.lockb, Cargo.toml, Cargo.lock, go.mod, go.work, go.sum, pyproject.toml, requirements.txt, Pipfile.lock, and poetry.lock. Also inspect workspace declarations such as npm workspaces, pnpm-workspace.yaml, Yarn workspaces, Cargo workspaces, Go workspaces/modules, Python project files, package scripts, repo setup scripts, build scripts, and existing hooks. For linkage=github, also inspect .github/workflows/. For linkage=unlinked or linkage=fully-local, do not inspect GitHub Actions or rulesets; derive locally supportable guidance from the repository files. Produce a concrete list of package/project areas required by known build, type-check, and test commands before choosing commands.

  2. Choose the bootstrap using only existing Shipper configuration.

    Use installCommand when a single command covers the relevant areas. For target=user, prefer an ordered compound command with && and subshells when multiple areas are needed, such as npm install && (cd packages/mobile && npm install) && (cd tools/codegen && npm install && npm run build). For target=repo, generate an executable .shipper/hooks/worktree-setup for additional idempotent package or project steps when a single command is not enough. Do not add a new bootstrap settings schema.

    Single root workspace install:

    {
    "installCommand": "npm install"
    }

    User-level multi-package bootstrap:

    {
    "installCommand": "npm install && (cd packages/mobile && npm install) && (cd tools/codegen && npm install && npm run build)"
    }

    Repo-level multi-package bootstrap can use a committed hook after explicit opt-in:

    #!/usr/bin/env bash
    set -euo pipefail
    (cd packages/mobile && npm install)
    (cd tools/codegen && npm install && npm run build)

    Save the script as .shipper/hooks/worktree-setup and run:

    Terminal window
    chmod +x .shipper/hooks/worktree-setup

    Hook-only bootstrap is valid for target=repo, or for target=user only after you explain why one command cannot represent bootstrap and the user explicitly opts into a committed bootstrap-hook fallback:

    {
    "installCommand": ""
    }

    For linkage=unlinked, leave this opted-in user-target hook in the working tree for manual review and commit. For linkage=fully-local, leave every repository change in the working tree for that handoff. Do not invoke setup PR finalization in either case.

    Deliberate no-bootstrap is recorded the same way in the target settings file after confirming with the user that the repository genuinely needs no install step:

    {
    "installCommand": ""
    }
  3. Handle native-build and special prerequisites conservatively.

    Look for Node native packages, Electron rebuild/package steps, Cargo build scripts, Python extension builds, Go CGO signals, and explicit workflow prerequisite commands. Configure only repository/package-level install, rebuild, or build commands that Shipper can safely run. Do not add apt, brew, Xcode Command Line Tools, SDK, compiler, or system-library provisioning to installCommand or .shipper/hooks/worktree-setup; list those prerequisites for the user to install manually.

  4. Verify the configured bootstrap through Shipper’s runtime primitive.

    Create a temporary cold verification checkout from the repository source under .shipper/tmp/bootstrap-verify-<unique-suffix>. This path is gitignored and absent from a clean worktree; create it only as a disposable verification checkout. Prefer git worktree add --detach <tmp> HEAD so the checkout includes the repository manifests, lockfiles, and source. If git worktree is unavailable, copy the tracked working tree instead. For target=user with linkage=github, verify that Shipper resolves the same personal settings through the GitHub remote; do not create a committed .shipper/settings.json overlay in the temporary checkout. For target=user with linkage=unlinked, use the detached temporary worktree to verify that Shipper resolves the exact supplied identity-keyed settings path; do not require or create a remote. For target=repo, overlay the just-written .shipper/settings.json to <tmp>/.shipper/settings.json. If you generated .shipper/hooks/worktree-setup, copy it to <tmp>/.shipper/hooks/worktree-setup and keep it executable. Then run:

    Terminal window
    shipper bootstrap --cwd <tmp>

    After bootstrap succeeds, run the single type-check/build follow-up from inside <tmp>. Remove the temporary checkout/worktree when verification finishes.

  5. Run exactly one lightweight follow-up verification when possible.

    After bootstrap succeeds, run exactly one known type-check command when available; otherwise run exactly one known build command. Do not run tests, lint, format, or aggregate commands that include tests. If no type-check/build command can be justified from CI or package scripts, state explicitly that bootstrap verification could not be performed.

  6. Report what was configured and why.

    Include the package/project areas covered by installCommand, the areas covered by .shipper/hooks/worktree-setup, any manual system prerequisites, the shipper bootstrap --cwd result, and the single type-check/build result or the reason that verification could not run.

Task 2: Generate or update the agent configuration file

Section titled “Task 2: Generate or update the agent configuration file”

For target=user, provide guidance only: explain which repository instruction file should contain verification commands and conventions, but do not create or modify it.

For target=repo, create or update the repository’s agent configuration file so coding agents know which verification commands to run.

  1. Select the target file.

    Use CLAUDE.md for Claude Code. Use AGENTS.md for Codex, Copilot, Grok Build, or OpenCode.

  2. Discover supported verification commands.

    For linkage=github, treat .github/workflows/ as the source of truth: read every workflow that exists and extract the exact lint, format-check, type-check, build, and test commands CI runs. For linkage=unlinked or linkage=fully-local, do not inspect GitHub Actions; derive only locally supported commands from existing package scripts, manifests, and agent configuration. Do not hardcode generic commands.

  3. Update an existing file in place.

    In target=user, read the file for context only and summarize the recommended Commands section. In target=repo, if the target file exists, preserve its content. Add a Commands section if it does not have one. If it already has a commands section, verify it matches CI and update only the commands that need to change.

  4. Create a missing file only with facts you can support.

    In target=user, explain what belongs in the missing file but do not create it. In target=repo, if the target file does not exist, create it with a brief project description inferred from the repository and a Commands section only when CI commands exist.

  5. Skip commands when no CI configuration exists.

    If .github/workflows/ is missing or has no CI commands, omit the Commands section in a new repo-target file. Leave an existing commands section unchanged. In target=user, explain that no CI-sourced command list is available.

  6. Keep the file synchronized with any workflow you create later.

    If Task 3 writes .github/workflows/pr-checks.yml under target=repo, immediately revisit this configuration file and make its Commands section match the selected checks.

Task 3: Scaffold PR-check workflow if missing

Section titled “Task 3: Scaffold PR-check workflow if missing”

For linkage=unlinked or linkage=fully-local, skip this GitHub-specific task. Do not inspect or write .github/workflows, query GitHub Actions, resolve a GitHub default branch, or make workflow recommendations that require GitHub. Provide only local verification guidance from Tasks 1 and 2, then skip to the end of Task 4.

For linkage=github with target=user, inspect enough to provide guidance, but do not write workflow files. Explain the recommended PR-checks workflow and why coding agents need deterministic green/red signals.

For target=repo with linkage=github, determine whether the repository already has PR-triggered GitHub Actions coverage. Create a workflow only when coverage is missing.

  1. Inspect .github/workflows/*.yml and .github/workflows/*.yaml.

    Treat a workflow as sufficient when its top-level on: block includes pull_request, a bare-list pull_request entry, or pull_request_target. Use tolerant string or line-based inspection. Do not add a YAML parser dependency.

  2. Skip scaffolding when PR coverage exists.

    If any workflow already covers pull requests, skip the workflow scaffold and continue to Task 4. In target=user, stop at guidance even when coverage is missing.

  3. Infer verification commands when PR coverage is missing.

    Reuse the repository signals from Tasks 1 and 2. The workflow install step must use the same configured installCommand. In target=user, present this as guidance only.

    • For Node projects, infer scripts named lint, format:check or format-check, typecheck or type-check, test, and build.
    • For Cargo projects, infer cargo fmt --check, cargo clippy, cargo test, and cargo build.
    • For Go projects, infer go vet, go test ./..., and go build ./....
    • For Python projects, infer commands from detected tools such as ruff, mypy, and pytest.

    Offer only commands you can justify from detected scripts, lockfiles, or tooling.

  4. Continue without writing a workflow when no commands can be inferred.

    Explain that Shipper recommends lint, format-check, type-check, test, and build scripts plus a PR-checks workflow and branch protections because coding agents need deterministic green/red signals and Shipper’s review and merge gates rely on them. Then continue to Task 4 without writing a workflow.

  5. Present inferred commands and require confirmation before writing.

    In target=user, do not proceed past guidance. In target=repo, describe the planned workflow in natural language only. Do not preview file contents. Explain that .github/workflows/pr-checks.yml will run on pull_request against the default branch, using one human-readable ubuntu-latest job per selected command. Before asking for the existing write confirmation, explain plainly that pushing a new commit cancels that pull request’s older queued or running checks. In target=user, recommend the same behavior and explain that it avoids spending resources on checks made obsolete by a newer commit.

  6. Resolve the default branch.

    Terminal window
    gh api repos/{owner}/{repo} --jq .default_branch
  7. Check for an existing target file before writing.

    If .github/workflows/pr-checks.yml already exists, do not overwrite it. Explain why and skip the write.

  8. Write .github/workflows/pr-checks.yml only after explicit confirmation.

    For target=repo, use on: pull_request: branches: [<default branch>] and this top-level concurrency policy:

    concurrency:
    group: ${{ github.workflow }}-${{ github.ref }}
    cancel-in-progress: ${{ github.event.action == 'synchronize' && github.run_attempt == '1' }}

    Create one job per selected command. Each job should use actions/checkout@v4, the matching ecosystem setup action, the configured installCommand, and then the single verification command. Keep the workflow simple: no matrix, no file-content preview, and no caching beyond what the setup action provides by default.

  9. Sync the agent configuration file.

    After writing the workflow, update CLAUDE.md or AGENTS.md so its Commands section matches the selected checks.

See Reference > CLI for command details.

For linkage=unlinked or linkage=fully-local, skip this GitHub-specific task. Do not offer or make branch-protection or ruleset changes, and do not run GitHub authentication, label, or ruleset diagnostics.

For linkage=github with target=user, provide guidance only and do not make branch-protection or ruleset API calls.

For target=repo with linkage=github, always ask whether to configure branch protections after Task 3 resolves, regardless of whether scaffolding succeeded, was skipped, was declined, or had no inferred commands.

  1. If the user declines, continue without configuring protections.

  2. If the user approves, create a repository ruleset.

    Use gh api repos/{owner}/{repo}/rulesets -X POST. Target ~DEFAULT_BRANCH and include a name field such as Shipper PR Checks.

  3. Add required status checks only when selected check names exist.

    If selected check names exist, include a required_status_checks rule with those names. If no selected check names exist because scaffolding was declined or no commands could be inferred, explain that Shipper cannot configure a “require PR checks to pass” ruleset yet and do not send an empty required_status_checks rule.

  4. Use a workflow-file rule only with the correct rule type.

    If Task 3 created .github/workflows/pr-checks.yml and you add a workflow-file rule, use the workflows rule type, not required_workflows. Resolve the repository ID first:

    Terminal window
    gh api repos/{owner}/{repo} --jq .id

    Include both repository_id and path: ".github/workflows/pr-checks.yml" in the workflow entry.

  5. Do not use classic branch protection APIs.

  6. Handle permissions failures without failing setup.

    If gh api returns 403, report that the user lacks permission to administer branch protections and continue setup.

After target=repo setup with linkage=fully-local:

  1. Verify raw .shipper/settings.json contains the contract-supplied cliVersion and explicit "transport": "none".
  2. Verify HEAD, the current branch, and all local branch references are unchanged.
  3. Summarize every changed path and report Repository posture: fully local (transport: none).
  4. State that no branch, commit, pull request, finalization, or adoption occurred.
  5. Tell the operator to review and commit the working tree.

Do not invoke the GitHub setup PR finalizer merely to reuse its output.