LPM CLI

CI/CD setup

Pin LPM CLI, authenticate, install from a committed lockfile, and run project checks in CI.

Use lpm ci to install a committed dependency graph. Keep authentication, package checks, and publication as explicit steps.

npm install --global @lpm-registry/cli@0.78.0
lpm ci --strict-integrity
lpm run build
lpm run test

The examples pin LPM CLI to 0.78.0. Update that version through your normal review process. The build and test commands require matching package scripts.

Commit project configuration

Commit package.json and lpm.lock. If lpm.json is present, commit it. Also commit the other LPM project files that the project uses, such as patches/, lpm-sources.json, lpm-agent-skills.json, and lpm-changes/. .lpm/ holds local state and keeps itself out of Git. See Files LPM CLI creates.

lpm.lock records the overrides and patches its resolution used, so a fresh CI checkout installs from the lockfile without state from an earlier install.

Use lpm.json for shared runtime versions, tasks, and publication targets. Registry credentials belong in the CI secret store.

lpm.json (example task configuration)
{
  "tasks": {
    "build": {
      "command": "tsc",
      "inputs": ["src/**", "tsconfig.json", "package.json"],
      "outputs": ["dist/**"],
      "cache": true
    }
  }
}

Install TypeScript as a project dependency for this example. Adapt the input and output lists to your build.

GitHub Actions

.github/workflows/ci.yml
name: CI
on: [push, pull_request]
permissions:
  contents: read
jobs:
  checks:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '22'
      - run: npm install --global @lpm-registry/cli@0.78.0
      - uses: actions/cache@v4
        with:
          path: ~/.lpm/store
          key: lpm-store-${{ runner.os }}-${{ runner.arch }}-0.78.0-${{ hashFiles('lpm.lock') }}
      - run: lpm ci --strict-integrity
      - run: lpm run build
      - run: lpm run test

This example uses public dependencies. Add credentials only to jobs that need protected packages. Pin action revisions and the runtime to your team's approved versions.

A cache miss is valid: the online frozen install downloads the locked packages. --offline is unnecessary for lockfile freezing.

Authenticate protected dependencies

LPM CLI supports public npm, private registries through .npmrc, and LPM.dev Registry. An LPM.dev Registry account is unnecessary for public npm.

For LPM.dev Registry, store a read-scoped token in the CI secret store:

- run: lpm ci --strict-integrity
  env:
    LPM_TOKEN: ${{ secrets.LPM_TOKEN }}

For npm-compatible private registries, provide endpoint-scoped credentials through .npmrc. See authentication for supported credential sources.

Use OIDC in the supported workflows

Registry OIDC supports publication, hosted Firewall checks, and credential setup for other npm-compatible clients.

It does not provide general OIDC authentication for lpm ci downloads of protected @lpm.dev/* packages. Use LPM_TOKEN for that workflow.

For an npm-compatible client that needs temporary Registry credentials:

lpm setup ci npmrc --oidc

lpm setup ci npmrc writes an owner-only .npmrc where installs read it: the workspace root, or else the nearest directory with a package.json. It refuses an .npmrc that Git tracks and adds the file to .git/info/exclude, which keeps it out of commits without changing a tracked file. The receiving client uses that file and its own supported install workflow.

Exclude the credential file from artifacts and caches. Writing it does not authenticate LPM CLI's direct Registry downloads.

GitHub Actions needs permissions: id-token: write on the trusted job. GitLab supplies LPM_OIDC_TOKEN with audience https://lpm.dev.

Pull-request triggers do not qualify for this Registry exchange. Configure the required trust before the job runs.

A supplied assertion cannot be reused after exchange. Obtain a fresh assertion for each independent exchange.

Understand frozen and offline installation

lpm ci --strict-integrity --no-skills --no-security-summary
OptionEffect
lpm ciRequires a current, replayable lockfile.
--strict-integrityRequires inline integrity for tarball-URL dependencies instead of first-use trust.
--offlineUses available local package data and fails when required data is missing, or when the overrides differ from the ones lpm.lock was resolved with.
--no-skillsSkips package skills and the restore of recorded agent skills. Without it, unavailable skills produce warnings and never fail the install.
--no-security-summarySkips the post-install report. Separate audit commands still work.

For an intentionally prepared offline job:

lpm fetch
lpm ci --offline --strict-integrity

Keep the populated store available to both commands. Local file: and link: dependencies also need their source directories.

Offline is not a network sandbox. Root lifecycle scripts still run and can access the network. Use a network-restricted runner for an actual egress boundary.

Dependency lifecycle scripts remain subject to script approval. Review required trust entries before committing them.

Run project and policy checks

For existing project scripts:

lpm run build
lpm run test
lpm run lint

Explicit lpm run preserves your scripts and arguments. lpm test and lpm lint can select their own supported runners.

Add the security and license gates that match your policy:

lpm audit --fail-on vuln
lpm licenses --fail-on copyleft,missing
lpm licenses --deny GPL-3.0 --deny AGPL-3.0

These commands return nonzero when their configured gate fails. See exit codes.

lpm trust diff compares the manifest with a local install snapshot. A successful install refreshes that snapshot.

A diff after lpm ci therefore does not detect changes against an approved Git revision. Review trust changes against your trusted repository baseline.

Enforce npm Firewall checks

- run: LPM_NPM_FIREWALL=enforce lpm ci --strict-integrity
  env:
    LPM_TOKEN: ${{ secrets.LPM_TOKEN }}

Hosted checks need eligible account coverage and network access. Enforce mode stops when the check is unavailable. Monitor mode warns and continues.

See Firewall for npm for scope, policy groups, and offline limitations.

Cache reusable data

PathUse
~/.lpm/storeDownloaded package data for installation.
~/.lpm/pluginsManaged tool binaries. Include platform and tool configuration in the cache key.
~/.lpm/cache/dlxOptional cache for temporary package commands.

These paths are under the LPM home. If the job sets LPM_HOME, cache the same subdirectories under $LPM_HOME instead.

Cache these directories separately from credentials. Do not cache the entire LPM home, which also holds login state and local env secrets, or project secret storage.

Regenerate node_modules from the lockfile and store. A restored store can still require downloads for another platform or missing package.

For shared task outputs, configure remote cache. Keep task inputs and outputs accurate before enabling cache reuse.

Publish from a trusted release job

For npm, configure Trusted Publishing, or supply NPM_TOKEN only to the publish step:

- run: lpm publish --npm --check --json
- run: lpm publish --npm --ignore-scripts --yes --json
  env:
    NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

npm Trusted Publishing uses GitHub Actions runtime identity or NPM_ID_TOKEN with audience npm:registry.npmjs.org. An available npm token can provide fallback authentication.

Build the package before these steps. If the release job intentionally authorizes publish lifecycle scripts, remove --ignore-scripts.

For LPM.dev Registry, configure a Trusted Publisher on an existing package. GitHub Actions needs id-token: write and a matching trusted release identity.

lpm publish --lpm --check --json
lpm publish --lpm --ignore-scripts --yes --wait --json

Registry OIDC authentication and Sigstore provenance use different audiences. See publishing a package for provenance and GitLab examples.

If a post-publish hook or availability wait fails, check the registry before retrying. The version can already be uploaded.

Troubleshooting

FailureRecovery
Missing or stale lockfileRun an online lpm install locally and review the updated lockfile.
Offline install reports changed overridesRun an online lpm install locally, commit lpm.lock, then retry.
Offline package missingPopulate the matching store online before the offline step.
OIDC exchange rejectedCheck the trigger, trust configuration, audience, and assertion reuse.
Build tool missingDeclare it as a project dependency and use the intended runtime.
Workspace selection is wrongPreview it with lpm filter.

See also