Skip to content
Security & privacy
Tier-1 local-first security

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 default
    Index, search and re-injection stay on-device
  • No trackers
    No analytics SDK, replay, or pixels
  • Auto-redact secrets
    Keys scrubbed at ingest and paste
  • Three-layer defense
    Host, Origin, CSP enforced

How we block every known attack path

Three independent gates. Any one failure returns 403. No request reaches your sessions otherwise.

MaliciouswebsiteHostallowlistOrigincheckCSP+ sanitize✕YoursessionsEvery request must pass all three layers. Any failure = instant 403.
  • 0
    Accounts required
  • 0
    Trackers or analytics
  • 127.0.0.1
    Only reachable from
  • 3×
    Layered rebinding defense

Security & privacy

Hero above covers trust posture and the four-layer rebinding defense. Detail:

#Verifying it yourself

bash
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 0600

What 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:

  1. Origin / Sec-Fetch-Site: rejects non-loopback origins
  2. Custom X-Recall-Launcher: 1 header: defeats simple-form-POST CSRF
  3. One-shot 60-second preflight token bound to the exact (project, model, limit, force) tuple
  4. 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, month and a rotating nonce - turn it on with recall telemetry on, off with recall 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 from CLAUDE_CODE_OAUTH_TOKEN when you have set that).
  • Where it goes: a GET to api.anthropic.com/api/oauth/usage, with the token as an Authorization: Bearer header. 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.

Last updated