Skip to content
Better PM
Esc
↑↓navigate↵open⌘Jpreview

Monorepo Setup

Configure Better PM for optimal monorepo workflows with pnpm, bun, or npm workspaces

Better PM is designed from the ground up for monorepo environments. It automatically detects your workspace structure and prevents common mistakes like accidentally installing all packages when you meant to install just one.

How Better PM Detects Monorepos

Better PM uses lockfile detection to identify your package manager and workspace root. It searches upward from your current directory to find:

  • pnpm-lock.yaml for pnpm workspaces
  • bun.lock or bun.lockb for bun workspaces
  • package-lock.json for npm workspaces

Once the lockfile is found, Better PM determines the monorepo root and checks for workspace configuration.

Supported Workspace Configurations

pnpm

Better PM reads your pnpm-workspace.yaml file to discover workspace packages:

packages:
  - 'apps/*'
  - 'packages/*'

The CLI parses this file line-by-line to extract glob patterns, then enumerates all matching packages.

bun

Bun workspaces are configured in package.json:

{
  "workspaces": ["apps/*", "packages/*"]
}

Or using the object syntax:

{
  "workspaces": {
    "packages": ["apps/*", "packages/*"]
  }
}

Both formats are supported and automatically detected.

npm

npm workspaces use the same package.json format as bun:

{
  "workspaces": ["apps/*", "packages/*"]
}

Better PM automatically uses the correct flags (-w) for npm workspace operations.

Context-Aware Installation

Better PM changes behavior based on where you run commands:

Inside a workspace package

When you run pm i from within a workspace package directory, Better PM automatically scopes the install to that package only:

cd apps/web
pm i  # Only installs apps/web and its dependencies

How it works:

  • Searches upward for the nearest package.json
  • Compares its directory with the lockfile directory
  • If they differ and the package is within the monorepo, applies a filter
  • For pnpm: uses -F @myapp/web... (includes transitive workspace deps)
  • For bun/npm: resolves all workspace dependencies recursively

At the monorepo root

Running pm i at the root shows a warning and lists all workspace packages:

cd ~/my-monorepo
pm i

Output:

[WARNING] You are at the monorepo root. This will install ALL packages.

Workspace packages:
├── apps/
│   └── web "@myapp/web"
└── packages/
    ├── core "@myapp/core"
    └── utils "@myapp/utils"

To install a specific package:
  pm i -F <package-name>

To install everything:
  pm i --sure

In non-interactive environments (like CI), use -y or --sure to bypass the prompt.

Targeted Package Installation

Install specific workspace packages from anywhere in your monorepo:

pm i -F @myapp/web
pm i -F @myapp/web -F @myapp/api
pm i -y  # or --sure

The -F flag (alias for --filter) works consistently across all package managers:

  • pnpm: maps to pnpm -F <pkg> install
  • bun: maps to bun install --filter <pkg>
  • npm: maps to npm install -w <pkg>

Workspace Navigation

Quickly navigate between workspace packages using pm cd:

# Jump to a specific package
pm cd @myapp/web

# Return to monorepo root
pm cd

# List all workspace packages
pm pls

Example Monorepo Workflow

Here’s a complete example of working with a typical monorepo:

Navigate to your project

cd ~/code/my-monorepo
pm pls  # List all packages

Output:

├── apps/
│   ├── web "@myapp/web"
│   └── api "@myapp/api"
└── packages/
    ├── ui "@myapp/ui"
    └── shared "@myapp/shared"

Work on a specific package

pm cd @myapp/web
pm add react-query
pm i  # Installs only @myapp/web (scoped automatically)

Install multiple packages

# From monorepo root or any subdirectory:
pm i -F @myapp/web -F @myapp/api

Add dependencies across packages

pm cd @myapp/api
pm add fastify @myapp/shared  # Works with workspace deps too

Best Practices

Always use pm i from package directories

When working within a package, let Better PM automatically scope your installs:

Good:

cd apps/web
pm i

Avoid:

cd ~/my-monorepo
pm i -F @myapp/web  # Works, but more typing
Use -y in CI environments

Continuous integration should never prompt interactively:

- name: Install dependencies
  run: pm i -y

The -y flag (alias for --sure) confirms root-level installs without prompting.

Leverage workspace dependency resolution

Better PM automatically includes workspace dependencies when installing:

If @myapp/web depends on @myapp/ui, running pm i from apps/web/ will install both packages.

For pnpm, this uses the ... suffix: -F @myapp/web... For bun/npm, dependencies are resolved recursively via collectWorkspaceDependencies.

Organize packages by type

Structure your workspace for clarity:

my-monorepo/
├── apps/           # Deployable applications
│   ├── web/
│   └── api/
├── packages/       # Shared libraries
│   ├── ui/
│   └── utils/
└── tools/          # Build tools, scripts
    └── eslint-config/

This makes pm pls output more readable and helps with workspace organization.

Common Issues

Advanced Configuration

Filter Patterns

Better PM passes filter values directly to your package manager, so you can use their native patterns:

# pnpm patterns
pm i -F "@myapp/*"      # All packages in @myapp scope
pm i -F "./apps/*"      # All packages in apps/ directory

# Multiple patterns
pm i -F "@myapp/web" -F "@myapp/api"

Package Manager Detection Order

Lockfiles are checked in this priority:

  1. pnpm-lock.yaml → pnpm
  2. bun.lock → bun
  3. bun.lockb → bun
  4. package-lock.json → npm

If multiple lockfiles exist (not recommended), the first match wins.

Workspace Dependency Resolution

For bun and npm, Better PM recursively resolves workspace dependencies by:

  1. Reading all workspace package package.json files
  2. Building a dependency graph of workspace packages
  3. Including all transitive workspace dependencies in the filter

This ensures that installing one package also installs its workspace dependencies.

Was this page helpful?