Skip to main content
Every file Observal reads or writes on the client (~/.observal/) and in each harness’s config directory.

Client-side: ~/.observal/

config.json schema

Authentication and identity fields are managed by observal auth. The config set command accepts only server_url, timeout, update_check, update_check_interval, and update_check_repo. Supported environment variables override persisted values for the current invocation; see Environment variables.

Durable session outbox

Python session exporters persist each observed batch in telemetry_buffer.db before network delivery. OpenCode and Pi use per-session files under their native outbox directories because their TypeScript runtimes cannot call the Python SQLite engine. All follow the same protocol: pending data survives process restarts and failed attempts, and the source line advances only when the server’s contiguous checkpoint covers the complete batch. Observal does not silently evict unacknowledged records at capacity. sync_state.json is a cache of acknowledged local positions, not the authority for delivered history. If it is missing, corrupt, or stale, recovery validates and restores positions from the authenticated server checkpoint. Finalized sessions also send a SHA-256 audit manifest; hashing is not performed on ordinary incremental uploads. Use observal ops telemetry status to inspect pending batch count, disk use, oldest pending time, and last successful acknowledgement.

aliases.json schema

Use anywhere that accepts a compatible reference by prefixing the alias with @.

last_results.json schema

Each list invocation replaces this cache, including an empty result. Numeric row references are valid only for the component type that produced the latest list.

harness-side

Claude Code

Kiro

Cursor

VS Code

Codex CLI

Pi

Two mutually exclusive installation modes are supported:
  • npm: npm:observal-pi is configured in ~/.pi/agent/settings.json (with or without a pinned version, and whether or not Pi has downloaded it yet). Observal never installs extensions/observal.ts in this mode — observal doctor only reports when a pinned version is older than the installed CLI, with a pi update npm:observal-pi reminder. Pi loads a local extensions/observal.ts in addition to the npm package, so if one is left over from local mode every session is sent twice; observal doctor patch removes a local copy it recognizes as its own (keeping it as observal.ts.bak) and leaves a file Observal did not write alone.
  • local: no npm package is configured. observal auth login and observal doctor patch install the extension bundled with the CLI directly to extensions/observal.ts, recording the installed CLI version in the adjacent manifest. A later CLI upgrade rewrites each of those files atomically — the two are written in sequence, not as a single atomic unit — and prints a reminder to restart Pi or run /reload; a newer local install than the current CLI is left alone. If the file still carries the current version but its contents have drifted from the bundled source — an edited working copy, say — doctor restores it and keeps the previous contents as observal.ts.bak.
Observal keeps a copy of the file whenever it rewrites or deletes one, named observal.ts.bak (.bak.1, .bak.2, … if that name is taken). The copy does not end in .ts, so Pi does not load it; delete it once you are satisfied with the result. There are two cases where no copy is made, because nothing is lost: adopting a file whose contents already match the bundle, where only the manifest is written, and observal doctor cleanup removing a tracked install that still matches what Observal wrote. Every other refresh, restore, migration and duplicate removal keeps one — a manifest records which CLI version wrote an install, not that its bytes are still unedited.

Migrating installs from before version tracking

CLI versions before the manifest existed wrote extensions/observal.ts with nothing beside it. Those installs are recognized by the doc header every Observal extension carries, and observal auth login or observal doctor patch migrates them: the existing file is copied to observal.ts.bak (.bak.1, .bak.2, … if that name is taken), the current extension is written in its place, and the manifest is created. The backup does not end in .ts, so Pi does not load it; delete it once you’re satisfied with the upgrade. If extensions/observal.ts exists without a matching manifest, doesn’t match the bundled source, and carries no Observal header, Observal treats it as unmanaged and never overwrites or removes it — remove or move the file aside, then re-run observal doctor patch --harness pi to let Observal manage it.

Safe writes

observal doctor patch and observal doctor cleanup write each managed configuration file atomically and preserve unrelated entries. Use --dry-run --output json to review planned harness changes before writing. Agent Pull reports every created or merged file in its result.

File permissions

Client-side files under ~/.observal/ are created with mode 0600 (owner read/write only). This holds your access token, so don’t loosen the permissions.