# lpm global (/docs/packages/global)



```bash
lpm global <subcommand>
```

CLI surface for the global package store at `~/.lpm/global/`. Globally installed packages — `lpm install -g <pkg>` — get their bins shimmed into `~/.lpm/bin/` and tracked in a manifest LPM CLI owns.

A package is committed as globally installed only after LPM CLI has created at least one safe, executable bin shim for it. Packages with no usable bins, unsafe bin names, or incomplete install roots fail closed and are rolled back before they reach the global manifest.

The same install / uninstall surface is reachable via the regular commands with `-g`:

| Equivalent                |                               |
| ------------------------- | ----------------------------- |
| `lpm install -g eslint`   | `lpm install --global eslint` |
| `lpm uninstall -g eslint` | `lpm global remove eslint`    |

This page documents the `lpm global` subcommands directly. For installing a global package, prefer [`lpm install -g`](/docs/packages/install).

## Examples [#examples]

```bash
lpm global list                          # what's installed globally
lpm global list --outdated               # which globals have updates available
lpm global list --verbose                # add install date, size, root path
lpm global bin                           # print ~/.lpm/bin/  (add this to PATH)
lpm global path eslint                   # print eslint's install root
lpm global link                          # expose the current package's bins globally
lpm global link ../my-cli                # expose a local checkout globally
lpm global unlink my-cli                 # remove a local global link
lpm global remove eslint                 # uninstall a global package
lpm global update                        # update every globally-installed package
lpm global update eslint                 # update one
lpm global update eslint@^9              # change the saved spec, then update
lpm global update --dry-run              # show the upgrade plan, change nothing
```

## Subcommands [#subcommands]

| Command             | Arguments          | Flags                     | Effect                                                                       |
| ------------------- | ------------------ | ------------------------- | ---------------------------------------------------------------------------- |
| `lpm global list`   | (none)             | `--outdated`, `--verbose` | List globally-installed packages and their exposed commands.                 |
| `lpm global bin`    | (none)             | (none)                    | Print the shim directory to add to `PATH`.                                   |
| `lpm global path`   | `<package>`        | (none)                    | Print one global package's install root.                                     |
| `lpm global link`   | `[path]`           | (none)                    | Link a local package's bins into the global PATH surface.                    |
| `lpm global unlink` | `<package>`        | (none)                    | Remove a local global link.                                                  |
| `lpm global remove` | `<package>`        | (none)                    | Remove a globally-installed package. Equivalent to `lpm uninstall -g <pkg>`. |
| `lpm global update` | `[package[@spec]]` | `--dry-run`               | Re-resolve one or all registry-backed globals against their saved specs.     |

### `list` [#list]

```bash
lpm global list [--outdated] [--verbose]
```

Lists every globally-installed package with its active version and exposed bin commands.

| Flag         | Effect                                                                                                                                                                                                                                                                          |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--outdated` | Resolve each install's saved spec against its registry and active cooldown policy; flag packages with newer installable matching versions. `@lpm.dev/*` globals use LPM.dev Registry batch metadata, while npm globals use the same npm metadata path as global install/update. |
| `--verbose`  | Add install date, on-disk size, and the absolute install root for each row                                                                                                                                                                                                      |

With `--outdated`, the human table shows `Package`, `Current`, `Wanted`, `Latest`, and `Bins`. `Wanted` is the newest installable version that still satisfies the global install's saved spec; `Latest` is the registry's newest installable version regardless of the saved range, so mature major-version jumps are visible even when the saved range would not select them. Local links are skipped because their source of truth is your checkout, not the registry.

If registry metadata is missing or the saved spec no longer resolves, `lpm global list --outdated` exits non-zero instead of reporting a clean result. In `--json` mode, inspect `success`, `unresolved`, and `count_unresolved` to distinguish "everything checked" from "some globals could not be compared."

### `bin` [#bin]

```bash
lpm global bin
```

Prints `~/.lpm/bin/` — the directory where global-install shims live. Add this to your `PATH` so installed CLIs resolve.

```bash
export PATH="$(lpm global bin):$PATH"     # in your shell rc
```

### `path <package>` [#path-package]

```bash
lpm global path eslint
```

Prints the install root for one specific globally-installed package. Useful for tooling that needs to find the package's `node_modules/`, `package.json`, or files.

For local links, this prints the linked source checkout.

### `link [path]` [#link-path]

```bash
lpm global link
lpm global link ../my-cli
```

Links a local package into the global manifest and exposes its `bin` commands through `~/.lpm/bin/`. Omit `path` to link the current working directory.

The linked package must have `name`, `version`, and at least one valid `bin` entry in `package.json`; each bin target must exist inside the package directory. LPM CLI refuses command-name collisions with existing global packages so a local checkout cannot silently take over a command you already installed.

### `unlink <package>` [#unlink-package]

```bash
lpm global unlink my-cli
```

Removes a local global link, its shims, and its global manifest entry. Registry-backed global packages are removed with `lpm global remove` or `lpm uninstall -g`.

### `remove <package>` [#remove-package]

```bash
lpm global remove eslint
```

Uninstalls a globally-installed package. Drops the entry from the global manifest, removes the install root, and unshims any bins it owned. &#x2A;*Equivalent to `lpm uninstall -g eslint`** — both invocations route through the same uninstall pipeline.

### `update [package[@spec]] [--dry-run]` [#update-packagespec---dry-run]

```bash
lpm global update                        # update every global
lpm global update eslint                 # update one, preserving its saved spec
lpm global update eslint@^9              # rewrite the saved spec, then update
lpm global update --dry-run              # plan only, no work
```

Three behaviors based on the argument:

| Argument       | Behavior                                                                                                                                                                                        |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| (none)         | Iterate every registry-backed global package. Re-resolve each one against its persisted `saved_spec`. Upgrade any that have a newer matching version. Local links are skipped.                  |
| `<pkg>`        | Same flow scoped to one registry-backed package. Local global links are not updated by this command; edit the linked checkout directly, or unlink and link it again after its metadata changes. |
| `<pkg>@<spec>` | Rewrite the saved spec using the [save policy](/docs/packages/save-policy) decision logic, then upgrade. Same precedence as `lpm install <pkg>@<spec>` in a project context.                    |

| Flag        | Effect                                            |
| ----------- | ------------------------------------------------- |
| `--dry-run` | Print the upgrade plan without changing any state |

If registry metadata is missing, the selected version is no longer present, or the saved spec cannot resolve, `lpm global update` exits non-zero instead of reporting a clean skip. In `--json` mode, `success` is `false` and the affected row appears as `failed` in `results` or `plan_error` in `plans` for `--dry-run`. Bulk updates remain best-effort: successful package rows may still be applied before the final non-zero exit.

Global update uses the global minimum release age chain: `~/.lpm/config.toml`, then the 24h default. Candidate versions for the globally installed package are skipped during planning while they are still inside the cooldown window, including `--dry-run`, so the plan only shows versions the nested install would accept.

## Bin collisions [#bin-collisions]

When a global install would expose a bin name that another global package already owns, LPM CLI refuses to silently take it over. In an interactive terminal, LPM CLI prompts per colliding command: replace the existing shim, install the new command under an alias, or cancel. In JSON and non-TTY runs, it exits with a collision error and shows copy-pasteable `--replace-bin` / `--alias` examples.

Use `--replace-bin` when the new package should deliberately take ownership:

```bash
lpm install -g foo --replace-bin serve
```

The previous owner keeps its install but loses `serve` from PATH; the new shim points at `foo`'s `serve` binary.

Use `--alias <ORIG=ALIAS>` when both packages should stay reachable:

```bash
lpm install -g foo --alias serve=foo-serve
```

Only `foo-serve` is emitted as the new PATH command; the original `serve` shim stays with its current owner. See [`lpm install -g`](/docs/packages/install) for the full collision surface.

| Install flag           | Effect                                                                                                                                                                                   |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--replace-bin <CMD>`  | Transfer ownership of one colliding PATH command to the package being installed. Repeatable.                                                                                             |
| `--alias <ORIG=ALIAS>` | Install the declared bin `<ORIG>` under a different PATH command `<ALIAS>`. The original name is not emitted for the new package. Repeatable, and comma-separated mappings are accepted. |

## Security gates on `-g` [#security-gates-on--g]

`lpm install -g` runs through the same install pipeline as project installs, with the same install-time security gates applied to the synthesized global project. Machine-wide controls, including the npm firewall mode set by [`lpm config firewall`](/docs/infra/config#npm-firewall), apply to global installs too:

| Flag                                               | Behavior on `-g`                                                                                                                                                                                                                                                                               |
| -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--allow-new`                                      | Bypasses the [minimum release age](/docs/packages/security-audit#layer-4-provenance--cooldown) cooldown                                                                                                                                                                                        |
| `--min-release-age=<DUR>`                          | Overrides the cooldown window (`<N>h`, `<N>d`, or seconds; `0` disables)                                                                                                                                                                                                                       |
| `--min-release-age-exclude <PKG>`                  | Exempts one exact package name from the cooldown; repeatable                                                                                                                                                                                                                                   |
| `--ignore-provenance-drift <PKG>`                  | Waives the [drift check](/docs/packages/security-audit#layer-4-provenance--cooldown) for one package (repeatable)                                                                                                                                                                              |
| `--ignore-provenance-drift-all`                    | Waives the drift check for every resolved package                                                                                                                                                                                                                                              |
| `--policy=deny\|allow\|triage`                     | [Script-policy](/docs/packages/install#lifecycle-scripts) for this invocation                                                                                                                                                                                                                  |
| `--yolo`                                           | Alias for `--policy=allow`                                                                                                                                                                                                                                                                     |
| `--triage`                                         | Alias for `--policy=triage`                                                                                                                                                                                                                                                                    |
| `--advisor=none\|claude-cli\|codex\|ollama`        | Triage advisor override (only consulted under `--policy=triage`)                                                                                                                                                                                                                               |
| `--auto-build`                                     | Auto-runs `lpm rebuild` for trusted packages immediately after install. On `-g` under `triage` with mixed-trust trees, this is the only way to trigger the rebuild — `package.json > lpm > scripts.autoBuild` is not consulted. Also useful under `deny` with an established global trust set. |
| `--strict-sandbox` / `--paranoid` / `--no-sandbox` | [Sandbox mode](/docs/packages/install#sandbox) for this invocation's dependency lifecycle scripts                                                                                                                                                                                              |

Two `-g`-specific notes:

* **No project-config tier.** Globals use a synthesized package.json that doesn't carry `lpm > scriptPolicy`, `lpm > minimumReleaseAge`, `lpm > minimumReleaseAgePolicy`, `lpm > minimumReleaseAgeExclude`, or `lpm > scripts.autoBuild`. The script-policy and cooldown precedence chains collapse to CLI flag > `~/.lpm/config.toml` > default. Triage on `-g` requires the explicit `--auto-build` flag for mixed-trust trees — there's no per-project knob.
* **Reinstall to rerun blocked scripts.** After `lpm approve-scripts --global`, the trust file is updated but the install root isn't re-executed. Run `lpm uninstall -g <pkg> && lpm install -g <pkg>` for each affected top-level global to actually run the approved scripts. `lpm rebuild --global` is a planned follow-up.

## Approving scripts for globals [#approving-scripts-for-globals]

Globally-installed packages have their own blocked-set for dependency lifecycle scripts. Manage it with:

```bash
lpm approve-scripts --global             # review the global blocked set
lpm approve-scripts --global --group     # group by top-level globally-installed package
```

Approvals write to `~/.lpm/global/trusted-dependencies.json` (separate from any project's `package.json`). The success banner enumerates the top-level globals affected so you can run the matching `lpm uninstall -g … && lpm install -g …` for each.

## See also [#see-also]

* [`lpm install -g`](/docs/packages/install) — install into the global root (with `--replace-bin` / `--alias`)
* [`lpm uninstall -g`](/docs/packages/uninstall) — equivalent to `lpm global remove`
* [`lpm approve-scripts --global`](/docs/packages/approve-scripts#global-vs-project) — script approval for globals
* [Save policy](/docs/packages/save-policy) — determines what `update <pkg>@<spec>` writes
