Immutability & File Layout
Relevant source files
The following files were used as context for generating this wiki page:
Numan employs a strict architecture centered on immutable package payloads and a deterministic file layout. This design ensures that installations are inert, reproducible, and safe from silent corruption. By separating the physical installation of artifacts from their activation within Nushell, Numan maintains a clear boundary between the package manager's state and the user's shell environment.
The system relies on content-addressed, versioned paths and atomic file operations to manage state changes. All mutations to the file system are governed by a mutation lock and documented via journals to support crash recovery and maintain the integrity of the Lockfile is ground truth principle.
Sources: AGENTS.md:143-149, README.md:16-30, CONTRIBUTING.md:112-120
Data Layout and Root Directory
Numan stores all state, configuration, and package data under a platform-specific root directory. This root can be overridden using the NUMAN_ROOT environment variable or the --root global flag.
Default Root Paths
| Platform | Default Path |
|---|---|
| Linux | ~/.local/share/numan |
| macOS | ~/Library/Application Support/numan |
| Windows | %LOCALAPPDATA%\numan |
Sources: README.md:255-263, AGENTS.md:52-53
Directory Structure
The internal structure of the Numan root is designed to isolate different types of data:
numan/
├── config.toml # Registries and default settings
├── lockfile # Pinned installs (The authoritative state)
├── packages/ # Immutable, versioned package payloads
├── registries/ # Cached registry indexes
├── state/ # Journals (activation, lifecycle, nupm imports)
├── nu_state/ # Cached Nu paths and active version markers
└── tools/ # Managed tool binaries (e.g., Nushell)
Sources: README.md:265-273, AGENTS.md:154-160, CHANGELOG.md:25-28
Immutable Payloads
One of Numan's core architecture rules is that installs are inert. When a package is installed, it is written to a unique, versioned directory that is never overwritten in place.
Payload Path Logic
Payload paths follow a specific naming convention to prevent collisions and ensure immutability:
packages/<type>/<owner>/<name>/<version>-<sha8prefix>/
- Type: The category of package (plugin, module, etc.).
- Version: The semantic version of the package.
- SHA8 Prefix: A short hash of the payload content to ensure uniqueness even if versions are re-published.
Sources: AGENTS.md:124-124, README.md:275-275, CONTRIBUTING.md:115-115
Managed Binaries
Managed Nushell versions also follow a versioned layout under <root>/tools/nushell/<version>/nu. This prevents different versions of Nushell from clobbering each other and allows Numan to manage side-by-side installations.
Sources: CHANGELOG.md:25-30
File Ownership and Safety
Numan protects the integrity of its file layout through ownership markers and strict path validation.
Ownership Markers
Numan identifies files it manages (such as the numan.nu vendor autoload file) using a specific OWNERSHIP_MARKER. Commands will refuse to overwrite or delete files that do not contain this marker, preventing the accidental destruction of foreign or user-created files.
Sources: src/nu/autoload.rs:184-188, CONTRIBUTING.md:118-118, REVIEW.md:24-24
Path Validation
To prevent directory traversal attacks and ensure files remain within the managed root, Numan validates all relative paths.
- Safe Relative Paths: Rejects paths containing
.., absolute paths, or platform prefixes. - Containment Check: Verifies that canonicalized entry paths still reside within the designated payload or Numan root directory.
Sources: src/nu/autoload.rs:59-106, CHANGELOG.md:31-33
Atomic State Mutations
All changes to Numan's internal state (lockfiles, journals, and configuration) must be atomic to prevent corruption during crashes or interruptions.
write_json_atomic
The system uses a helper utility, write_json_atomic, which follows a pattern of writing to a temporary file in the target directory and then performing an OS-atomic rename/persist operation.
Mutation Locking
To prevent concurrent destructive operations, all mutating commands (such as install, remove, update, or gc) must acquire a mutation lock. This is an advisory file-descriptor lock on the Numan root.
Sources: CONTRIBUTING.md:116-116, REVIEW.md:20-20, AGENTS.md:141-142
Module Autoload Layout
For Nushell modules, Numan manages a specific file within the Nushell vendor autoload directory.
Autoload File Lifecycle
Numan generates a numan.nu file that contains use statements for all activated modules. This process involves creating a candidate file, validating it with the Nu binary, and then replacing the live file.
Autoload Integrity Table
| Component | Responsibility | File Reference |
|---|---|---|
| Entry Resolution | Validates .nu extension and safety | src/nu/autoload.rs:48 |
| Statement Rendering | Escapes paths for Nu string literals | src/nu/autoload.rs:149 |
| Candidate Placement | Writes temporary .tmp file (not .nu) | src/nu/autoload.rs:247 |
| Validation | Checks syntax with nu -n | src/nu/autoload.rs:277 |
Sources: src/nu/autoload.rs:13-33
Conclusion
The Numan file layout is designed for resilience. By treating package payloads as immutable artifacts and using atomic operations for all state updates, the system ensures that the package management state remains consistent. The use of ownership markers and strict path validation further secures the environment against accidental file drift or malicious path manipulation.
Sources: AGENTS.md:143-152, REVIEW.md:17-25