Nowadays, we talk with AI more than our friends.
And these conversations become part of our life, and the problem is they are too many.
Finding the chat from three weeks ago, reusing prompts, sorting, exporting, cleaning up. If you use more than one AI, you do that work four times, in four different sidebars.
I found a tool for all such basic little things that frustrate me a lot, Recallery, a Chrome extension that adds those tools to ChatGPT, Claude, Gemini and Grok. This post is two halves: what's in the box, then how it's built, since this is DEV and the second half is the interesting part.
The tools
One command palette
Cmd/Ctrl+Shift+K on any of the four sites opens a palette. Type, press Enter.
The other shortcuts work in any message box: // for prompts, .. for chains, @@ to pull in another chat as context.
Search across all four AIs
Each site's own search is fine for that site. The gap is between them: you don't remember whether the answer was in ChatGPT or Claude. One box searches all four, over message text, not just titles.
Operators narrow a long list: ai:claude, role:me, "exact phrase", -word, after:/before:.
Prompts and templates
// inserts a saved prompt where the cursor is, your draft intact. Prompts can have blanks: {{audience}}, {{tone:friendly}} for a default, {{tone|friendly|formal}} for a drop-down.
Chains
.. runs a sequence of prompts, each sent when the previous reply finishes, up to 30 steps, with a Stop button.
The rest, briefly
- Continue in another AI opens the current chat in a new tab on another model, ready to send.
- Folders in every sidebar, holding chats from any of the four sites.
- Bulk delete / archive with filters and checkboxes.
- Export a chat to Markdown, PDF, HTML, text or JSON.
- Bookmarks for single messages, smart tags by keyword, a reply-finished sound, and backup/restore.
How it's built
The constraint that shaped everything: local-first, no backend for user data. The extension never sends your chats anywhere. So the hard parts (reading history, searching, licensing) all had to work in the browser.
Stack
Manifest V3, TypeScript, Preact (not React) with esbuild. The only runtime dependencies are preact and fflate (for zip export). Vitest with fake-indexeddb for unit tests, Playwright with axe-core for end-to-end and accessibility. Roughly 130 source files and 33 test files.
Injecting UI without fighting the host page
The UI mounts in a closed shadow root (attachShadow({ mode: "closed" }) in production, open in the test build so Playwright can see it). Styles go in via adoptedStyleSheets rather than an inline <style>, because a strict Content-Security-Policy on the host page blocks inline styles but not constructable stylesheets.
Isolation isn't just CSS. The host stops propagation of keyboard, input, paste and composition events so the site's own shortcuts don't eat your keystrokes while you're typing in the palette.
Four sites behind one interface
There's a PlatformAdapter interface and one implementation per site (chatgpt.ts, claude.ts, gemini.ts, grok.ts). An adapter exposes identity (currentChatId, account), history (listChats as an async generator, fetchChat), optional deleteChats/archiveChats, DOM accessors (composer, send/stop buttons, message list, sidebar anchor), and a pacing profile.
The index is not scraped from the DOM. Each adapter calls the site's own web-app API from the content script with the user's existing session cookies, exactly as the site itself does. ChatGPT uses /backend-api/conversations, Claude its /api/organizations/... endpoints, Gemini a batchexecute RPC, Grok its /rest/app-chat endpoints.
Reading history politely
A background Indexer syncs 4s after load, then every 15 minutes. Only one tab per account indexes (a 90s lease held by the service worker); other tabs skip. Syncs are incremental: list chats, compare updatedAt, re-read only stale ones. Every request goes through a token-bucket rate limiter, and a 429 pauses the bucket for the site's Retry-After. If a list comes back empty while chats are known, it assumes a sign-out rather than deleting the index.
Storage
chrome.storage.local for the library (folders, prompts, chains, bookmarks, tags) as JSON. IndexedDB for the search index, in the extension's own origin, so clearing the site's data doesn't wipe it. If the DB is ever corrupt it's dropped and rebuilt, since it's only a cache of data that lives on the sites.
Search, honestly
No search library and no inverted index. The service worker keeps folded text in memory and scans it with compiled predicates. Text is folded to be case- and accent-insensitive. The query parser is hand-written and supports phrases, OR, exclusions, in:title, role:, ai:/platform:, tag:, folder:, is:bookmarked, and date ranges. Ranking is a plain heuristic (title hit, capped message hits, a recency decay), not BM25. Snippets map match ranges back onto the original text through a fold map so highlighting lands in the right place.
Reply-finished detection
A single shared MutationObserver on document.documentElement, coalesced to one tick per gap. "Finished" is "the stop button is no longer visible", debounced ~900ms because sites briefly swap the stop and send buttons. Chains and the reply sound both hang off that signal, so there's no polling.
Licensing without a license server call
Pro is a compact ES256 JWT (ECDSA P-256). After a Polar purchase, the site hands the token to the extension over externally_connectable, and the extension verifies it offline with WebCrypto. Public keys are baked into the build; the build script refuses anything that isn't a public P-256 JWK. The trade-off is that revocation ships as a bundled list, so a refund takes effect on the next release, not instantly. The extension makes zero requests to any Recallery server at runtime.
Permissions
storage, unlimitedStorage, scripting, contextMenus. No tabs, no activeTab. Host access is optional and granted per site from onboarding, and content scripts are registered at runtime with chrome.scripting only for sites you've enabled.
Try it or read the code-level guides
Free plan with limits (5 prompts, 5 folders, 1 chain, 30-day search). Pro removes them: $6/mo or $48/yr, 7-day trial, no card.
If a particular tool is interesting, there's a short guide for each on the site (search, prompts, templates, chains, folders, export, bulk delete). Happy to answer build questions in the comments.







Top comments (0)