Spec: Stamp (Intent Tracker)

Objective

Build a lightweight yet powerful wrapper for native package managers. Stamp lets developers install, search, get info, and remove packages and repositories across multiple package managers through a single CLI — tracking every intentional choice into a portable, version-controllable TOML manifest. The primary workflow is using stamp install as a unified wrapper to guarantee total traceability from day one. It also acts as a passive safety net, allowing developers to track changes retroactively via local snapshot diffing (stamp reconcile) if they bypass the tool. It fully supports tracking custom repositories (taps, remotes) across all supported package managers.

Tech Stack

Command Blueprint

The complete surface area of the CLI, including aliases and flags.

Global Flags:

Flag Standardization Rules

  1. Every flag SHOULD have a single-character short form (e.g. --manager, -m).
  2. Actions MUST be subcommands, not flags. (e.g. stamp man install, not stamp man --install).
  3. Boolean flags for enabling/disabling behavior are acceptable (e.g. --dry-run, --json).

Core Commands:

Command Aliases Flags Description
stamp     Prints welcome message suggesting stamp hello or stamp --help.
stamp setup hello   Runs first-time setup wizard: completions, man pages, init, doctor.
stamp init     Initializes manifest.toml and takes baseline snapshot.
stamp install <pkg> add --manager, -m <name>, --note, -n <text> Installs natively and records intent.
stamp remove <pkg> uninstall, rm, delete, del --manager, -m <name> Removes natively and untracks.
stamp reinstall <pkg>     Reinstalls natively and records intent. Works for both manifest-tracked and pre-existing packages.
stamp search <query>   --manager, -m <name> Searches across managers.
stamp info <pkg>   --manager, -m <name> Shows package information across managers, including raw outputs.
stamp reconcile   --dry-run, -d, --manager, -m <name> Detects drift since last snapshot and auto-tracks discovered packages and repositories.
stamp restore   --dry-run, -d, --manager, -m <name> Reinstalls repos and packages on a new machine.
stamp update upgrade --manager, -m <name>, --package, -p <pkg>, --serial, -s Runs system upgrades across all managers. Parallel by default. Use -s for serial, -p for single-package.
stamp list ls --json, -j, --manager, -m <name> Lists all intentionally installed packages.
stamp doctor   --json, -j, --manager, -m <name> Checks manager availability, manifest integrity, and UNIX compliance.
stamp self-update self-upgrade --check, -c Checks for and installs the latest version of stamp.
stamp completion [shell]   --stdout, -s Generates and installs shell completion scripts. Auto-detects shell if not specified.
stamp man     Command group for system reference page management.
stamp auto-reconcile on\|off   --period, -p hourly\|daily(default)\|weekly Installs or removes automated reconcile timer (systemd/launchd).

Man Subcommands:

Command Flags Description
stamp man   Shows help for stamp man command group. Same as stamp man help.
stamp man install --prefix <path> Installs man page to system or user path. Default: ~/.local/share/man/man1/.
stamp man check   Verifies installed man page version matches stamp version.

Repository Commands:

Command Aliases Flags Description
stamp repo add <name> [url] install --manager, -m <name> (Required) Adds custom repository and records it.
stamp repo remove <name> uninstall, rm, delete, del --manager, -m <name> (Required) Removes a repository and untracks it.
stamp repo list ls --json, -j, --manager, -m <name> Lists all tracked repositories.

Supported Package Managers

System Managers

Manager OS Notes
DNF / YUM Fedora/RHEL/CentOS DNF preferred, YUM fallback when DNF unavailable
APT / apt-get Debian/Ubuntu  
Paru Arch Linux Preferred when both Paru and Pacman are installed
Pacman Arch Linux Fallback when Paru not installed
Zypper openSUSE/SLES  
Snap Linux (universal)  
Flatpak Linux (sandboxed)  
Brew macOS, Linux User-space, no sudo for most operations
MacPorts macOS  

Language Toolchain Managers

Manager Scope Notes
go install Go binaries Full module paths required
pipx Python CLI tools  
uv Python CLI tools Faster alternative to pipx

Package Manager Resolution Engine

When a user runs a package or repository command (e.g., stamp install htop) without specifying --manager, the tool resolves ambiguity using a three-tier engine:

  1. Tier 1: Explicit Override: If --manager <name> or -m <name> is provided, stamp directly executes that manager’s command.

  2. Tier 2: User Preference (Declarative): If the package exists in multiple managers, stamp checks the user’s config.toml precedence list:
    precedence = ["dnf", "flatpak", "brew"]
    

    If a match is found, stamp automatically selects the manager with the highest configured precedence.

  3. Tier 3: Interactive Choice (Fallback): If no precedence is defined (or there’s a tie) and the process runs in an interactive terminal (TTY), stamp prompts the user to select the manager. In non-interactive environments (scripts/pipelines), the command fails with a clean error prompting the user to specify --manager.

Configuration

The stamp configuration is stored securely at ~/.config/stamp/config.toml. It allows users to define global precedence and regex-based routing rules.

TOML Schema:

# ~/.config/stamp/config.toml

# The global order of preference when a package exists in multiple managers.
# Checked from left to right.
precedence = ["dnf", "flatpak", "brew"]

# Pattern-based rules override the global precedence list.
# Useful for routing specific patterns (like reverse-DNS or development libs).
[[rules]]
pattern = "^com\\..*|^org\\..*" # Matches reverse-DNS App IDs
prefer = "flatpak"

[[rules]]
pattern = "^lib.*|-devel$"     # Matches libraries and dev headers
prefer = "dnf"

Precedence Matching Logic:

  1. Rule Match: The resolution engine iterates through the [[rules]] slice. If the package name matches a defined regular expression pattern, the engine immediately selects the associated prefer manager.
  2. Global Precedence: If no pattern rules match, the engine scans the global precedence array from left to right. The first manager in the list that reports the package as “available” is selected.
  3. Tie-Breaker: If the package is not found in the precedence list (or the list is empty), the engine falls back to prompting the user (in an interactive TTY) or failing cleanly (in scripts).

Commands Specs

Detailed specifications, execution behaviors, and business rules for every subcommand.

stamp (root)

stamp setup (alias hello) — Setup Wizard (C1)

stamp init

stamp install <pkg> (alias add)

stamp remove <pkg> (aliases uninstall, rm, delete, del)

stamp reinstall <pkg> (C4)

stamp search <query>

stamp info <pkg> (C2)

stamp reconcile

stamp restore

stamp doctor

stamp update (alias upgrade)

stamp self-update (alias self-upgrade)

stamp completion [shell]

stamp man

stamp repo


Data Model

The TOML manifest supports notes for user context and a repositories block.

[[repositories]]
name = "flathub"
manager = "flatpak"
url = "https://dl.flathub.org/repo/flathub.flatpakrepo"

[[packages]]
name = "lazygit"
manager = "brew"
notes = "better git TUI than default"

Project Structure

stamp/
├── cmd/stamp/         → Main application entrypoint
├── internal/
│   ├── cli/           → Cobra commands (init, reconcile, restore, install, etc.)
│   ├── manager/       → Package manager adapters (dnf/yum, brew, flatpak)
│   ├── state/         → Local JSON snapshotting and delta calculation
│   ├── manifest/      → TOML parsing and writing
│   └── config/        → XDG path resolution and user config
├── tools/docgen/      → Build-time doc generation tool
├── docs/              → ADRs, specifications, generated docs
└── README.md

Code Style

Idiomatic Go with strict error wrapping and interface-driven design for testability.

Testing Strategy

Go Adapter

The Go adapter supports go install <path>@latest for installing end-user CLI tools. It follows the pipx model — installing user-facing tools, not project dependencies.

Package Names

ListInstalled (Name-space Contract)

Search / Doctor / Repos

Update

GOBIN / GOPATH Resolution

Pipx Adapter

The Pipx adapter supports pipx install for CLI tools from the Python ecosystem.

Package Names

ListInstalled

Search / Doctor / Repos

Update

Uv Adapter

The Uv adapter supports uv tool install for CLI tools from the Python ecosystem.

Package Names

ListInstalled

Search / Doctor / Repos

Update

Boundaries

Edge Cases

Reinstall Gap

Scenario: A package is removed and reinstalled between two stamp reconcile runs. Snapshot diffing sees no net change and reports no drift. This edge case only applies when the user bypasses stamp and uses native package manager commands (dnf, brew, flatpak) directly, then relies on reconcile as a safety net.

Root Cause: Snapshot diffing is a point-in-time comparison between two snapshots. If the removed package is reinstalled before the next reconcile, the baseline and current snapshots are identical. Stamp has no event monitoring — it cannot observe intermediate states.

Mitigation:

UNIX Compliance & Documentation Strategy

To be a “good UNIX citizen”, stamp must adhere to:

Success Criteria

  1. Init: Running stamp init creates the correct XDG directories and an empty manifest.toml, and takes baseline snapshots for each available manager.
  2. Reconcile (No Drift): If system state matches the last snapshot, reconcile exits cleanly with "No drift detected".
  3. Reconcile (Drift): If flatpak install com.spotify.Client is run externally, stamp reconcile detects this one new package and auto-tracks it to manifest.toml without prompting.
  4. Reconcile (Dry Run): stamp reconcile --dry-run shows all discovered drift but does NOT save manifest or snapshots.
  5. Reconcile (Pre-existing): Packages installed before stamp init are never detected by stamp reconcile. To track them, use stamp reinstall <pkg>.
  6. Reinstall (Manifest-tracked): stamp reinstall htop reinstalls a manifest-tracked package using its recorded manager.
  7. Reinstall (Pre-existing): stamp reinstall htop installs a pre-existing package not in the manifest, resolves its manager, runs native reinstall, and records it in the manifest.
  8. Restore: Running stamp restore successfully adds repositories before executing the respective package manager install commands concurrently.
  9. Notes: A user can pass --note "reason" to stamp install or stamp edit, which will be correctly saved in the TOML manifest.
  10. Doctor: stamp doctor reports manager status, manifest health, and UNIX compliance in both TTY and JSON.
  11. Man Pages: stamp man displays help; stamp man install installs man pages; stamp man check verifies version matches binary.
  12. Completions: stamp completion bash|zsh|fish|powershell generates valid shell completion scripts.
  13. Info: stamp info htop -m dnf prints raw dnf info metadata directly.
  14. Install: stamp install htop installs the package natively via the resolved manager and records it in manifest.toml.
  15. Remove: stamp remove htop removes the package natively and removes it from the manifest.
  16. Search: stamp search ripgrep returns matching packages from all available managers.
  17. Repo Add: stamp repo add myrepo -m brew adds the repository via the specified manager and records it.
  18. Repo Remove: stamp repo remove myrepo -m brew removes the repository and untracks it.
  19. Repo List: stamp repo list prints all tracked repositories; --json outputs machine-readable.
  20. Setup: stamp setup runs the setup wizard with completion, man pages, init, and doctor. stamp hello works as an alias.
  21. Completion: stamp completion bash|zsh|fish|powershell generates valid shell completion scripts for each shell.
  22. Reconcile (Repo Drift): If a new flatpak remote or brew tap is added externally, stamp reconcile detects and auto-tracks the repository alongside packages.
  23. Reconcile (Manager Scope): stamp reconcile -m dnf scopes drift detection to a single manager only.
  24. Reinstall (Manager Flag): stamp reinstall htop -m brew overrides manager resolution via the --manager flag for pre-existing packages.
  25. Reinstall (Adapters): adapter.Reinstall() executes the native reinstall command for each manager (brew reinstall, dnf reinstall, flatpak install).
  26. Reconcile (Snapshot Save on No Drift): If reconcile detects no drift, the current snapshot is saved to disk so future package removals are tracked correctly.
  27. Update: stamp update runs native upgrade commands for all available managers concurrently. Errors from one manager don’t block others. --manager flag scopes to a single manager. Non-zero exit if any manager fails.
  28. Auto-Reconcile: stamp auto-reconcile on --period daily installs a systemd or launchd timer to run stamp reconcile automatically at the configured interval.