Your Claude conversations stay on your machine by default.
No account, no cloud sync, no trackers. Indexing, search and context re-injection are fully local. Everything else that leaves is user-initiated or opt-in and off by default, apart from the license activation and revocation check that come with a Pro license: the revocation check runs 30 seconds after the daemon starts and every 24 hours after that, once a key is stored, and sends the key alone. The network-activity table lists every destination with its exact payload.
- Local-first by defaultIndex, search and re-injection stay on-device
- No trackersNo analytics SDK, replay, or pixels
- Auto-redact secretsKeys scrubbed at ingest and paste
- Three-layer defenseHost, Origin, CSP enforced
How we block every known attack path
Three independent gates. Any one failure returns 403. No request reaches your sessions otherwise.
- 0Accounts required
- 0Trackers or analytics
- 127.0.0.1Only reachable from
- 3×Layered rebinding defense
Security & privacy
Hero above covers trust posture and the four-layer rebinding defense. Detail:
#Verifying it yourself
lsof -iTCP -sTCP:LISTEN -P | grep recall # 127.0.0.1 only
sudo tcpdump -i any -n "host not 127.0.0.1 and not 0.0.0.0" # see note below
curl -H "Host: attacker.com" 127.0.0.1:<port>/api/health # 403 (rebinding blocked)
curl -H "Origin: https://evil.com" 127.0.0.1:<port>/api/stats # 403 (cross-origin blocked)
ls -la ~/.recall/daemon.token # mode 0600What the tcpdump line will actually show. Indexing, search, and context re-injection are
fully local, so browsing and searching produce no outbound traffic. You will see traffic if you
are licensed (a revocation check to clauderecall.com 30s after the daemon starts, then daily), and
from any optional feature you switched on. The README's network-activity table lists every
destination with its exact payload. "No outbound at all" is only true of an unlicensed install
with nothing enabled.
#Auto-redaction at ingest
If you paste an API key into Claude Code mid-conversation, it lands in the JSONL at ~/.claude/projects/. Recall
scrubs it at index time before SQLite or the search index see it.
Patterns scrubbed: Anthropic / OpenAI / AWS / GitHub / Stripe / Slack / Google keys, JWTs, SSH/RSA private keys, URLs
with embedded passwords, assignment-style token= / api_key= secrets.
The original JSONL stays untouched; only the derived store is scrubbed. Retroactively scrub older sessions: recall index --force.
#Bug Patterns launcher (token-spend defense)
Four gates before a browser request can spend a token:
- Origin / Sec-Fetch-Site: rejects non-loopback origins
- Custom
X-Recall-Launcher: 1header: defeats simple-form-POST CSRF - One-shot 60-second preflight token bound to the exact (project, model, limit, force) tuple
- Server ceilings: 500-session max per request, 1M tokens / 24h rolling, per-project lock
Audit log at ~/.recall/launcher-audit.log. Same combined budget covers extract-outputs and bug-pattern synthesis.
#What we deliberately don't build
- No VS Code clipboard extension (compromised marketplace = global keylogger vector)
- No global clipboard daemon (privilege-escalation magnet)
- No analytics SDK, no session replay, no ad or attribution pixels, no third-party trackers
- No always-on telemetry. The only thing Recall reports about you to us is a once-a-month install ping that is off
by default and sends
event,version,platform,arch,monthand a rotating nonce - turn it on withrecall telemetry on, off withrecall telemetry off. Two optional features call Anthropic rather than us; both are off by default and both are disclosed below - No cloud sync by default (team-sharing, when it ships, will be opt-in and e2e encrypted)
#Pro license
Machine-bound (SHA-256 fingerprint of hostname/user/OS/arch). Three-device limit per key. Activation is one HTTPS call to clauderecall.com; the signed JWT (ES256) validates offline.
The only periodic call to us is the revocation check, and it only runs once you are licensed: a check to
clauderecall.com/api/license/check sending your license_key, 30 seconds after the daemon starts and every 24
hours after that. It exists so a refunded or revoked key stops working. It sends no session content. If it cannot reach
the network your license keeps working offline.
It is not the only periodic call Recall can make. The optional Fable status-line column below polls Anthropic on its own schedule, and it is not license-gated: it behaves identically on Free and on Pro.
#Optional features that call Anthropic
Two features are off out of the box, are switched on only by you, and talk to Anthropic rather than to us. Neither one is part of indexing, search, or context re-injection, and neither requires Pro.
#Fable weekly column in the status line
Off by default. macOS only. Not license-gated. Turn it on with recall statusline fable on, off again with
recall statusline fable off.
The rest of the status line is built from data Claude Code already hands it, with no network call and no credential read. This one column is the exception, and it does both:
- What it reads: your Claude Code OAuth token, out of the macOS login keychain via
security find-generic-password(or fromCLAUDE_CODE_OAUTH_TOKENwhen you have set that). - Where it goes: a
GETtoapi.anthropic.com/api/oauth/usage, with the token as anAuthorization: Bearerheader. There is no request body. - How often: at most once every 15 minutes, and only while a session is rendering. It runs in a detached worker, never on the render path.
- What comes back: your Fable weekly percentage and its reset time. Nothing else is kept.
- No session content is sent. Not a message, not a title, not a file path.
The token is never logged, never written to disk, never passed as a command-line argument, and never included in an
error message. ANTHROPIC_BASE_URL is honored if you have set one, which is deliberate parity with Claude Code and
the Anthropic SDK.
#AI tagging with your own API key
Off by default. It needs your own Anthropic API key plus an explicit enable; there is no key in the box. When a scan
runs it sends, to api.anthropic.com/v1/messages: your top-50 tag vocabulary across the whole database, the
session's current_tags, the project folder name (not the full path), alias, git_branch,
first_user_message (in full, not truncated), and message_sample (5 messages sampled across the session,
first 400 characters of each).
Note that alias carries your editor tab name, which may contain a client or project name. Worth a look before you
turn this on for work sessions.
Tagging runs only when you ask for it. Switch autopilot on as well and it also runs in the background, kicked once when the daemon starts.
#XSS hardening
Every markdown render goes through DOMPurify with a strict allowlist. href and src forbidden. javascript:
and data: URIs impossible by construction. Only class and title survive.