Repository navigation
Mono repo considerations and best practices #581
Description
Activity
I was thinking about this too. There is no native support for different project structures, but you can either:
- Init spec-kit in each subproject, which will involve you more in the feature design process. Less "vibecoding" approach, and more predictable outcomes for large monorepos.
- Init it in the root folder, which also works fine. With this approach, your agent will be able to work on a broader-scope features.
Regrettably, the first choice forces you to code within the subproject's working directory.
In my case, we use a monorepo-within-monorepo structure because each sub-monorepo has a different tech stack. Ex:
- repo
- platform: web-based tech stack; nextjs
- apps/web
- apps/admin
- functions: lambda functions for tasks; python
- throttle-login
- backup
- platform: web-based tech stack; nextjs
Each sub-monorepo comes with its own container setup. To support this, we use a spec-kit in each sub-monorepo and make small adjustments in the
common.shscript, for example:platform/.specify/scripts/bash/common.sh# Get repository root, with fallback for non-git repositories get_repo_root() { + # This repo was configured in non-git mode, so we need to use the script location + # if git rev-parse --show-toplevel >/dev/null 2>&1; then + # git rev-parse --show-toplevel) + # else # Fall back to script location for non-git repos local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" (cd "$script_dir/../../.." && pwd) + # fi }
This setup works well for us, so I think
get_repo_rootshould prioritize the--no-gitconfig overgit rev-parse.Reacted by François Séguin- repo
I just had a situation in a mono-repo:
repo-root └── project-root ├── .specifyinitially after running
/specify, thespecsdirectory was inserted intorepo-root. I moved it toproject-root. I'm hoping this doesn't mess things up.Should
specsbe parallel to where ever the.specifydirectory is (in general)? That way, the specifications are tied to the memory.Reacted by Jaco Alberts, Andrey Voroshkov and Yang Hanlininitially after running
/specify, thespecsdirectory was inserted intorepo-root. I moved it toproject-root. I'm hoping this doesn't mess things up.
It should notShould
specsbe parallel to where ever the.specifydirectory is (in general)? That way, the specifications are tied to the memory.
They should be placed in the same dir.@schnee, you have initialized the spec-kit in the subproject directory. Now, you need to set it as the current working directory.
@outp1 thank you.
When I initialized spec-kit, it was something like:
cd repo-root mkdir project-root && cd project-root && uvx --from git+https://github.com/github/spec-kit.git specify init --here --ai opencode --script shthat apparently did not set the subproject directory (project-root) as the current working directory (which in this case should be project-root because of the --here correct?). How do I set spec-kit's current working directory? I doesn't seem to be a "cd" command.
Would the idea then to be, init the spec kit in the repo root. Then use spec kit to describe the project as a whole. Going through and defining what each application does and how they relate to one and other. Then when I want to work an app to add a feature, I could then do "/spec" making sure I refer to the correct app within the mono repo?
Experiencing similar frustration with location of the
specfolder in the REPO_ROOT in a mono repo, working with worktrees almost exclusively. In my mind this should be located int the PROJECT_ROOT or WORKSPACE_ROOT? Especially for worktrees this would be preferred in our case.
Having thespecsfolder in the REPO_ROOT causes confusion and does not support separation of concerns. The simplest solution might be to just allow the user to specify the root and record it in Spec Kit's memory for future use? Although that might complicated the scripts.
For now, i have edited the scripts to look in the workspace root instead of REPO_ROOT. This works, but is far from an ideal long term fix. I subsequently rolled these changes back to avoid future headaches.
Keep in mind that mono repos by their mere existence and definition means hosting multiple project "repos" in one git repo. The physical limitation of git's "limited" support for sub-repos made this a necessity.I have found that I can "force" the behavior I want with commands such as:
/tasks specs/001-feature/plan.mdthat is, being very explicit with the pathing (the above assumes I'm in PROJECT_ROOT).
Thinking about mono-repos, one could envision a future where a repo-level constitution.md exists, as well as project-level constitutions. Spec-kit could assemble them as it processes, allowing for a cascade of governance.
I did this
get_repo_root() { + # This repo was configured in non-git mode, so we need to use the script location + # if git rev-parse --show-toplevel >/dev/null 2>&1; then + # git rev-parse --show-toplevel) + # else # Fall back to script location for non-git repos local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" (cd "$script_dir/../../.." && pwd) + # fi }and search replaced "repo root" with "project root" in the commands, so far seems to do the trick
Reacted by Brent SchneemanI did this
get_repo_root() { + # This repo was configured in non-git mode, so we need to use the script location + # if git rev-parse --show-toplevel >/dev/null 2>&1; then + # git rev-parse --show-toplevel) + # else # Fall back to script location for non-git repos local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" (cd "$script_dir/../../.." && pwd) + # fi }and search replaced "repo root" with "project root" in the commands, so far seems to do the trick
I did this too. The problem with this is that if you apply any updates from spec-kit to your repo/project then the scripts will be overwritten and you lose the change. So not ideal, but it works.
Reacted by Shashi KumarSame here, the workaround worked partially and it was trying to inspect the code in the root dir.
Ideally whenever initializing in a subdir, the tool should bootstrap the script automatically to handle specifying a base directory
Reacted by Andrey VoroshkovStrongly vote for changing all scripts to use project root instead of monorepo root as well.
Reacted by William Goulois, Moritz Laass, Jaco Alberts, Dima Ryskin, Damien Lecan, Jackson, Ivan Martinez, acgxv, Yoshiyuki Kinjo, tourze and 11 morePlease support this. It becomes more and more important for managing big project with AI.
My temporary fix is:
mv .git .git.bak specify init --no-git --ai codex --script sh mono-repo-sub-project cd mono-repo-sub-project CODEX_HOME=.codex codex # run /specify.cmds # exit codex cd .. mv .git.bak .gitReacted by Moritz Laass, acgxv, Christfried Focke, Shashi Kumar and KAOSTECKReacted by Osher El-NetananyI did this
get_repo_root() { + # This repo was configured in non-git mode, so we need to use the script location + # if git rev-parse --show-toplevel >/dev/null 2>&1; then + # git rev-parse --show-toplevel) + # else # Fall back to script location for non-git repos local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" (cd "$script_dir/../../.." && pwd) + # fi }and search replaced "repo root" with "project root" in the commands, so far seems to do the trick
We could do a slightly more precise approach like this: qdentity@3c57223
basically just check if there is a .specify in the cwd, otherwise use repo root. wdyt?
Reacted by shunsuke.aki and Damien LecanI tried spec-kit on mono-repo of Git.
I encountered the issue when I run/speckit.implement.My another suggestion is making your LLM Agent to allow modify
.specify/scripts/bash/common.sh
to support mono repo at startup phase of LLM.My usecase is such as
$ export CODEX_HOME=path-to-dot-codex/.codex codex "You can modify $PWD/.specify/scripts/bash/common.sh` If you had to support this mono repo. If you modified the script then tell me if you did."
Then changes like below is to be made by LLM in common.sh. If you disallow LLM to modify the other non-related directory, you are safe!
# Get repository root, with fallback for non-git repositories get_repo_root() { # Prefer the .specify root relative to this script to keep spec-kit scoped local script_dir="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" local script_root="$(cd "$script_dir/../../.." && pwd)" if [ -d "$script_root/.specify" ]; then echo "$script_root" elif git rev-parse --show-toplevel >/dev/null 2>&1; then git rev-parse --show-toplevel else # Fall back to script location for non-git repos echo "$script_root" fi }- marked How to spec bootstrap across multiple projects in a Micro-service architecture #1440 as a duplicate of this issue
on Jan 8, 2026 Gemini apparently got frustrated with not finding the files where the PS scripts were looking for them in my repo, so it patched the common.ps1 file itself:
function Get-RepoRoot { # Check relative to script location first (handles monorepos/subdirs) $scriptRelativeRoot = (Resolve-Path (Join-Path $PSScriptRoot "../../..") -ErrorAction SilentlyContinue).Path if ($scriptRelativeRoot -and (Test-Path (Join-Path $scriptRelativeRoot ".specify"))) { return $scriptRelativeRoot } try { $result = git rev-parse --show-toplevel 2>$null if ($LASTEXITCODE -eq 0) { return $result } } catch { # Git command failed } # Fall back to script location for non-git repos return $scriptRelativeRoot }+1 from me on this. My use case is a monorepo with tens of unrelated projects focused on learning, rapid prototyping and experimentation. It would be a huge improvement if SpecKit could treat the current working directory as the primary project root (with repo-root fallback), so each project could keep its specs fully independent and relevant only to that directory.
Reacted by Illia Bukatych, Ismael Hamed, tobias sasse and Sergii KovalovMono repo support has been delivered by disconnecting Git and features from each other. As such this issue can now be closed. If there is any more to be done please start a new discussion or open a new feature request with specifics
Hello,
I use a mono repo for my organization. So each app/website/api is a folder in the mono repo. The big picture is that they all use the same db structure as the glue that bind them together. However each app/api has a specific job to do. For example, kubernetes provisioning a work load, or sending an email.
I am wondering how do I use spec kit in this situation? Is there one spec for the whole repo or can there be a spec in each dir for each micro service. Here is the dir structure
repo
- main website
- kubernetes api
- email api
- stripe api
- admin website
- proxmox api
I hope this question makes sense. I tried separate repo's for each micro service and it was just too cumbersome when making global changes. I am the only dev so it seems to work for me.
The project is fantastic btw.
Brad