Nushell Integration & Paths
Relevant source files
The following files were used as context for generating this wiki page:
Nushell integration in Numan is the process by which installed packages—specifically plugins and modules—are registered or made available to a Nushell environment. Unlike the install command, which is strictly inert and only writes to the $NUMAN_ROOT, integration is handled by the activate and deactivate commands. This isolation ensures that Numan does not modify the user's shell configuration until explicitly requested.
Integration relies on robust path management and validation. Numan tracks the Nu executable hash, version, and vendor autoload directories to ensure that active integrations remain compatible with the current environment. If a version drift is detected (e.g., after a Nu upgrade), Numan requires a refresh of these cached paths to maintain stability.
Sources: README.md:12-25, AGENTS.md:130-140, CONTRIBUTING.md:65-75
Module Autoload Architecture
Numan manages module integration through exactly one external file located in the Nushell vendor autoload directory: numan.nu. This file contains use statements that point to the absolute paths of installed module payloads within the Numan root.
The Autoload Lifecycle
The integration process follows a strict "Candidate-Validation-Replacement" flow to prevent corrupting the shell configuration with invalid scripts.
The flow ensures that before the live numan.nu is updated, the new content is verified by the actual Nushell binary to ensure it can be parsed without errors.
Sources: src/nu/autoload.rs:1-15, AGENTS.md:144-150
Key Autoload Components
| Component | Description |
|---|---|
OWNERSHIP_MARKER | A header string identifying files managed by Numan; prevents overwriting foreign files. |
ResolvedEntry | A validated descriptor containing absolute path, import mode, and scoped ID. |
CandidateRunner | A trait for executing nu -n against candidate files for validation. |
write_candidate | Writes a .<uuid>.candidate.tmp file to ensure same-filesystem atomic moves. |
numan.nu | The single vendor autoload file owned by Numan. |
Sources: src/nu/autoload.rs:25-40, src/nu/autoload.rs:230-245, src/nu/autoload.rs:325-330
Path Management & Safety
Numan enforces strict path safety to prevent directory traversal and ensure that module entries remain within the designated payload and root boundaries.
Path Validation Rules
- Containment: The resolved entry path must reside under the payload directory, which in turn must reside under the Numan root.
- Regular Files: Entries must be regular files; symlinks are explicitly rejected to prevent unexpected execution or escapes.
- Extension: Module entries must end with the
.nuextension. - Safe Relative Paths: All relative paths must be "safe" (no
.., no root/platform prefixes).
Sources: src/nu/autoload.rs:45-120, REVIEW.md:25-35
Nu Path Literal Escaping
When rendering use statements for numan.nu, Numan performs platform-specific escaping to ensure the strings are valid Nushell literals.
// src/nu/autoload.rs:165-175
pub fn render_use_statement(path: &Path, mode: &ModuleImportMode) -> Result<String> {
let path_str = path.to_str().with_context(|| ... )?;
// Escape for a Nu double-quoted string literal:
// 1. backslashes -> \\ (Windows paths)
// 2. double quotes -> \"
let escaped = path_str.replace('\\', "\\\\").replace('"', "\\\"");
let stmt = match mode {
ModuleImportMode::Module => format!("use \"{escaped}\""),
ModuleImportMode::All => format!("use \"{escaped}\" *"),
};
Ok(stmt)
}
Sources: src/nu/autoload.rs:155-180
Integration State & Identity
Integration is not just a boolean state; it is tied to a specific "Activation Identity." A package is considered active only when its record matches the current environment.
Activation Identity Components
The PluginActivation and ModuleActivation records in the lockfile track the following to detect drift:
- Nu Executable SHA256: Ensures the integration is tied to a specific binary.
- Nu Version: Prevents ABI mismatches (critical for plugins).
- Vendor Autoload Directory: Tracks where the managed files were written.
- Managed File Path: The absolute path to the integration file.
If any of these four parts drift (e.g., after numan init --refresh), the package is treated as inactive until re-activated.
Sources: AGENTS.md:133-143, src/cmd/search.rs:50-65
Sequence: Activating a Module
The following sequence diagram illustrates how Numan interacts with the Nushell binary to safely integrate a new module.
Sources: src/nu/autoload.rs:250-320, AGENTS.md:160-165
Nu Version Compatibility
Numan uses a Resolver to match package requirements against the detected Nu version. This is surfaced in commands like search and info.
- Search: By default,
numan searchhides packages that are incompatible with the current Nu version unless the--allflag is used. - Info: The
infocommand provides detailed version compatibility markers, explaining why specific versions may be incompatible (e.g., "needs Nu >=0.113.0").
Sources: src/cmd/search.rs:15-40, src/cmd/info.rs:30-60
Summary of Integration Safety
Numan's integration architecture is built on the principle of Failure-Closed Safety. If any part of the activation process fails—whether it is path validation, Nushell syntax verification of the candidate file, or the atomic rename—the system reverts to the last known good state. This is supported by the journal.rs and autoload_journal.rs files, which allow for crash recovery if the process is interrupted.
Sources: AGENTS.md:140-160, REVIEW.md:20-30