Monitor snapshots #
albedo-monitor emits one versioned JSON object to stdout, then exits. It uses
$ALBEDO_HOME (default ~/.albedo); --home PATH overrides discovery and
--timeout SECONDS sets the overall startup/request budget
(default 5, maximum 30).
Without --start-daemon the helper only observes an existing daemon.
albedo-monitor
albedo-monitor --home /path/to/albedo-home --timeout 3
albedo-monitor --start-daemon
The standalone flake package is packages.<system>.albedo-monitor; the overlay
also exports albedo-monitor. Its runtime includes Python and the suite
albedo-defaults CLI, pinned by absolute executable path; no ambient CLI is needed.
Running the source script directly uses albedo from PATH.
Contract version 1 #
{
"version": 1,
"online": true,
"error": "",
"sessions": [{
"id": "session-id",
"title": "Agent title",
"workspace": "/workspace",
"model": "model-id",
"status": "working",
"phase": "generating",
"parent_id": null,
"clients": null
}],
"accounts": [{
"id": "public-account-id",
"provider": "openai-codex",
"account": "Account display label",
"windows": [{
"label": "5 hours",
"remaining_percent": 75.0,
"resets_at": "2026-05-02T14:00:00Z",
"resets_at_epoch": 1777730400.0,
"observed_at": "2026-05-02T12:00:00Z",
"observed_at_epoch": 1777723200.0,
"stale_reason": "",
"status": "ok",
"stale": false
}],
"error": ""
}],
"accounts_error": ""
}
onlinemeans/serverreturned a ready protocol-3 daemon whose available identity fields match discovery. Later errors can leaveonline: truewith partial arrays; consumers must checkerrorbefore showing aggregate counts.- Session status is
workingfor preparing, generating, running, compacting or interrupting;waitingfor idle with blocked inputs;idleotherwise; unknown phases becomeunknown. This is daemon activity, not process CPU usage or attached-client presence. All unarchived families and subagents are included; closed members are omitted. Client counts are unavailable and always null.modelandparent_idmay be null. - Accounts come from the daemon's native multi-account inventory, not historical
quota rows. Unsupported and never-measured accounts remain visible with
quota_unavailable. Missing or ambiguous OAuth mappings instead usequota_identity_unavailableorquota_identity_ambiguous. Canonical provider names includeanthropic,openai-codex,google-antigravityandopencode-go. - Windows use cached daemon samples only.
remaining_percentis100 - usedonly for finite percentages in range, otherwise null. Timestamps are RFC3339 strings or null. The additive optionalresets_at_epochfield is finite Unix seconds parsed from a timezone-aware reset timestamp, otherwise null; clients must also accept its absence from older version-1 snapshots. Stale means observation missing/unparseable, older than 30 minutes, implausibly future-dated, or reset elapsed. Stale values are historical, never renewed guesses. The optional additiveobserved_at_epochfield gives observation time in Unix seconds, not snapshot time.stale_reasonis empty when fresh, orobservation_missing,observation_old,clock_skeworreset_passed. Provider status is retained; raw provider errors become fixed codes. Only the newest report per account/provider contributes windows; newer failures or reduced reports cannot resurrect older successful limits. - Errors are fixed codes, not exception text.
errorcovers discovery/session failures;accounts_errorcovers inventory/identity failures or possible quota truncation; accounterrorcovers missing/failed quotas. Empty string means no error observed, not a guarantee of freshness. Process exit is zero for a valid snapshot, including offline/error snapshots. Invalid arguments exit nonzero.
Safety and limitations #
By default the helper never starts, attaches to, restarts or upgrades the daemon.
--start-daemon explicitly permits the native albedo daemon command only when
discovery is missing or its PID no longer exists. A live PID (even an unreachable
or incompatible daemon) and invalid discovery never trigger startup. Concurrent
monitor startups are serialized by a nonblocking monitor-start.lock in the home;
a competing invocation reports daemon_start_in_progress. Startup failures and
startup timeouts report daemon_start_failed, without native command output.
The helper never creates a session or attaches a session client. Existing live
daemons are observed directly, never passed through native CLI startup. Requests
are authenticated GETs to loopback only: /server, /auth and paginated
/sessions?scope=all&archived=false. No provider quota requests are triggered.
Redirects and proxies are not followed. Discovery is capped at 64 KiB, each HTTP
response at 8 MiB, credentials at 1 MiB and session collection at 20 pages of 100.
The daemon's /server currently caps quota readings at 200; reaching this limit
is reported as possibly truncated.
GET /auth is the ordinary native account-list API. Upstream can initialize
missing stable account IDs and update display metadata in creds.json; it does
not change credential secrets, account selection or remotely refresh tokens.
Without the startup flag the helper itself writes no files. Opt-in startup can
create the home, its monitor lock and native daemon files. It reads creds.json
locally only to map the
public account ID onto non-secret quota identity fields. Tokens, refresh secrets,
API keys, MCP configuration, prompts, previews and transcripts are never emitted.
Raw exceptions and HTTP error bodies are never included in JSON.
Identity matching follows the pinned upstream store semantics: Claude uses
accountId or email, Codex stored email or accountId, Antigravity email, and
OpenCode Go email/org/account label. Token-derived fallback identities and JWT
claims are deliberately not computed. Missing/ambiguous mappings remain unknown;
no single-account or label-similarity guess is made. API-key-only provider profiles
outside native account inventory are not listed. Revisit this adapter when
upstream exposes the quota identity directly in its public account API.
The suite builds the quota core with Zig's baseline CPU target rather than the build host's native instruction set. This prevents cached builds from crashing with an illegal instruction on machines without the builder's CPU features (for example AVX-512). A failed poll replaces the current account report with an error; previous samples remain in history. The monitor cannot force provider polls. A fresh snapshot must not be treated as a fresh provider observation.
Poller recovery #
The daemon schedules a newly discovered account immediately instead of waiting for the previous ten-minute discovery timer. In-flight work is excluded from idle deadlines, avoiding a 250 ms wake loop. Obsolete timer and worker replies cannot replace newer state.
Provider polls have a two-minute deadline; account discovery has a five-minute deadline. Timed-out workers are stopped and retried on the existing cadence and backoff. Poll failures replace current windows with a sanitized error; failed discovery preserves previously known targets. Historical quota rows are retained. These deadlines can interrupt an unusually slow provider or a large discovery round, rather than leaving the daemon's quota collection wedged indefinitely.
Verification #
python3 -m unittest discover -s test -p monitor_test.py -v
nix build .#checks.x86_64-linux.monitor .#albedo-monitor
Tests use isolated temporary homes and local HTTP fixtures; they never read live credentials, contact providers or start/restart a real daemon.