-
Notifications
You must be signed in to change notification settings - Fork 10.1k
docs: add monorepo guide #3084
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
PascalThuet
wants to merge
5
commits into
github:main
Choose a base branch
from
PascalThuet:docs/monorepo-guide
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+112
−0
Open
docs: add monorepo guide #3084
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
34e456f
docs: add monorepo guide
PascalThuet 43adf23
docs: correct monorepo Git guidance
PascalThuet 516878d
docs: drop open-issue reference and polish monorepo guide prose
PascalThuet 211af06
docs: fix SPECIFY_INIT_DIR error example (absolute path, non-project …
PascalThuet 9f38d40
docs: address Copilot wording nits in monorepo guide
PascalThuet File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| # Using Spec Kit in a Monorepo | ||
|
|
||
| A Spec Kit project is **directory-scoped**: the project is whichever directory | ||
| contains `.specify/`. A monorepo can hold several independent Spec Kit projects | ||
| under one repository root, each with its own `.specify/`, `specs/`, constitution, | ||
| and feature numbering. | ||
|
|
||
| Root resolution already prefers the **nearest** `.specify/` over the Git | ||
| toplevel, so commands run from inside a member project resolve to that project, | ||
| not the repo root. | ||
|
|
||
| ## Layout | ||
|
|
||
| ```text | ||
| my-monorepo/ | ||
| ├── .git/ # one Git repository at the root | ||
| ├── apps/ | ||
| │ ├── web/ | ||
| │ │ └── .specify/ # Spec Kit project "web" | ||
| │ │ └── memory/constitution.md | ||
| │ └── api/ | ||
| │ └── .specify/ # Spec Kit project "api" | ||
| │ └── memory/constitution.md | ||
| └── packages/ | ||
| └── ui/ | ||
| └── .specify/ # Spec Kit project "ui" | ||
| ``` | ||
|
|
||
| Initialize each member project independently: | ||
|
|
||
| ```bash | ||
| specify init apps/web --integration claude | ||
| specify init apps/api --integration claude | ||
| ``` | ||
|
|
||
| Each project keeps its own `specs/` directory and numbers features | ||
| independently (`apps/web/specs/001-…`, `apps/api/specs/001-…`). | ||
|
|
||
| ## Working inside a member project | ||
|
|
||
| The default workflow is unchanged: change into the project directory and run the | ||
| slash commands. Root resolution finds the nearest `.specify/`. | ||
|
|
||
| ```bash | ||
| cd apps/web | ||
| # then run /speckit.specify, /speckit.plan, … in your agent | ||
| ``` | ||
|
|
||
| ## Targeting a member project from the repo root | ||
|
|
||
| For non-interactive or CI runs where you do not want to `cd`, set | ||
| **`SPECIFY_INIT_DIR`** to the member project root (the directory *containing* | ||
| `.specify/`). Relative paths resolve against the current directory. | ||
|
|
||
| ```bash | ||
| # operate on apps/web from the monorepo root (no cd required) | ||
| export SPECIFY_INIT_DIR=apps/web | ||
| ``` | ||
|
|
||
| The path must exist and contain `.specify/`. If it does not, the command | ||
| **errors and does not fall back** to the current directory or the Git toplevel. | ||
| This is deliberate: a typo never writes specs into the wrong project. A | ||
| nonexistent path is reported as you typed it; a path that exists but is not a | ||
| Spec Kit project is reported as its resolved absolute path: | ||
|
|
||
| ```text | ||
| # SPECIFY_INIT_DIR=apps/wbe (typo: no such directory) | ||
| ERROR: SPECIFY_INIT_DIR does not point to an existing directory: apps/wbe | ||
|
|
||
| # SPECIFY_INIT_DIR=apps (exists, but has no .specify/ of its own) | ||
| ERROR: SPECIFY_INIT_DIR is not a Spec Kit project (no .specify/ directory): /home/you/my-monorepo/apps | ||
| ``` | ||
|
|
||
| `SPECIFY_INIT_DIR` selects the **project**; `SPECIFY_FEATURE_DIRECTORY` selects | ||
| the **feature** within it. They compose: set both to pick a project and a | ||
| feature non-interactively. See the | ||
| [`SPECIFY_INIT_DIR` reference](../reference/core.md#environment-variables) for | ||
| the full contract and the two-axes model. | ||
|
|
||
| ## How `SPECIFY_INIT_DIR` reaches your agent | ||
|
|
||
| `SPECIFY_INIT_DIR` is read by the shell scripts that the slash commands invoke | ||
| (`get_repo_root` in Bash, `Get-RepoRoot` in PowerShell). It takes effect only | ||
| when it is present in the environment of the shell that runs those scripts. | ||
|
|
||
| - **Scripted / CI runs:** export it in the same shell that drives the commands; | ||
| it is reliable there. | ||
| - **Interactive agents:** whether an exported variable reaches the shell tool an | ||
| agent uses is agent-specific. Export `SPECIFY_INIT_DIR` *before* launching the | ||
| agent, and verify once (e.g. run `/speckit.specify` and confirm the new feature | ||
| landed under the intended project's `specs/`). | ||
|
|
||
| ## Git in a monorepo | ||
|
|
||
| > [!NOTE] | ||
| > Spec Kit project files are scoped to the **resolved project root**, but Git | ||
| > operations still run in the containing Git work tree. In a monorepo with a | ||
| > single Git repository at the root and projects in subdirectories, feature | ||
| > branch creation creates or switches branches in the shared root repository. | ||
| > Spec directories still live under the selected member project, while the Git | ||
| > branch namespace is shared by the whole monorepo. Manage branches and commits | ||
| > at the repository root, or initialize Git per member project if you want | ||
| > isolated per-project branch namespaces. | ||
|
|
||
| ## Constitutions | ||
|
|
||
| Each member project has its own `.specify/memory/constitution.md` and | ||
| `/speckit.constitution` edits the local project's file. There is no base/inheritance | ||
| mechanism today, so shared engineering rules must be duplicated per project or kept | ||
| out of the constitution. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While correct it is certainly possible for a constitution.md to refer to another constitution in another directory. But that plumbing is something one would have to do yourself