Install
$ agentstack add skill-precisionutilityguild-virtual-monorepo-virtual-monorepo ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Virtual Monorepo
A "virtual monorepo" is a parent directory holding symlinks to several real repos plus a workspace-level CLAUDE.md that explains how the system fits together. Claude Code works one repo at a time; this convention gives it the whole system in one working tree. You (the model) do all setup and maintenance with plain Bash. There is no CLI binary, no index, no daemon.
Refuse permanently
Never, under any framing, create: a background process/watcher, a database or SQLite file, a JSON/YAML index of the repos, or a per-file catalog. A repo summary is one paragraph of prose, not a file listing. If asked to "keep it in sync automatically" or "index the code," decline and explain: the workspace is regenerated on demand by re-reading, one shot. This constraint is the product. Prior in-house attempts at an index measured no better than plain grep — do not rebuild it.
1. Discover
Given a starting repo or directory, find candidate sibling repos and propose the set before creating anything.
Algorithm: scan the parent dir one level down for entries containing a .git (dir or file — a .git file means a worktree, still counts). Enumerate all candidates first, then prune any candidate whose realpath is contained inside another candidate's realpath (drop the nested one). Apply the skip-list by directory name at that single level.
- Skip (by dir name at this level):
node_modules,dist,build,target,.next, plus
.git internals and any dir the user excludes.
- Optionally ask the user for extra roots beyond the parent dir.
- List each candidate with its path and (if present) its
package.json/pyproject.toml/go.mod
name. Ask the user to confirm/trim the set. Do not proceed silently.
2. Set up
- Pick a workspace dir: default
~/workspaces/, or a user-chosen path. Ask for ``. - Containment check — do this BEFORE
mkdir. Resolve the workspace path and every candidate
repo with realpath, then refuse if the resolved workspace path is prefix-contained in any resolved repo path (symlink-loop / repo-pollution hazard). Only proceed to relocate outside every candidate.
- Create the workspace:
mkdir -p "". - For each confirmed repo:
ln -s "" "/". **Quote every
path** — a space in any path silently breaks or mislinks otherwise.
- Name collisions: if two repos share a basename, disambiguate (
api-web,api-mobile,
or -) and tell the user the mapping.
- Different disks: symlinks work across volumes; note that git operations still run
per-repo (no cross-disk cross-repo git). This is fine — each symlink is just a door.
- Windows: symlinks require Developer Mode enabled (or admin);
ln -smaps to
mklink /D. If on Windows, tell the user to enable Developer Mode first.
- Generate
"/CLAUDE.md"(see section 4).
3. Wire into Claude Code
- Launch from the workspace dir (
cd "" && claude) for ongoing multi-repo work: the
workspace CLAUDE.md loads as context and every repo is reachable through its symlink. This is the default for a system you return to.
--add-dirfor ad-hoc sessions:claude --add-dir ""adds one extra root to a
session already running in a single repo, without building a workspace. Use it for a one-off "also look at that repo" — no symlinks, no CLAUDE.md, nothing to clean up.
- Rule of thumb: recurring system → workspace; one-time glance →
--add-dir.
Headless / permission-restricted sessions
In non-interactive sessions (e.g. claude -p) the permission system may deny ln -s. When a command you need is denied, present the exact commands for the user to run themselves and stop — never bypass a permission gate through another mechanism (e.g. scripting the symlink through an interpreter). A denied gate is a stop, not an obstacle to route around.
4. Generate the workspace CLAUDE.md
Read each repo once and write prose. The file (see spec/output-samples/workspace-CLAUDE.md for the golden shape) contains, in order:
- System overview — one sentence naming what the whole system does.
- Per-repo summary — one paragraph per repo. Derive it by reading that repo's
README,
CLAUDE.md, and package manifest (package.json / pyproject.toml / go.mod / Cargo.toml): what it is, its stack, how it's run. Prose, not a file tree.
- Cross-repo relationships — who calls whom and shared packages, derived one-shot by
reading: dependencies/devDependencies naming sibling repos, file:/workspace: deps, and obvious API-client code (base URLs, generated clients, shared types). State it as a snapshot ("as of "), not a live index. If unsure, say so rather than guess.
- How to run — per-repo start/test commands (pulled from
scripts/ Makefile / README),
and any known startup order.
Keep it tight — a page or two. It is a map, not a mirror of the code.
5. Maintain (all one-shot)
- Stale symlinks:
find "" -maxdepth 1 -type l '!' -exec test -e {} ';' -print
lists only broken links, on both BSD/macOS and GNU find (ls -l can't — it prints the target whether or not it exists). Offer to remove or re-point each broken one.
- Add a repo: confirm it's a git dir,
ln -s "" "/"(watch for name
collision), then append a summary paragraph and update the relationships section.
- Remove a repo:
rm "/"(removes the symlink only, never the real repo —
confirm the target is a symlink first with test -L "/"), then prune its paragraph.
- Regenerate the summary: on request, re-read the repos and rewrite
CLAUDE.mdfresh. This is
the "keep it current" answer — a manual regenerate, never a watcher.
Edge cases checklist
- Workspace dir inside a repo → refuse, relocate.
- Repos on different disks → symlinks fine; git stays per-repo.
- Windows → needs Developer Mode for symlinks.
- Name collisions → disambiguate and report the mapping.
- A
.gitfile (worktree) → still a valid candidate; treat as a repo.
What "done" looks like
A workspace dir of symlinks + one hand-written CLAUDE.md, launchable with cd && claude. No process running, no file the user has to keep fed. If you created anything that must be kept in sync automatically, you did it wrong — delete it and regenerate on demand instead.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: PrecisionUtilityGuild
- Source: PrecisionUtilityGuild/virtual-monorepo
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.