LPM-cli

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 only

Actions

ActionEffect
pathPrint the cache root (~/.lpm/cache/) or one of its subcategories
cleanWipe ephemeral caches (~/.lpm/cache/). lpm cache clear is an alias.
statusReport local task-cache usage and hosted remote-cache status for the current project
pruneReference-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 degrades to tombstone-only mode and still exits zero unless tombstone inspection or the --apply tombstone sweep fails. In JSON mode, registry_corrupt: true and registry_corrupt_reason carry the registry problem; success becomes false only for tombstone_count_error or tombstone_sweep_error.

How it decides what to keep

LPM 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.

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.
  • Tombstone-only degraded mode. If the registry is missing, corrupt, or unreadable AND no --project <path> is supplied, prune cannot identify orphans safely (without trustworthy roots, every link entry would look unreachable). --apply skips orphan removal in this case, runs the tombstone sweep regardless, and prints a warning naming the cause. For corrupt registries the warning 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, and lpm query invocations through the store reader/writer lock — dry-run takes the shared half, --apply takes the exclusive half. See lpm store — Locking model.

Flags

FlagApplies toEffect
--applypruneActually remove orphans + sweep tombstones (default is dry-run)
--max-age <DUR>pruneOnly prune entries last touched older than this. Accepts <N>d (days) or <N>h (hours) — nothing else
--project <PATH>pruneManual 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:

FieldMeaning
local.path / local.bytes / local.sizeLocal task-cache location and usage
remote.enabled / remote.statusHosted cache configuration and server status
remote.usage_bytes / remote.limit_bytesHosted usage and included quota when the server returns them
remote.errorStatus lookup error, if any

prune --json reports both the orphan walk and the tombstone sweep:

FieldMeaning
successfalse when prune could not complete every requested inspection or cleanup step
appliedtrue when --apply was passed
projects_walked / registry_entries_droppedProject-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
bytes_freed_or_eligibleBytes the orphan walk would free (dry-run) or did free (apply)
registry_missing / registry_corrupt / registry_corrupt_reasonDegraded-mode flags — when either is true, orphan paths arrays are empty (walk was skipped) and tombstones are the only mutation reported
tombstones_pending / _swept / _retained[] / tombstone_bytes_freedTombstone 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