lpm cache
Manage ephemeral caches and prune the global package store.
lpm cache <action>lpm cache covers two adjacent concerns: ephemeral caches under ~/.lpm/cache/ (registry metadata, task results, dlx tarballs) and the global package store at ~/.lpm/store/.
Examples
lpm cache path # print ~/.lpm/cache/
lpm cache path metadata # print ~/.lpm/cache/metadata/
lpm cache clean # wipe metadata + tasks + dlx
lpm cache clean metadata # only wipe registry metadata
lpm cache clean tasks # only wipe task-runner cache
lpm cache clean dlx # only wipe dlx tarball cache
lpm cache status # local task cache usage + remote status
lpm cache status --json # structured status for CI
lpm cache prune # preview orphan store entries (dry-run)
lpm cache prune --apply # actually remove orphans
lpm cache prune --max-age 30d --apply # only entries last touched > 30d ago
lpm cache prune --project ./my-app # manual repair: walk one project onlyActions
| Action | Effect |
|---|---|
path | Print the cache root (~/.lpm/cache/) or one of its subcategories |
clean | Wipe ephemeral caches (~/.lpm/cache/). lpm cache clear is an alias. |
status | Report local task-cache usage and hosted remote-cache status for the current project |
prune | Reference-aware orphan removal from the global store (~/.lpm/store/) plus a sweep of deferred global-install tombstones |
clean accepts an optional subcategory (metadata, tasks, dlx); without one, all three are wiped. clean never touches the global package store — for that, use prune.
Status
lpm cache status reports the local task-cache path and size. If the current project has lpm.json > remoteCache.enabled, it also calls the hosted cache status endpoint and reports the remote status, usage, and quota when the server returns them.
Remote status failures do not make lpm cache status fail; the JSON envelope includes remote.error so CI can decide whether to warn or ignore.
Prune
lpm cache prune walks the global store and removes entries no project still references, then sweeps any deferred global-install tombstones left behind by lpm uninstall -g. Default is dry-run; pass --apply to mutate.
Human output ends with an elapsed summary; --json keeps the machine-readable report shape and includes success.
The tombstone sweep runs even when the orphan walk is skipped (registry missing or corrupt — see Safety rails), so lpm uninstall -g's deferred cleanup always has a way to reach disk.
If the project registry is corrupt, prune disables only the project-reachability
walk. It still plans or applies crash recovery and age-based eviction for
compatibility islands and native build artifacts, cleans their orphaned lock
files, and sweeps global-install tombstones. In JSON mode,
registry_corrupt: true and registry_corrupt_reason carry the registry
problem; tombstone inspection and sweep failures are reported separately.
How it decides what to keep
LPM CLI tracks every project it has installed into in a registry at ~/.lpm/known-projects.json. For each registered project, prune walks the project's node_modules/ symlinks back into ~/.lpm/store/v2/links/<graph-key>/, then BFS through each link entry's sidecar metadata to mark every reachable graph-key. Anything not marked is an orphan. Object directories under ~/.lpm/store/v2/objects/ are pruned the same way — by collecting every surviving link entry's object reference and removing the rest. On macOS, cached compatibility islands under ~/.lpm/store/v2/compat/ are pruned by crash recovery and LRU age: incomplete islands are eligible immediately, and complete islands are eligible only when their last-used sentinel is older than --max-age.
Native lifecycle-build artifacts under ~/.lpm/store/v2/builds/ use the same
crash-recovery and LRU rule on macOS and Linux. An incomplete publication is
eligible immediately. A complete artifact is kept unless its last-used
sentinel is older than --max-age. This cleanup is independent of project
reachability, so it remains safe and active when the project registry is
missing or corrupt. --apply also removes advisory build-key lock files that
no longer have an artifact and graph-entry lock files whose link entry was
removed.
Stale registry entries (projects that have moved or been deleted) are dropped silently during the walk. The --max-age filter operates on each link entry's last_referenced_at timestamp (recorded in the entry's sidecar at first population, refreshed by lpm install cache hits) — not on the project registry's last_seen, which is set at install-time only.
Manual repair: --project <path>
When the registry is missing, corrupted, or doesn't reflect actual machine state (after a restore, after copying ~/.lpm/ between machines, etc.), pass --project <path> to walk only that project's lockfile + node_modules/ for roots. The registry is ignored.
This mode is for scripted cleanup of a single project's footprint. Default mode is safer when you have multiple projects on the machine — --project only sees the one you point it at, so any link entry referenced by another project would look like an orphan.
Safety rails
- Dry-run by default. No deletions without
--apply. - Reachability-degraded mode. If the registry is missing, corrupt, or unreadable AND no
--project <path>is supplied, prune cannot identify link/object orphans safely (without trustworthy roots, every link entry would look unreachable).--applyskips only link/object orphan removal. Reachability-independent compatibility-island and native-build-artifact cleanup, orphan lock cleanup, and the tombstone sweep still run. LPM CLI prints a warning naming the cause; for corrupt registries it includes the parser's reason ("not valid JSON" / "unknown schema version" / I/O details) so you can repair the file or delete it for a clean rebuild. - Canonicalized paths. The registry stores fully resolved absolute paths, so symlink-cwd quirks don't accumulate aliased entries.
- Atomic registry rewrites. Updates go through
<path>.tmp.<pid>→ rename. No partial-write corruption. - In-flight installs are respected. Prune coordinates with concurrent
lpm install,lpm audit, andlpm queryinvocations through the store reader/writer lock — dry-run takes the shared half,--applytakes the exclusive half. Seelpm store— Locking model.
Flags
| Flag | Applies to | Effect |
|---|---|---|
--apply | prune | Actually remove orphans + sweep tombstones (default is dry-run) |
--max-age <DUR> | prune | Only prune entries last touched older than this. Accepts <N>d (days) or <N>h (hours) — nothing else |
--project <PATH> | prune | Manual repair: walk only this project's roots, ignore the registry |
Plus the global flags.
JSON output
lpm cache status --json
lpm cache prune --json # dry-run report
lpm cache prune --apply --json # post-apply report (same shape, mutations recorded)status --json emits:
| Field | Meaning |
|---|---|
local.path / local.bytes / local.size | Local task-cache location and usage |
remote.enabled / remote.status | Hosted cache configuration and server status |
remote.usage_bytes / remote.limit_bytes | Hosted usage and included quota when the server returns them |
remote.error | Status lookup error, if any |
prune --json reports both the orphan walk and the tombstone sweep:
| Field | Meaning |
|---|---|
success | false when prune could not complete every requested inspection or cleanup step |
applied | true when --apply was passed |
projects_walked / registry_entries_dropped | Project-registry coverage stats |
link_entries_total / _reachable / _orphaned[] | Link-entry walk results; _orphaned[] is a list of paths |
object_entries_total / _reachable / _orphaned[] | Object-entry walk results |
compat_islands_total / _orphaned[] | Cached compatibility-island results; _orphaned[] lists incomplete or stale LRU islands |
build_artifacts_total / _orphaned[] | Native lifecycle-build artifact results; _orphaned[] lists incomplete or stale LRU artifacts |
bytes_freed_or_eligible | Bytes the orphan walk would free (dry-run) or did free (apply) |
registry_missing / registry_corrupt / registry_corrupt_reason | Reachability-degraded flags — when either is true, link/object orphan arrays are empty because that walk was skipped; compatibility-island, native-build-artifact, lock, and tombstone cleanup still operate independently |
tombstones_pending / _swept / _retained[] / tombstone_bytes_freed | Tombstone sweep results — _swept and _bytes_freed are zero on dry-run |
lpm cache clean emits a parallel {success, cleaned[], total_bytes_freed, total_freed} envelope per subcategory.
See also
- Content-addressable store — design overview, on-disk layout
lpm store— integrity checks, store path, blunt full wipelpm doctor— surfaces store-size hints alongside other checks