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

Nushell Interop & Autoloading

Nushell Interop and Autoloading in Numan provides a safe, explicit mechanism for integrating installed packages with a user's Nushell environment. While the install command remains inert to prevent accidental side effects, the activate command manages the registration of plugins and the generation of a managed vendor-autoload file for modules. This system ensures that Numan owns exactly one external file—numan.nu—within the Nushell vendor-autoload directory, maintaining strict boundaries between Numan-managed state and user configuration.

The architecture relies on a "Lockfile as Ground Truth" principle, where derived projections like autoload-state.json are used for verification, but the lockfile remains the authoritative record of activation status. All external mutations are journaled to ensure crash recovery and prevent state corruption during the transaction between Numan's root and the external Nushell data directory.

Managed Autoload Architecture

Numan interacts with Nushell primarily through a single managed file located in the Nushell vendor-autoload directory. This file, numan.nu, contains deterministic use statements that load installed modules into the shell at startup.

Ownership and Safety

To prevent overwriting user-defined files or files managed by other tools, Numan uses an OWNERSHIP_MARKER. Every managed numan.nu file must begin with this specific header. Before any mutation (overwrite or delete), Numan verifies the marker and checks the file's SHA-256 against its internal state.

Transaction Flow

The activation of modules follows a strict multi-stage transaction to maintain integrity.

flowchart TD
    A[Start Activation] --> B[Acquire Mutation Lock]
    B --> C[Generate Candidate Content]
    C --> D[Write Temporary Candidate File]
    D --> E[Validate Candidate via Nu -n]
    E -- Success --> F[Write Prepared Journal]
    E -- Failure --> G[Cleanup & Abort]
    F --> H[Replace live numan.nu]
    H --> I[Write Replaced Journal]
    I --> J[Update Lockfile & Autoload State]
    J --> K[Clear Journal & Release Lock]
Loading

The flow ensures that only validated code is promoted to the live Nushell environment.

Module Activation Logic

Module activation transforms installed package payloads into executable Nushell code. This involves resolving entry points and rendering safe use statements.

Entry Resolution

Numan validates that module entry paths are safe, ensuring containment within the Numan root and verifying that the entry is a regular .nu file. It explicitly rejects symlinks or paths that attempt to escape the payload directory using .. or absolute paths.

Content Generation

The content of the numan.nu file is generated deterministically, sorted by the canonical scoped package ID. This ensures human-readable and reproducible output.

Component Description
OWNERSHIP_MARKER Header: # Generated and managed by Numan. Do not edit.
Path Escaping Double-quotes paths; doubles backslashes on Windows; escapes internal double-quotes.
Import Modes Supports Module (use "path") and All (use "path" *).

Validation and Execution

Numan uses a "Candidate Validation" pattern to ensure that generated autoload files will not crash Nushell on startup.

Candidate Runner

The system defines a CandidateRunner trait to abstract the execution of the Nushell binary. The NuCandidateRunner implementation invokes nu -n <candidate-path>. This "no-config" mode allows Nu to parse and validate the file without loading the user's existing configuration, providing a clean room for testing.

pub trait CandidateRunner {
    fn run(&self, candidate: &Path) -> Result<()>;
}

Fake Runner for Testing

For unit and integration testing, a FakeCandidateRunner is utilized to simulate success or failure without spawning real Nushell processes, allowing for high-coverage testing of the transaction logic and recovery paths.

Nushell Environment Caching (NuPaths)

Numan caches critical paths and metadata about the host Nushell installation in nu_state/paths.json. This cache is populated during numan init or numan init --refresh.

Cached Information

The NuPaths structure tracks the identity and capabilities of the Nu binary.

Field Description
nu_executable_hash SHA-256 of the Nu binary to detect upgrades/drift.
nu_version The semantic version of Nushell.
vendor_autoload_dirs List of directories where Nu looks for autoload files.
vendor_autoload_dir The Numan-selected safe target (usually <data-dir>/vendor/autoload).

Drift Detection

Activation is tied to the specific Nu binary and version cached in NuPaths. If the binary on PATH changes (detected via hash mismatch), Numan blocks activation/deactivation and requires the user to run numan init --refresh to re-validate the environment.

Journaling and Crash Recovery

Because activation spans two separate domains (the Numan root and the Nushell data directory), Numan uses a pending-autoload.json journal to ensure atomicity.

Transaction Stages

  1. Prepared: The candidate file has been generated and validated. Numan is about to replace the live file.
  2. Replaced: The live file has been replaced, but Numan's internal lockfile has not yet been updated.

If Numan crashes, the next activate or deactivate call will detect the journal and attempt to reconcile the state based on these stages.

Conclusion

The Nushell Interop & Autoloading system provides a robust bridge between package management and shell runtime. By combining deterministic code generation, real-shell validation, and journaled transactions, Numan ensures that package activation is both safe and reversible, protecting the user's shell environment from configuration errors or partial writes.

Clone this wiki locally