Update, Remove & GC
Relevant source files
The following files were used as context for generating this wiki page:
The Update, Remove, and Garbage Collection (GC) systems in Numan manage the lifecycle of installed packages after their initial installation. These systems ensure that the local package library remains current, consistent, and free of orphaned data while adhering to Numan's core architecture principles of immutability and explicit activation.
These operations are governed by strict safety invariants, including mandatory mutation locks and the use of journals for crash recovery. Together, they allow users to upgrade versions, delete unwanted packages, and prune disk space used by old, unreferenced package payloads.
Sources: README.md:144-150, AGENTS.md:58-64
Lifecycle Management Overview
Numan categorizes post-install operations into three primary commands: update, remove, and gc. Each command interacts with the lockfile (the ground truth of the system) and the packages/ directory where immutable payloads are stored.
Core Architecture Rules
All lifecycle mutations must follow specific architectural boundaries to prevent data loss or state corruption:
| Rule | Description |
|---|---|
| Mutation Lock | Every mutating command must call acquire_mutation_lock(root) to prevent concurrent writes. |
| Immutable Payloads | Installs are land-versioned and content-addressed. Update/Remove never overwrite in place. |
| Snapshotting | A state snapshot is created via create_snapshot() before any mutation occurs. |
| Atomic Writes | All changes to the lockfile or state files use write_json_atomic. |
Sources: CONTRIBUTING.md:73-86, REVIEW.md:23-35, AGENTS.md:148-154
Package Update
The update command upgrades installed packages to newer versions available in the registry. Because Numan utilizes immutable payload paths, an update does not overwrite the existing package but rather installs a new version alongside it and updates the lockfile reference.
Active Plugin Mutation Gate
A critical safety feature in the update process is the "Active Plugin Gate" (Issue #22). Numan refuses to update or remove a package if it has an active plugin activation record, as modifying a plugin while it is loaded by Nushell could lead to instability.
- Default Behavior: Updates are blocked if a plugin is active.
- Opt-in Orchestration: Users can enable automatic
deactivate→upgrade→reactivateflow by setting the environment variableNUMAN_ENABLE_ACTIVE_PLUGIN_MUTATION=1. - Manual Flow: Without the opt-in, users must run
numan deactivate <pkg>before updating.
Sources: AGENTS.md:65-66, src/util/hints.rs:188-216, CHANGELOG.md:46-51
The update flow ensures that active plugins are safely handled through either manual deactivation or opted-in orchestration.
Sources: AGENTS.md:112-117, src/util/hints.rs:200-216
Package Removal
The remove command deletes a package entry from the lockfile and removes its associated payload. Similar to the update process, removal is protected by activation checks.
- Plugin Constraints: Active plugins cannot be removed. The
--forceflag does NOT bypass this restriction. - Module Constraints: Active modules can be removed using
numan remove --force <pkg>, which bypasses the module activation check. - Safety: A snapshot is created before the lockfile is modified, allowing for rollback in case of error.
Sources: AGENTS.md:67-68, CHANGELOG.md:61-62, src/util/hints.rs:188-195
Garbage Collection (GC)
The numan gc command identifies and deletes orphaned payload directories within the $NUMAN_ROOT/packages/ hierarchy. A directory is considered "live" and immune to collection if it is referenced by:
- The current authoritative
lockfile. - Any existing immutable activation snapshot.
GC Execution Flow
GC ensures that only unreferenced data is removed, preserving the integrity of snapshots used for rollbacks.
Sources: AGENTS.md:69, README.md:150, CHANGELOG.md:92
Crash Recovery and Journals
Lifecycle operations utilize the state/pending-lifecycle.json journal to ensure system consistency even if a process is interrupted.
| Journal File | Purpose | Derived From |
|---|---|---|
pending-lifecycle.json | Tracks update/remove operations in progress. | AGENTS.md:79-80 |
pending-plugin-deactivate.json | Manages plugin unregistration stages (Prepared → Unregistered). | AGENTS.md:77-78 |
migration-journal.json | Manages transitions from legacy single-binary layouts to versioned layouts. | AGENTS.md:81-86 |
Recovery is typically triggered during the next invocation of a related command or via numan doctor.
Sources: AGENTS.md:126-130, README.md:154-155
Summary
The Update, Remove, and GC modules provide a robust framework for managing Numan's immutable package store. By enforcing mutation locks, gating active plugin modifications, and using snapshots/journals, Numan ensures that lifecycle transitions are safe, reproducible, and recoverable.
Sources: AGENTS.md:144-154, README.md:158-164