LPM CLI

lpm doctor / lpm health

Find project, runtime, registry, and environment problems, and apply supported fixes.

Use lpm doctor to find project and environment problems. Use lpm health to examine one registry.

lpm doctor [OPTIONS] [COMMAND]
lpm doctor list [--code <CODE>] [--category <CATEGORY>] [--json]
lpm doctor sandbox-setup [--project <PATH>] [--metadata-dir <PATH>]... [--tool-dir <PATH>]... [--user-sid <SID>] [--apply | --remove] [-y|--yes] [--json]
lpm health [--registry <URL>] [--json]

Quickstart

Run the fast checks from the project directory or any directory inside it:

lpm doctor

The command examines the nearest directory at or above the current one that has a package.json or an lpm.json. The search stops before your home directory. When that project is not the current directory, doctor prints which directory it uses. Without such a directory, doctor examines the current directory.

Doctor reports failures and warnings, then returns a summary.

Choose a command or mode

CommandPurposeUse it when
lpm doctorRun fast local checks for the current projectAn install, runtime, lockfile, or project state does not look correct
lpm doctor --allAdd network, tooling, global-install, and security checksYou need a complete environment report or a CI gate
lpm doctor listShow every check that doctor can reportYou need a check code, description, or remediation
lpm doctor sandbox-setupPreview or explicitly apply Windows sandbox permissionsProtected directories prevent sandboxed scripts from running
lpm healthSend one health request to the selected registryYou need to know whether the registry responds

lpm.json behavior

If lpm.json exists, doctor reads it automatically. You do not need a separate option.

For example:

{
  "runtime": {
    "node": "22"
  },
  "tools": {
    "biome": "2.6.2"
  },
  "tunnel": {
    "domain": "my-api.lpm.fyi"
  }
}

The fast mode checks the JSON structure and every top-level field in the canonical lpm.json schema. It reports unknown fields as warnings.

It also checks value types and the details of runtime, task, tool, and service fields. Unreadable runtime pin files and invalid linker values appear as failed checks. The remaining checks still run.

The fast mode also checks the configured Node.js or Bun version.

The full mode uses tools pins for installed lint and format tools. A workspace member can inherit these pins from the project root. Doctor reports an unavailable pinned tool without downloading another version.

There is no doctor configuration block or flag to ignore lpm.json for one run. Use --all to extend the check set and --yes to apply available fixes without a prompt.

The full mode checks the configured tunnel domain. If authentication is available, it also checks ownership and reachability.

Read lpm tunnel for the complete tunnel configuration.

Fast and full checks

lpm doctor runs the fast mode by default. This mode reads local project and LPM CLI state.

The fast mode examines:

  • Local storage and install state
  • package.json, node_modules, and lockfiles
  • Dependency synchronization and local dependency paths
  • lpm.json structure and runtime pins
  • Node.js and Bun readiness
  • Workspace cycles
  • Policy extensions
  • Local authentication and secret storage
  • Sigstore settings

Without repairs, fast mode does not contact a registry or tunnel service. It does not start background update requests or run lint or format checks.

Use --all to add:

  • Registry and authentication requests
  • Tunnel ownership and reachability
  • Lint and format checks
  • TypeScript readiness and plugin updates
  • Global-install health
  • Sandbox and script-policy checks
  • Manifest compatibility checks
  • Tracked .lpm/ state and store-orphan checks
lpm doctor --all

The full mode can take more time because it runs tools and sends network requests.

Recipes

Diagnose the current project

Run doctor from the project root or one of its subdirectories:

cd /path/to/project
lpm doctor

The fast output usually hides passing rows. It keeps the resolved linker mode and active policy extensions for context.

Run a complete environment check

lpm doctor --all

Use this command after a machine change, a toolchain change, or a difficult install failure.

Use doctor as a CI gate

lpm doctor --json > doctor-report.json

Add --all for tool, machine, and connected-service checks. Full mode requires registry credentials for a passing authentication result.

If a check fails, doctor exits with code 1. Warnings keep exit code 0.

The JSON report contains both the summary and every emitted check. Match automation on the stable code field.

Apply supported fixes

Save your project changes before you use --fix. Some fixes can change project files or installed dependencies. Repairs can download packages and runtimes, even without --all.

lpm doctor --fix

--fix shows the available actions and asks once before it changes anything. Doctor then reruns the selected checks and reports the resulting state.

Use --all --fix to include fixes from the full check set:

CAUTION: --all --fix can prune the shared store, update installed plugins, and claim a tunnel domain.

lpm doctor --all --fix

The full fix mode can also format the project.

Find one check in the catalog

lpm doctor list --code node_modules_symlinked

The result explains when the check appears and how to resolve it. The --code value is an exact match.

Find checks by category

lpm doctor list --category runtime
lpm doctor list --category "project state" --json

The category filter is not case-sensitive. It matches any category that contains the supplied text.

Examine a specific registry

lpm health --registry https://registry.example.com

The command reports the registry URL, its health state, and one response-time measurement.

Automatic fixes

Doctor can apply fixes for selected results. The available fix depends on the emitted check code.

Supported fixes include:

  • Install the pinned Node.js version
  • Install the pinned Bun version
  • Run lpm install for missing or inconsistent project state
  • Run lpm fmt for formatting failures
  • Reconcile lpm.lockb with lpm.lock
  • Replace a linked project node_modules path with a real directory
  • Prune unreachable entries from the shared store during a full run
  • Claim an available tunnel domain during a full run
  • Update an installed plugin during a full run

lpm doctor list --json shows the supported action before a fix run. For each code, auto_fix identifies the action or is null.

The JSON field fixes_applied lists completed fixes. fixes_failed lists unsuccessful actions and their errors. Targeted actions include the plugin name, tunnel domain, or runtime version selector. After repairs, doctor reloads root and member manifests before it reruns the same check set. A failed repair appears in the final terminal summary and keeps the exit code at 1.

Repairs apply once to the initial report. The final report can show remaining or newly discovered problems.

lpm doctor --fix runs the selected checks before it changes the project. If automatic fixes exist, doctor shows the planned actions and asks once.

The default response is No. If you decline, doctor makes no changes.

-y and --yes imply --fix and skip the confirmation. Use either flag for CI, scripts, or JSON output:

lpm doctor --yes
lpm --json doctor --yes

Without --yes, --fix returns an error when standard input is not a terminal. It also returns an error with --json.

Doctor makes no changes in both cases. If no automatic fix exists, doctor returns the normal result without a prompt.

Windows sandbox permission setup

Windows may block Node.js scripts from reading metadata for protected parent directories. System-installed tools can also need explicit read and execute permissions. This affects publishing hooks and sandboxed dependency scripts.

Preview the required permissions from your normal PowerShell terminal:

lpm doctor sandbox-setup --project 'C:\work\my-package' --tool-dir 'C:\Program Files\nodejs'

The preview changes nothing and runs no package scripts. It shows your Windows user SID, each directory, and the requested access. It includes the ancestors of your project and temporary directory. Use --metadata-dir <path> for an additional temporary, cache, or build directory.

The two permission types have different scope:

PermissionAccess
metadataRead directory metadata and traverse that directory. No directory listing, file contents, or inherited access.
tool_read_executeRead and execute files in the selected tool directory and its descendants. No writes.

Select only the tool directories that your scripts need. The command does not approve every directory on PATH automatically. Tool setup skips links and junctions, and refuses files with multiple hard links. The selected tool path must not contain a link or junction in any component. Use a separate tool copy if its installation contains hard-linked files. A drive root cannot be selected as a tool directory.

Apply the preview

  1. Review the permissions in the preview.
  2. Open PowerShell with Run as administrator.
  3. Run the administrator command printed by the preview.
  4. Confirm the changes.
  5. Return to your normal terminal and retry publishing.

The printed command includes --user-sid and the original directory paths. Keep those arguments when another administrator performs setup for you. On a managed machine, give the preview to your IT administrator.

Setup does not elevate later installs or publishes. Package scripts continue to run in the sandbox as your normal user. Project-secret restrictions remain active. Explicitly approved tool directories avoid repeated permission walks when scripts run. Other directories on PATH can still add preparation time.

For automation, review a JSON preview first:

lpm doctor sandbox-setup --project 'C:\work\my-package' --tool-dir 'C:\Program Files\nodejs' --json

Run the printed apply_args with lpm in an administrator terminal. Add --yes --json for a non-interactive apply. The JSON output includes success, operation, user_sid, grants, count, and apply_args.

Repeat or remove setup

Grants belong to a Windows user and the selected directory identities. Repeat setup after moving or replacing a tool directory, or when a new protected path is reported. A new project may reuse existing ancestor grants. Adding another protected tool requires selecting its directory explicitly.

To remove selected grants, repeat the administrator command with --remove instead of --apply. Use the same project, additional directories, tool directories, and user SID. Removal preserves unrelated permissions. Shared ancestor grants can affect other projects for that user. Stop active installs and publishes before removal.

If setup fails partway through, some permissions may have changed. Preview the same selection again, then retry the same operation. A tool grant becomes active only after its permission walk completes. Neither --apply nor --remove runs on non-Windows platforms.

Setup flags

FlagPurpose
--project <PATH>Select the project; defaults to the current directory.
--metadata-dir <PATH>Add a directory whose ancestors need metadata access. Repeat for additional directories.
--tool-dir <PATH>Approve one tool directory for read and execute access. Repeat for additional tools.
--user-sid <SID>Configure the normal user's permissions from a different administrator account.
--applyApply the previewed permissions from an administrator terminal.
--removeRemove the selected grants from an administrator terminal. Conflicts with --apply.
--yes, -yConfirm changes without an interactive prompt. Required for non-interactive changes.
--jsonReturn structured output. Does not grant permission to apply changes.

Check catalog

This catalog explains every check that lpm doctor can report. The tables group related codes so that you can find a result quickly.

Match automation on the code value. Human-readable descriptions can change.

Run lpm doctor list for the same catalog in the terminal. Use lpm doctor list --json for the complete machine-readable metadata.

In the JSON catalog, auto_fix identifies the action that --fix supports for each code. A null value means that no automatic fix exists.

Paths under ~/.lpm refer to the LPM home. When LPM_HOME is set, they are under that directory instead.

pass is a healthy or informational result. warn needs attention but keeps exit code 0. fail causes exit code 1.

Infrastructure

CodeSeverityDescription
registry_reachablepassThe configured registry responds to its health endpoint.
registry_unreachablefailThe configured registry did not respond. Fix: Examine the network, firewall rules, and registry status page.
global_store_accessiblepassThe shared content-addressable store at ~/.lpm/store/ resolves.
global_store_inaccessiblefailLPM CLI cannot locate or read the shared package store. Fix: Make sure that $HOME is set and ~/.lpm/store/ is writable. Then run lpm install.

Auth

CodeSeverityDescription
auth_validpassA registry auth token is present and whoami succeeds.
auth_invalidfailThe registry rejected the selected credential. Fix: Replace or unset LPM_TOKEN if it supplies the token. For a rejected saved login, run lpm login.
auth_missingfailNo registry auth token is configured. Fix: Run lpm login.
auth_storage_keychainpassLPM CLI stores authentication material for this registry in the OS keychain.
auth_storage_fallbackwarnLPM CLI stores authentication material in encrypted files instead of the OS keychain. Fix: Unlock or repair the keychain. Then run lpm login again.
vault_storage_keychainpassmacOS Keychain is the selected backend for local secrets. This result does not probe Keychain access or secret decryption.
vault_storage_nativepassA native data key exists, or the OS secure store is the preferred backend for new local secrets. Read the detail to distinguish these states.
vault_storage_fallbackwarnLocal secrets use the fallback key .vault-fallback-key in the LPM home. The detail shows its full path. Processes from the same user can read this key. Fix: Unlock or repair the OS secure store.
vault_storage_unavailablefailEncrypted local secret files exist, but LPM CLI cannot access either local key. Fix: Unlock the secure store. If necessary, restore the fallback key in the LPM home from backup.
lpm_home_default_state_unusedwarnLPM_HOME names a directory other than ~/.lpm, and ~/.lpm still holds login or local env files. The selected LPM home keeps its own login and env secrets, so LPM CLI does not use the files in ~/.lpm. The detail lists them. Fix: With this LPM_HOME, run lpm login and run lpm env pull in each project. Alternatively, unset LPM_HOME to use ~/.lpm again.
auth_unverifiedwarnThe credential could not be checked because the registry request failed.
vault_storage_native_with_fallbackwarnA native data key and a local fallback key both exist. The fallback key still permits offline decryption. Fix: Check the ownership and permissions of the LPM home, then run an lpm env command again so that LPM CLI can remove the fallback key.

Policy extensions

CodeSeverityDescription
policy_extensions_not_configuredpassNo active install-time policy extensions are configured in ~/.lpm/config.toml.
policy_extensions_configuredpassOne or more active install-time policy extensions are configured. Inspect: Run lpm policy status or lpm policy doctor.
policy_extension_report_modewarnA configured policy extension is report-only. Fix: If the policy is ready to block installs, set mode = "enforce".
policy_extension_command_unavailablefailA configured policy extension command cannot be found or executed. Fix: Install the executable or fix [policy.extensions.<name>].command.
policy_extension_config_invalidfailPolicy extension configuration is malformed. Fix: Repair the [policy.extensions] table, then rerun lpm policy doctor.

Project state

CodeSeverityDescription
package_json_presentpassA readable package.json exists in the project directory.
package_json_missingfailNo package.json exists in the project directory: the nearest directory with a package.json or lpm.json, else the current directory. Fix: Run lpm init in the project root.
linker_mode_resolvedpassShows the selected linker mode and its source: CLI, global configuration, environment, package, workspace, or default.
node_modules_isolated_healthypassnode_modules/ exists and is backed by an isolated .lpm/wrappers/ store.
node_modules_hoisted_healthypassnode_modules/ exists and uses the hoisted layout.
node_modules_virtual_healthypassnode_modules/ symlinks point into the active global virtual store.
node_modules_symlinkedfailThe project-level node_modules path is a symlink or directory junction. Fix: Run lpm doctor --fix, then run lpm install.
v2_store_orphanspass/warnThe v2 or v3 store has no orphans, or reports entries that no project uses. Fix: Run lpm cache prune, then run lpm cache prune --apply.
node_modules_mixed_layoutwarnBoth isolated and hoisted layout state are present in node_modules/. Fix: Re-run lpm install to converge on the configured linker layout.
node_modules_no_storewarnnode_modules/ exists but no LPM CLI-owned store is present. Fix: Run lpm install to rebuild the layout under LPM CLI ownership.
node_modules_legacy_layoutwarnAn older LPM CLI layout is on disk and a one-time migration is pending. Fix: Run lpm install to migrate to the current layout.
node_modules_missingfailnode_modules/ is missing — dependencies have not been installed. Fix: Run lpm install.
lockfile_presentpasslpm.lock is present at the project root.
lockfile_missingwarnNo lpm.lock was found at the project root. Fix: Run lpm install — it generates the lockfile alongside node_modules/.
lockfile_binary_validpasslpm.lockb matches lpm.lock and parses cleanly.
lockfile_binary_missingwarnlpm.lockb is missing while lpm.lock is present and the graph fits the binary format. Fix: Run lpm doctor --fix to regenerate, or run lpm install.
lockfile_binary_stalewarnlpm.lockb does not match the contents of lpm.lock, or stale binary bytes remain for a TOML-only graph. Fix: Run lpm doctor --fix to reconcile, or run lpm install.
lockfile_binary_corruptwarnlpm.lockb does not parse as a valid binary lockfile. Fix: Run lpm doctor --fix to reconcile from lpm.lock.
project_state_untrackedpassGit tracks nothing in the project's .lpm directory, other than the dependencies a deploy output commits there: its .gitignore, store/, and deploy-workspace/.
project_state_trackedwarnGit tracks files in .lpm, under any spelling the file system treats as .lpm, in the project's repository or in a repository of .lpm's own. The directory holds machine-local state such as install checkpoints, trust snapshots, certificates, and tunnel captures. A deploy output's committed .gitignore, store/, and deploy-workspace/ aren't counted. Fix: Run the git rm --cached command the warning names, then commit. .lpm ignores itself, so the files stay out of later commits. In a deploy output, the command names only the machine-local files and leaves the dependencies committed.
deploy_output_dependencies_committablepassIn a deploy output in a Git work tree, or whose .lpm is a repository of its own, Git ignores none of the files its dependencies are: node_modules, .lpm/store, and .lpm/deploy-workspace. Each repository is asked about the files it commits.
deploy_output_dependencies_ignoredwarnIn a deploy output in a Git work tree, or whose .lpm is a repository of its own, a rule Git reads ignores files its dependencies are, so a commit leaves them out and a clone can't load them: a .gitignore a dependency brought, or any rule once the output's own .gitignore no longer takes them back. The warning also names a rule above the output that ignores the output as a whole, such as apps/. Fix: Run the git add -f command the warning names, one for each repository, then commit; for an output ignored as a whole, change the rule it names.
deps_sync_cleanpasslpm.lock and package.json agree on the declared dependency set.
deps_sync_driftwarnlpm.lock and package.json disagree — manifest changes have not been resolved. Fix: Run lpm install to reconcile.
local_source_dir_okpassA file: / link: dependency points at a directory with a readable package.json.
local_source_tarball_okpassA file: dependency points at a readable tarball.
local_source_dir_no_pkgfailA file: / link: dependency points at a directory with no package.json. Fix: Add package.json to the local path or update the dep target.
local_source_invalid_typefailA file: / link: dependency points at an unexpected file type. Fix: Re-target the dependency at a directory or a tarball file.
local_source_link_to_filefailA link: dependency points at a file instead of a directory. Fix: Use a project directory. Use file: for tarballs.
local_source_unreadablefailLPM CLI cannot read a file: or link: target. Fix: Restore the target or correct its permissions. Then run lpm install.
package_json_invalidfailThe manifest is unreadable or invalid. Repair it before installing.
linker_config_invalidfailA linker configuration value is invalid. Repair the source named in the detail.
store_orphan_analysis_unavailablewarnDoctor could not determine which store entries are unused.
lockfile_corruptfailThe lockfile cannot be read safely. Restore a valid copy or regenerate it.

lpm.json

CodeSeverityDescription
lpm_json_validpassDoctor accepts the lpm.json syntax and recognized fields.
lpm_json_schema_warningswarnDoctor reports an unknown field or an incorrect value type. It also reports a vaultSync block, which is one checkout's env sync state. Fix: Review the detail and the lpm.json reference. For vaultSync, run lpm env pull or lpm env push, which moves the state to .lpm/env-sync.json, or drops it when Git has it committed. Then commit lpm.json without it.
lpm_json_invalid_syntaxfaillpm.json is not valid JSON. Fix: Fix the JSON syntax error reported in detail.
lpm_json_not_objectfaillpm.json's top-level value is not an object. Fix: Replace with a JSON object literal { ... }.
lpm_json_unreadablefailLPM CLI cannot read lpm.json. Fix: Correct the file permissions. Then run doctor again.

Runtime

CodeSeverityDescription
node_engine_compatiblepassThe selected runtime satisfies package.json > engines.node.
node_engine_mismatchfail/warnThe selected managed runtime or trusted system runtime violates engines.node. Strict mode fails. Other modes warn. Select a compatible runtime with lpm use.
node_managed_matchpassA managed Node install matches the pinned spec.
node_pinned_unmetwarnA pinned Node version has no matching managed install. The first Node on trusted system PATH can differ. Fix: Run lpm use node@<version>.
node_missing_pinnedfailProject pins a Node version and the trusted system PATH cannot resolve Node. Fix: Run lpm use node@<version> to install the pinned version.
node_system_unpinnedpassNo Node version is pinned, and the trusted system PATH resolves Node. Fix: For reproducible runs, pin a version in lpm.json > runtime.node.
node_missing_unpinnedfailNo Node version is pinned and the trusted system PATH cannot resolve Node. Fix: Install Node via lpm use node@22 (or your preferred version).
bun_managed_matchpassA managed Bun install matches lpm.json > runtime.bun.
bun_pinned_unmetwarnProject pins a Bun version but no managed Bun install matches. Fix: Run lpm use bun@<version> to install and pin the managed version.
bun_missing_pinnedfailProject pins a Bun version and no Bun is reachable. Fix: Run lpm use bun@<version> to install the pinned version.
node_config_invalidfailA Node.js pin file cannot be read. Repair the file; other checks continue.

Tunnel

CodeSeverityDescription
tunnel_activepassThe configured domain is claimed by your account and responds to a request.
tunnel_idlepassThe configured domain is claimed by your account, but no tunnel is active.
tunnel_unauthenticatedpassA tunnel domain is configured, but no authentication is available. Fix: Run lpm login to examine ownership.
tunnel_unverifiedwarnThe registry request for domain ownership failed. Fix: Run lpm health. Then run doctor again.
tunnel_not_claimedwarnYour account does not own the configured tunnel domain. Fix: Run lpm doctor --all --fix, claim the domain, or change it.
tunnel_owned_by_otherwarnA different account owns the configured tunnel domain. Fix: Choose a different domain.
tunnel_unreachablewarnYour account owns the domain, but the domain does not respond. Fix: Examine DNS and tunnel state.
tunnel_unknown_basewarnThe LPM.dev Registry does not recognize the configured base domain. Fix: Use a supported base domain or contact the registry team.
tunnel_domain_no_dotwarnConfigured tunnel domain has no dot separating subdomain from base. Fix: Set the full domain: <subdomain>.lpm.fyi or <subdomain>.lpm.llc.
tunnel_domain_empty_labelwarnConfigured tunnel domain has an empty label, for example ..lpm.fyi. Fix: Remove the empty label.
tunnel_domain_label_too_longwarnA label in the configured tunnel domain exceeds 63 characters (DNS limit). Fix: Shorten the offending label.
tunnel_domain_too_longwarnTotal tunnel domain length exceeds the DNS limit. Fix: Shorten the domain.
tunnel_subdomain_lengthwarnTunnel subdomain length is outside the allowed range. Fix: Pick a subdomain between the documented bounds.
tunnel_subdomain_charswarnTunnel subdomain contains characters outside the allowed alphabet. Fix: Use only lowercase letters, digits, and hyphens.
tunnel_subdomain_hyphenwarnTunnel subdomain starts or ends with a hyphen. Fix: Subdomains must start and end with an alphanumeric character.

Code quality

CodeSeverityDescription
lint_cleanpassOxlint reports no issues for the project.
lint_warningswarnOxlint reported warnings for the project. Fix: Run lpm lint to inspect, then address.
lint_errorsfailOxlint reported errors for the project. Fix: Run lpm lint and fix the reported errors.
lint_unparseablewarnDoctor cannot parse the Oxlint output. Fix: Run lpm lint to see the raw output.
fmt_cleanpassBiome reports the project formatting is clean.
fmt_unformattedwarnBiome found files that need reformatting. Fix: Run lpm fmt to apply formatting.
fmt_other_issuewarnBiome reported a parse or configuration error. Fix: Run lpm fmt --check to see the raw Biome output.

TypeScript

CodeSeverityDescription
typescript_healthypassProject-local tsc resolves through the node_modules/.bin chain.
typescript_missing_for_tsconfigwarntsc is reachable only from the system PATH. The project has no local install. Fix: Run lpm install -D typescript.
typescript_unavailablefailtsc is not reachable for a directory with tsconfig.json. Fix: If typescript is declared, run lpm install. Otherwise, run lpm install -D typescript.

Plugin

CodeSeverityDescription
plugin_up_to_datepassAn installed plugin is at the latest known version.
plugin_update_availablewarnA newer version of an installed plugin is available upstream. Fix: Run lpm plugin update <name> to update.

| plugin_pin_unavailable | warn | The pinned tool is unavailable or lacks a valid verification receipt. Run the tool command to install that version. |

Workspace

CodeSeverityDescription
workspace_acyclicpassNo dependency cycles among workspace members.
workspace_cyclefailA dependency cycle exists among workspace members. Fix: Break the cycle by removing or restructuring the offending workspace dep.

Global installs

CodeSeverityDescription
global_manifest_validpass~/.lpm/global/manifest.toml parses and is structurally valid.
global_manifest_absentpassNo global install manifest is present (no global installs yet).
global_manifest_corruptfail~/.lpm/global/manifest.toml is unreadable or malformed. Fix: Inspect and repair the file, or reinstall affected global packages.
global_manifest_structurally_invalidfailThe global manifest contains invalid package roots, aliases, or tombstones. Fix: Repair the affected rows or reinstall the affected global packages.
global_bin_on_pathpass~/.lpm/bin is on the current PATH.
global_bin_off_pathwarn~/.lpm/bin is not on the current PATH. Fix: Add ~/.lpm/bin to the shell PATH.
global_shims_cleanpassEvery shim in ~/.lpm/bin belongs to a recorded global install.
global_shims_no_dirpassGlobal bin directory does not yet exist.
global_shims_orphanswarnFiles exist in ~/.lpm/bin without a matching manifest entry. Fix: Remove the orphan files, or run lpm install --global to re-register.
global_shims_unreadablewarnLPM CLI cannot read the global binary directory. Fix: Correct its permissions. Then run doctor again.
global_shim_targets_healthypassManifest-owned global commands and aliases point to their expected targets. Covers Unix links and Windows command shims.
global_shim_targets_stalewarnGlobal commands or aliases are missing or point to unexpected targets. This includes a missing global binary directory. Reinstall the affected global package.
global_install_roots_emptypassNo global installs are recorded.
global_install_roots_healthypassEvery global install root exists and carries a ready marker.
global_install_roots_unhealthyfailOne or more global install roots are missing or incomplete. Fix: Reinstall the affected globals (lpm install --global <pkg>).
global_trusted_deps_validpass~/.lpm/global/trusted-dependencies.json parses cleanly.
global_trusted_deps_absentpassNo host-global trusted-dependencies file is present yet.
global_trusted_deps_corruptfail~/.lpm/global/trusted-dependencies.json is unreadable, malformed, or uses a newer schema. Fix: Repair or delete it, then re-approve globals as needed.

Sandbox + scripts

CodeSeverityDescription
sandbox_availablepassThe OS sandbox backend used by lifecycle scripts is available.
sandbox_setup_requiredwarnProtected project or temporary-directory ancestors need sandbox metadata access. Fix: Use Windows sandbox permission setup.
sandbox_helper_missingfailOn Windows, lpm-sandbox-helper.exe is not beside the running lpm, and LPM_SANDBOX_HELPER names no existing file, or LPM_SANDBOX_HELPER holds a relative path, which LPM CLI refuses. Without it, LPM CLI runs lifecycle scripts only with the sandbox off: --no-sandbox, or [sandbox] mode = "none". Fix: Reinstall @lpm-registry/cli. For a Cargo install, install the helper. For a binary from a GitHub release, save that release's lpm-sandbox-helper-win32-x64.exe beside it as lpm-sandbox-helper.exe. If the helper is elsewhere, set LPM_SANDBOX_HELPER=<path>.
sandbox_degradedwarnThe Linux kernel can't block network access, so strict mode contains the filesystem only under an approved allow-degraded configuration. Review the detail and your approved sandbox configuration.
sandbox_disabled_by_userwarnAn approved configuration disables containment. Dependency scripts have normal user access. Restore the default through lpm config.
sandbox_config_approval_requiredfailThe requested sandbox configuration is weaker than the approved security floor. Fix: Approve the change or restore default or strict mode.
sandbox_kernel_too_oldwarnThe kernel cannot provide the requested sandbox. Scripts stop unless an approved configuration allows a supported fallback. Upgrade the kernel or review sandbox configuration.
sandbox_unsupported_platformwarnNo supported sandbox exists on this platform. Scripts that require containment stop. Use a supported host or an approved change to sandbox configuration.
sandbox_probe_failedfailThe sandbox probe errored unexpectedly. Fix: File a bug with the detail text.
policy_force_security_floorwarnforce-security-floor = true suspends approvals and keeps the security floor active. Review security controls.

Sigstore provenance

CodeSeverityDescription
sigstore_verify_enforcedpassWhen verification runs, a rejected attestation stops the install or approval. This result does not examine verification scope or fetch availability.
sigstore_verify_warn_modewarnWarn mode is requested. It applies only when security approvals and managed policy permit it.
sigstore_verify_disabledwarnDisabled verification is requested. It applies only when security approvals and managed policy permit it.
sigstore_config_approval_requiredfailThe requested verification mode needs approval or conflicts with managed policy. Restore the approved mode or follow the reported remediation.

Manifest compat

CodeSeverityDescription
unsupported_override_valueswarnTop-level overrides or resolutions values are not strings, so LPM CLI ignores them. Fix: Use string targets and parent selectors such as parent>dependency.
pnpm_overrides_driftwarnEntries in pnpm.overrides that LPM CLI is not honoring through lpm.overrides, top-level overrides, or resolutions. Fix: Run lpm migrate to translate, or mirror the entries verbatim in lpm.overrides.
pnpm_patches_driftwarnLPM CLI cannot bind some pnpm.patchedDependencies entries. Fix: Run lpm patch. Alternatively, mirror a patch only after it applies cleanly.
pnpm_peer_rules_driftwarnSome pnpm peer rules are not active in LPM CLI. Use lpm migrate or configure lpm.peerDependencyRules.
engines_npm_ignoredwarnLPM CLI ignores engines.npm. It still enforces engines.node and engines.lpm.
engines_pnpm_ignoredwarnLPM CLI does not enforce the engines.pnpm version. Fix: Remove the field or accept that LPM CLI ignores it. engines.node and engines.lpm remain active.
engines_yarn_ignoredwarnLPM CLI does not enforce the engines.yarn version. Fix: Remove the field or accept that LPM CLI ignores it. engines.node and engines.lpm remain active.
engines_bun_ignoredwarnLPM CLI does not enforce the engines.bun version. Fix: Use lpm.json > runtime.bun for managed Bun. LPM CLI still enforces engines.node and engines.lpm.

Incomplete probes

CodeSeverityRecovery
lint_probe_failedwarnRepair or reinstall the selected lint tool, then retry.
fmt_probe_failedwarnRepair or reinstall the selected formatter, then retry.
plugin_update_check_failedwarnCheck network access, then retry the full report.
workspace_discovery_failedfailRepair workspace configuration before relying on workspace results.

JSON output and exit codes

Use --json for CI and scripts:

lpm doctor --json
{
  "success": true,
  "mode": "fast",
  "no_failures": false,
  "clean": false,
  "has_warnings": false,
  "passed": 0,
  "failed": 1,
  "warnings": 0,
  "fixes_applied": [],
  "fixes_failed": [],
  "checks": [
    {
      "code": "node_modules_missing",
      "check": "node_modules",
      "passed": false,
      "severity": "fail",
      "detail": "not found — run: lpm install"
    }
  ]
}

In doctor JSON, success: true means that LPM CLI created the report. It does not mean that every check passed.

Use these fields for automation:

FieldMeaning
modefast or all
no_failurestrue when no check failed
cleantrue when no check failed or produced a warning
has_warningstrue when at least one warning exists
passed, failed, warningsResult counts
checksAll emitted results
fixes_appliedFixes that doctor applied
fixes_failedFailed repairs, with action and error

Match on checks[].code. The check and detail text can change.

Doctor uses these exit codes:

ResultExit code
No failures0
Warnings without failures0
A check or repair failed1

Registry health

lpm health sends one health request to the selected registry. It does not check the current project.

lpm health
lpm health --json
{
  "success": true,
  "healthy": true,
  "registry_url": "https://lpm.dev",
  "response_time_ms": 87
}

The command does not collect repeated measurements. The response_time_ms value is the time for one request.

Both output modes return a nonzero exit code for an unhealthy response or a failed request:

Registry resultHuman outputJSON output
HealthyExit code 0healthy: true, exit code 0
Registry reports unhealthyNonzero exit codesuccess: false, error, and error_code; nonzero exit code
Request failsNonzero exit codeNonzero exit code

A successful JSON response has success: true and healthy: true. The health request has a five-second deadline and does not retry.

Recovery

Repair project install state

If doctor reports a missing install or dependency drift, run lpm install. Then run doctor again.

lpm install
lpm doctor

Repair a linked project node_modules

The node_modules_symlinked check reports a project-level symlink or directory junction. LPM CLI does not install through this path.

lpm doctor --fix
lpm install
lpm doctor

The fix removes only the link entry. It creates a real node_modules directory and does not change the linked target.

Do not run lpm cache prune or lpm store clean for this error. The global store is not the cause.

Resolve registry or authentication failures

Run the registry check first:

lpm health

If the registry responds, view the current account:

lpm whoami

If the account is not correct, sign in again:

lpm login

Read lpm login for authentication options.

Read the remediation for a check

Use checks[].code from lpm doctor --json:

lpm doctor list --code <CODE>

Flags

lpm doctor

FlagEffect
--allRun the fast and extended checks
--fixShow a plan, then ask once before applying supported fixes
-y, --yesImply --fix and skip the confirmation prompt
--jsonPrint structured output

--all and --fix apply only to the diagnostic run, not to its subcommands. The catalog also ignores --yes. Sandbox setup uses --yes to approve an explicit --apply or --remove.

lpm doctor list

FlagEffect
--code <CODE>Select one exact check code
--category <SUBSTRING>Select category names that contain the supplied text
--jsonPrint the catalog as structured output

lpm health

FlagEffect
--registry <URL>Examine a specific registry URL
--jsonPrint structured output

See also