A tier-aware package manager for Arch Linux — pacman with a safety net, written in Rust.
Arch Linux is fast, current, and beautifully simple. But rolling releases treat every package the same — when an update is available, it gets installed. Your kernel and core libraries update automatically alongside a trivial icon theme. One bad kernel update and your machine doesn't boot.
There is no safety net. One bad sync and you're in single-user mode at 2 AM.
nog exists to change that.
nog is a thin, readable Rust wrapper around pacman that adds a single idea: not all packages deserve equal urgency. Every package on your system belongs to one of three tiers, and each tier has its own update rules. The kernel, bootloader, and glibc sit behind a longer hold window. Your desktop environment gets a shorter one. Everything else flows through quickly.
We believe managing your system should be:
- Safe — critical packages are never updated without a community-tested buffer
- Transparent — nog is a pacman wrapper, not a replacement; no magic, no surprises
- Familiar — if you know pacman, you know nog; same commands, same flags, same mental model
- Readable — the whole source is a few hundred lines of Rust, deliberately simple
nog was born from a simple frustration: why does Arch give you everything except control over which updates reach you and when? It doesn't have to be that way.
- 🎚 Three-tier package classification — every package is Tier 1, Tier 2, or Tier 3
- 🕒 Date-based hold windows — 30 / 15 / 7 day holds let community testing surface regressions before updates land on your machine
- 🔒 Tier 1 protection — kernel, bootloader, glibc, systemd, mesa held for 30 days by default; expert mode swaps to manual-only promotion
- 📦 Status-grouped update output — every
nog updategroups pending upgrades into Ready / Held / Unknown with Catppuccin Mocha tier colors - 🧩 AUR helper integration — auto-detects
yayorparu; AUR pending upgrades are classified, date-evaluated (via the helper's cached metadata), and bucketed alongside official repo packages; transactions are handed off to the helper for combined-Syu - ❓ Interactive Unknown handling — packages with no resolvable build date (locally-built, disabled-repo, or AUR query failure) are prompted case-by-case
- 🧑 No-sudo rule — run
nogas your user; it escalates to root only viasudo pacmanandsudo tee /etc/nog/tier-pins.toml. See Privilege model below. - ⚡ Tier 3 fast track — everything else flows through pacman on a short hold
- 🎨 Color-coded search — every
nog searchresult tagged with its tier - 📌 Persistent tier pinning —
nog pin <pkg> --tier=<N>writes to/etc/nog/tier-pins.toml - 🔓 Promote escape hatch —
nog unlock <pkg> --promoteforce-upgrades a held Tier 1 package now - 🛡 Pacman-native — uses
pacman --ignorefor holds, no patching or shadowing - 📖 Man page included —
man nogfor full reference
Every package nog manages falls into one of three tiers. Tier assignments live in /etc/nog/tier-pins.toml and can be adjusted at any time with nog pin. Hold durations live in /etc/nog/nog.conf.
The most critical packages on your system. Updates are held for 30 days after upstream publish date — a full month of community testing before an update reaches your machine. Once the hold expires, the update flows through nog update like any other package.
Default Tier 1 packages:
linux, linux-zen, linux-lts, linux-hardened, systemd, systemd-libs, glibc, grub, efibootmgr, mkinitcpio, pacman, mesa
Expert mode. Set
manual_signoff = trueunder[tier1]intier-pins.tomlto switch Tier 1 off the auto-release and require explicitnog unlock <pkg> --promotefor every kernel/glibc/systemd update. Recommended only if you want to personally eyeball every critical upgrade.
Key desktop applications and system services. Updates are held for 15 days — enough time for major regressions to surface, not so long that you fall behind.
Default Tier 2 packages:
plasma-meta, plasma-desktop, sddm, pipewire, pipewire-pulse, wireplumber, networkmanager, firefox, dolphin, konsole, kate, grubforge, alacritty, fish, alacrittyforge
Everything else. Updates are held for 7 days — a short safety buffer without meaningful delay.
- Arch Linux (or Arch-based distribution)
pacmanandpacman-contribyayorparu— optional; enables AUR support. nog functions without one; official repos only.- Rust toolchain (only for building from source)
nog is available on the Arch User Repository: https://aur.archlinux.org/packages/nog
yay -S noggit clone https://github.com/jetomev/nog.git
cd nog
cargo build --release
sudo install -Dm755 target/release/nog /usr/bin/nog
sudo install -Dm644 config/nog.conf /etc/nog/nog.conf
sudo install -Dm644 config/tier-pins.toml /etc/nog/tier-pins.toml
sudo install -Dm644 nog.1 /usr/share/man/man1/nog.1| File | Location | Description |
|---|---|---|
nog binary |
/usr/bin/nog |
The nog executable |
nog.conf |
/etc/nog/nog.conf |
Main configuration file |
tier-pins.toml |
/etc/nog/tier-pins.toml |
Tier 1/2/3 package assignments |
nog.1 |
/usr/share/man/man1/nog.1 |
Man page |
Run
nogas your regular user. nog escalates viasudoonly where genuinely required; you'll see the prompt at that moment. See Privilege model.
# Install a package (respects tier rules, routes to AUR helper if needed)
nog install <package>
# Update the system (tier holds applied; AUR included when a helper is configured)
nog update
# Search with tier annotations
nog search <query>
# Pin a package to a specific tier
nog pin <package> --tier=<1|2|3>
# Force-upgrade a held Tier 1 package
nog unlock <package> --promote
# Remove a package
nog remove <package>
# Version
nog --version
# Help
nog --helpWhen you run nog update, nog:
- Calls
checkupdates(pacman-contrib) to get the list of pending official repo upgrades — no sync-DB side effects - If an AUR helper is configured, calls
<helper> -Quato append pending AUR upgrades to the same list - Loads build dates: first from every enabled pacman sync DB, then (for AUR packages not found in any sync DB) from the helper's cached metadata via
<helper> -Sai - Classifies each pending package and evaluates its hold window against the combined build-date map
- Groups the result into three buckets:
- Ready to install — hold expired, safe to upgrade
- Held — either still inside the hold window, or Tier 1 under
manual_signoff = true - Unknown — no resolvable build date (locally-built, disabled-repo, or helper lookup failed)
- For each Unknown package, prompts
update anyway? [y/N] - Hands off the transaction:
- With helper:
<helper> -Syu --ignore=<held + skipped-unknowns>— one combined upgrade for official + AUR. The helper runs as your user and sudo-s pacman internally for the pacman step. - Without helper:
sudo pacman -Syu --ignore=<...>— official repos only.
- With helper:
- If everything is held, exits cleanly without invoking anything.
All classification happens before the transaction, so you always see the plan before anything is touched.
extra/firefox 138.0-1 [Tier 2 — 15d hold]
Fast, Private & Safe Web Browser
extra/linux-zen 6.19.10-1 [Tier 1 — 30d hold]
The Linux ZEN kernel
extra/htop 3.4.1-1 [installed] [Tier 3 — 7d hold]
Interactive process viewer
nog: checking for pending updates...
Ready to install (2):
libmpc 1.4.0-1 -> 1.4.1-1 [Tier 3 · 24 days past window]
lib32-libngtcp2 1.22.0-1 -> 1.22.1-1 [Tier 3 · 14 days past window]
Held (3):
linux 6.19.10-1 -> 6.19.11-1 [Tier 1 · 22 days remaining]
firefox 138.0-1 -> 138.0.2-1 [Tier 2 · 11 days remaining]
fresh-editor-bin 0.2.24-1 -> 0.2.25-1 [Tier 3 · 6 days remaining]
Unknown (1):
my-local-pkg 0.9-1 -> 1.0-1 [Tier 3 · no build date in sync DB]
nog: 1 package(s) have no resolvable build date.
This usually means a locally-built package or an AUR query failure.
my-local-pkg (Tier 3 0.9-1 -> 1.0-1) — update anyway? [y/N] n
nog: handing off to yay...
:: Starting full system upgrade...
(Package names are tier-colored — Tier 1 red, Tier 2 yellow, Tier 3 green — using the Catppuccin Mocha palette.)
nog reads two configuration files from /etc/nog/.
General nog settings — version, logging, paths, and the authoritative hold durations for each tier.
[general]
version = "1.0.2"
log_level = "info"
[paths]
tier_pins = "/etc/nog/tier-pins.toml"
pacman_conf = "/etc/pacman.conf"
log_file = "/var/log/nog.log"
[holds]
tier1_days = 30
tier2_days = 15
tier3_days = 7
[aur]
# AUR helper to use for AUR-only packages and AUR update detection.
# "auto" — prefer yay, fall back to paru, skip AUR support if neither installed
# "yay" — require yay; error if not installed
# "paru" — require paru; error if not installed
# "none" — disable all AUR-aware paths (official repos only)
helper = "auto"The tier assignment file — who goes in Tier 1, Tier 2, or Tier 3. Anything not listed here falls into Tier 3 by default. As of v0.8.0, the obsolete hold_days field has been removed — hold durations are owned by nog.conf's [holds] section (single source of truth).
[tier1]
# false (default): Tier 1 auto-updates after the 30-day hold window.
# true (expert): Tier 1 stays wholesale held until `nog unlock <pkg> --promote`.
manual_signoff = false
packages = [
"linux",
"linux-zen",
"systemd",
"glibc",
"grub",
"mesa",
# ...
]
[tier2]
manual_signoff = false
packages = [
"plasma-desktop",
"firefox",
# ...
]
[tier3]
manual_signoff = false
# everything not listed above falls here automaticallyThe manual_signoff field is only meaningful on [tier1]. Tier 2 and Tier 3 do not consult it.
nog/
|-- Cargo.toml # Package manifest — dependencies, metadata
|-- src/
| |-- main.rs # Entry point, CLI definition via clap
| |-- commands/
| | |-- mod.rs # All subcommand implementations
| |-- tiers.rs # Tier classification engine
| |-- pacman.rs # pacman subprocess wrapper (invokes sudo pacman)
| |-- aur.rs # AUR helper detection (yay / paru) + delegation
| |-- sync_db.rs # pacman sync-DB reader (build-date lookup)
| |-- holds.rs # Hold-status evaluator (pure function)
| |-- config.rs # Config loader
|-- config/
| |-- nog.conf # Default nog configuration
| |-- tier-pins.toml # Default tier assignments
|-- nog.1 # Man page
|-- PKGBUILD # AUR package build file
|-- LICENSE # GPL v3
nog is built around one principle: never surprise the user with a kernel update.
Every system action goes through three layers of protection:
- Classification — every package is assigned a tier before any operation
- Transparency — holds, their remaining duration, and their reason are always reported before a change is made
- Pacman-native enforcement — holds use pacman's own
--ignoremechanism, so there is no way for nog to silently bypass them
Explicit commands (install, remove, pin) execute the user's intent without gating — tier protection lives in the passive path (update). Installing linux-lts is always allowed; what's governed is when the next kernel update lands on your machine.
nog does not replace pacman. It does not patch pacman. It does not shadow pacman commands. It is a small, readable wrapper — you can read the entire source in an afternoon.
nog is designed so that you never need to invoke it with sudo. It runs as your regular user and only escalates to root at the specific moments where root is genuinely required. Every elevation is visible — you will see the sudo password prompt when it happens.
Run nog as your user. Never sudo nog.
If you forget and prefix sudo while an AUR helper is configured, nog detects it (via $SUDO_USER/$SUDO_UID) and exits with a clear error. This is a hard stop because yay and paru both refuse to run as root. Without a helper configured, sudo nog still works — sudo-as-root is a no-op passthrough — but it isn't necessary.
nog invokes sudo in exactly two places. Both are transparent to the user (you see the prompt directly):
| Operation | Command invoked | When |
|---|---|---|
| Package transactions | sudo pacman -S | -R | -Syu ... |
install, remove, update, unlock --promote — only when no AUR helper is configured. When a helper is configured, nog calls the helper (as your user) and the helper runs its own sudo pacman internally. |
| Tier-pin writes | sudo tee /etc/nog/tier-pins.toml |
Only during nog pin. The new file contents are rebuilt in memory and piped through sudo tee. nog itself never runs as root; only tee does. |
That is the complete list. nog never invokes sudo anywhere else.
All of these are world-readable on a standard Arch install, so nog reads them as your user:
/etc/nog/nog.conf— nog main configuration/etc/nog/tier-pins.toml— tier assignments/etc/pacman.conf— for repo enablement and priority ordering/var/lib/pacman/sync/*.db— sync DBs, for package build-date lookup
Exactly one file is ever written by nog itself:
/etc/nog/tier-pins.toml— written viasudo teeduringnog pin. No other persistent file is created or modified by nog.
The entire rest of your system is out of scope:
/etc/pacman.conf— never modified/etc/pacman.d/**(mirrorlists, etc.) — never modified/var/lib/pacman/local/**— pacman's own installed-package state; nog never touches it/var/lib/pacman/sync/**— read-only access for date lookups/var/cache/pacman/**— never touched- Pacman's GPG keyring and signature verification — unmodified; every transaction runs through pacman's own checks
/etc/sudoers, PAM configuration, any other auth state — never touched/usr/bin,/usr/lib, or any other system binary location — never touched directly; pacman and the helper own these paths
nog does not shadow, patch, or replace pacman. It is purely a wrapper that calls pacman (or an AUR helper) as a subprocess. Every install, remove, and upgrade goes through pacman's signature verification and conflict resolution — nog cannot bypass them.
When [aur] helper in nog.conf resolves to yay or paru:
- nog calls
<helper> -Qua(as your user) to list AUR pending upgrades - nog calls
<helper> -S ...(as your user) for installs, or<helper> -Syu --ignore=...for the combined upgrade - The helper fetches PKGBUILDs and runs
makepkgas your user - The helper runs
sudo pacmaninternally when it reaches its pacman steps — thatsudoprompt comes from the helper, not from nog
nog never invokes sudo yay or sudo paru. That is a deliberate refusal — both helpers refuse to run as root precisely because makepkg needs to run as a non-root user.
nog runs as your user. It escalates exactly twice: sudo pacman for package transactions, and sudo tee /etc/nog/tier-pins.toml for the one file it ever writes. It never modifies any other file on your system, never bypasses pacman's signature verification, and never runs as root itself. If a helper is configured, transactions are handed off to yay or paru as your user, and those helpers escalate themselves.
- CLI skeleton with all subcommands
- Three-tier classification engine
- Real pacman subprocess integration
-
nog searchwith color-coded tier annotations - System-wide install at
/usr/bin/nog -
nog pinwith persistent tier changes totier-pins.toml - AUR package
- Man page
- Phase 1 — sync DB reader — reads every enabled pacman sync database (gzip + zstd), extracts build dates for all packages across all repos
- Phase 2 — hold evaluation logic — pure function returning Expired / Holding / Unknown for any package; 6 unit tests; 30/15/7 day windows live in
nog.conf - Phase 3 — wired into
nog update—checkupdatesintegration, status-grouped output (Ready / Held / Unknown) with Catppuccin Mocha tier colors, interactive y/N prompt for Unknowns,manual_signoffhonored as Tier 1 expert-mode toggle, Tier 1 install block removed - Phase 4 — AUR helper detection — auto-detects
yay/paru; AUR pending upgrades fold into the status-grouped output; transactions hand off to the helper for combined-Syu; one consistent no-sudo rule;nog pinwrites viasudo tee; root-guard catchessudo noginvocations when a helper is configured - Phase 5a — AUR build-date resolution — AUR pending upgrades now get real build dates via the helper's cached metadata (
<helper> -Sai), parsed to Unix timestamps and fed into the hold evaluator; AUR packages bucket as Ready/Held based on actual dates instead of always Unknown; zero new dependencies, zero new network surface from nog itself - Phase 5b — documentation polish (docs) — full man page rewrite (COMMANDS, TIER SYSTEM, DESCRIPTION, FILES now accurate through v0.12.0 behavior and mention AUR integration); clap help-text refresh (top-level
long_about+ per-subcommand short + long descriptions)
-
Phase 1 — sync DB reader with gzip + zstd support✅ -
Phase 2 — hold evaluation logic✅ -
Phase 3 — wire into✅nog update -
Phase 4 — AUR helper detection✅ -
Phase 5a — AUR build-date resolution✅ -
Phase 5b — documentation polish (man + help)✅
- PKGBUILD in tree at repo root, kept in lockstep with the latest tag
- AUR submission —
ssh://aur@aur.archlinux.org/nog.gittracks releases; maintained via~/Programs/aur-nog-remote/ - Dogfood — full
TEST-MATRIX.mdrun captured inTEST-REPORT-v1.0.md; the dogfood surfaced the v1.0.1 zstd fix and the v1.0.2 polish batch, both validated on the AUR-delivered binary - Release discipline — every release now runs through local
makepkg -sitest → AUR push → uninstall + fresh AUR install verification
- First-run wizard — on first
nog update, ask the user whether Tier 1 should auto-update after 30 days (default, novice-friendly) or require manualunlock --promoteper kernel/glibc/systemd upgrade (expert mode). Writes the chosen value totier-pins.toml [tier1] manual_signoff. - Chaotic-AUR binary package (submit once v1.0 is stable)
-
nog history— log of all tier changes and package actions -
nog status— dashboard showing what's held, what's ready, what's overdue -
nog rollback— revert a recent update using pacman cache - Hook support for notifying a GUI companion like
nogforge
Dogfood-surfaced polish batch
Five small fixes and two matrix refinements, all caught during the end-to-end dogfood of the AUR-installed v1.0.1 binary. See TEST-REPORT-v1.0.md for the full run — every finding is documented there with observed behavior, severity, and fix rationale.
Fixes:
- 🛑 F5 — graceful exit on missing tier-pins.
load_tiers()no longer panics with a Rust-native backtrace hint when/etc/nog/tier-pins.tomlis unreadable. Cleaneprintln!+std::process::exit(1)with the attempted path in the error message for diagnostic clarity. - 🗂 F4 — single-warning config load.
NogConfig::load_default()now cached viaOnceLock— no more duplicate "no nog.conf found" warnings on misconfigured systems, and repeat callers read from the cache instead of re-hitting the filesystem. - 🔒 F2 — release binaries no longer embed the maintainer's build path. The
CARGO_MANIFEST_DIRdev-fallback branch is gated behind#[cfg(debug_assertions)]. Release binaries passstringschecks cleanly; dev clones still work as before viacargo run. Resolves themakepkg$srcdirwarning. - 🎨 F1 —
nog searchtier annotations are now config-aware and consistent. Tier 1 shows30d holdby default (was the misleadingmanual sign-off), flipping tomanual sign-offonly whentier1 manual_signoff = true. Tier 3 shows7d hold(wasfast-track). All day counts read fromnog.conf's[holds]section. - 📝 F3 — error messages no longer duplicate "exit status". Every
eprintln!("... exited with status {}", status)now usesstatus.code().unwrap_or(-1)so output readsexited with status 1instead ofexited with status exit status: 1.
Matrix refinements:
- 📋 M1 —
TEST-MATRIX.mdcheck 15.3 updated:.pacsave/.pacnewsiblings are expected after any uninstall/reinstall cycle (the PKGBUILD'sbackup=directive intentionally preserves user-modified configs) - 📋 M2 —
TEST-MATRIX.mdcheck 3.5 no longer keys the pass criterion on a specific exit code for nonexistent packages — helpers have inconsistent behavior here (yay returns 0 with "nothing to do"; paru may return non-zero)
No behavior changes beyond the error-path polish and the search label text. 6/6 hold tests still green. Same zstd-via-pkg-config dynamic-linking contract as v1.0.1.
Hotfix — AUR build failure on fresh environments
- 🔨
Cargo.toml: switchzstd = "0.13"tozstd = { version = "0.13", features = ["pkg-config"] }. The previous config relied onzstd-sys's bundled static build, which failed to link under Arch's makepkg environment (LLD +-Wl,--as-needed+-nodefaultlibs) becausezstd-sysdidn't emit the static-library link directive in that toolchain config - 📚 Now uses system
libzstdvia dynamic linking — zero extra runtime dep (pacman already depends on libzstd, so it's always present on Arch) - 📄 Man page header + README badge + Cargo.toml +
nog.confall bumped to 1.0.1 - ℹ No behavior changes; 6/6 hold tests still green. Caught by the v1.0 dogfood pass — exactly what a dogfood is for.
Initial stable release.
nog is now a complete tier-aware wrapper for pacman and the common AUR helpers, built and polished across six deliberate phases documented in the entries below. This release declares the core contract stable:
What nog does
- Classifies every package into Tier 1 (kernel / bootloader / glibc / systemd / mesa — 30-day hold), Tier 2 (DE and key applications — 15-day hold), or Tier 3 (everything else — 7-day hold)
- Computes a full tier-aware upgrade plan before any transaction runs, grouping pending updates into Ready, Held, and Unknown buckets with Catppuccin Mocha tier colors
- Resolves build dates from every enabled pacman sync database (gzip + zstd), then falls back to the configured AUR helper's cached metadata (
<helper> -Sai) for AUR-only packages — so AUR upgrades get real hold evaluation, not always-Unknown - Hands off the final transaction to pacman or the helper with
--ignore=<held + skipped>— pacman-native enforcement, no shadowing - Escalates to root only via
sudo pacmanfor transactions andsudo teefor writing/etc/nog/tier-pins.toml. Runnogas your user — never withsudo. The one-rule privilege model is documented exhaustively in the Privilege model section.
What nog doesn't do
- Does not shadow, patch, or replace pacman — every transaction goes through pacman's signature verification
- Does not modify any system file outside
/etc/nog/tier-pins.toml - Does not make direct network calls — the helper owns all AUR network I/O
- Does not install, upgrade, or remove anything without pacman's own confirmation prompts
- Does not gate explicit user commands —
nog install linux-ltsalways proceeds; tier protection lives in the passiveupdatepath
Ecosystem nog is the native package manager for KognogOS, with a TUI companion (nogforge) and bootloader/terminal utilities (grubforge, alacrittyforge).
Known limitations carried into v1.0
- AUR build-date resolution depends on the helper's cached metadata being fresh. If the cache is stale, hold windows are evaluated against the cached date rather than live upstream data. Running
<helper> -Sy(oryay -Syy) refreshes it. - Tier pinning of AUR packages works, but AUR packages without a
Last Modifiedfield still fall into the Unknown bucket and trigger the y/N prompt.
Thanks Development happened in deliberate phases (see below). Every phase closed with a tagged pre-release and a working dev build; the v1.0.0 tag is the moment the release kit (AUR submission + dogfood) begins.
Phase 5b (docs) — man page and help-text accuracy pass
- 📜 Full man page rewrite: DESCRIPTION updated (30/15/7 day windows, AUR helper mention, expert-mode pointer); COMMANDS updated for every subcommand's real v0.12.0 behavior (no more stale "Tier 1 blocked" on install, accurate
nog updatebucketing description,nog unlocknew semantics); TIER SYSTEM rewritten with auto-release default + expert mode; FILES now lists sync DBs and pacman.conf as read paths and notessudo teefor tier-pins writes - 🏷
man nogheader bumped tov0.12.0 - 💬 Clap help text refresh — top-level
long_aboutnow summarizes the tier system and no-sudo rule in a few sentences; every subcommand (install,remove,update,search,pin,unlock) has a short description for the command list plus a longer one shown in<cmd> --help - 🗂 Roadmap split Phase 5's polish work: screenshots + v1.0.0 CHANGELOG consolidation moved into the v1.0 dogfood + release kit step (more honest framing — they belong at release time, not pre-release)
- ℹ No behavior changes; no test regressions (6/6 still green); warnings unchanged at 7
Phase 5a — AUR build-date resolution (the last Unknown falls)
- 📅 AUR pending upgrades now get real Unix-timestamp build dates by parsing the
Last Modifiedfield from the helper's cached metadata (<helper> -Sai) — no direct AUR RPC calls from nog - 🧮 The hold evaluator sees a unified build-date map (sync-DB ∪ AUR) and buckets AUR packages as Ready or Held based on their actual dates, with countdown/past-window reasons identical to official repo packages
- 🧩 New
aur::build_dates_for(helper, packages)— batched-Saisubprocess call, robust colon-split parser that tolerates variable column widths across yay/paru, Unix-timestamp conversion viadate -d - 🛟 Soft-fail discipline preserved — if the helper is unreachable, the
Last Modifiedline is missing, ordatecan't parse the string, those packages fall back to the Unknown bucket and hit the existing y/N prompt. No hard errors, no crashes, no change to current user-facing error paths - 🔒 Zero new dependencies, zero new network surface from nog itself — threat model identical to v0.10.0: nog spawns subprocesses, the helper owns all AUR network I/O
- 🗣 Unknown-bucket message updated — "no resolvable build date" is more accurate than "no build date in any sync DB" now that lookup has multiple paths
- ⚠ Only truly orphan packages (locally-built, disabled-repo, AUR query failure) reach the prompt now — most previous "Unknown" cases resolve automatically
Phase 4 — AUR helper integration + unified no-sudo privilege model
- 🧩 New
aurmodule — helper detection (yay→paru→none) driven by[aur] helperinnog.conf. Supports"auto","yay","paru","none"; hard-errors if the user requests a specific helper that isn't installed - 📦
nog updatefolds AUR pending upgrades (<helper> -Qua) into the existing status-grouped output alongside official repo packages fromcheckupdates. AUR packages bucket as Unknown for now (no sync-DB build date); the y/N prompt already handles them correctly - 🔄
nog updatetransaction handoff routes through the helper when configured (<helper> -Syu --ignore=...) for a single combined official+AUR upgrade. Without a helper, pacman handoff is unchanged - 📥
nog install <pkg>routes through the helper when configured, so AUR-only packages "just work" without a pre-check. The helper resolves sync repos before AUR automatically - 🔓
nog unlock --promotesimilarly routes through the helper when configured - 🧑 No-sudo rule — single consistent UX: run
nogas your user.pacman.rsnow invokessudo pacmaninternally;tiers::pin_packagewrites/etc/nog/tier-pins.tomlviasudo tee.nog pinno longer needs shell-level sudo. Fully backwards-compatible:sudo nog <cmd>still works for non-helper paths (sudo-as-root passes through) - 🛑 Root-guard — if nog is invoked via sudo (detected via
$SUDO_USER/$SUDO_UID) and a helper is configured, it exits with a clear message pointing the user to drop thesudo. Necessary becauseyay/parurefuse to run as root - 📖 New "Privilege model" section in README — documents exactly where nog escalates (
sudo pacman,sudo tee /etc/nog/tier-pins.toml), which files it reads without elevation, the single file it ever writes, and the comprehensive list of system files it never touches (pacman.conf, pacman.d, /var/lib/pacman/local, keyring, sudoers, etc.) - 📜 Man page gains a targeted PRIVILEGES AND SUDO section mirroring the README content; version header bumped to 0.10.0; EXAMPLES dropped their
sudoprefixes. Full man page rewrite (command descriptions, tier metadata) deferred to Phase 5 polish - ℹ No regressions in existing behavior: 6/6 hold tests still green, 7 warnings (unchanged since Phase 3)
Phase 3 — wired into nog update (the tier system goes live)
- 🔌
nog updatenow callscheckupdates(pacman-contrib) to list pending upgrades without the-Syside effect, then classifies every pending package against its tier's hold window - 📊 Status-grouped output: three labelled buckets —
Ready to install,Held,Unknown— each showing package name, version bump, tier, and either "N days past window", "N days remaining", or "no build date in sync DB" - 🎨 Tier-colored output using the Catppuccin Mocha palette (Tier 1 red
#F38BA8, Tier 2 yellow#F9E2AF, Tier 3 green#A6E3A1) — muted subtext color#A6ADC8for version/metadata - ❓ Interactive
[y/N]prompt per Unknown package (AUR-only, locally-built, or disabled-repo); EOF / non-TTY stdin auto-skips remaining Unknowns with a warning instead of hanging - 🎚 Tier 1 policy change, novice-friendly default:
manual_signoffnow defaults tofalse— Tier 1 auto-updates once the 30-day hold expires. Expert users can setmanual_signoff = trueto restore always-held-until-promoted behavior - 🔓
nog unlock <pkg> --promotekept as the expert-mode escape hatch: force-upgrade a held Tier 1 package right now, bypassing the hold andmanual_signoff - 🗑 Tier 1 install block removed —
nog install linux-ltsnow proceeds normally; tier classification is shown as informational output only. Explicit user commands execute user intent; tier protection lives in the passive update path - 🧹
nog unlockwithout--promotenow honestly reports it has no session state to toggle, and points the user at--promotefor the real action - ⚠ Warnings reduced to 7 — previously-unused
is_manual_signoffmethod is now live; the orphanedtier1_packages()helper was removed
Phase 2 — Hold evaluation logic (the date-math engine)
- 🧮 New
holdsmodule with a pureevaluate()function — given a package, tier, build-date map, and hold config, returns one ofExpired { days_past_window },Holding { days_remaining }, orUnknown - ✅ 6 unit tests covering all three states, the exact-window boundary, partial-day rounding (ceiling per spec), and future-dated-package edge cases
- 🔒 All inputs explicit including
now: SystemTime— tests run deterministically, no hidden clock dependency - 🗓 New hold spec live in
nog.conf: Tier 1 = 30 days, Tier 2 = 15 days, Tier 3 = 7 days - 🧹 Removed obsolete
hold_daysfield fromtier-pins.toml— hold durations now owned exclusively bynog.conf [holds](single source of truth) - 🔧
tiers.rscleanup: droppedhold_daysfield and method, simplifiedDisplayforTierenum, removed unusedstd::path::Pathimport - 🧪 Hidden
_debug-hold <package>subcommand added for internal verification — classifies, looks up build date, evaluates hold, prints result - ⚠ Warnings reduced from 11 to 9 — previously-unused
HoldsConfigfields are now active - ℹ This phase adds no user-visible commands. The
_debug-holdtool is hidden from--help. Phase 3 will wire this evaluator intonog update.
Phase 1 — Sync DB reader (foundation for date-based holds)
- 🧱 New
sync_dbmodule reads every enabled pacman sync database and builds a map of package → build-date Unix timestamp - 🗜 Auto-detects gzip (core, extra, multilib) and zstd (Chaotic-AUR and similar) compression via magic-byte sniffing
- 📋 Respects
pacman.confrepo priority — first repo wins on name collisions, matching pacman's own resolution - 🛡 Graceful fallback when
pacman.confis unreadable — scans the sync directory directly - 📦 Indexes 18,000+ packages across all enabled repos on a standard Arch install
- 🧪 Verified against
pacman -Sioutput for official and Chaotic-AUR packages — exact timestamp match - ➕ Dependencies added:
flate2,tar,zstd - 🔢 Version bumped to 0.7.0 to mark v1.0 development in progress
- ℹ This phase adds no user-visible commands. It is infrastructure for Phase 2 and onward.
AUR package + man page
- 📦
nogavailable on the AUR — install withyay -S nog - 📖 Man page added —
nog.1installed to/usr/share/man/man1/ - 🔢 Version now reads from
CARGO_PKG_VERSION— no hardcoded strings - 📋 PKGBUILD installs binary, config files, license, and man page
nog pin — persistent tier changes
- 📌
nog pin <package> --tier=<1|2|3>writes changes to/etc/nog/tier-pins.toml - ➕ Pinning to Tier 1 or 2 adds the package to the correct section
- ➖ Pinning to Tier 3 removes it from Tier 1/2 — Tier 3 is the default, no entry needed
- ♻ Changes survive reboots and are immediately reflected in
nog searchannotations
nog update — Tier 1 properly excluded
- 🛡
nog updatepasses Tier 1 packages to pacman via--ignoreflags - 🔒 Tier 1 packages are genuinely untouchable during a system upgrade
- ✅ Confirmed: system upgraded 14 packages, zero Tier 1 packages touched
nog search + system install
- 🎨
nog searchshows color-coded tier annotations for every result - 📂 Installed system-wide with config files at
/etc/nog/ - 🚀
nogcallable from anywhere on the system without a path
Tier system + real pacman calls
- 🎚 Three-tier classification engine fully implemented in
tiers.rs - 📋
tier-pins.tomldefines all Tier 1/2/3 package assignments - 🔌
pacman.rswires real subprocess calls — nog installs, removes, and updates for real - ⛔
nog installblocks Tier 1 packages with a clear error message - 🔓
nog unlock --promoteallows manual Tier 1 upgrades - ⚙
config.rsreads/etc/nog/nog.confwith graceful fallback
Initial release — nog CLI skeleton
- 🦀 Rust CLI using clap with derive macros
- 📝 All subcommands defined: install, remove, update, search, pin, unlock
- 🏗 Three-tier architecture designed and stubbed
The parent distribution where nog is the native package manager. Arch-based, KDE Plasma on Wayland, Zen kernel, Catppuccin Mocha. https://github.com/jetomev/KognogOS
A TUI for managing nog, plus unified interface for AUR helpers, Flatpak, and Snap. Built on top of nog to extend it into a full graphical package management experience. https://github.com/jetomev/nogforge
A TUI for managing the GRUB bootloader. Ships with KognogOS, pinned to Tier 2. https://github.com/jetomev/grubforge
A TUI for managing and customizing the Alacritty terminal emulator. Ships with KognogOS, pinned to Tier 2. https://github.com/jetomev/alacrittyforge
jetomev — idea, vision, direction, testing
Claude (Anthropic) — co-developer, architecture, implementation
This project is a collaboration between a human with a clear vision for what Linux package management should feel like, and an AI that helped design and build the tools to make it real — one command at a time.
nog is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License v3.0 as published by the Free Software Foundation.
See LICENSE for the full license text.
nog is in early alpha. Ideas, feedback, and contributions are welcome — open an issue or pull request on GitHub.
If this project resonates with you, consider starring the repository. It helps others find it and motivates continued development.