Skip to content
tonythethompson edited this page Jul 10, 2026 · 1 revision

System Architecture Design

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.

Core Architectural Components

The Numan system is organized into distinct layers: a CLI entry point, core domain logic, installation transactions, and state management.

Module Layout

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.

Component Relationship Diagram

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
Loading

This diagram shows how the CLI layer coordinates activities across specialized modules while interacting with persistent storage.

Package Lifecycle and Mutability

Numan enforces strict rules on how data is written and modified to prevent state corruption.

Immutable Payloads

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.

Mutation Locking

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.

Atomic State Transitions

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 and Autoload System

Activation is the process of making installed packages available to Nushell. Numan manages this through a specific vendor-autoload mechanism.

Managed Autoload File

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
Loading

This sequence ensures that only valid Nushell code is ever placed into the autoload path.

Activation Safety Invariants

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.nu that Numan checks before overwriting to ensure it doesn't touch foreign files.

Interoperability: nupm Migration

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.

Crash Recovery and Reliability

Numan uses a multi-stage journaling system to reconcile interrupted operations.

Journal Stages

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.

Data Structure: ResolvedEntry

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.

Clone this wiki locally