Authentication
Choose credentials for each registry, use them in CI, and recover a stored session.
LPM CLI selects a registry first, then a credential for that registry. Public package installs do not require a login.
The CLI works with npm, LPM.dev Registry, and private npm-compatible registries. A login for one registry does not authenticate another.
# Create a local LPM.dev Registry session
lpm login
lpm whoami
# Inspect the active account and available credential sources
lpm whoami --jsonChoose an authentication method
| Method | Use it for | Where the credential lives |
|---|---|---|
| Browser login | Local work with LPM.dev Registry | Operating-system credential storage, with an encrypted file fallback |
| Environment token | CI, containers, or one command | Process environment |
| npm Trusted Publishing | npm publication from a trusted CI workflow | Short-lived OIDC exchange |
| GitHub CLI or GitLab CLI | Package publication through an existing host session | gh or glab storage |
| Stored registry token | Publication without a host session | LPM CLI credential storage |
.npmrc credentials | Private npm-compatible package reads | Protected user or CI configuration |
lpm login creates a session or checks a credential source. lpm setup writes authentication configuration for other package clients.
Registry routing and project configuration
lpm.json can select a publish destination. It does not store registry credentials or change their priority.
{
"publish": {
"registries": ["npm"],
"npm": {
"registry": "https://npm.example.com"
}
}
}Store a credential for that destination:
lpm login --login-registry https://npm.example.com --token <TOKEN>
lpm publishFor one publication, use lpm publish --publish-registry <URL>. The selected URL determines the credential. A generic NPM_TOKEN does not authenticate a custom publish registry.
Package reads use .npmrc routes. Only @lpm.dev/* packages always route through LPM.dev Registry. See Registries for route selection.
Private packages in CI
For npm-compatible reads, configure both the registry route and its credential reference:
@acme:registry=https://npm.example.com/
//npm.example.com/:_authToken=${NPM_TOKEN}Protect the file, then supply the token through the CI secret environment:
chmod 600 ~/.npmrc
NPM_TOKEN=<TOKEN> lpm installBare NPM_TOKEN and stored publish logins do not authenticate npm-compatible reads. This also applies to lpm search and lpm info.
User and CI-owned configuration can expand environment secrets. Project .npmrc files cannot expand those secrets. Registry URLs cannot contain usernames or passwords.
Configuration merges global, user, then project or workspace files. Later assignments can override or clear earlier values.
Credentials match the request origin and the longest matching URL path. A credential for /team/ does not authenticate /other/ on the same host.
On Unix, a credential file must have no group or other permission bits. LPM CLI refuses credential fields from an unprotected layer. It still uses that layer's registry routes and TLS configuration.
A refused credential does not replace a protected credential from a lower layer. See private registry authentication for Basic authentication and recovery.
Publish from CI
npm
For token-based publication, supply NPM_TOKEN:
NPM_TOKEN=<TOKEN> lpm publish --npmWhen a supported CI identity token is available, LPM CLI first attempts npm Trusted Publishing. The npm package must trust that workflow.
If the OIDC exchange fails, LPM CLI uses an available npm token. Without a token, the command reports the exchange error. Custom registries use registry-scoped tokens.
See lpm publish for trusted workflow configuration and publish targets.
GitHub Packages
For local publication, use an existing GitHub CLI session:
gh auth login --hostname github.com
lpm publish --githubFor CI, supply GITHUB_TOKEN with the required package permissions. LPM CLI reads a host CLI token at request time. It does not copy that token into its own storage.
GitLab Packages
GitLab CI can supply CI_JOB_TOKEN to eligible jobs:
lpm publish --gitlabThe project also needs publish.gitlab.projectId in lpm.json. A nonempty GITLAB_TOKEN takes priority over CI_JOB_TOKEN.
For self-managed GitLab, store a token for the full package endpoint:
lpm login --login-registry https://gitlab.example.com/api/v4/projects/12345/packages/npm --token <TOKEN>Credential priority
Publication uses these sources in order:
| Destination | Priority |
|---|---|
| LPM.dev Registry | --token → LPM_TOKEN → stored access token or refresh-backed session |
npm (registry.npmjs.org) | Supported CI OIDC exchange → NPM_TOKEN → stored npm token → effective npm configuration |
| GitHub Packages | GITHUB_TOKEN → gh auth token --hostname github.com → stored fallback token |
GitLab Packages on gitlab.com | GITLAB_TOKEN → CI_JOB_TOKEN → glab auth token → stored fallback token |
| Self-managed GitLab | Token stored for the full package endpoint |
| Custom publish registry | Token stored for the selected registry URL |
GitHub and GitLab login commands do not persist environment tokens unless you pass --save-env-token.
For one command, disable host CLI lookup with LPM_DISABLE_HOST_CLI_AUTH=1:
LPM_DISABLE_HOST_CLI_AUTH=1 lpm publish --githubAn environment token still takes priority. Otherwise, LPM CLI uses an available stored fallback.
Sessions and token lifetime
A browser login can store both an access token and a refresh token. LPM CLI refreshes that session when an authenticated operation needs it.
lpm setup with ci npmrc, lpm swift-registry, and automatic Swift setup refresh the session before they copy its token. A refresh failure stops the command.
Explicit tokens, environment tokens, CI tokens, and older token-only logins do not refresh automatically. Third-party registry tokens also require replacement when they expire.
lpm token-rotate rotates a stored LPM.dev Registry session. It does not rotate npm, GitHub, GitLab, or custom registry tokens.
Credential storage
| Platform | Preferred storage |
|---|---|
| macOS | Data Protection Keychain for official signed builds |
| Linux | Secret Service-compatible keyring |
| Windows | Credential Manager |
Credentials use the lpm-cli service and remain separate by registry.
Login state belongs to the LPM home: ~/.lpm, or the directory that LPM_HOME names. A home other than ~/.lpm adds a suffix derived from its location to the service names, so it keeps its own logins. After you change LPM_HOME, sign in again with it. lpm doctor warns with lpm_home_default_state_unused when ~/.lpm still holds login files that the selected home doesn't use.
If a new credential cannot use native storage, LPM CLI can save it in the encrypted .credentials file in the LPM home. lpm doctor reports this fallback as degraded. The file and its key are owner-only: 0600 on Unix, without access list entries that the directory would pass on on macOS, and a protected access list on Windows. In a Git repository that the LPM home can't be kept out of, LPM CLI refuses to save them. See the LPM home.
An outage does not activate an old file credential when native storage holds the current credential. LPM CLI refuses ambiguous or stale copies.
For an older encrypted-file login, retain .credentials, .key, and .salt in the LPM home. Recovery preserves the login when its saved key can decrypt the credentials.
The first recovery of an older file key needs about 1 GiB of memory. Later Unix reads can use .key-derived in the LPM home, an authenticated private cache. Native keyring keys do not enter this cache.
macOS upgrades and permission prompts
Official signed releases use a restricted Keychain access group. Unsigned and third-party builds cannot read that group's credentials. Source builds can use their own login or an environment token.
An upgrade migrates older credentials when it first needs them. LPM CLI checks the credential identity before it removes the old copy. Interrupted cleanup resumes on a later read.
Older CLI versions cannot read the migrated shared login. If access fails after an upgrade, update the CLI and sign in again.
During migration, macOS can request permission for an older Keychain item. Select Always Allow to keep later authorized reads silent. A denied request cannot use that credential.
Logout and revocation
Clear a selected stored credential:
# LPM.dev Registry only
lpm logout
# A third-party credential
lpm logout --npm
lpm logout --github
lpm logout --gitlab
lpm logout --logout-registry https://npm.example.com
# All credentials stored by LPM CLI
lpm logout --allLogout does not clear environment variables, .npmrc entries, or host CLI sessions.
To request server revocation of the LPM.dev Registry session and browser pairings:
lpm logout --revokeLocal cleanup and remote revocation are separate results. A revocation failure returns an error even if local cleanup succeeds. See lpm logout for flag combinations and JSON fields.
Recovery
An environment token overrides your saved login
If the registry rejects LPM_TOKEN, replace it or unset it:
unset LPM_TOKEN
lpm whoamiLPM CLI preserves saved credentials and reports env_token_rejected in JSON output. See environment-token recovery for CI steps.
Logout leaves access active
Inspect the credential priority for the selected registry. Remove the environment token, .npmrc entry, or host CLI session that still supplies access.
A private install returns an authentication error
Check the .npmrc route, credential path, and file permissions. A publish login alone does not authenticate package reads.
chmod 600 ~/.npmrc
lpm installNative storage is unavailable
Restore access to the operating-system credential service, then retry. Use lpm doctor to inspect storage health. An existing native credential does not automatically fall back to a stale file copy.
Inspect the active source
lpm whoami --json
lpm doctor
lpm setup ci npmrc --jsonlpm whoami reports available third-party sources. It does not contact every third-party registry to check each token.
The setup JSON shows a redacted file shape. The live token appears only in the protected .npmrc file.
See also
lpm login,lpm logout, andlpm whoami— manage credentialslpm setup— configure package clientslpm token-rotate— rotate a stored session- Registries — choose package routes
- Environment variables — supply temporary credentials