One manager to manage them all - unified CLI for brew, cargo, uv, go, and more
Project description
onepkg
One manifest to rule them all.
A unified CLI that manages packages across Homebrew, Cargo, uv, Go, Bun, and more — all from a single YAML file.
Why onepkg?
Setting up a new machine means running brew install, cargo install, go install, uv tool install, and more — each with their own syntax and state. onepkg consolidates everything into one manifest:
general:
brew:
- ripgrep
- fzf
python:
- ruff
- pyright
rust:
- bat
- eza
go:
- github.com/jesseduffield/lazygit
Then sync everywhere with one command:
onepkg sync
Features
- Single manifest — Track all packages in
~/.config/packages.yaml - 10 package managers — brew, cask, mas, conda, python, rust, go, bun, winget, custom
- Cross-platform — macOS, Linux, and WSL support with platform-specific sections
- Smart syncing — Only installs what's missing, skips what's already there
- Lock file support — Pin exact versions for reproducible deployments
- Diff & export — Compare manifest vs system, export installed packages
- Diagnostics — Built-in doctor, outdated, and clean commands
- Fallback syntax — Define preferred managers with automatic fallbacks (
tmux:brew) - Custom packages — Shell script-based installs for anything else
- Shell completions — Tab completion for bash, zsh, and fish
- Beautiful output — Rich terminal UI with progress and status
Supported Package Managers
| Type | Tool | Platform | Description |
|---|---|---|---|
brew |
Homebrew | macOS | CLI tools and formulae |
cask |
Homebrew Cask | macOS | GUI applications |
mas |
Mac App Store | macOS | App Store apps (by ID) |
conda |
micromamba | All | Conda packages |
python |
uv | All | Python CLI tools |
rust |
cargo | All | Rust binaries |
go |
go install | All | Go binaries |
bun |
bun | All | JavaScript/TypeScript tools |
winget |
winget.exe | WSL | Windows packages from WSL |
custom |
shell scripts | All | Custom installation scripts |
Installation
# Using uv (recommended)
uv tool install onepkg
# Or from source
git clone https://github.com/JiwanChung/pkgmanager
cd onepkg
uv tool install .
Shell Completions
# Bash
onepkg completions bash >> ~/.bashrc
# Zsh
onepkg completions zsh >> ~/.zshrc
# Fish
onepkg completions fish > ~/.config/fish/completions/onepkg.fish
Quick Start
1. Create a manifest
mkdir -p ~/.config
cat > ~/.config/packages.yaml << 'EOF'
general:
python:
- ruff
- black
rust:
- bat
- eza
go:
- github.com/jesseduffield/lazygit
EOF
2. Sync packages
onepkg sync
3. Add more packages
onepkg install brew ripgrep
onepkg install python poetry
onepkg install go github.com/charmbracelet/glow
Commands
Core Commands
| Command | Description |
|---|---|
sync / init |
Install all packages from manifest |
install <type> <name> |
Install a package and add to manifest |
remove <name> |
Remove a package and update manifest |
update [name] |
Update packages (all or specific) |
list |
List tracked packages by category |
lock |
Create lock file with exact versions |
Inspection Commands
| Command | Description |
|---|---|
diff |
Show differences between manifest and system |
status |
Show package manager availability |
show <name> |
Display detailed package info |
search <query> |
Search for packages across managers |
outdated |
Show packages with available updates |
Maintenance Commands
| Command | Description |
|---|---|
doctor |
Diagnose issues with setup |
clean |
Remove untracked packages |
export |
Export installed packages to YAML |
bootstrap |
Install package managers themselves |
edit |
Open manifest in editor |
completions |
Generate shell completions |
Usage Examples
Sync from manifest
onepkg sync # Install all packages
onepkg sync --types brew,rust # Install specific types only
onepkg sync --dry-run # Preview what would be installed
onepkg sync --quiet # Suppress non-essential output
onepkg sync --locked # Install exact versions from lock file
Lock versions
onepkg lock # Create packages.lock.yaml
onepkg lock --types python # Lock only specific types
onepkg lock -o deploy.lock.yaml # Custom output file
# Then install with locked versions on another machine:
onepkg sync --locked
Install packages
onepkg install brew ripgrep # Homebrew formula
onepkg install cask raycast # Homebrew cask (GUI app)
onepkg install mas 937984704 # Mac App Store (by ID)
onepkg install python ruff # Python tool via uv
onepkg install rust miniserve # Rust binary via cargo
onepkg install go github.com/junegunn/fzf # Go binary
onepkg install bun typescript # Bun global package
onepkg install custom fisher # Custom script package
Check differences
onepkg diff # Show manifest vs installed
# Output:
# brew
# + ripgrep (not installed)
# - unused-tool (untracked)
Export current setup
onepkg export > packages.yaml # Export all to YAML
onepkg export --types brew # Export only brew packages
onepkg export --format list # Simple list format
Diagnose issues
onepkg doctor
# Output:
# ✓ Manifest file exists
# ✓ brew: brew is available
# ✓ python: uv is available
# ! rust: 2 packages not installed
# ✗ go: go not found but manifest has 3 packages
Clean up untracked packages
onepkg clean --dry-run # Preview what would be removed
onepkg clean --types python # Clean only python packages
Check for updates
onepkg outdated # Show all outdated packages
onepkg outdated --types brew # Check only brew
Manifest Format
The manifest lives at ~/.config/packages.yaml (override with $PACKAGE_CONFIG):
# macOS-specific packages
mac:
brew:
- ripgrep
- fzf
- jq
cask:
- raycast
- ghostty
mas:
- '937984704' # Amphetamine
# Cross-platform packages
general:
conda:
- python
- nodejs
python:
- ruff
- pyright
- poetry
rust:
- bat
- eza
- miniserve
go:
- github.com/jesseduffield/lazygit
- github.com/charmbracelet/glow
bun:
- typescript
- prettier
# WSL-specific packages (Windows from Linux)
wsl:
winget:
- Microsoft.PowerToys
# Custom script-based packages
custom:
- fisher
- my-custom-tool
Platform-specific packages
Restrict packages to specific platforms:
general:
python:
- ruff
- { name: "linux-only-tool", platform: "linux" }
- { name: "mac-only-tool", platform: "darwin" }
Fallback syntax
Prefer one manager but fall back to another:
general:
conda:
- python
- tmux:brew # Use brew on macOS, conda elsewhere
Custom Packages
Define custom packages in a specs.yaml bundled with onepkg:
fisher:
description: Fish plugin manager
shell: fish
check: type -q fisher
install: curl -sL https://git.io/fisher | source && fisher install jorgebucaran/fisher
remove: fisher self-uninstall
my-tool:
check: command -v my-tool
install: |
curl -L https://example.com/install.sh | bash
depends:
- curl
Command-Line Flags
Global flags
| Flag | Description |
|---|---|
--env, -e |
Path to manifest file |
--dry-run, -n |
Preview without executing |
--help, -h |
Show help |
Install/Sync flags
| Flag | Description |
|---|---|
--types, -t |
Filter by package types |
--quiet, -q |
Suppress non-essential output |
--force, -f |
Force reinstall |
--continue-on-error, -c |
Continue if a package fails |
--locked |
Install exact versions from lock file |
--lock-file |
Path to lock file (default: packages.lock.yaml) |
Environment Variables
| Variable | Description | Default |
|---|---|---|
PACKAGE_CONFIG |
Path to manifest file | ~/.config/packages.yaml |
EDITOR |
Editor for onepkg edit |
vim |
Development
# Clone and install with dev dependencies
git clone https://github.com/JiwanChung/pkgmanager
cd onepkg
uv pip install -e ".[dev]"
# Run tests
uv run pytest tests/ -v
# Check types
uv run mypy onepkg/
Project Structure
onepkg/
├── cli.py # CLI commands (1,279 lines)
├── managers.py # Package manager implementations (1,129 lines)
├── manifest.py # Manifest handling (344 lines)
├── models.py # Data classes (57 lines)
├── utils.py # Utilities (100 lines)
└── specs.yaml # Custom package specs
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file onepkg-0.6.0.tar.gz.
File metadata
- Download URL: onepkg-0.6.0.tar.gz
- Upload date:
- Size: 31.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b5de82f6f1d1fb42fba4ea5aec7e25b9c741314bd792a3a466d30f7060bb9380
|
|
| MD5 |
6d10f6a3212ab2050b267e1ffe18be77
|
|
| BLAKE2b-256 |
af737e664d833173d059ef6c458927ae8130643c6b2422e8d4d3f5c5f0eae2f0
|
File details
Details for the file onepkg-0.6.0-py3-none-any.whl.
File metadata
- Download URL: onepkg-0.6.0-py3-none-any.whl
- Upload date:
- Size: 26.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0d085d3c9fd82d6e2e1515b2b0094c58e9a062ea82424a07df25a8d4fe235b3a
|
|
| MD5 |
9126318b5986c6195c66f3dc79fd718d
|
|
| BLAKE2b-256 |
20a42e94a3392aa30a51faeb912fa17a70087dc39c8fb95dd650c5232a773091
|