car-registry
File-based agent registry for cross-process discovery, used by menubar / tray UIs that want to enumerate locally running agents without running a coordinating daemon.
How it works
Each agent owns one JSON file under ~/.car/registry/<name>.json. On
startup it calls AgentRegistry::register, which atomically writes the
entry (temp file + rename). Periodically it calls heartbeat to bump
last_heartbeat_at. On shutdown — or after a panic, on next launch —
unregister removes the file. UIs poll with list, optionally
calling reap_stale(timeout) first to drop entries whose last
heartbeat is too old.
There is no daemon, no shared lock, no IPC. The directory is the shared state; atomic writes give consistency.
API
use ;
let reg = new?; // ~/.car/registry/
reg.register?;
reg.heartbeat?;
let agents = reg.list?;
reg.reap_stale?;
reg.unregister?;
File layout
~/.car/registry/
musicart.json
flyx.json
car-host.json
Each file is a AgentEntry serialized as JSON. Filenames mirror the
agent name; non-filesystem-safe characters are rejected at register
time.
Crash-durable reboot cutover proof
The crate also contains the prove-first reboot_cutover filesystem
transaction for Parslee-ai/car#1127.
It preserves a LaunchAgent generation across SIGKILL and simulated power loss,
but is intentionally not wired into an installer or launchd. Its filesystem
transaction compiles only on Unix; other targets retain the public API and
return UnsupportedPlatform before creating transaction state. The transaction
states, ownership rules, sync coverage, and 52-boundary interruption matrix are
documented in
docs/reboot-cutover-transaction-2026-09-10.md.
Why a separate crate
Agents that consume the registry don't necessarily depend on
car-engine (a tray UI does not need the runtime). Splitting the
registry off keeps it a thin dependency while hosting lifecycle primitives
shared by native CAR hosts.
Tracking issue
#111 — agent registry + menubar discovery.