Skip to main content

Multi-Repo Workspaces

hatch3r can manage multiple git repositories from a single workspace root. A shared .hatch3r/ directory at the workspace root holds the workspace.json manifest and shared state, and hatch3r sync cascades configuration into each sub-repo. Canonical content itself is read from the bundled npm package (not materialized at the workspace root).

What is a workspace?

A workspace is a non-git directory that contains multiple git repositories as subdirectories. hatch3r treats the parent directory as the workspace root and each git subdirectory as a managed sub-repo.

my-platform/ <- Workspace root (not a git repo)
.hatch3r/ <- Shared workspace state
workspace.json <- Workspace manifest
hatch.json <- Workspace-level content selection
overrides/ <- Shared user-tier overrides (optional)
mcp/mcp.json <- Resolved MCP config
frontend/ <- Git repo
.hatch3r/hatch.json <- Per-repo manifest
.cursor/ <- Generated adapter output
CLAUDE.md <- Generated adapter output
backend/ <- Git repo
.hatch3r/hatch.json
CLAUDE.md
infra/ <- Git repo
.hatch3r/hatch.json
.cursor/
CLAUDE.md

Canonical content (agents, skills, rules, commands, hooks) is read from the bundled npm package by each adapter — neither the workspace root nor any sub-repo materializes a .agents/ content tree.

Setting up a workspace

Run hatch3r init inside the workspace root directory. If the directory is not a git repo but contains git subdirectories, init auto-detects the workspace layout and prompts to confirm.

cd ~/projects/my-platform
npx hatch3r init

To skip the prompt, pass --workspace:

npx hatch3r init --workspace

Init walks through the standard setup flow (platform, tools, content profile, features, MCP servers) and then asks which subdirectories to include as managed repos.

Workspace manifest

The workspace manifest lives at .hatch3r/workspace.json. It tracks which repos are managed, their per-repo overrides, and the sync strategy.

{
"version": "1.0.0",
"syncStrategy": "on-sync",
"repos": [
{
"path": "frontend",
"tools": ["cursor", "claude"],
"sync": true,
"overrides": {
"include": ["hatch3r-implementer", "hatch3r-reviewer"],
"exclude": ["hatch3r-board-fill"]
}
},
{
"path": "backend",
"tools": ["claude"],
"sync": true,
"overrides": {}
}
]
}
FieldDescription
syncStrategy"manual" -- sync only when you run hatch3r sync; "on-sync" -- cascade on every sync
repos[].pathRelative path from workspace root to the sub-repo
repos[].toolsTools enabled for this repo (overrides workspace-level tools)
repos[].syncSet to false to skip this repo during sync cascades
repos[].overridesPer-repo content include/exclude lists

Syncing content to sub-repos

hatch3r sync generates tool-specific files in each sub-repo from the bundled canonical content plus the workspace-level selection and any per-repo overrides.

npx hatch3r sync # sync all repos
npx hatch3r sync --repos frontend # sync one repo
npx hatch3r sync --repos frontend backend # sync specific repos
npx hatch3r sync --dry-run # preview without writing
npx hatch3r sync --force # overwrite even if unchanged

Sync uses copy-based distribution -- each sub-repo receives independent copies of the generated files, not symlinks. This means sub-repos work correctly when opened in isolation.

Per-repo overrides

Each repo entry in workspace.json can override tools, features, and content:

  • Tools -- different repos can target different coding tools
  • Include -- add content IDs beyond the workspace defaults
  • Exclude -- remove specific content IDs from this repo
{
"path": "frontend",
"tools": ["cursor", "claude"],
"sync": true,
"overrides": {
"include": ["hatch3r-a11y-audit"],
"exclude": ["hatch3r-devops", "hatch3r-ci-pipeline"]
}
}

Content inheritance model

Content resolution follows three layers, applied in order:

  1. Workspace defaults -- content selected during hatch3r init at the workspace root (stored in hatch.json)
  2. Per-repo includes -- additional content IDs added via overrides.include
  3. Per-repo excludes -- content IDs removed via overrides.exclude

The final content set for each sub-repo is: (workspace defaults + includes) - excludes.

How AI tools behave

Different coding tools handle file inheritance differently, and workspace layout accounts for this:

  • Claude Code walks up the directory tree looking for CLAUDE.md. A sub-repo CLAUDE.md can be lean because Claude will also find the workspace-level instructions if the workspace root is an ancestor directory.
  • Cursor does not inherit from parent directories. Each sub-repo needs a complete .cursor/ directory with all rules, agents, and MCP config. hatch3r sync handles this automatically.
  • Copilot reads configuration from the project root only. Sync generates complete files in each sub-repo.

Managing repos via hatch3r config

Use hatch3r config to manage workspace repos interactively:

npx hatch3r config

The config flow includes workspace management options:

  • Add new sub-repos to the workspace
  • Remove repos from sync management
  • Toggle sync on/off for individual repos
  • Change per-repo tool and content overrides
  • Switch the sync strategy

You can also edit .hatch3r/workspace.json directly.

Sync strategies

StrategyBehavior
manualSub-repos are only updated when you explicitly run hatch3r sync
on-syncEvery hatch3r sync (and hatch3r update) cascades changes to all enabled sub-repos

Choose manual if you want full control over when sub-repos are updated. Choose on-sync (the default) for a hands-off workflow where changes propagate automatically.

Change the strategy via hatch3r config or by editing syncStrategy in workspace.json.