Architecture

How the omg CLI and omgd daemon use caches, a Unix socket, and a status snapshot read by Bash and Zsh prompt helpers.

Two release binaries

The OMG binaries and their roles

BinaryRole
omgThe CLI handles arguments, package operations, policy, output, interactive views, and prompt counters
omgdThe daemon maintains an in-memory package index, background status refresh, and caches

Current Linux and macOS release archives include both binaries. Archives from v0.1.222 and earlier omit omgd on non-Arch targets. The CLI talks to the daemon over a Unix socket when omgd is running. Bash and Zsh hooks provide prompt count helpers that read the fixed-size omg.status snapshot beside the socket. Separate omg ec/tc/oc/uc commands were added after v0.1.223.

What happens on a search

Search request path A running daemon answers from memory. Without one, the same query takes the direct backend path.
Search request pathSearch request path. Steps in reading order: omg search (your command); omgd daemon (only when running); Direct backend (no daemon needed); Cache lookup (in-memory hit or miss); In-memory index; Official repositories (libalpm, APT, RPM); AUR (over HTTPS). Connections: omg search to omgd daemon (daemon running); omg search to Direct backend (no daemon); omgd daemon to Cache lookup; Cache lookup to In-memory index (cache miss); In-memory index to Official repositories; In-memory index to AUR (AUR query); Direct backend to Official repositories.omg searchyour commandomgd daemononly when runningDirect backendno daemon neededCache lookupin-memory hit or missIn-memory indexOfficial repositorieslibalpm, APT, RPMAURover HTTPSdaemon runningno daemoncache missAUR query
  1. A simple omg search or omg info call takes an optimized path. Search may query a running daemon; Debian package info can read the local APT database directly.

  2. When a daemon answers, it checks its in-memory cache.

  3. On a daemon cache miss, the daemon searches its in-memory package index and remote sources.

  4. The daemon caches that result and returns it to the CLI.

  5. If the daemon is unavailable, the CLI uses the same direct backend path. On Arch, official repositories and the AUR can be queried in parallel.

On Arch, OMG binds libalpm through direct FFI instead of invoking pacman for queries. Debian and Ubuntu read the native APT database. Fedora reads RPM data directly, with a subprocess fallback when the database format requires it. AUR requests use HTTPS. Fedora support does not establish RHEL compatibility.

What happens on a runtime switch

Runtime switch path Every step stays inside your own data directory, so no administrator password is involved.
Runtime switch pathRuntime switch path. Steps in reading order: Detect the runtime (node, python, rust); Version installed? (checked in the data dir); Download release (from the provider); Check integrity data (provider-specific); Extract version (versions/runtime/version); Update current link; Project PATH updated (by the shell hook). Connections: Detect the runtime to Version installed?; Version installed? to Download release (missing); Download release to Check integrity data; Check integrity data to Extract version; Extract version to Update current link; Update current link to Project PATH updated.Detect the runtimenode, python, rustVersion installed?checked in the data dirDownload releasefrom the providerCheck integrity dataprovider-specificExtract versionversions/runtime/versionUpdate current linkProject PATH updatedby the shell hookmissing
  1. The CLI detects the runtime type and checks whether the requested version is installed.

  2. If not, it downloads the release from its configured provider and checks the integrity data available for that provider.

  3. The version is extracted under versions/runtime/version in the OMG data directory.

  4. The current symlink records the selected version. When a project pin exists, the shell hook prepends that concrete version directory to PATH.

Cache tiers

From hottest to most durable

TierWhat it holds
In-memoryRecent searches, package details, and system status shared by all CLI instances
Status snapshotsVersioned JSON persisted with atomic writes for quick status and history-independent cache state
Binary status fileFixed-size omg.status counts read by Bash and Zsh hook helpers; separate CLI count commands with daemon and backend fallbacks were added after v0.1.223

Search indexes are rebuilt from the native package-manager databases rather than treated as durable authority, so deleting the persistent cache is always safe. Transaction history, audit logs, and runtime artifacts remain separate from status snapshots. Snapshots are written with a same-directory temporary file, fsync, and atomic rename.

The binary snapshot is a fixed record, not a summary

# omg.status is exactly 32 bytes, laid out as:
#   offset 0   4 bytes   magic 0x4F4D4753 ("OMGS")
#   offset 4   4 bytes   format version
#   offset 8  16 bytes   four u32 counts: total, explicit, orphan, updates
#   offset 24  8 bytes   unix timestamp in seconds

# Hook helpers accept the file only when its owner, size, format, and age pass
# validation. When it is missing or stale, check current state with omg status.
omg-ec   # explicitly installed packages in Bash or Zsh
omg-uc   # updates available in Bash or Zsh

IPC protocol

  • Transport is a Unix domain socket with length-delimited framing.
  • Messages use a compact binary serialization format chosen for low latency.
  • Requests cover search, package info, system status, security audits, explicit package listings, and cache or health controls.
  • A daemon cache hit returns the stored result. A miss searches the in-memory index and, when the command needs them, the native databases and remote sources.
  • Without a running daemon, the CLI falls back to direct package-manager queries instead of failing.

What one call puts on the wire

# frame = [ length ][ version prefix ][ bitcode payload ]
#   both peers reject a version prefix they do not understand

# 1. the CLI writes one request frame
# 2. the daemon decodes it and routes it to a handler
# 3. the daemon writes one response frame
# 4. a decode error fails the call; it is never reported as an empty success

# The socket path resolves from OMG_SOCKET_PATH, then $XDG_RUNTIME_DIR/omg.sock.
# Without XDG_RUNTIME_DIR, Unix uses /run/user/$UID/omg.sock when available,
# otherwise a validated private /tmp/omg-$UID directory or home fallback.
# It will not use another user's socket when ownership checks fail.
omg daemon-status

Security paths

  1. Runtime and self-update downloads verify expected SHA-256 digests.

  2. AUR key preparation uses gpg to inspect and import required keys.

  3. omg audit slsa verifies a Sigstore hashedrekord artifact signature and Rekor signed entry timestamp. It does not verify a Merkle inclusion proof or establish build provenance.

  4. In v0.1.223, omg audit needs omgd and queries supported OSV ecosystems. Current main has a direct fallback and native Arch and Fedora advisory paths.

  5. Arch installs and updates check policy.toml against prepared transactions. Native APT, DNF, and Homebrew mutations refuse explicit policy.

Runtime operations stay inside the user data directory. System package operations can elevate through sudo when the native backend requires it. Sensitive writes use atomic replacement where implemented, and audited security events are appended to a hash-chained log.

Background workers and shutdown

  • A status refresh worker probes runtime versions, counts vulnerabilities, updates caches, and rewrites the binary status file and JSON snapshot.
  • An optional ALSA scanner periodically fetches Arch security advisories and matches them against installed packages.
  • On SIGINT or SIGTERM the daemon stops accepting connections, lets active requests finish, stops workers, and cleans up the socket.

Because workers only maintain derived state, killing the daemon never corrupts package operations. Restart it with omg daemon and the caches repopulate on demand.