-
-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
Numan is a cross-platform, production-grade package manager for Nushell written in Rust. Its architecture is designed to maintain a strict separation between package installation and shell integration. The system emphasizes safety through immutable payloads, cryptographically verified registries, and journaled state transitions to ensure recovery from interrupted operations.
The architecture is built on the principle that "Install is inert." Commands that modify the filesystem (install, remove, update) only touch the Numan root directory, while shell integration is handled exclusively by the activate and deactivate commands. This isolation prevents Numan from corrupting the Nushell environment during routine package management tasks.
The Numan system is organized into distinct layers: a CLI entry point, core domain logic, installation transactions, and state management.
Numan's internal structure is partitioned to isolate concerns:
-
src/core/: Pure domain logic including platform detection, package types, registry verification, and version resolution. -
src/install/: Logic for the full install flow, including downloading, verification, and extraction. -
src/state/: The authoritative state layer, managing the JSON lockfile, journals for crash recovery, and activation snapshots. -
src/nu/: Integration logic for Nushell, such as path caching and autoload generation.
The following diagram illustrates the relationship between the major architectural blocks:
flowchart TD
CLI[CLI Layer: src/cmd] --> Core[Core Logic: src/core]
CLI --> Install[Install Flow: src/install]
CLI --> State[State Management: src/state]
CLI --> Nu[Nu Integration: src/nu]
Install --> Core
Install --> State
Nu --> State
subgraph Storage
LF[(Lockfile)]
JR[(Journals)]
PL[(Payloads)]
end
State --> LF
State --> JR
Install --> PL
This diagram shows how the CLI layer coordinates activities across specialized modules while interacting with persistent storage.
Numan enforces strict rules on how data is written and modified to prevent state corruption.
Packages are installed into content-addressed, versioned paths: <root>/packages/<type>/<owner>/<name>/<version>-<sha8prefix>/. These paths are immutable; updates result in new directories rather than in-place overwrites. Orphaned directories are later cleaned up via a Garbage Collection (gc) process.
To prevent concurrent destructive operations, all mutating commands (such as install, remove, update, and nupm import) must acquire a mutation lock. This is an advisory file lock located at $NUMAN_ROOT/state/mutation.lock.
State files, including the lockfile and journals, are updated using atomic JSON writes. This involves writing a temporary file in the same directory and then persisting it via an OS-level rename to ensure the file is either fully updated or left unchanged.
Activation is the process of making installed packages available to Nushell. Numan manages this through a specific vendor-autoload mechanism.
Numan manages exactly one external file in the Nushell vendor-autoload directory: numan.nu. This file contains use statements that point to absolute paths in Numan's immutable package store.
sequenceDiagram
participant CLI as Numan CLI
participant Journal as Autoload Journal
participant Nu as Nu Binary
participant FS as File System
CLI->>CLI: Generate candidate content
CLI->>FS: Write .candidate.tmp
CLI->>Nu: Validate: nu -n candidate
Nu-->>CLI: Success/Failure
CLI->>Journal: Log Stage: Prepared
CLI->>FS: Rename candidate to numan.nu
CLI->>Journal: Log Stage: Replaced
CLI->>CLI: Update Lockfile
CLI->>Journal: Clear Journal
This sequence ensures that only valid Nushell code is ever placed into the autoload path.
A package is only considered "active" if multiple identity markers match the current environment:
- Nu Executable Hash: Prevents loading plugins/modules after a Nu binary upgrade without re-validation.
- Nu Version: Ensures compatibility with the running shell.
-
Ownership Marker: A header in
numan.nuthat Numan checks before overwriting to ensure it doesn't touch foreign files.
Numan provides a read-only discovery and one-way import mechanism for nupm packages. The architecture treats nupm imports as "snapshots"—once imported, Numan uses its own immutable copy, and subsequent changes in the nupm source do not affect Numan until an explicit re-import occurs.
| Feature | Numan Approach to nupm |
|---|---|
| Discovery | Read-only scan via $NUPM_HOME or --nupm-home. |
| Import | One-way copy to Numan's immutable revision store. |
| Trust | Imported local content is not upgraded to "registry-verified" status. |
| Drift | Detection of changes between Numan's snapshot and nupm source. |
Numan uses a multi-stage journaling system to reconcile interrupted operations.
Journals (e.g., pending-activation.json, pending-autoload.json, pending-lifecycle.json) track progress through critical sections.
| Stage | Description |
|---|---|
| Prepared | The operation is planned and validated; no external state has changed yet. |
| PayloadsStaged | Files have been copied to a temporary staging area. |
| PayloadsPromoted | Files have been moved to their final immutable locations. |
| SelectionCommitted | The lockfile has been updated to reflect the new state. |
The system uses the ResolvedEntry structure in the autoload module to manage validated module paths for generation.
pub struct ResolvedEntry {
pub absolute_path: PathBuf,
pub import_mode: ModuleImportMode,
pub scoped_id: String,
}The Numan architecture prioritizes environment stability, ensuring that Nushell remains functional even if package management operations are interrupted or if the shell binary is upgraded. By centralizing all configuration and state in a single $NUMAN_ROOT and managing integration through a single, validated autoload file, it provides a predictable and safe package management experience.
Numan wiki for tonythethompson/numan · v0.1.4 · MIT