# lpm self-update (/docs/infra/self-update)



```bash
lpm self-update
```

Checks GitHub Releases for the latest LPM version, compares against the running version, and runs the appropriate upgrade command for whichever channel you installed from. The install method is auto-detected from the executable path.

## How it works [#how-it-works]

1. **Probe for the latest version.** The npm registry is the primary source — `https://registry.npmjs.org/@lpm-registry/cli/latest` — which is anonymous and unmetered, so most users never touch a rate-limited path. If npm is unreachable, falls back to GitHub Releases (`api.github.com/repos/lpm-dev/rust-client/releases/latest`). The two sources stay in lockstep because every release publishes from the same tag.
2. **Cache the result.** Successful probes write `~/.lpm/update-check.json` with a 10-minute TTL — a second `lpm self-update` inside that window short-circuits the network call. Use `--refresh` to bypass the cache. A recent probe failure also caches a cooldown so the network isn't hammered after an outage.
3. Compare against the current binary's version (baked in at build time).
4. If newer, detect the install channel from the executable path:

| Detected via                            | Channel                                                                                                         |
| --------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| Path under a Homebrew Cellar            | `brew upgrade lpm`                                                                                              |
| Path under an npm global root           | `npm install -g @lpm-registry/cli@<latest>`                                                                     |
| Path under a Cargo install root         | `cargo install --git https://github.com/lpm-dev/rust-client --tag v<latest> lpm-cli --force`                    |
| Anything else (standalone curl install) | Direct download of `lpm-<platform>` for `v<latest>` from GitHub Releases, replacing the running binary in place |

5. Spawns the upgrade command. The current process continues; the new binary is in place for the next invocation.

If the running version is already the latest, prints `Already on the latest version (<v>)` and exits cleanly.

## GitHub fallback rate limits [#github-fallback-rate-limits]

The npm primary path has no per-IP limit you're likely to hit. The GitHub fallback does — 60 unauthenticated requests/hour per IP. You'd only see this when npm is unreachable AND you're probing repeatedly. Set `GITHUB_TOKEN` (or `GH_TOKEN`, the `gh` CLI convention) for 5000 req/hour. The token only needs `public_repo` read scope.

When the GitHub fallback is rate-limited, `lpm self-update` reports the reset time:

```
GitHub API rate limit hit. Try again in 17 minutes. Set GITHUB_TOKEN or GH_TOKEN for 5000 req/hr (vs 60 unauthenticated).
```

## Examples [#examples]

```bash
lpm self-update
lpm self-update --refresh   # ignore the 10-minute version-lookup cache
lpm self-update --json      # structured: current, latest, up_to_date, install_method, update_command, cache_hit
```

## Channel-specific equivalents [#channel-specific-equivalents]

If you'd rather drive the upgrade yourself:

| Channel                           | Manual command                                                                                                                                  |
| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| Homebrew                          | `brew upgrade lpm`                                                                                                                              |
| npm                               | `npm install -g @lpm-registry/cli@<latest>`                                                                                                     |
| Cargo                             | `cargo install --git https://github.com/lpm-dev/rust-client --tag v<latest> lpm-cli --force`                                                    |
| Standalone (macOS / Linux)        | `curl -fsSL https://github.com/lpm-dev/rust-client/releases/download/v<latest>/lpm-<platform> -o $(which lpm) && chmod +x $(which lpm)`         |
| Standalone (Windows / PowerShell) | `Invoke-WebRequest -Uri https://github.com/lpm-dev/rust-client/releases/download/v<latest>/lpm-win32-x64.exe -OutFile (Get-Command lpm).Source` |

`lpm self-update` is just a convenience wrapper that picks the right one and pins the exact version it just resolved. For npm and Cargo the wrapper substitutes the resolved version into `<latest>`; the npm `@latest` dist-tag and an unpinned `cargo install --git` work too if you want channel-latest semantics, at the cost of skipping past any release the wrapper would have pinned. The npm channel relies on npm's normal optional-dependency and install-script behavior so the platform binary is installed and verified during the update.

The standalone installer at `https://cli.lpm.dev/install` is the get-started helper for new users — it always resolves `releases/latest` itself and writes to `~/.lpm/bin/`. Use it for first installs, not for in-place upgrades.

## CI [#ci]

Skip `lpm self-update` in CI. CI pipelines should pin LPM to a specific version (via the npm package or a downloaded standalone binary) and bump that pin deliberately, not in-band during a build. Auto-updating CI's tooling is how reproducible builds become un-reproducible.

For a smoke test that the registry is reachable, use [`lpm health`](/docs/infra/doctor) instead.

## Flags [#flags]

| Flag        | Description                                                                                                                                                    |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--refresh` | Bypass the 10-minute version-lookup cache and probe GitHub directly. Only affects the version check — the upgrade itself always installs the resolved release. |
| `--json`    | Emit structured JSON: `current`, `latest`, `up_to_date`, `install_method`, `update_command`, `cache_hit`.                                                      |

Plus the standard [global flags](/docs/commands#global-flags).

## See also [#see-also]

* [Installation](/docs/installation) — initial install methods (and uninstall)
* [`lpm doctor`](/docs/infra/doctor) — environment health, separate from version updates
* [Releases on GitHub](https://github.com/lpm-dev/rust-client/releases) — what's in each version
