Sps2
atomic package manager for macos
Install / Use
/learn @alexykn/Sps2README
sps2
A modern, atomic package manager for macOS ARM64 with rollback capabilities and hermetic builds.
Early Development Notice
This project is in the early stages of development. It is not yet recommended for production use. The API, package format, and internal architecture are still subject to change. There is no public package repository yet.
Current Status
- ✅ Working:
install,uninstall,rollback,history,cleanup,list,vulndb update,check-health - 🚧 In Progress:
draftandbuild(functional but incomplete) - ⚠️ Untested:
update,upgrade,info,search,reposync,audit,self-update
Features
- 🔄 Atomic Updates - All package operations are atomic with instant rollback
- 📦 Content-Addressed Storage - Deduplication via dual-hash system (BLAKE3 + xxHash)
- 🏗️ Hermetic Builds - Reproducible builds in isolated environments
- 🔐 Security First - Minisign signatures, SBOM generation, CVE scanning
- 🚀 Fast & Parallel - Concurrent downloads and installations
- 🎯 Single Prefix - Clean design with everything in
/opt/pm/live/ - 🐍 Python-Style Versions - Familiar version constraints (
>=1.2.0,<2.0.0) - 📝 YAML Recipes - Declarative, staged build definitions
Installation
Prerequisites
- macOS with Apple Silicon
- Rust 1.90.0 or later
- SQLite 3.x
- sudo access for
/opt/pmdirectory
Build from Source
# Clone the repository
git clone https://github.com/yourusername/sps2.git
cd sps2
# Build the project
cargo build --release
# Run setup script (requires sudo)
sudo ./setup.sh
# Add to PATH in your shell config
echo 'export PATH="/opt/pm/live/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
# Verify installation
sps2 --version
Quick Start
Installing Packages
Some working .sp packages in the test_build/ dir. Layout is messy, will eventually clean that up.
# Install from repository (when available)
sps2 install jq
# Install specific version
sps2 install "jq==1.7"
# Install with version constraints
sps2 install "curl>=8.0.0,<9.0.0"
# Install from local .sp file
sps2 install ./package-1.0.0-1.arm64.sp
# Build and install
sps2 build my-package.yml
# Build without installing
sps2 build my-package.yml -o ./packages/
Generating Build Recipes
Use the draft command to automatically generate recipes:
# From a Git repository
sps2 draft -g "https://github.com/BurntSushi/ripgrep"
# From a source archive URL
sps2 draft -u "https://example.com/package-1.0.tar.gz"
# From a local directory
sps2 draft -p ./my-project
# From a local archive
sps2 draft -a ./my-archive.tar.gz
# Specify output file
sps2 draft -g "https://github.com/helix-editor/helix" -o helix.yml
Building Packages
Example recipe for ripgrep (generated by draft):
metadata:
name: ripgrep
version: "14.1.1"
description: "Line-oriented search tool that recursively searches for regex patterns"
license: "MIT"
homepage: "https://github.com/BurntSushi/ripgrep"
environment:
network: true # Cargo needs network for dependencies
source:
git:
url: "https://github.com/BurntSushi/ripgrep"
ref: "14.1.1"
build:
system: cargo
args: ["--release"]
Build with various options:
# Basic build
sps2 build ripgrep.yml
# Build with custom output directory
sps2 build ripgrep.yml -o ./packages/
# Build with maximum compression
sps2 build ripgrep.yml --max
# Build with custom job count
sps2 build ripgrep.yml -j 8
Packaging from Directory
The pack command allows you to create packages from an already-built staging directory, skipping the build process:
# Package from a built directory with manifest
sps2 pack --directory ./build-output --manifest manifest.toml
# Package from a recipe without rebuilding (if already built)
sps2 pack --recipe myapp.yml --no-post
# Include SBOM in the package
sps2 pack --directory ./build-output --manifest manifest.toml --sbom sbom.json
# Custom output directory
sps2 pack --recipe myapp.yml -o ./packages/
Managing Packages
# List installed packages
sps2 list
# Example output:
# ┌─────────┬─────────┬───────────┬─────────────┐
# │ Package ┆ Version ┆ Status ┆ Description │
# ╞═════════╪═════════╪═══════════╪═════════════╡
# │ bat ┆ 0.25.0 ┆ Installed ┆ - │
# ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤
# │ helix ┆ 25.1.1 ┆ Installed ┆ - │
# ├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤
# │ ripgrep ┆ 14.1.1 ┆ Installed ┆ - │
# └─────────┴─────────┴───────────┴─────────────┘
# Show package info
sps2 info jq
# Search for packages
sps2 search rust
# Update packages (respects version constraints)
sps2 update
# Upgrade to latest versions
sps2 upgrade curl
# Uninstall packages
sps2 uninstall jq
State Management
# View recent state history (filtered by retention policy)
sps2 history
# Show all states (no availability filtering)
sps2 history --all
# Verify CAS availability for states (caps by config: state.history_verify_limit)
sps2 history --verify
# Override per-run verify limit
sps2 history --verify --limit 50
Cleanup Storage (CAS)
# Preview cleanup actions without deleting anything
sps2 cleanup --dry-run
# Perform cleanup based on policy (see config)
sps2 cleanup
Verification & Repair
# Verify current system; levels: quick, standard, full; scopes: live, store, all
sps2 verify --level standard --scope live
# Verify and attempt to heal discrepancies
sps2 verify --heal
# After a successful verify/heal, sync DB refcounts from the active state (one-off)
sps2 verify --sync-refcounts
# Example output:
# ┌────────────────────────┬─────────┬───────────┬──────────────────┬──────────┐
# │ State ID ┆ Current ┆ Operation ┆ Created ┆ Packages │
# ╞════════════════════════╪═════════╪═══════════╪══════════════════╪══════════╡
# │ 48b6f85f-78bb-4dc5-... ┆ * ┆ install ┆ 2025-06-13 16:12 ┆ 4 │
# ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
# │ a7be49ca-a976-4f75-... ┆ ┆ install ┆ 2025-06-13 16:11 ┆ 3 │
# └────────────────────────┴─────────┴───────────┴──────────────────┴──────────┘
# Rollback to previous state
sps2 rollback
# Rollback to specific state
sps2 rollback 48b6f85f-78bb-4dc5-9487-a8a60e97423b
# Clean up orphaned packages and old states
sps2 cleanup
# Check system health
sps2 check-health
Security Features
# Update vulnerability database
sps2 vulndb update
# Show vulnerability database statistics
sps2 vulndb stats
# Audit installed packages for vulnerabilities
sps2 audit
# Audit specific package
sps2 audit --package curl
# Fail on critical vulnerabilities
sps2 audit --fail-on-critical
Repository Management
# Sync repository index
sps2 reposync
# Update sps2 itself
sps2 self-update
How It Works
sps2 uses an innovative atomic update system:
- Content-Addressed Store - All package files are stored by their BLAKE3 hash
- State Directories - Each system state is a complete filesystem tree
- Atomic Swaps - Updates use APFS clones and atomic renames
- Instant Rollback - Previous states are preserved and can be restored instantly
Directory Structure
/opt/pm/
├── live/ # Current active state (add /opt/pm/live/bin to PATH)
├── store/ # Content-addressed package storage
├── states/ # Historical states for rollback
└── state.sqlite # Package database
Building Your Own Packages
sps2 uses YAML format for package recipes with declarative, staged build definitions. See Build Script Documentation
Example: Rust Application (Helix Editor)
metadata:
name: helix
version: "25.1.1"
description: "A post-modern modal text editor"
license: "MIT"
homepage: "https://github.com/helix-editor/helix"
environment:
network: true # Cargo needs network access
source:
git:
url: "https://github.com/helix-editor/helix"
ref: "25.1.1"
build:
system: cargo
args: ["--release"]
Example: Meson Project (pkgconf)
metadata:
name: pkgconf
version: "2.4.3"
description: "A system for managing library compile/link flags"
license: "ISC"
homepage: "https://github.com/pkgconf/pkgconf"
source:
git:
url: "https://github.com/pkgconf/pkgconf"
ref: "pkgconf-2.4.3"
build:
system: meson
args: ["--buildtype=release"]
Example: Building from Source Archive
# sps2 build recipe for curl
#
# This recipe builds curl from source archive.
# It enables support for OpenSSL, zlib, and nghttp2 (for HTTP/2).
metadata:
name: curl
version: "8.14.1"
description: "Command-line tool for transferring data with URLs"
license: "MIT"
homepage: "https://curl.se"
dependencies:
runtime:
- openssl
- zlib
- nghttp2
- brotli
- libssh2
- libidn2
- libpsl
environment:
defaults: true # Optimized flags for macOS ARM64
source:
fetch:
url: "https://github.com/curl/curl/releases/download/curl-8_14_1/curl-8.14.1.tar.bz2"
checksum:
sha256: "2893f7b7614192c2a4d8289f3d0009798a7c5f5d895011b5e4c0cf910c4a8b1e"
build:
system: cmake
args:
- "-DCMAKE_BUILD_TYPE=Release"
- "-GNinja"
- "-DBUILD_SHARED_LIBS=ON"
- "-DBUILD_STATIC_LIBS=OFF"
- "-DCURL_USE_OPENSSL=ON"
- "-DCURL_ZLIB=ON"
- "-DUSE_NGHTTP2=ON"
- "-DENABLE_IPV6=ON"
- "-DCURL_USE_LIBSSH2=ON"
- "-DUSE_LIBIDN2=ON"
- "-DCURL_BROTLI=ON"
- "-DCURL_USE_LIBPSL=ON"
- "-DBUILD_TESTING=OFF"
- "-DENABLE_CURL_MANUAL=OFF"
post:
patch_rpaths:
style: homebrew # curl needs absolute paths
install:
auto: true
Developer Tools
Store List (sls) - Debugging Content-Addressed Storage
The sls utility is a specialized debugging tool for exploring sps2's cont
Related Skills
himalaya
343.3kCLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language).
node-connect
343.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
92.1kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
coding-agent
343.3kDelegate coding tasks to Codex, Claude Code, or Pi agents via background process
