Multi-Repo Workflows skill for Claude Code

Change several repos without breaking any consumer. Claude picks the right setup for the job, from --add-dir for a quick sibling edit to a parent workspace folder whose CLAUDE.md maps every repo, and knows what each setup does not load. Cross-repo changes start with a written plan ordered producer first with a compatibility strategy, every repo gets its own branch and its own test run, and pull requests link to each other with an explicit merge and deploy order.

  • namemulti-repo-workflows
  • size163 lines · ≈1,850 tokens
  • files1
  • licenseMIT
  • updated

What Claude sees before loading it

This description is the only part of the skill that sits in context all the time. Claude reads it to decide when to load the full playbook below.

description: Runs Claude Code across several repositories or services at once using --add-dir, /add-dir, permissions.additionalDirectories, or a parent workspace folder with a shared CLAUDE.md map, then plans cross-repo changes contract-first, keeps each repo's branch, tests, and conventions separate, and opens linked pull requests merged in a safe order. Use when a change spans a backend and frontend repo, a shared library and its consumers, microservices, or an SDK and its docs, or when Claude cannot see or edit a sibling repository.

Try asking

  • This API change needs matching updates in our web-app repo — do both
  • Set me up so Claude can work across our five service repos in one session
  • Bump the shared types package and update every consumer repo with linked PRs

Use it when

  • A change spans a library and its consumers, or a backend and frontend repo
  • Claude cannot see or edit a sibling repository
  • You want a daily setup for several related repos
  • Coordinated pull requests need a safe merge and deploy order

Skip it when

How to check the result

Each touched repo has its own branch with its own test command passing, local links are removed from lockfiles, and the linked PRs state an order in which no deployed consumer breaks.

The common mistake it prevents

Assuming --add-dir loads the sibling repo's CLAUDE.md, hooks and settings, so Claude edits it with the launch repo's conventions and none of its own checks run.

~/.claude/skills/multi-repo-workflows/SKILL.md

--- name: multi-repo-workflows description: Runs Claude Code across several repositories or services at once using --add-dir, /add-dir, permissions.additionalDirectories, or a parent… license: MIT ---

A cross-repo change is done when every repo it touches has its own branch, its own passing tests run with that repo’s commands, PRs that link to each other with a stated merge order, and no intermediate state where a deployed consumer breaks. Claude should never be guessing which repo’s conventions apply to the file it is editing.

Choose the setup

SituationSetupWhy
Main repo plus occasional reads/edits in one or two siblingsclaude --add-dir ../api ../shared or /add-dir mid-sessionQuick; grants file access only
Same sibling set every daypermissions.additionalDirectories in .claude/settings.local.jsonPersists per developer
Many repos worked as one system (polyrepo “workspace”)Launch from a parent folder that contains all clones, with a workspace CLAUDE.mdEach repo’s CLAUDE.md loads when Claude works in it
Independent parallel tasks per repoOne session per repo (or worktree), coordinated by a written planClean contexts, no cross-talk
A monorepoNot this skill; see monorepo-navigationSingle git history, different tooling

What --add-dir does and does not do

  • Grants Read/Edit access (and sandbox write access) to the added directories.
  • Does not load most .claude/ configuration from them (settings, hooks, agents); skills in an added directory’s .claude/skills/ do load.
  • Does not load the added repos’ CLAUDE.md unless you start with CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1.
  • The session’s project root, hooks, permissions, and .mcp.json stay those of the directory you launched from.
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir ../billing-api ../web-app
{ "permissions": { "additionalDirectories": ["../billing-api", "../shared-types"] } }

Workspace folder pattern

~/work/acme/
├── CLAUDE.md            # workspace map (below), not committed to any repo
├── billing-api/         # own CLAUDE.md, own .git
├── web-app/
└── shared-types/

Launch claude in ~/work/acme. The workspace CLAUDE.md loads at start; each repo’s CLAUDE.md loads when Claude reads files inside it. Keep the workspace file to a map and cross-repo rules:

# Acme workspace
Each subfolder is a separate git repo with its own CLAUDE.md, branch, and test commands.
Always `cd` into a repo before running git or its tests.

| Repo | Role | Test | Default branch |
|---|---|---|---|
| shared-types | Published TS types (npm @acme/types) | `pnpm test` | main |
| billing-api | Go service, consumes shared-types via generated client | `make test` | main |
| web-app | Next.js, consumes billing-api REST | `pnpm test` | develop |

## Cross-repo rules
- Contract changes start in shared-types; publish before consumers depend on them.
- Never commit across repos in one command; one branch and PR per repo.
- API changes are additive first; removals only after all consumers migrated.

Workflow for a cross-repo change

- [ ] 1. Map the change: which repos, which contract (API, schema, types, events)
- [ ] 2. Write the plan with order and compatibility strategy
- [ ] 3. Create one branch per repo with the same name
- [ ] 4. Implement producer first, then consumers, testing each in its own repo
- [ ] 5. Integration check across repos locally (link or pin pre-release)
- [ ] 6. Open linked PRs with merge/deploy order; confirm with the user before pushing
- [ ] 7. After merge: bump pins, remove compatibility shims in a follow-up

1–2. Map and plan

Find every consumer before changing a contract:

for r in */; do (cd "$r" && git grep -n "InvoiceStatus" -- ':!*.lock' | sed "s|^|$r|"); done
rg -n "/v1/invoices" --glob '!**/node_modules/**' .

Write the plan to a file in the workspace (not in any repo), e.g. plan-invoice-status.md:

StepRepoChangeCompatible with old consumers?Verify
1shared-typesadd "disputed" to InvoiceStatusyes (additive)pnpm test, publish 1.8.0-rc.1
2billing-apiemit disputed; accept old clientsyesmake test, contract test
3web-apprender disputed; bump typesn/apnpm test, e2e invoice page

Compatibility strategies: expand-then-contract (add new, migrate, remove old), version the endpoint, feature-flag the consumer, or tolerant readers (unknown enum values handled). Never plan a step where a deployed consumer meets a producer it cannot handle.

3–4. Branches and per-repo work

for r in shared-types billing-api web-app; do git -C "$r" switch -c feat/invoice-disputed; done
  • Run each repo’s own test command from inside it (cd billing-api && make test); a root-level npm test in the workspace folder means nothing.
  • Respect each repo’s conventions; read its CLAUDE.md before editing there.
  • For long or parallel work, delegate per repo to subagents with a self-contained brief (repo path, step from the plan, test command, what to return).

5. Integration check

EcosystemLocal linking
npm/pnpmpnpm add ../shared-types temporarily, or publish a pre-release tag
Gogo work init ./billing-api ./shared-go or a temporary replace directive
Pythonuv pip install -e ../shared-lib
Rust[patch.crates-io] shared = { path = "../shared" }

Remove local links before committing; lockfiles must point at published versions.

6. Linked PRs

gh pr create -R acme/shared-types --title "feat: add disputed invoice status" --body-file pr1.md
gh pr create -R acme/billing-api  --title "feat: emit disputed status" --body "Depends on acme/shared-types#412. Merge after it is published."

Each body states: depends on, merge order, deploy order, rollback. Pushing and opening PRs are shared-state actions: show the user the list and get confirmation first.

Gotchas

  • Hooks and permissions come from the launch directory only. A formatter hook in web-app/.claude/settings.json does not run when you launched from billing-api.
  • git commands run in the shell’s current directory; always use git -C <repo> or cd first, or you commit to the wrong repo.
  • Relative paths in CLAUDE.md files are relative to that file; workspace-level imports of repo files need correct relative paths.
  • Different package managers, Node versions, or Go versions per repo: check each repo’s .nvmrc, .tool-versions, packageManager field before running commands.
  • Large sibling repos inflate search noise; scope searches with paths and globs.
  • Do not copy code between repos to “unblock” a consumer; depend on the published artifact.

Output

**Change:** add `disputed` invoice status across 3 repos (plan: ~/work/acme/plan-invoice-status.md)
| Order | Repo | Branch | Tests | PR |
|---|---|---|---|---|
| 1 | shared-types | feat/invoice-disputed | pnpm test pass | acme/shared-types#412 (publish 1.8.0) |
| 2 | billing-api | feat/invoice-disputed | make test pass, contract test pass | acme/billing-api#977 (after #412) |
| 3 | web-app | feat/invoice-disputed | pnpm test pass, e2e pass | acme/web-app#1503 (after #977 deployed) |
**Compatibility:** additive enum; web-app tolerates unknown statuses; no breaking window
**Follow-up:** remove fallback rendering after 2 releases

About this skill

Written and maintained by the Claude Skills editors to the same editorial standard as every skill in the directory: a selective trigger, a real workflow, known pitfalls and a verification step. First published , last updated . MIT licensed.

esc