A declarative package manager for nushell and nu-scripts.
This project is in a experimental stage.
Expect: breaking changes, bad UI, random crashes, etc.
TOC:
A alternative overview can be found here.
Dependencies: python3, nu, and git.
http get --raw "https://raw.githubusercontent.com/Jan9103/numng/main/numng.py" | save -r numng.py
python3 numng.py --nu-config init # generate a basic config
rm numng.py # no longer needed since it now installs and updates itself
nu # open a new nu session to reload the configNote: All numng managed binaries (including itself) are only available within nushell since it uses its own PATH entry.
In case anything goes wrong:
- removing the
sourceline from your nu config completly disables numng - the
numng.pycan be found at~/.local/share/nushell/numng/git/github/jan9103/numng/main/numng.py - complete removal:
rm -r ~/.local/share/nushell/numng ~/.config/nushell/numngand remove thesourceline from your nu config
Example configuration (~/.config/nushell/numng/numng.json):
{
"name": "nu-config",
"depends": [
{"name": "jan9103/numng"},
{"name": "fdncred/nu_plugin_file"},
{"name": "nushell/nu_scripts/theme/gruvbox-dark"},
{"name": "jan9103/nu-snippets/integration/carapace"},
{"name": "jan9103/nu-snippets/prompt/starship"}
],
"registry": [
{"source_uri": "https://github.com/Jan9103/numng_repo", "package_format": "numng", "path_offset": "repo"}
]
}if something is not available in a registry you can define the package inline:
{
"depends": {
{"name": "nu_plugin_file", "nu_plugins": ["target/release/nu_plugin_file"], "build_command": "cargo build --release",
"source_uri": "https://github.com/fdncred/nu_plugin_file", "package_format": "numng"}
}
}Applying the config: numng --nu-config build or numng -n b
Updating installed packages: numng --nu-config build --pull-updates or numng -n b -u
Note: For better packer.nu compatability include the top-level-dependency {"name": "packer.nu", "source_uri": "carview.php?tsp=https://github.com/jan9103/packer.nu"}
Note: If you want to use numng installed binaries in other shells add ~/.local/share/nushell/numng/nu_config_nupm_home/bin to their PATH.
With such a setup it is possible to install nushell/nushell using numng for automatic updates.
Create a numng.json in your project (or add --package-file PATH to all commands):
(or generate it using numng init)
{
"name": "project-name",
"depends": [
{"name": "1kinoti/stdx.nu"}
],
"linkin": {
"webserver:nulibs/webserver": {"name": "jan9103/webserver.nu"}
},
"registry": [
{"source_uri": "https://github.com/Jan9103/numng_repo", "package_format": "numng", "path_offset": "repo"}
]
}Dependencies:
If you want to keep your project nupm compatible use depends and $env.NUPM_HOME for dependencies.
If that's not a concern linkin is more reliable (always the right version, easier to use, no need for overlays, etc).
Both are explained below in Nupm package format
Command:
numng build (short: numng b) is the base command.
If you want to update the packages add --pull-updates (short: -u) to the command
If you use depends for your dependencies or if one exports/.. CLI commands you have to use one of two options:
- add
--script-file script.nu(short:-s script.nu) and activate it usingsource script.nu. - add
--overlay-file overlay.nu(short:-o overlay.nu) and activate it usingoverlay use overlay.nu.
base package refers to the numng.json you call the command on (your shell config, project config, etc) in contrast to the downloaded ones.
| key | type | description |
|---|---|---|
| name | string |
name of the package (REQUIRED in dependencies, linkins, etc) |
| linkin | record[string, package] |
symlink a package into this package (the key is [PATH_IN_PACKAGE:]PATH_HERE (similar to docker -v)) |
| source_type | string |
type of the source (only git is supported so far) (default: git) |
| source_uri | string |
from where does the package come (example: ssh://github.com/foo/bar, https://github.com/foo/bar, file:///home/user/my_package) |
| git_ref | string |
git reference (tag, commit, or branch) to use (default: main) |
| path_offset | string |
path of the package within the source (example: nu-scripts within https://github.com/amtoine/scripts) |
| depends | list[package or string] or package or string |
packages this package depends on |
| package_format | string |
format of the package (numng, nupm, or packer) (default: auto detect) |
| ignore_registry | boolean |
Usually package definitions get auto-expanded using registries, which could end up messing something up. This disables it for this package (not recursive). |
| version | semver |
Select a version (only applicable when using a registry) (example: ^1.2.1) (explanation below) |
numng package specific keys:
| key | type | description |
|---|---|---|
| nu_plugins | list[path] |
nu plugin files, which should get registered via plugin add |
| registry | list[package] or package |
(only in base package) packages containing a registry (registries require package_format) |
| nu_libs | record[string, path] |
directories and files, which should get linked into a $env.NU_LIB_DIRS (string is the target name) |
| shell_config | record[str, list[path] or path] |
things to load into the shell config. available keys: source, source_env, use, and use_all (use path *) |
| bin | dict[str, path] |
put a file into the path and make it executable (key is the name) |
| build_command | string |
build commands for the project (executed as nu -c $build_command in the package directory) (examples: cargo build --release, make, nu build_script.nu) |
semver (not 100% semver compatible):
- Up to 3 numbers separated by dots (
.). Example:1.0.0,1.2,3. - Missing parts mean
any/latest. Example:"depends": "mylib/1.2"could usemylib/1.2.3 - Prefixes can be used to be more precise:
^1.2.3means1.2.3or newer, but older than2.0.0~1.2.3means1.2.3or newer, but older than1.3.0<1.2.3means anything older than1.2.3>1.2.3means anything newer than1.2.3
latestis a special version. Used in a repository its newer than anything else. Used in a depends its short for>0[a-zA-Z]+versions are possible and only used if specifically requested by the user. example use-case:githead,experimental
(you can have multiple ones active as long as their naming schemes don't collide)
- numng-official (overview)
- size: over 700 packages (including over 450 themes).
- package-freshness: all packages have a
git-HEAD version available. The packages which do have versions get updated at least once per week. - snippet for adding:
{"source_uri": "carview.php?tsp=https://github.com/Jan9103/numng_repo", "package_format": "numng", "path_offset": "repo"} - package names:
[author-name]/[repo-name]if the repo contains only 1 package[author-name]/[repo-name]/[package-name]if the repo contains multiple packages
- package format:
numng/ mixed
- nupm-official
- size: over 20 packages.
- package-freshness: it only contains official package releases and is currently (2024-12-02) lagging multiple months behind resulting in every
nu_pluginpackage beeing broken, etc. - snippet for adding:
{"source_uri": "carview.php?tsp=https://github.com/nushell/nupm", "package_format": "nupm"} - package-names:
[package-name] - package format:
nupmonly
Any numng package can be a registry. You just have to register it as such.
The packages are defined by [PACKAGE_NAME].json files (with UNIX-style / directory separation).
These json files should contain a dictionary with a semver as key and a package definition
(same as in a numng.json) in its value.
It is also possible to set fallback values for all versions by creating a version called _.
A version-alias can be created by just putting the target version as string into the value of a version (example: "latest": "0.8").
I initially started it in rust, but I'm not confident in my rust skills
and ended up abandoning it for years at this point.
A non-rust compiled language wouldn't be a good fit for the community in my opinion.
Nu is a great language, but breaking changes, etc created a lot of issues for the
predecessor of this (example: you had to update packer before doing a system
update in case nu updated and broke the old packer version).
Python is already installed on most devices and can be read by almost every programmer.
- Its available in pythons standard library, which makes installation a lot easier.
nuonis pretty complex with its special datatype and the last time i tried to parse it i gave up.- I dislike like parts of the yaml spec.
marshal,pickle,hmac, andiniwould pose issues outside of python.
I don't want to deal with packaging python since its a annoying mess.
Also easier install, etc.