A browser extension (Chrome / Edge / Firefox) that syncs your OpenRouter chat history across devices and browsers.
OpenRouter's chat playground is local-first: conversations live in your browser's IndexedDB with no server-side sync, and the only official tools are manual Export/Import JSON. ChatSync automates that: it watches the local database and merges every room into a remote backend you own, so any device pointing at the same backend converges to the same chat list.
openrouter.ai (content script) your storage backend
┌──────────────────────────┐ ┌────────────────────────┐
│ IndexedDB │ push / │ manifest.json │
│ openrouter:playground:v3│ pull │ rooms/<roomId>.json │
└──────────────────────────┘ └────────────────────────┘
▲ service worker (diff / merge / alarms)
- Format: each room is serialized as
orpg.3.0JSON, byte-compatible with OpenRouter's official Export. Files in the sync root can be imported by hand at any time. - Merging: per-room content hash against a remote manifest. Rooms are matched by their OpenRouter-issued ids; conflicting edits resolve last-write-wins by
room.updatedAt. - Deletions: propagate in both directions via tombstones. Deleting a chat on one device removes it everywhere on the next sync; a remotely-deleted room that was edited locally afterwards is resurrected instead of lost. A fresh/empty remote never deletes local data.
- Application: pulled rooms are upserted into IndexedDB by id (idempotent, same semantics as the official Import) and the openrouter.ai tab reloads to show them.
- Size: optional "strip model catalog snapshots" mode drops
characters[].modelInfo(typically ~90% of payload). Base64 images inside items are synced as-is.
| Backend | Auth | Notes |
|---|---|---|
| GitHub repo | Fine-grained PAT (Contents read/write) | Every changed room is its own commit, so you get full history and rollback via git. |
| WebDAV | Basic auth | Works with Nextcloud, nutstore, Synology, or a self-hosted server. |
pnpm install
pnpm zip:all # chrome + edge + firefox zips in .output/
pnpm test # sync engine unit testsThen load the unpacked build (.output/chrome-mv3, .output/edge-mv3, or .output/firefox-mv3):
- Chrome / Edge:
chrome://extensions(oredge://extensions) → enable Developer mode → Load unpacked - Firefox (128+):
about:debugging#/runtime/this-firefox→ Load Temporary Add-on → pick.output/firefox-mv3/manifest.json, or install the signed zip from releases
Grab prebuilt zips from releases.
- Open the extension options and configure a backend (GitHub token + repo, or WebDAV URL + credentials).
- Click save & test connection.
- Open https://openrouter.ai/chat, click the ChatSync icon, and hit sync now. Optionally set an auto-sync interval (minutes) in options.
Syncing requires an openrouter.ai tab (the extension opens one in the background automatically if none exists, and closes it when done).
src/
├── entrypoints/
│ ├── background.ts # sync orchestration, tab bridging, alarms
│ ├── content.ts # IndexedDB bridge on openrouter.ai
│ ├── popup/ # status + manual sync
│ └── options/ # backend configuration
└── lib/
├── types.ts # orpg.3.0 + sync manifest models (from live recon)
├── orpg.ts # export assembly / import planning / hashing
├── playground-db.ts # IndexedDB read / upsert / delete
├── sync-engine.ts # pure diff/merge engine (+ unit tests)
└── adapters/ # github, webdav
Chat content only ever travels between your browser and the backend you configure. Credentials are stored in chrome.storage.local. No telemetry.
MIT