A single-file, dependency-light package manager and bundler written in pure C.
CAPP packages apps into .capp files — plain ZIP archives with an install script, an uninstall script, and a metadata manifest — and manages installing, updating, and removing them from a self-contained directory under your home folder. No system-wide installation, no root required, works wherever a C compiler and curl/zip (or PowerShell on Windows) are available — including Termux on Android.
- Single C file, no dependencies beyond stdlib — compiles with
gcc capp.c -o cappon Linux, macOS, Windows, or Android (Termux) .cappbundle format — a ZIP archive containinginstall.sh/install.bat,uninstall.sh/uninstall.bat, a requiredmetadata.json, and an optionalinstructions.*file- Script review before execution — every install/uninstall script is printed to the terminal for the user to review before running
- Executable-disguised-as-instructions detection — instructions files are scanned for ELF/Mach-O/PE magic bytes, shebangs, and script extensions, and rejected if they look like a hidden executable
- Mirror-based distribution — point
CAPP_MIRRORat any static file host (e.g. a GitHub repo served via raw URLs) servingpackages.txtandpackages.json; CAPP fetches, merges, and dedupes package indexes across multiple mirrors - Multi-package operations —
install,install-remote, anduninstall/removeall accept multiple package names or bundle files in a single command - Per-app metadata cache — installed package metadata and cached instructions live under
~/.capp/data/<AppName>/, independent of the stored bundle - Everything self-contained — all state lives under
~/.capp/; nothing touches system paths
Prebuilt static binaries are published on the Releases page for:
| Platform | Architectures |
|---|---|
| Linux | x86_64, x86, aarch64, arm |
| macOS | x86_64, aarch64 |
| Windows | x86_64, aarch64 |
Download the asset matching your platform (named capp-<os>-<arch>, e.g. capp-linux-x86_64), make it executable, and place it on your PATH:
chmod +x capp-linux-x86_64
mv capp-linux-x86_64 ~/.capp/bin/capp# Linux / macOS
gcc -o capp capp.c
# Windows
gcc -o capp.exe capp.cNo external libraries are linked — CAPP shells out to curl and zip/unzip (or PowerShell's Compress-Archive/Expand-Archive on Windows) at runtime, so make sure those are available on PATH.
After building, add ~/.capp/bin to your PATH (CAPP creates this directory on first install) so installed apps' launchers are reachable from anywhere:
# ~/.bashrc or equivalent
export PATH="$HOME/.capp/bin:$PATH"capp create — bundle a folder into a .capp file
capp install [-V] <App.capp> [App2.capp ...] — install one or more .capp bundles
capp install-remote [-V] [-v <ver>] <Name> [...] — install one or more packages from mirror
capp uninstall [-V] <AppName> [AppName2 ...] — uninstall one or more apps
capp remove [-V] <AppName> [AppName2 ...] — alias for uninstall
capp update [-V] — refresh package indexes from mirrors
capp upgrade [-V] [AppName] — upgrade one or all packages
capp list [-V] — list all available packages
capp list-installed [-V] — list all installed packages
capp search <query> — search available and installed packages
capp show <AppName> — show package metadata
capp man [-V] <AppName> — open instructions for a package
capp clear-cache — remove cached instructions files
Flags
-V,--verbose— show detailed progress output (most commands are quiet by default)-v <version>— (install-remoteonly) install a specific version instead of the latest
Environment variables
CAPP_MIRROR=https://...— override the default mirror URL. Defaults to a GitHub-raw mirror atdev-sudeep/CAPP-mirror.
# Create a bundle interactively
capp create
# Install a local bundle, with progress output
capp install -V MyApp.capp
# Install several apps from a mirror at once
capp install-remote textedit imageviewer notes
# Install a specific version
capp install-remote -v 2.1.0 textedit
# Remove multiple apps
capp remove textedit notes
# Check what's installed and what's available
capp list-installed
capp search editor
# Refresh indexes, then upgrade everything
capp update
capp upgradeA .capp file is a ZIP archive with this layout:
MyApp.capp
├── install.sh / install.bat (required)
├── uninstall.sh / uninstall.bat (required)
├── metadata.json (required — must include a "name" field)
└── instructions.* (optional — shown to the user after install)
metadata.json supports arbitrary extra fields (author, description, homepage, etc.) — anything beyond name and version is displayed automatically by capp show.
A mirror is just a static file host (commonly a GitHub repo accessed via raw URLs) serving two files at its root:
packages.txt— pipe-delimited lines:name|version|filename.capppackages.json— richer metadata per package (description, author, custom fields), keyed by name and version
Bundle files themselves are expected under a packages/ subdirectory on the mirror. Set CAPP_MIRROR to point at your own mirror to distribute private or custom packages:
export CAPP_MIRROR="https://raw.githubusercontent.com/yourname/your-mirror/main"
capp updateAll CAPP state lives under ~/.capp/:
~/.capp/
├── bin/ — installed app launchers (add to PATH)
├── bundles/
│ ├── installed.txt — list of installed app names
│ ├── available.txt — merged package index from all mirrors
│ ├── packages.json — merged rich metadata from all mirrors
│ └── <AppName>.capp — stored bundle for each installed app
└── data/
└── <AppName>/
├── metadata.json
└── instructions.*
- Install and uninstall scripts are always printed for review and require explicit
yconfirmation before running. - Instructions files are checked for executable signatures and refused if they appear to be disguised binaries or scripts.
- CAPP does not currently resolve dependencies between packages — bundles are expected to be self-contained. This is a deliberate scope decision: a package with a long dependency chain means a long chain of scripts to review, which works against the "review before you run" security model.
MIT