Skip to main content

When you need this

Skip this page entirely if your repo isn’t a workspace of multiple packages — leave packages: [] and everything works exactly as described elsewhere in these docs. Read on if the repo shipflow runs in (or any repo listed under repos: in polyrepo) is itself an npm/pnpm/yarn workspace, an Nx or Turborepo monorepo, a Lerna repo, a Go multi-module repo, or a .NET solution with several projects — one work item can need changes in more than one package.
Monorepo is not polyrepo. repos: is for separate git repositories, each getting its own branch and PR — see Polyrepo. packages: is for multiple packages inside one git repository — they share a single branch and a single PR. A repo can use both: a polyrepo repos[] entry can itself declare packages if that particular repo is a monorepo.

The core idea

Packages never get their own branch or PR. Only repos causes that fan-out. packages only changes three things: feature-context/feature-plan ground and assign tasks per package, feature-tests runs each touched package’s own test command, and feature-verify grades AC evidence per package — all within the one diff and one PR the repo already has.

Configuring packages

In shipflow.config.md:
Each entry needs a name (used in grounding, plan, and verify output — not branches, since there are none per package), a path relative to the repo root, and an optional tests override for when packages use different frameworks or need a workspace-scoped command (pnpm --filter <name> test, nx test <name>, turbo run test --filter=<name>).

Worked example

Say AB#1234 is “show the user’s subscription tier in account settings,” in a pnpm-workspace monorepo with packages/web and packages/api.
1

Context

feature-context normalizes two ACs (AC1: API returns tier, AC2: settings page displays it) and, since packages is non-empty, takes a first pass at which packages are likely touched — api for AC1, web for AC2. A first read, not a commitment, exactly like polyrepo’s repo grounding but for packages within the one repo.
2

Plan

feature-plan commits to the touched set and tags every task with its package:Unlike polyrepo’s repo table, there’s no “gets a PR” column — packages never get one.
3

Implement

One branch, feature/1234-subscription-tier, for the whole repo. Tasks tagged api are made in packages/api; tasks tagged web in packages/web — same branch throughout.
4

Tests

Runs per touched package: pnpm --filter api test for the API change, pnpm --filter web test for the UI change — both on the same branch, reported separately.
5

Verify

Aggregates per package within the one diff: AC1 is MET only if packages/api’s code + test satisfy it; AC2 only if packages/web’s do. If api’s change lands but web’s doesn’t, the item is NOT READY — same aggregation rule as polyrepo, just without a second branch.
6

PR

Opens exactly one PR for the repo. Its AC checklist may note AC1 — packages/api, AC2 — packages/web for the reviewer’s benefit, but there is only ever one PR regardless of how many packages were touched.

What changes vs. a single package

Combining with polyrepo

If a polyrepo repos[] entry is itself a monorepo, set packages on that entry instead of at the top level:
platform still gets exactly one branch and one PR (per the polyrepo rule); its two packages are graded separately within that one PR (per the monorepo rule). The two mechanisms compose without special-casing — repo-level fan-out and package-level grounding are independent.