lpm migrate
Convert npm, pnpm, Yarn, or Bun lockfiles, install dependencies, and verify your project.
Use lpm migrate to move an existing JavaScript project to LPM CLI while you keep its current package manager available.
lpm migrate [OPTIONS]
# Preview the conversion, then migrate
lpm migrate --dry-run
lpm migrateRun the command from the directory that contains package.json and the source lockfile. Unlike lpm install, migration does not search parent directories for a package.json.
The default flow converts the lockfile, configures .npmrc, installs dependencies, and runs available build and test scripts.
LPM CLI works with npm, private registries, and LPM.dev Registry. Your project does not need an LPM.dev Registry account for public npm dependencies.
| Mode | Command | Result |
|---|---|---|
| Preview | lpm migrate --dry-run | Check conversion and pnpm translations without project writes or script execution. |
| Migrate | lpm migrate | Convert, install, and verify the project. |
| Repeat | lpm migrate --force | Replace an existing lpm.lock and retain the original rollback snapshots. |
| Restore | lpm migrate --rollback | Restore managed files from the migration snapshots. |
Examples
# Convert without an install, verification, or registry configuration
lpm migrate --no-install --skip-verify --no-npmrc --no-ci
# Install dependencies but skip build and test scripts
lpm migrate --skip-verify
# Generate a template for the existing CI platform
lpm migrate --ci
# Get one JSON result for automation
lpm migrate --no-install --skip-verify --no-npmrc --no-ci --json
# Retry after a failed install or verification
lpm migrate --forceThe command is non-interactive. -y and --yes are accepted no-ops and do not imply --force.
--no-install only skips dependency installation. Use --skip-verify to also skip build and test.
Configuration changes, lockfile conversion, backups, and requested CI templates remain independent of these two flags.
Add a project task
lpm.json has no dedicated migration configuration. Use a task for a repeatable conversion command:
{
"tasks": {
"convert-lockfile": {
"command": "lpm migrate --no-install --skip-verify --no-npmrc --no-ci",
"cache": false
}
}
}lpm run convert-lockfile
lpm run convert-lockfile -- --dry-run
lpm run convert-lockfile -- --forceThe explicit task command takes precedence over a package script with the same name.
cache: false makes each invocation run the command. See Tasks for task configuration.
Source lockfile
The command selects the most recently modified supported lockfile in the current directory.
For equal timestamps, the priority is bun.lockb, bun.lock, pnpm-lock.yaml, yarn.lock, then package-lock.json.
Other detected lockfiles stay in place.
Binary Bun conversion uses the Yarn text output from the Bun executable.
| Input | Supported format |
|---|---|
package-lock.json | npm lockfile versions 1, 2, and 3. |
pnpm-lock.yaml | pnpm lockfile major versions 5, 6, and 9. |
yarn.lock | Yarn Classic and Yarn Berry lockfiles. |
bun.lock | Bun text lockfile with JSON comments and trailing commas. |
bun.lockb | Binary lockfile converted with the bun executable on PATH. |
The conversion reads a fixed snapshot of the selected file. A selected bun.lockb does not fall back to an older bun.lock.
The command reports unsupported package entries and conversion warnings.
Review these reports before you commit the result. See Files LPM CLI creates for the files to commit.
Input limits
Each source file has a 64 MiB size limit and a 200,000-entry package limit. Malformed input stops conversion before project writes.
npm lockfiles also have these limits:
- Package paths: 32 KiB.
- Package nesting: 256 levels.
- Dependencies per package: 10,000.
- Total dependency edges: 1,000,000.
For bun.lockb, the converter has a 30-second deadline, a 64 MiB output limit, and a 64 KiB diagnostic limit.
Converted files and installation
Conversion writes a version 12 staging lpm.lock and, when the graph permits it, a binary lpm.lockb companion.
The default online lpm install resolves the final package instances and writes the current version 13 TOML lockfile. Run migration from the workspace root. A member-directory invocation fails before conversion or backups.
--rollback from a member directory restores the workspace root's migration. If an earlier LPM CLI release left a backup in that member, rollback uses that backup instead.
At a workspace root, this install includes the root and workspace members. It runs each target's install lifecycle once.
The online install resolves manifest requirements again and can change the imported versions and node_modules.
Dependency lifecycle scripts remain subject to the script policy.
If you use --no-install, run lpm install before an offline or frozen install:
lpm migrate --no-install --skip-verify
lpm install --no-frozen-lockfileAn install failure makes migration fail. The converted files and backups remain available for a retry or rollback.
pnpm configuration
Migration translates supported entries from these package.json fields:
| Existing field | Destination |
|---|---|
pnpm.overrides | lpm.overrides |
pnpm.patchedDependencies | lpm.patchedDependencies and lockfile patch records |
pnpm.peerDependencyRules | lpm.peerDependencyRules |
The command checks conflicts, patch paths, and integrity bindings before it writes the conversion.
Patch files move through copies into patches/<package>@<version>.patch. Scoped names use __ in place of /.
Original patch files remain in place.
The pnpm fields remain available. For copied patches, migration updates their pnpm paths to the new patch copies.
See Migrating from pnpm for supported translations and conflicts.
Registry configuration
Unless you pass --no-npmrc, migration adds this scope mapping when the project .npmrc has no active mapping:
@lpm.dev:registry=https://lpm.dev/api/registry/An existing valid @lpm.dev:registry mapping stays in place. The default registry setting also stays in place.
See Registries for npm and private registry configuration.
Build and test verification
Unless you pass --skip-verify, migration runs the build and test scripts that exist in package.json.
It uses the managed runtime, project environment, pre/post hooks, and configured task cache.
An explicit lpm.json task command does not replace these selected package scripts during migration verification.
A script failure makes migration fail. Verification keeps the converted files so you can inspect the result. A successful migration does not prove compatibility for scripts that the project does not define.
With --json, stdout contains one result or error object. Install diagnostics, verification output, and cache replay go to stderr.
CI templates
--ci detects an existing CI configuration and writes a separate template:
| Detected platform | Template |
|---|---|
| GitHub Actions | .github/workflows/ci.lpm.yml |
| GitLab CI | .gitlab-ci.lpm.yml |
| CircleCI | .circleci/config.lpm.yml |
| Bitbucket Pipelines | bitbucket-pipelines.lpm.yml |
Detection uses this table order. Without a detected platform, the command does not generate a template.
Without --ci, it shows a hint to repeat migration with --force --ci. That command repeats installation and verification too. --no-ci suppresses both the hint and generation, including when --ci is present.
GitLab jobs install the CLI and dependencies in each job environment.
The templates run both build and test. Review their scripts, credentials, and trigger rules before use.
GitHub Actions recognizes the generated file in .github/workflows. The other platforms require integration into their active configuration.
Rollback and recovery
lpm migrate --rollbackBefore migration changes a file, it keeps a copy in .lpm/migrate-backup/, which Git ignores.
This covers converted lockfiles, prior workspace-member lockfiles, translated manifests, copied patches, changed .npmrc files, and generated CI templates.
A repeated migration keeps each file's earliest copy. If you edit a file between migrations, the next migration keeps your edit as the file's copy instead, so rollback returns the file to your edit.
When a repeated migration changes a file whose last writer LPM can't tell, such as one left by an interrupted migration or an earlier LPM CLI release, the backup keeps what that migration found beside the earliest copy, for every such migration.
If a repeated migration fails while it writes files, it restores the files it changed and keeps the earlier backup.
One migration or rollback runs in a project at a time; another one waits for it.
Rollback restores those files and removes the files and directories migration created.
It restores a file only while the file still holds what migration wrote. When a file changed after migration, migration stopped before it recorded what it wrote, or a migration replaced content LPM can't attribute and no later backup recorded the file again, rollback restores nothing and lists those files. For the last kind, it names the absolute path where the backup keeps each version that migrations found, newest first.
Run lpm migrate --rollback --force to restore them anyway to the copies the backup keeps from before the migrations.
A complete rollback removes .lpm/migrate-backup/.
Rollback covers these managed files. It does not undo node_modules, store changes, or arbitrary files changed by install, build, or test scripts.
After rollback, use your previous package manager to restore its dependency layout.
Rollback checks the complete recovery record before it changes files. Unsafe paths, linked directories, malformed records, and unknown record versions cause an error.
Backups from earlier LPM CLI releases, .backup files beside the originals with .lpm-migrate-manifest.json, are read too. They don't record what migration wrote, so restoring a file that differs from its original requires --force. Rollback restores each file with the permissions it had before migration; a file restored from such a backup gets the backup's own, which on macOS and Linux those releases kept owner-only.
If an install or script fails, fix the reported error, then retry with --force.
To restore the original managed files instead, use --rollback.
Keep .lpm/migrate-backup/ until you accept the migration.
--rollback and --dry-run cannot be combined.
Flags
| Flag | Effect |
|---|---|
--dry-run | Check conversion and translations without project writes. |
--force | Replace an existing lpm.lock. With --rollback, also restore files that changed after the migration, files LPM can't tell it wrote, and files whose earlier content the backup keeps, each to the backup's copy. |
--no-install | Skip dependency installation. |
--skip-verify | Skip the build and test verification scripts. |
--no-npmrc | Skip project .npmrc configuration. |
--ci | Generate a template for the detected CI platform. |
--no-ci | Suppress CI hints and template generation. |
--rollback | Restore managed files from the migration backups. Conflicts with --dry-run. |
-y, --yes | Accepted no-op. Migration already runs without prompts. |
--json | Write one JSON result or error to stdout. |
See Global flags for shared options.
Commands inside workspace hooks
Workspace lifecycle hooks cannot start another command that needs the same install lock. The child command fails with a parent-installation conflict.
Run these commands after installation. Commands that need no install lock, such as lpm --help, remain available inside hooks.