Package Manager
aux4 includes a built-in package manager (pkger) for installing, managing, and publishing packages from the aux4 hub. All package manager commands are accessed through aux4 aux4 pkger.
Requirements
The package manager is included with aux4. If you need to install or update it separately, install the aux4/pkger package:
1> aux4 aux4 pkger install aux4/pkgerInstallation Directory
Packages are installed to ~/.aux4.config/packages/. The package manager maintains a registry file at ~/.aux4.config/packages/all.json that tracks all installed packages, dependencies, and system dependencies.
After installation, packages are automatically available via the aux4 command — their commands are merged into the global environment via ~/.aux4.config/global.aux4.
Install
Install a package from the aux4 hub:
1> aux4 aux4 pkger install aux4/testInstall several packages at once:
1> aux4 aux4 pkger install aux4/test aux4/config aux4/adapterInstall a specific version:
1> aux4 aux4 pkger install aux4/test@0.2.18Install a semver range — the highest published version that satisfies it is installed. Quote the reference: ^, >, <, * and | are shell metacharacters.
1> aux4 aux4 pkger install 'aux4/config@^0.2.0'See Version Ranges for the full grammar and how a range behaves when the package is already installed.
Install from a local file:
1> aux4 aux4 pkger install --fromFile ./my-package_1.0.0.zipInstall from a private repository:
1> aux4 aux4 pkger install --repository my-org aux4/internal-toolForce a reinstall or downgrade with --force. This overrides the currently installed version regardless of dependencies, so you can reinstall a package or roll back to an older version without first uninstalling everything that depends on it:
1> aux4 aux4 pkger install aux4/test@0.2.18 --forceThe installer automatically:
- Resolves and installs dependencies
- Detects your platform (darwin/linux/windows, amd64/arm64) for multi-platform packages
- Installs system dependencies (e.g., Node.js via brew/apt/pkgx) if needed
- Signs executables on macOS with codesign
Version Ranges
A package reference is scope/name, optionally followed by @ and a version. That version can be an exact version, latest, or an npm-style semver range. Ranges work in both places a reference appears — on the install command line and in a package's dependencies — and always resolve to the highest published version that satisfies the range.
| Form | Example | Means |
|---|---|---|
| Caret | ^1.2.3 | >=1.2.3 <2.0.0 — the left-most non-zero segment is held, so ^0.2.3 is >=0.2.3 <0.3.0 and ^0.0.3 is >=0.0.3 <0.0.4 |
| Tilde | ~1.2.3 | >=1.2.3 <1.3.0; ~1.2 is >=1.2.0 <1.3.0; ~1 is >=1.0.0 <2.0.0 |
| Comparators | >=1.2.0 >1.2.0 <=2.0.0 <2.0.0 =1.2.3 !=1.2.3 | A partial version is allowed after a comparator: >=1.2 is >=1.2.0, >1.2 is >=1.3.0, <=1.2 is <1.3.0 |
| x-range | 1.x 1.2.x | 1.x is >=1.0.0 <2.0.0; 1.2.x is >=1.2.0 <1.3.0 |
| Any | * | Any published version |
| Hyphen | 1.2.3 - 2.0.0 | >=1.2.3 <=2.0.0; an incomplete upper bound covers the whole missing segment, so 1.2.3 - 2.3 is <2.4.0 |
| AND | >=0.1.0 <0.2.0 | A space between terms means both must hold |
| OR | ^0.1.0 || ^0.2.0 | || separates alternatives |
Prereleases are excluded from a range unless the range itself mentions one, so a published 2.1.0-beta.1 is never picked up by ^2.0.0.
A bare version is never a range — including a partial one. A reference is only treated as a range when it fails to parse as a complete semver version and carries range syntax (a leading ^ ~ > < =, a ||, a whitespace-delimited -, or an x/X/* segment). So 1.2.3 is exact, the prerelease 1.0.0-local is exact, latest still means latest, and a bare partial such as 0.2 is exact too — it asks for the literal version 0.2:
1> aux4 aux4 pkger install aux4/config@0.21Package aux4/config@0.2 not foundThis differs from npm, where 0.2 means 0.2.x. aux4 keeps it exact on purpose: every version already written in an existing .aux4 keeps meaning exactly what it meant before ranges existed. Write 0.2.x (or ~0.2) when you want the range.
Exact references and latest keep their fast path — they resolve without asking the hub for the version list, so only a real range costs an extra request.
Dependency Versions and Automatic Upgrades
Only one version of a package is installed at a time, so a dependency declared with a version has to be reconciled against what is already installed. What a reference means for that decision:
| Reference | Constraint |
|---|---|
| aux4/config | Unconstrained — accepts any installed version and never blocks an upgrade |
| aux4/config@latest | Unconstrained, same as above |
| aux4/config@0.2.10 | Exact pin — a constraint of exactly 0.2.10, so it caps the whole tree: while that package is installed, nothing can move the dependency off 0.2.10 |
| aux4/config@^0.2.0 | Range — any version it matches is acceptable |
When a newly installed package requires a version the installed dependency does not satisfy, the dependency is upgraded only with unanimous consent: to the highest published version that satisfies the new requirer and every package that already depends on it. The upgrade goes through the normal install path and is never silent:
1> aux4 aux4 pkger install tester/upgrade-b1Upgrading aux4/config 0.1.1 -> 0.2.10 (required by tester/upgrade-b@^0.2.0)
2Unzipping package aux4 config 0.2.10
3Loading package aux4 config 0.2.10
4Unzipping package tester upgrade-b 1.0.0
5Loading package tester upgrade-b 1.0.0
6Installed packages:
7 ✓ aux4/config 0.2.10
8 ✓ tester/upgrade-b 1.0.0If no published version satisfies everyone, the install fails and names the package that blocks it — usually an exact pin held by another dependent — along with the versions that are published:
1tester/upgrade-b requires aux4/config@^0.2.0, but aux4/config 0.1.1 is installed.
2Cannot upgrade: tester/upgrade-a requires aux4/config@0.1.1.
3Published versions: 0.2.10, 0.2.0, 0.1.1, 0.1.0A dependency is never downgraded automatically. If the only version everyone agrees on is older than the installed one, the install fails rather than breaking the dependent that works today:
1tester/old-pin requires aux4/config@~0.1.0, but aux4/config 0.2.10 is installed.
2Cannot upgrade: the highest version satisfying every dependent is 0.1.1, which is older than the installed 0.2.10. pkger never downgrades a dependency automatically.--force bypasses range enforcement entirely: the package is installed and the dependency is left at whatever version is already there.
Two exemptions keep local development working: an installed prerelease — a local build such as 0.2.10-local — is checked as its release version, so a range like ^0.2.0 accepts it and your local build is never silently upgraded over; and an installed version that is not semver at all is not comparable, so enforcement is skipped for it rather than guessed.
Uninstall
Remove an installed package:
1> aux4 aux4 pkger uninstall aux4/testRemove several packages at once:
1> aux4 aux4 pkger uninstall aux4/test aux4/configIf other packages depend on the package you're trying to uninstall, the command will fail with an error showing which packages still need it.
Use --force to remove it anyway. Force uninstall cascades: the package and every package that depends on it — directly or transitively — are removed together, so the package database is never left referencing a package that is gone:
1> aux4 aux4 pkger uninstall aux4/test --forceList
List all installed packages:
1> aux4 aux4 pkger list1 ✓ aux4/aux4 5.1.20
2 ✓ aux4/test 0.2.18
3 ✓ aux4/config 1.0.5Show dependencies:
1> aux4 aux4 pkger list --showDependencies true1 ✓ aux4/test 0.2.18
2 ↪ aux4/config 1.0.5Filter packages by name:
1> aux4 aux4 pkger list --filter configSearch
Search for packages on the aux4 hub:
1> aux4 aux4 pkger search databaseSearch in a specific repository:
1> aux4 aux4 pkger search --repository my-org internalDiscover Installed Commands
aux4 aux4 pkger search looks at the remote hub for packages you could install. find does the opposite: it searches what's already installed on your machine and resolves a query straight down to the command you need.
Search by what you want to do, not by package name — list --filter returns package names, and a package name is not a command.
1> aux4 aux4 pkger find "get a configuration value"1aux4 config set (aux4/config)
2If file is not provided it will look for a file named config.yaml, config.yml, or config.json in the current directory.
3
4aux4 config get (aux4/config)
5If file is not provided it will look for a file named config.yaml, config.yml, or config.json in the current directory.The first line of each result is the exact command to run, with its package beside it; the line below is a short description from its documentation.
Limit how many results come back:
1> aux4 aux4 pkger find "send an email" --limit 3It searches a local index built over every installed package's README.md and command man pages. You should never need to manage it: it is built the first time you search, and rebuilt automatically whenever your set of installed packages has changed. To force a rebuild:
1> aux4 aux4 pkger reindexThis used to be a separate aux4/pkger-finder package. It is now part of aux4/pkger, so no install step is needed. If you still have aux4/pkger-finder installed, you can uninstall it.
Build
Build a package into a distributable .zip file:
1> aux4 aux4 pkger build packageThis creates a .zip file in the current directory, named {scope}_{name}_{version}.zip.
Build only for the current platform (useful for testing multi-platform packages locally):
1> aux4 aux4 pkger build package --currentPlatform trueThe build process:
- Validates that .aux4, LICENSE, and README.md exist
- Detects man pages in man/ and test files in test/ and sets hasMan/hasExample flags
- For multi-platform packages (with dist/ directory), creates platform-specific zips plus a meta-package
- Excludes .DS_Store, .git, .gitignore, .npmignore, .idea, .vscode
Publish
Publish a package to the aux4 hub (requires authentication):
1> aux4 aux4 pkger publish aux4_mypackage_1.0.0.zipPublish to a specific repository:
1> aux4 aux4 pkger publish --repository my-org aux4_mypackage_1.0.0.zipMan
Display documentation for an installed package:
1> aux4 aux4 pkger man aux4/testOpen in browser:
1> aux4 aux4 pkger man aux4/test --browser trueOutput raw markdown:
1> aux4 aux4 pkger man aux4/test --markdown trueAuthentication
Login
Authenticate with the aux4 hub. This starts a device authorization flow — you'll be given a URL and code to enter in your browser:
1> aux4 aux4 login1Go to https://sso.aux4.io/device_code/verify and enter the code: ABCD-1234After authorization, your session is saved to ~/.aux4.config/credentials.
For CI/CD environments, don't log in interactively. Create a durable publishing token (a client id/secret pair) once on user.aux4.io → Scopes → your scope → Tokens → Create token (Publish to Hub), store the Client ID and Client Secret as secrets, then mint a fresh, short-lived hub token per run and expose it as AUX4_ACCESS_TOKEN:
1export AUX4_ACCESS_TOKEN=$(curl -sf -u "$AUX4_CLIENT_ID:$AUX4_CLIENT_SECRET" \
2 -d grant_type=client_credentials https://sso.aux4.io/token | jq -r '.access_token')A pasted access token expires and breaks CI; the client id/secret is durable, and you mint a new token each run. If you publish from GitHub Actions, aux4/action@v1 does this for you — see GitHub Actions.
Logout
Revoke your session and remove credentials:
1> aux4 aux4 logoutSystem Dependencies
Packages can declare system-level dependencies that are automatically installed when the package is installed. System dependencies are defined in the .aux4 metadata:
1{
2 "system": [
3 ["node --version", "brew:node", "apt:nodejs", "pkgx:node"]
4 ]
5}Each entry is an array where:
- The first element with prefix test: (or without a prefix) is a command to check if the dependency is already installed
- Remaining elements specify the package name for each supported package manager
Supported system package managers:
- brew — Homebrew (macOS/Linux)
- apt — APT (Debian/Ubuntu)
- dnf — DNF (Fedora/RHEL)
- yum — YUM (CentOS/RHEL)
- apk — APK (Alpine Linux)
- npm — Node.js packages
- pkgx — pkgx universal package manager
Package Metadata
The .aux4 file in a package root contains metadata about the package:
1{
2 "scope": "my-org",
3 "name": "my-package",
4 "version": "1.0.0",
5 "description": "A useful tool",
6 "license": "MIT",
7 "git": "https://github.com/my-org/my-package",
8 "tags": ["utility", "automation"],
9 "dependencies": ["aux4/config@1.0.0"],
10 "system": [],
11 "platforms": ["darwin", "linux"],
12 "profiles": [...]
13}Required fields: scope, name, version, license
Optional fields: description, git, tags, dependencies, system, platforms, distribution