Skip to content

Repository files navigation

bliptracker

Chrome Web Store users rating license: MIT

bliptracker is the scope for your AI chats — a Chrome extension that labels your claude.ai conversations with a 🔴 / ✅ prefix so you can see at a glance which ones are waiting on you versus done — on desktop and on mobile. → bliptracker.xyz

⚠️ Unofficial community tool. Not affiliated with or endorsed by Anthropic. It uses undocumented claude.ai endpoints and may break without notice.

bliptracker — know which AI chats are waiting on you

Install

➕ Add to Chrome — the easy way.

Or load from source (unpacked)
  1. Clone or download this repo.
  2. Go to chrome://extensions → enable Developer modeLoad unpacked → select the extension/ folder.
  3. A setup tab opens automatically — copy the preference prompt into your Claude profile settings (it links you straight there).

After installing, do the one-time setup (below) and you're done.

Demo

▶️ A short walkthrough GIF is coming. Recording spec: marketing/demo-gif-spec.md.

Screenshots

Waiting-on-you, labelled The queue popup One-time setup
Labelled chat list Waiting-on-you queue One-time setup

How it works

  1. A one-time preference prompt in your Claude profile makes Claude end substantive replies with a machine-readable marker: 🔴 Waiting on you: <reason> or ✅ Resolved — safe to archive. This runs everywhere you use Claude, including mobile.
  2. The extension reads that marker and renames the chat title with a 🔴 / prefix. Because titles are stored server-side, the labels sync to the claude.ai mobile app automatically — you only run the extension on desktop.
  3. Click the toolbar icon for a “waiting on you” queue of your 🔴 chats; the badge shows the count.
  4. Not ready to deal with a chat yet? Snooze it from the popup — six presets (1 hour, this evening, tomorrow 9am, 3 days, next Monday, 1 week) or a specific date and time, picked on a half-hour grid. It leaves the queue and the badge, its title becomes 💤🔴 … (synced to mobile like any label), and it sits in a collapsed Snoozed section until it wakes — automatically, via a one-shot alarm, even between sweeps. Wake times live in local extension storage, so snooze schedules are per-machine.

Classification is deterministic — a string match on the marker Claude wrote, never an after-the-fact guess.

Settings

Right-click the toolbar icon → Options (or the Settings link in the popup):

  • Enabled — master switch.
  • Mirror status to stars — also star 🔴 chats / unstar ✅ ones, so the Starred section is your mobile queue. Off by default so it doesn't collide with stars you set manually.
  • Sweep interval — how often to re-check all chats. The chat you're actively viewing updates instantly regardless.

Architecture

Three layers, each with one job:

  • Orchestrator (extension/lib/orchestrator.js) — platform-agnostic. Owns the sweep, the on-demand re-check, the seen cache and the badge. Knows only the adapter interface, never an endpoint.
  • Service adapters (extension/adapters/*.js) — one per platform, running in the service worker. Own endpoints, auth and response parsing, and normalise everything to {id, name, isStarred, updatedAt, lastAssistantText, isTemporary}. Registered in adapters/index.js.
  • DOM adapters (the DOM_ADAPTERS map in extension/content.js) — one entry per host, running in the page. Own selectors: currentId(location) and titleNodes(id).

The split follows a process boundary, not just a file boundary: service adapters need the worker's cookie context, DOM adapters need the page. That's why content.js carries its own map rather than importing the registry.

Beyond the layering:

  • Two triggers, one brain. content.js (instant, the chat you're viewing) and the alarm sweep (periodic, all chats incl. mobile-finished) both funnel through checkConversation/applyStatus in the orchestrator. No classify or rename logic is duplicated in the content script.
  • Idempotent renames. Renaming bumps a chat's updated_at, so the next sweep re-checks it — titleTransform() is idempotent, so the re-check is a no-op. Convergence by design, no bookkeeping.
  • Best-effort DOM paint. The instant sidebar update writes to the page's DOM; if React reverts it, the resulting mutation re-triggers our observer and we re-apply. The server-side rename is the source of truth regardless.
  • No backend. All requests go directly to the platform with your own session; nothing is sent anywhere else. See PRIVACY.md.

Confirmed endpoints (recon 2026-06-12)

Used only by the Claude service adapter (extension/adapters/claude.js); no other module references them. All under /api/organizations/{orgId}:

Method Path Use
GET /chat_conversations?limit=N&offset=M list, updated_at desc (incl. is_starred); a short page means end-of-list
GET /chat_conversations/{uuid} full chat incl. chat_messages[]
PUT /chat_conversations/{uuid} {"name":…} rename
PUT /chat_conversations/{uuid} {"is_starred":bool} star
DELETE /chat_conversations/{uuid} delete (unused)

Roadmap

See ROADMAP.md for shipped features, what's next, and planned future work (e.g. a popup "Resolve" button, one-click preference injection, bulk-archive, and multi-AI adapters).

Development

Pure JS, no build step, no dependencies. Load extension/ unpacked at chrome://extensions.

Tests use Node's built-in runner (Node ≥ 20):

npm test          # node --test 'tests/**/*.test.mjs'

tests/helpers/ holds a ~50-line chrome stub and an in-memory fake adapter, so the orchestrator can be driven without a browser. Adding a platform means writing a service adapter and a DOM adapter — see ROADMAP.md.

Feedback & contributing

Found a bug, or got an idea? Open an issue — feedback on the onboarding especially welcome. PRs are warmly received; it's a small, no-build codebase, so jump straight in.

License

MIT © 2026 Andrew Miller

About

Tracking AI chat followups

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages