How it works
The honest version. What runs on your machine, what hits the network, what the extension actually does on each chat platform.
Local-first architecture
The whole archive lives on your filesystem. Three artifacts:
| Artifact | Location | What it stores |
|---|---|---|
| Vault | ~/.kept/vault/ | One markdown file per conversation, plus assets/ for downloaded images |
| FTS index | ~/.kept/index.db | SQLite database with FTS5 tables. Rebuildable from the vault. |
| Knowledge graph | ~/.kept/kg.db/ | CozoDB store with topics, entities, embeddings. Rebuildable from the vault. |
Delete the index and the graph; they regenerate on next launch. The vault is the source of truth.
The desktop app talks to all three. The Chrome extension talks only to the desktop app, via localhost:18241.
What hits the network
Three things, and only when you cause them:
- The Chrome extension fetches conversations from the chat platform you're authenticated to. Reading what your browser already has access to — same-origin requests with your existing session cookies.
- The agent (continuing a chat, Smart Recall, etc.) sends prompts to your selected model provider. Same trust boundary as any normal API call you'd make. Your API key, your bill.
- Updater checks for a new desktop app release on Tauri's updater endpoint, on a configurable interval. Disable in Settings → Updates if you don't want them.
That's the complete list of outbound traffic. The vault index, KG store, the embedding cache, the topic clustering — all local. Pointing the agent at Ollama makes (2) local too: zero outbound traffic end to end.
How the extension reads each platform
The extension uses your existing browser session — it doesn't store credentials, doesn't proxy through a third party. Each chat platform has its own provider script under extension/platforms/ that knows that platform's specifics:
ChatGPT
GET chatgpt.com/api/auth/session→ access token from your existing sessionGET chatgpt.com/backend-api/conversations?offset=&limit=&order=updated→ list of your conversationsGET chatgpt.com/backend-api/conversation/{id}→ the full conversation tree- Images: detects
image_asset_pointerparts (file-service:// and sediment:// prefixes), fetches the signed download URL, saves the image to~/.kept/vault/chatgpt/assets/
The conversation comes back as ChatGPT's mapping node tree. The extension walks it, filters to user / assistant / system / tool roles, sorts by create_time, and serializes to markdown.
Claude
GET claude.ai/api/organizations/{org}/conversations→ listGET claude.ai/api/organizations/{org}/conversations/{id}→ detail withchat_messagesarray- Images: not currently downloaded (Claude's image hosting requires a re-auth flow we haven't implemented; conversations reference images by URL, but the URL won't work outside Claude's context)
Gemini
- Uses Gemini's
batchexecuteRPC with two operation IDs:MaZiqc(list) andhNvQHb(detail) - Pagination via a token at
parsed[1], max 100 conversations per page - Images: external CDN URLs (
lh3.googleusercontent.com). Not downloaded — CORS blocks the fetch from extension context. Conversations reference these by URL.
Grok
POST grok.com/rest/app-chat/conversations/list→ listPOST grok.com/rest/app-chat/conversations/{id}/load-responses→ node map + messages- Two-step fetch: first get the node map, then fetch the response payload separately
- Images: downloaded from
assets.grok.comto~/.kept/vault/grok/assets/
Kimi
kimi.com/api/chat/list→ listkimi.com/api/chat/{id}/messages→ message blocks- Messages come as
blocks[].text.contentarrays in reverse-chronological order; the extension reverses them - Images: not currently implemented
The full per-platform breakdown lives at kept/extension/api_process_flow.md in the repo.
What the extension does NOT touch
- It does not send anything to the chat platform —
@keptis captured in the input box before submission and the trigger text is removed before any send event fires. - It does not request
<all_urls>for general access. The only<all_urls>content script is the inline@keptpalette renderer; it attaches a key listener and renders an in-DOM element, nothing else. - It does not store credentials. No password fields, no token storage, no cookies copied. It uses your existing browser session.
Permission model in detail
The extension's manifest.json requests:
- Host permissions for the five chat platforms plus a few CDNs (
files.oaiusercontent.com,lh3.googleusercontent.com,assets.grok.com,kimi-img.moonshot.cn) needed to download referenced images - Local connection to
localhost:18241and127.0.0.1:18241— the Kept desktop app's local HTTP server storagefor extension settings (vault path, sync interval, enabled platforms)alarmsfor auto-sync schedulingidleto pause auto-sync when the system is idle (avoids hammering platforms when you're away)
It does not request: tabs, webRequest (general), cookies, <all_urls> host access, nativeMessaging, or any other broad permission.
Code execution sandbox
Every code-execution request from the agent prompts you for explicit consent. There's no "always allow" toggle by design.
The sandbox:
- Read access: vault directory, scratch directory, plus any directory you've explicitly added via Settings → Knowledge base
- Write access: scratch directory only
- No internet access (no
urllib,requests,socket,subprocessfor outbound) - No environment variables, no shell access, no other-process introspection
It's a Python interpreter with a restricted import list and a process boundary. Not isolated to the level of a separate VM, but tight enough that the failure mode of running an LLM-generated script is a wrong answer, not a compromised filesystem.
Updates
Tauri's auto-updater pings the configured update endpoint on launch (or on a schedule). If a new release is available, you get a prompt to install. The update is signed — Tauri verifies the signature against the public key bundled in the app. Settings → Updates controls the schedule and disables it.
Data export
The vault is plain markdown. Copy it to a backup, sync it to git, ship it to another machine — Kept doesn't lock anything. The only Kept-specific artifacts are the FTS index and the KG store, both rebuildable.
If you uninstall Kept, your vault remains. If you delete ~/.kept/, you lose the index and graph but the markdown vault is untouched (assuming you've moved it elsewhere; the default is inside ~/.kept/, in which case it goes with the rest).