Skip to content

Short, honest answers to the questions people actually ask. Where a claim is load-bearing, it reflects the behavior of the shipped code, not an aspiration.

Does the archive contain sensitive data?

Yes. Be clear-eyed about this: a transcript is a faithful record of everything that passed through a session — your prompts, the agent’s replies, the file contents it read, the command output it saw. If a secret appeared on screen, it is in the transcript, and Recall preserves it as faithfully as everything else. Recall does not redact or rewrite content; a converter that “improves” content is exactly what the invariants forbid.

What Recall does exclude is credential files, by name, at sync time. From the sync script’s exclusion rules:

GEMINI_EXCLUDE_FILES = {"oauth_creds.json", "google_accounts.json"}
GEMINI_CRED_FILES = {"antigravity-oauth-token"}
CODEX_EXCLUDE_FILES = {"auth.json"} # credentials never enter the archive

The Claude stage sweeps only ~/.claude/projects/, so Claude Code’s own credential and settings files are never touched at all. That is file-level hygiene, not content redaction. Treat the dataset root with the same sensitivity as the home directories it mirrors — because that is what it is.

Does anything leave my machine?

Not by Recall’s hand. The sync reads local directories and writes to a local dataset root; it is pure Python stdlib with no network calls and no cloud API — there is nothing in the code that could phone home. The local preservation path never crosses a cloud mount, and the installer refuses cloud-synced paths for the local root outright.

Getting the archive off the machine is a choice you make, in two explicitly named tiers: consolidation (each machine pushes its subtree into a shared root, which may sit on a vendor cloud mount — the installer names that choice when you make it) and replication to cloud storage, which is permanently delegated to a byte-mover you already trust — rclone, a vendor client, Syncthing, plain rsync. By design, Recall never speaks a cloud API. See Topologies.

Does it use an LLM anywhere?

No. The pipeline is deterministic, idempotent, and zero-LLM: same input, byte-identical output; re-runs rewrite nothing; no API calls in sync or convert. The processing layer that projects the raw archive into per-project Markdown is a format converter, not an editor — it never summarises, rewrites, or copy-edits a transcript. Profiles drop whole events or blocks by declared rule; they never alter a kept block. Anything that wants an LLM reads the archive from the outside; the pipeline itself never calls one.

Does it need a server or a daemon?

No. There is no server and no resident process. An hourly scheduler unit native to the platform — a LaunchAgent on macOS, a systemd user timer on Linux, Task Scheduler on WSL — runs the sync script, which runs to completion and exits. The unit points straight at the repo checkout: nothing is installed into ~/.claude or ~/.pibmo, there is no deployed copy and no self-updater, and updating is git pull — the next tick runs the new code.

Does it work offline, or with no cloud account at all?

Yes. A single computer with no cloud anything is the whole product, not a degraded mode: install, accept the proposed local root, activate the scheduler unit — done. The prerequisites are Python 3.9+ and nothing else; a cloud account or client is explicitly not one. Cloud storage only enters the picture at the multi-machine replication tier, and even there it is optional and delegated. The archive itself never depends on a network being up.

What happens when a tool rewrites or compacts a transcript?

The archived original survives. This is the core invariant: a genuine append extends the archived copy; a divergent rewrite — for example a compaction — is kept as a sibling fork, {uuid}.fork-{sha8}.jsonl, never written over the original; a shrunk source file is a regression and is skipped. Which state is canonical is decided at process time, not by the sync. Nothing in the archive is ever deleted. See the v1 on-disk contract for the naming.

What happens if two syncs run at the same instant?

One syncs; the other exits immediately. Runs are serialized by a non-blocking exclusive flock keyed by the dataset root, held in a local lock directory rather than in the root itself — deliberately, because flock semantics over cloud-synced storage are unreliable and lock churn would replicate. A manual run alongside the hourly tick is therefore safe at any time. And per the diagnostics invariant, an environment failure (an unwritable lock directory, a foreign-owned lock file) raises an error instead of masquerading as “already running” forever.

Which tools does it archive?

Three sources, swept for this user only (a machine-wide multi-user sweep is a separate opt-in, in design):

SourceSwept fromLands underNotably excluded
Claude Code~/.claude/projects/{root}/{machine}/claude/projects/{encoded}/per-project memory directories; the rest of ~/.claude is never swept
Gemini CLI + Antigravity~/.gemini/{root}/{machine}/gemini/OAuth credentials, extension code, the browser profile, media/binaries/caches
Codex CLI~/.codex/{root}/{machine}/codex/auth.json, tmp/, cache/

Raw is a faithful per-machine mirror of each tool’s native layout — no renames, no remapping. Grouping sessions into logical projects happens at process time via projects.json; see Configuration.

How do I know it is actually archiving?

Ask the doctor — and take the question seriously, because Recall’s own history answers why: a fleet machine once failed silently for five weeks because a one-line PATH defect was swallowed instead of surfaced. The doctor exists so that class of failure is asked about on purpose:

Terminal window
python3 ~/code/pibmo-recall/scripts/sync/doctor.py --root <ROOT>

It checks that the machine is registered, that the root is reachable and writable (a write-and-delete canary under logs/ — the raw archive is never touched), that the scheduler unit exists, matches a fresh render, and points at code that still exists, and that the last sync heartbeat is younger than 26 hours (an hourly schedule plus a slept-through laptop day). With a consolidated root it also measures per-machine replication lag there. Every failure prints its exact fix; exit 0 on pass, 1 on any failure. The optional session-start banner watches the watchers: it prints a loud Archive: ⚠ STALE at session start when this machine’s last sync is older than 26 hours, and a quiet Archive: OK when it is not. See Troubleshooting.

How big does the archive get?

It only grows — that is the point, so be deliberate about it. There is no retention policy and no size cap: nothing ages out, and no flag deletes. What keeps growth proportionate is the shape of the data and the preservation engine: transcripts are line-oriented JSON text; a fork copies a file only on a divergent rewrite; other files are stored as content-addressed blob versions, so unchanged content is not stored twice; SQLite snapshots are gated on a logical hash, so an unchanged database is not re-snapshotted.

The envelope is one developer’s coding sessions across a personal fleet of machines, swept hourly. It is not designed as a team-wide ingestion service. If you need disk space back, that is a human decision made with open eyes — the tooling will never make it for you.

How is this different from just backing up ~/.claude?

A backup preserves what the tool still had at backup time — and the tools rotate and rewrite. A mirror-style backup faithfully replicates the loss: a compacted transcript overwrites the original in the next pass, and a deleted one disappears from the mirror. Recall adds the discipline a plain copy lacks:

  • Capture inside the rotation window. Hourly sweeps archive a transcript before the tool ages it out.
  • Append-only preservation with forks. A rewrite lands as a sibling, never over the archived original; regressions are refused; nothing is deleted.
  • Provenance. Every run, per-file observation, and JSONL schema change is recorded in {root}/{machine}/pibmo.db.
  • Credential exclusion by rule, so the archive is not also a copy of your auth tokens — a raw ~/.claude or ~/.codex backup would be.
  • Process-time projection. projects.json plus denylist profiles turn the raw archive into merged per-project Markdown without ever touching raw.

If all you want is yesterday’s state, a backup is fine. Recall is for never losing a transcript.

Does it work on Windows?

Via WSL. Recall runs inside a WSL2 distro and archives that environment’s own ~/.claude (and ~/.gemini, ~/.codex) — sessions you run in WSL, not Windows-native ones; those are plainly not archived. The local root must live on the distro’s ext4 filesystem — /mnt/* paths are refused, because Windows drives cross drvfs (slow, permission-mangling, and possibly cloud-synced on the Windows side where WSL cannot tell). Scheduling is preferred from the Windows side via Task Scheduler, which starts WSL on demand, so nothing depends on a window staying open. See Getting started for the exact command.

How do I remove it?

There is no uninstall command; removal is deleting what the installer wrote. On a machine named <machine>:

WhatWhere
Scheduler unit (macOS)~/Library/LaunchAgents/com.pibmo.recall.sync.plistlaunchctl bootout gui/$UID com.pibmo.recall.sync first
Scheduler unit (Linux)~/.config/systemd/user/pibmo-recall-sync.timer + .servicesystemctl --user disable --now pibmo-recall-sync.timer first
Cron fallback line (if you chose it)remove via crontab -e
Machine registrationthis machine’s row in {root}/machines.json
Banner hook (if wired)the SessionStart entry in ~/.claude/settings.json, and the banner’s own map ~/.claude/machines.json
The codethe repo checkout (e.g. ~/code/pibmo-recall)
The archive itselfthe dataset root

Deleting the dataset root deletes every transcript it holds — the one deletion the tooling itself will never perform, so it is yours to make deliberately. Under a multi-machine setup, the consolidated root still holds this machine’s replicated subtree; removing the data everywhere means the local root, the consolidated root, and any replicas your replication tool made.