quiver is a module manager for Nushell, written in Rust. It handles dependency resolution, fetching, and lockfile management for Nushell modules distributed as git repositories. Think of it as a minimal package manager (similar in spirit to uv or cargo) for the Nushell ecosystem.
Quiver should run on macOS, Linux, and Windows.
The codebase is a single-crate Rust CLI application. All source lives in src/ with one file per responsibility:
| Module | Purpose |
|---|---|
main.rs |
Entry point; dispatches CLI subcommands to cmd_* handler functions |
cli.rs |
CLI definition using clap derive macros (Cli, Commands enum) |
manifest.rs |
Parsing and serializing nupackage.toml manifests (Manifest, Package, DependencySpec) |
lockfile.rs |
Parsing and serializing quiver.lock lockfiles (Lockfile, LockedPackage) |
resolver.rs |
Dependency resolution including transitive deps and conflict detection (ResolvedDep) |
installer.rs |
Orchestrates the install/update flow: resolve → fetch → checksum → place → lock |
git.rs |
Git operations via git2: cloning, fetching, ref resolution, tree export, tag discovery |
checksum.rs |
Deterministic SHA-256 hashing of directory contents for lockfile integrity |
error.rs |
Centralized error types using thiserror (NuanceError enum, Result<T> alias) |
nupackage.toml → resolver (fetches git repos, resolves refs, detects conflicts)
→ installer (exports trees into .nu-env/modules/, computes checksums)
→ quiver.lock (pins exact commit SHAs and checksums)
- Git cache:
~/.local/share/quiver/installs/git/— bare clones of fetched repos, keyed by URL - Installed modules:
.nu-env/modules/in the project directory - Manifest:
nupackage.toml— user-edited package metadata and dependency declarations - Lockfile:
quiver.lock— auto-generated, should be committed to version control
- Language: Rust (edition 2024)
- CLI framework:
clapv4 (derive API) - Git operations:
git2v0.20 (libgit2 bindings) - Serialization:
serde+tomlfor TOML manifest/lockfile handling - Hashing:
sha2+hexfor SHA-256 checksums - Error handling:
thiserrorfor ergonomic error enums - File walking:
walkdirfor recursive directory traversal - Distribution:
cargo-distviadist-workspace.toml; releases target macOS, Linux, and Windows (x86_64 + aarch64)
- Each source file is a single, focused module with a clear responsibility
- Public functions use
/// doc comments; modules re-export only what is needed - Error handling uses a project-wide
Result<T>alias backed by theNuanceErrorenum — never useunwrap()in non-test code - All user-facing output goes to stderr via
eprintln!; stdout is reserved for structured data
- Unit tests live in
#[cfg(test)] mod testsblocks within each source file - Run tests with
cargo test - Tests that touch the filesystem use
std::env::temp_dir()and clean up after themselves
cargo buildfor developmentcargo testto run all tests- Release builds use the
distprofile (lto = "thin") configured indist-workspace.toml - Put release notes for changes in the
CHANGELOG.mdfile and follow the standard convention therein.
- Each dependency must specify exactly one of
tag,branch, orrev - Tags are preferred for stability; branches are resolved to a commit and locked
- Dependency conflicts (same name, different source/rev) are hard errors — no silent resolution
- Rust source files use
snake_case.rs - Project files:
nupackage.toml(manifest),quiver.lock(lockfile),mod.nu(Nushell entry point)