working-in-monorepos
Use when working in repositories with multiple subprojects (monorepos) where commands need to run from specific directories - prevents directory confusion, redundant cd commands, and ensures commands execute from correct locations
Packaged view
This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.
Install command
npx @skill-hub/cli install technicalpickles-pickled-claude-plugins-working-in-monorepos
Repository
Skill path: plugins/working-in-monorepos/skills/working-in-monorepos
Use when working in repositories with multiple subprojects (monorepos) where commands need to run from specific directories - prevents directory confusion, redundant cd commands, and ensures commands execute from correct locations
Open repositoryBest for
Primary workflow: Ship Full Stack.
Technical facets: Full Stack.
Target audience: everyone.
License: Unknown.
Original source
Catalog source: SkillHub Club.
Repository owner: technicalpickles.
This is still a mirrored public skill entry. Review the repository before installing into production workflows.
What it helps with
- Install working-in-monorepos into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
- Review https://github.com/technicalpickles/pickled-claude-plugins before adding working-in-monorepos to shared team environments
- Use working-in-monorepos for development workflows
Works across
Favorites: 0.
Sub-skills: 0.
Aggregator: No.
Original source / Raw SKILL.md
---
name: working-in-monorepos
description: Use when working in repositories with multiple subprojects (monorepos) where commands need to run from specific directories - prevents directory confusion, redundant cd commands, and ensures commands execute from correct locations
---
# Working in Monorepos
## Overview
Helps Claude work effectively in monorepo environments by ensuring commands always execute from the correct location using absolute paths.
**Core principle:** Bash shell state is not guaranteed between commands. Always use absolute paths.
**Announce at start:** "I'm using the working-in-monorepos skill."
## When to Use
Use this skill when:
- Repository contains multiple subprojects (ruby/, cli/, components/\*, etc.)
- Commands must run from specific directories
- Working across multiple subprojects in one session
Don't use for:
- Single-project repositories
- Repositories where all commands run from root
## The Iron Rule: Always Use Absolute Paths
When executing ANY command in a monorepo subproject:
✅ **CORRECT:**
```bash
cd /Users/josh/workspace/schemaflow/ruby && bundle exec rspec
cd /Users/josh/workspace/schemaflow/cli && npm test
```
❌ **WRONG:**
```bash
# Relative paths (assumes current directory)
cd ruby && bundle exec rspec
# No cd prefix (assumes location)
bundle exec rspec
# Chaining cd (compounds errors)
cd ruby && cd ruby && rspec
```
**Why:** You cannot rely on shell state. Absolute paths guarantee correct execution location regardless of where the shell currently is.
## Constructing Absolute Paths
### With .monorepo.json Config
If `.monorepo.json` exists at repo root:
1. Read `root` field for absolute repo path
2. Read subproject `path` from `subprojects` map
3. Construct: `cd {root}/{path} && command`
Example:
```json
{
"root": "/Users/josh/workspace/schemaflow",
"subprojects": { "ruby": { "path": "ruby" } }
}
```
→ `cd /Users/josh/workspace/schemaflow/ruby && bundle exec rspec`
### Without Config
Use git to find repo root, then construct absolute path:
1. First get the repo root: `git rev-parse --show-toplevel`
2. Use that absolute path: `cd /absolute/path/to/repo/ruby && bundle exec rspec`
**Example workflow:**
```bash
# Step 1: Get repo root
git rev-parse --show-toplevel
# Output: /Users/josh/workspace/schemaflow
# Step 2: Use absolute path in commands
cd /Users/josh/workspace/schemaflow/ruby && bundle exec rspec
```
**Why not use command substitution:** `cd $(git rev-parse --show-toplevel)/ruby` requires user approval. Instead, run `git rev-parse` once, then use the absolute path directly in all subsequent commands.
**⚠️ Git subtree caveat:** In repositories containing git subtrees (nested git repos), `git rev-parse --show-toplevel` returns the innermost repo root, not the monorepo root. This makes it unreliable for subtree scenarios. Creating a `.monorepo.json` config is the robust solution that works in all cases.
## Workflow When Working Without Config
When working in a repo without `.monorepo.json`:
1. **Get repo root ONCE at start of session:** Run `git rev-parse --show-toplevel`
2. **Store the result mentally:** e.g., `/Users/josh/workspace/schemaflow`
3. **Use absolute paths for ALL commands:** `cd /Users/josh/workspace/schemaflow/subproject && command`
**Do NOT use command substitution like `cd $(git rev-parse --show-toplevel)/subproject`** - this requires user approval every time. Get the path once, then use it directly.
**Important limitation:** `git rev-parse --show-toplevel` may not work correctly in repositories with git subtrees (nested git repos), as it returns the innermost repository root. For subtree scenarios, a `.monorepo.json` config is strongly recommended to explicitly define the true monorepo root.
## Setup Workflow (No Config Present)
When skill activates in a repo without `.monorepo.json`:
1. **Detect:** "I notice this appears to be a monorepo without a .monorepo.json config."
2. **Offer:** "I can run ~/.claude/skills/working-in-monorepos/scripts/monorepo-init to auto-detect subprojects and generate config. Would you like me to?"
3. **User accepts:** Run `~/.claude/skills/working-in-monorepos/scripts/monorepo-init --dry-run`, show output, ask for approval, then `~/.claude/skills/working-in-monorepos/scripts/monorepo-init --write`
4. **User declines:** "No problem. I'll get the repo root once with git rev-parse and use absolute paths for all commands."
5. **User wants custom:** "You can also create .monorepo.json manually. See example below."
**Helper Script Philosophy:**
The `monorepo-init` script is designed as a **black-box tool**:
- **Always run with `--help` first** to see usage
- **DO NOT read the script source** unless absolutely necessary - it pollutes your context window
- The script exists to be called directly, not analyzed
- All necessary usage information is in the help output
**Script Location:**
The script is located at `~/.claude/skills/working-in-monorepos/scripts/monorepo-init` (absolute path). Since skills are symlinked from the dotfiles repo via `home/.claude/skills/` → `~/.claude/skills/`, this path works universally regardless of which project directory you're currently in.
```bash
# Run from any directory - use the absolute path
~/.claude/skills/working-in-monorepos/scripts/monorepo-init --help
~/.claude/skills/working-in-monorepos/scripts/monorepo-init --dry-run
~/.claude/skills/working-in-monorepos/scripts/monorepo-init --write
```
## Command Execution Rules (With Config)
If `.monorepo.json` defines command rules:
```json
{
"commands": {
"rubocop": { "location": "root" },
"rspec": {
"location": "subproject",
"command": "bundle exec rspec",
"overrides": { "root": { "command": "bin/rspec" } }
}
}
}
```
**Check rules before executing:**
1. Look up command in `commands` map
2. Check `location`: "root" | "subproject"
3. Check for `command` override
4. Check for context-specific `overrides`
**Example:**
- rubocop: Always run from repo root
- rspec in ruby/: Use `bundle exec rspec`
- rspec in root project: Use `bin/rspec`
## Common Mistakes to Prevent
❌ **"I just used cd, so I'm in the right directory"**
Reality: You cannot track shell state reliably. Always use absolute paths.
❌ **"The shell remembers where I am"**
Reality: Shell state is not guaranteed between commands. Always use absolute paths.
❌ **"It's wasteful to cd every time"**
Reality: Explicitness prevents bugs. Always use absolute paths.
❌ **"Relative paths are simpler"**
Reality: They break when assumptions are wrong. Always use absolute paths.
## Quick Reference
| Task | Command Pattern |
| ----------------------- | ------------------------------------------------------------------------------------------------------- |
| Get repo root | `git rev-parse --show-toplevel` (run once, use result in all commands) |
| Run tests in subproject | `cd /absolute/path/to/repo/subproject && test-command` |
| With config | `cd {root}/{subproject.path} && command` |
| Check for config | `test -f .monorepo.json` |
| Generate config | `~/.claude/skills/working-in-monorepos/scripts/monorepo-init --dry-run` (works from any directory) |
| Always rule | Use absolute path + cd prefix for EVERY command. Get repo root first, then use absolute paths directly. |
## Configuration Schema
`.monorepo.json` at repository root:
```json
{
"root": "/absolute/path/to/repo",
"subprojects": {
"subproject-id": {
"path": "relative/path",
"type": "ruby|node|go|python|rust|java",
"description": "Optional"
}
},
"commands": {
"command-name": {
"location": "root|subproject",
"command": "optional override",
"overrides": {
"context": { "command": "context-specific" }
}
}
}
}
```
**Minimal example:**
```json
{
"root": "/Users/josh/workspace/schemaflow",
"subprojects": {
"ruby": { "path": "ruby", "type": "ruby" },
"cli": { "path": "cli", "type": "node" }
}
}
```