Skip to content
Back to skills

Working In Monorepos

ASecurity

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

  • 10 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added February 9, 2026
toolspythonrustgojavarubyshellbashnodegit

Works with

  • cli

Security analysis

A100/100

Pro scans all 7 files and shows the line behind each finding

Scanned February 12, 2026

npx -y skills add technicalpickles/pickled-claude-plugins --skill working-in-monorepos --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Working In Monorepos?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Working In Monorepos
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/technicalpickles-working-in-monorepos/badge)](https://www.skillsdirectory.com/skills/technicalpickles-working-in-monorepos)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
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" }
  }
}
```

Files in this skill

  • README.md1.4 KB
  • SKILL.md8.2 KB
  • examples/schemaflow.json268 B
  • examples/zenpayroll.json702 B
  • scripts/monorepo-init4.1 KB
  • tests/baseline-results.md10.1 KB
  • tests/baseline-scenarios.md1.8 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.