LPM CLI

Monorepo setup

Install workspace dependencies, run selected tasks, and prepare a deployable application.

Use one workspace root to share a lockfile and link local packages. Each member keeps its own manifest and dependency declarations.

lpm install
lpm run build --all

Run these commands from the workspace root after defining members and their build scripts.

Declare the workspace

package.json
{
  "name": "acme-workspace",
  "private": true,
  "workspaces": ["apps/*", "packages/*"]
}

Create member manifests under those directories. For example:

packages/shared/package.json
{
  "name": "@acme/shared",
  "version": "1.0.0",
  "type": "module",
  "main": "dist/index.js",
  "files": ["dist"],
  "scripts": { "build": "tsc" }
}
apps/web/package.json
{
  "name": "web",
  "version": "1.0.0",
  "private": true,
  "dependencies": { "@acme/shared": "workspace:*" },
  "scripts": { "build": "vite build", "test": "vitest run" }
}

Add the source files and build configuration for each member. Install the tools that those scripts use:

lpm install -D typescript --filter @acme/shared
lpm install -D vite vitest --filter web
lpm install

LPM CLI also accepts the object form workspaces: { "packages": [...] }. It combines member patterns from package.json and pnpm-workspace.yaml.

Keep one lockfile

At the workspace root, bare lpm install installs all members and the root. From a member directory, it remains member-local.

# Widen a member-local install to the owning workspace
lpm install --recursive

# Install only the root project from the workspace root
lpm install --no-recursive

The workspace uses isolated dependency links by default. Members can use their declared dependencies and linked local packages.

Commit the root lpm.lock. Workspace lockfiles do not have an lpm.lockb companion.

A successful recursive install migrates obsolete member lockfiles into the root lockfile. The root replacement occurs after every selected target succeeds.

Add dependencies to selected packages

lpm install react --filter web
lpm install -D typescript -w
lpm install zod --filter web --filter @acme/shared --yes

The first command adds a dependency to web. -w selects the root manifest for shared tooling.

Interactive changes across several members ask for confirmation. --yes skips the prompt. Non-interactive and JSON runs proceed without a prompt.

Use --fail-if-no-match to catch an empty combined selection.

Use workspace:* for a required local package. The root can also serve as a local package if it has a matching name.

Configure tasks in lpm.json

For each member that needs cached builds, add a task configuration beside its manifest:

packages/shared/lpm.json
{
  "tasks": {
    "build": {
      "command": "tsc",
      "dependsOn": ["^build"],
      "inputs": ["src/**", "tsconfig.json", "package.json"],
      "outputs": ["dist/**"],
      "cache": true
    }
  }
}

Adapt the command and input list for each member. Include every file that affects its output.

lpm run build --all
lpm run build --filter 'web...'
lpm run build --all --no-cache

^build waits for the build tasks of workspace dependencies. A task command in lpm.json overrides the package script.

--no-cache disables task cache use for that run. See task runner for task selection and cache rules.

Preview a package selection

lpm filter 'web...'
lpm filter '...@acme/shared' --explain
lpm filter --filter-prod '...@acme/shared'
ExpressionSelection
webThe package named web.
@acme/*Packages whose names match the glob.
./apps/*Packages under matching paths.
web...web and its workspace dependencies.
...@acme/sharedThe shared package and its workspace dependents.
[origin/main]Packages changed relative to the Git reference.
!webExclude web from the selection.

Quote expressions that contain shell glob characters. Name matching is exact or glob-based: shared does not match @acme/shared.

Repeated --filter options combine selections. --filter-prod excludes development edges when it expands dependency relationships.

Run affected tasks in CI

Fetch the comparison reference before the affected run:

lpm ci
lpm run test --affected --base origin/main
lpm run build --filter web --fail-if-no-match

--affected includes changed packages and their dependents. The default base is main.

A README change still counts unless you configure an ignore pattern:

lpm run test --affected --base origin/main \
  --changed-files-ignore-pattern '**/README.md'

For test-only changes that must not select every dependent:

lpm run test --affected --base origin/main --test-pattern '**/*.test.js'

The changed package remains selected. See workspaces for persistent diff configuration and the complete filter grammar.

Prepare an application for deployment

Build the application before creating its deployment directory:

lpm run build --filter 'web...'
lpm deploy ../deploy-web --filter web --dry-run
lpm deploy ../deploy-web --filter web

The destination must be outside the workspace and empty for a normal run. The filter must match exactly one member.

The output contains the selected package, its production dependency closure, a local store, and a lockfile. Local workspace references become relative file dependencies.

--prod is the default. --dev selects development dependencies instead. It does not add them to the production selection.

Make sure that files includes the application's build output. Deployment does not run the application's build for you.

Deployment copies the files that lpm publish would pack, then leaves out .env* files, credential files, LPM state, and symbolic links. See lpm deploy.

See Docker deployments for a container recipe and build credentials.

Troubleshooting

ProblemAction
A member is missingCheck workspace patterns and the member's package.json.
A filter matches nothingUse the full package name and preview it with lpm filter.
A local dependency cannot resolveCheck its name, version, and workspace: requirement.
A task cannot find a toolDeclare the tool where the member uses it, then install again.
CI cannot find the base referenceFetch that branch or commit before the affected run.
Deployment omits built filesCorrect the member's files or ignore rules, then build and deploy again.

See also