A quick and dirty personal package manager
- Lua 81.3%
- Go 14.1%
- C 3.8%
- Makefile 0.8%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
PR Checks / lint-and-test (pull_request) Successful in 5m2s
Closes #345, #346 |
||
| .forgejo/workflows | ||
| bin | ||
| lfs_pkgdefs | ||
| lib/qpkg | ||
| luapp | ||
| pkgdefs | ||
| src | ||
| templates | ||
| tests | ||
| .busted | ||
| .gitignore | ||
| .luacheckrc | ||
| .luacov | ||
| .pre-commit-config.yaml | ||
| DESIGN.md | ||
| golua.md | ||
| Makefile | ||
| packages.md | ||
| pkglist.txt | ||
| README.md | ||
| selene.toml | ||
| stylua.toml | ||
qpkg
qpkg is a source-based package manager that operates within a user's home
directory. It downloads, builds, and installs software from source into
hash-based install directories under ~/.thwap.d/pkgs/<os>/<arch>/, then
symlinks the installed files into a unified root at .../root/ using
lndir-style recursive directory mirroring.
Features
- Source-based — builds everything from source with SHA256 verification
- Isolated builds — each package builds in a temp directory, installed
into a hash-based install directory keyed by
os-arch-name-version - Unified root — installed files are symlinked into
.../root/via recursive lndir (directories created, files symlinked, subdirs handled) - Dependency resolution —
pkgdef_dependencieswith recursive install and automatic activation of dependencies so builds can find them via$rootdir/bin/,$rootdir/lib/, etc. - Binary packages —
-bflag creates/consumes.qpkgarchives from~/.thwap.d/qpkg/binpkgs/for fast reinstall - Phase/tagged builds —
pkg@tagsyntax for multi-phase builds (e.g.gcc-15.2.0@phase1,gcc-15.2.0@phase2) with$tagsubstitution in build commands - Meta packages —
srcuri = "meta"for dependency-only umbrella packages - pkgdef_output — prints
KEY=VALUEpairs to stdout for shell eval:eval "$(qpkg install go-1.26.4)" - Platform detection —
$platform,$arch,$rootdirsubstitution variables available in all build commands - Logging — all build output goes to
~/.thwap.d/qpkg/logs/; only status messages and errors go to stderr.--verbosefor full output. - Registry — tracks installed packages in
~/.thwap.d/qpkg/packages.luawith active version management andactivate/deactivatecommands - Additive relink —
relinkscans install directories and creates missing symlinks without touching existing ones. Safe for PROMPT_COMMAND: new files (e.g. pip-installed scripts) appear in.../root/bin/instantly without a full deactivate/activate cycle
Installation
git clone https://git.lan.thwap.org/thwap/qpkg.git
cd qpkg
mkdir -p ~/.thwap.d/qpkg
ln -s "$PWD/bin/qpkg" ~/.thwap.d/qpkg/bin/qpkg
export PATH="$HOME/.thwap.d/qpkg/bin:$PATH"
Commands
| Command | Description |
|---|---|
qpkg help |
Show help message |
qpkg version |
Show version |
qpkg add <pkg>[-<ver>][@tag] |
Build and install a package |
qpkg del <pkg> |
Remove an installed package |
qpkg search [query] |
Search available pkgdefs |
qpkg show <pkg>[-<ver>][@tag] |
Show pkgdef details and status |
qpkg profile [-a] |
Show active packages (all versions with -a) |
qpkg info <pkg>[-<ver>] |
Show detailed package information |
qpkg init |
Print shell integration snippet |
qpkg use <pkg>[-<ver>][@tag] |
Activate a version (symlink into root) |
qpkg drop <pkg>[-<ver>] |
Deactivate a version (remove symlinks) |
qpkg relink [<pkg>[-<ver>]] |
Relink missing symlinks for active package(s) |
Options
-r <path>— override pkgdef repository root--verbose, -v— show full build output on stderr-b— use binary packages (create on build, consume on install)
Usage
# Install a package
qpkg add lua-5.4.8
qpkg add -b gcc-15.2.0@phase1
# List/search
qpkg profile
qpkg search lua
qpkg show lua-5.4.8
# Activation management
qpkg profile
qpkg use gcc-15.2.0@phase2
qpkg drop python-3.13.14
# Relink (additive — skips already-present symlinks)
qpkg relink # relink all active packages
qpkg relink python # relink only python's active version
# Fast enough for $PROMPT_COMMAND usage (pure C, no shell forks):
# export PROMPT_COMMAND="$(qpkg relink)"
For package definition format and pkgdef development, see pkgdefs/README.md.
Directory Structure
~/.thwap.d/qpkg/
qpkg.conf -- user configuration (Lua)
packages.lua -- installed package registry
binpkgs/ -- binary package archives (*.qpkg)
logs/ -- build logs
tmp/ -- temporary build directories
pkgdefs/ -- package definition files
pkgs/
linux/
x86_64/
<hash>/ -- install dir for one package version
bin/ -- compiled binaries
lib/ -- shared libraries
include/ -- header files
.qpkg-meta -- package metadata
root/ -- unified symlink root
bin/ -- symlinks to installed binaries
lib/ -- symlinks to libraries
include/ -- symlinks to headers
Configuration
qpkg reads ~/.thwap.d/qpkg/qpkg.conf as a Lua file. Defaults:
qpkg_install_root = os.getenv("HOME") .. "/.thwap.d/pkgs"
qpkg_pkgdef_root = os.getenv("HOME") .. "/.thwap.d/qpkg/pkgdefs"
Development
lua bin/qpkg help # run from checkout
lua tests/test.lua # run tests
pre-commit run --all # lint + format