Local-first inbox debt tracker. Upload a screenshot of your messaging app inbox and get a dashboard of likely pending replies.
- Node.js 18+
- A Google AI Studio API key
-
Install dependencies:
npm install
-
Copy the env example and add your API key:
cp .env.example .env.local
Edit
.env.local:GOOGLE_AI_API_KEY=your_key_hereTo test without a Google API key, see Test without Google API key below.
First time or if dev feels stuck compiling:
npm run dev:cleanNormal dev:
npm run devOpen http://localhost:3000.
Dev uses Webpack (not Turbopack) and ignores src-tauri/standalone/ so desktop build artifacts do not slow the file watcher. Use npm run dev:turbo only if you want Turbopack.
If you previously ran npm run build:desktop, delete the heavy standalone copy with npm run clean before web dev.
If Next.js warns about multiple lockfiles and picks your home folder as the workspace root, remove any stray ~/package-lock.json (not part of this project). next.config.ts pins the project root so the watcher does not scan your entire home directory.
Live demo: https://freixanet.github.io/replydebt/
GitHub Pages serves static files only, so the hosted demo runs in browser-only mode:
- Mock screenshot analysis (no Gemini API key on the server)
- Data stored in
localStoragein your browser - Full UI: dashboard, onboarding, priority contacts, guided scan
For live Gemini analysis and SQLite storage, run locally with npm run dev or use the desktop app.
Deploys automatically from main via GitHub Actions (.github/workflows/deploy-pages.yml). Build locally with:
npm run build:pagesOutput goes to out/. In the repo settings, set Pages → Build and deployment → Source to GitHub Actions if it is not already.
ReplyDebt can run as a native macOS app. The desktop build wraps the same Next.js app: in dev it connects to next dev; in production it bundles a local Next.js standalone server + Node runtime.
- Rust
- Xcode Command Line Tools:
xcode-select --install
Runs Next.js and opens a native window:
npm run dev:desktopWeb dev mode is unchanged:
npm run devnpm run build:desktopOutput: src-tauri/target/release/bundle/macos/ReplyDebt.app
Open the .app from Finder. Without code signing, macOS may show an “unidentified developer” warning — use Open Anyway in System Settings or right-click → Open.
- Web dev:
./data/replydebt.db(project folder) - Desktop app:
~/Library/Application Support/com.replydebt.app/replydebt.db - Captured screenshots: app cache folder (
captures/under ReplyDebt cache)
In the desktop app, Analyze and Guided Scan show a Capture Current Screen button. It captures the main display once when clicked — no background monitoring, no automatic app switching.
Required permission: macOS Screen Recording (System Settings → Privacy & Security → Screen Recording → enable ReplyDebt).
- Run
npm run dev:desktop - Open Analyze or Guided Scan
- Switch to your messaging inbox on the primary display
- Click Capture Current Screen and grant Screen Recording if prompted
- Confirm the preview appears, select the source app, then click Analyze
Manual upload/drag-and-drop remains available as fallback.
| Symptom | Likely cause | What to do |
|---|---|---|
| Button not visible | Using web dev (npm run dev) |
Use npm run dev:desktop |
| Permission error | Screen Recording disabled | Enable ReplyDebt in Screen Recording settings |
| Wrong content captured | Inbox not on primary display | Switch to inbox before clicking Capture |
| Black or empty image | Permission not granted yet | Retry after enabling permission |
| Capture OK, analyze fails | Missing Google API key | Use ANALYZE_MODE=mock in .env.local |
- No code signing (Gatekeeper may block on first launch)
- Build is architecture-specific (Apple Silicon vs Intel)
- Bundle size ~80–120 MB (includes Node.js runtime)
- No auto-updater
- Screen capture is macOS desktop only; web dev uses manual upload
- First launch may take 1–3 seconds while the internal server starts
better-sqlite3must be built on the same machine/architecture as the desktop build
- On your phone or desktop, open a messaging app (WhatsApp, Telegram, Instagram, Messenger, or Messages).
- Navigate to the conversation list (inbox view), not an open chat.
- Take a screenshot showing several conversations.
- In ReplyDebt:
- Select the matching source app.
- Upload the screenshot.
- Click Analyze inbox.
- Verify the dashboard shows four buckets: Pending, Review, Done, and Snoozed.
- Check each card shows: app, contact name, preview, timestamp, last sender, confidence, status, and reason.
- Use item actions: Done, Snooze 1h, Snooze 24h, Ignore, High priority, Reset.
- Analyze a screenshot and move one item to Done, snooze another, ignore a contact.
- Hard refresh the browser (Cmd+R) — items should remain in the same buckets.
- Stop the dev server (
Ctrl+C) and runnpm run devagain — open http://localhost:3000; saved items should still appear. - Local database file:
data/replydebt.db. Delete it to reset all saved state.
ReplyDebt cannot call Cursor's AI from the Analyze button. For local testing without Gemini, use one of these options:
-
In
.env.local:ANALYZE_MODE=mock -
Restart
npm run dev. -
Open Analyze, pick a source app, and click Analyze inbox (screenshot optional).
-
The dashboard fills with sample pending/review items. OTP and newsletter rows are filtered out automatically.
-
In
.env.local:DEV_JSON_IMPORT=1 -
Restart
npm run dev. -
Share your inbox screenshot in Cursor chat and ask for JSON only, matching this shape:
{ "items": [ { "contactName": "Alex", "preview": "Are you free tomorrow?", "timestampText": "Yesterday", "likelyLastSender": "them", "confidence": 0.92, "reason": "Direct question from contact" } ] }likelyLastSendermust be"me","them", or"unknown".confidenceis 0–1. -
In ReplyDebt, open Analyze → expand Paste model JSON (dev) → paste the JSON → Analyze inbox (screenshot optional).
Guided Scan walks you through all five messaging apps in order: WhatsApp → Telegram → Instagram → Messenger → Messages. Upload is manual — no automatic screen capture.
- Start the app (
npm run dev) with mock mode if you have no Google API key (ANALYZE_MODE=mockin.env.local). - Click Start Guided Scan in the header.
- For each app step:
- Read the on-screen instructions (open the conversation list, not a single chat).
- Take a screenshot on your phone or desktop.
- Upload it in the modal and click Analyze screenshot (screenshot optional in mock mode).
- Or click Skip this app to move on without scanning.
- Use the app chips (WA, TG, IG, FB, MSG) to rescan any app — click a chip, upload a new screenshot, analyze again.
- Click Stop for now to pause; a Resume banner appears on the dashboard until you finish.
- After all five apps are scanned or skipped, review the summary and click View pending list — results merge into the normal Pending tab.
- Rescanning the same contact with the same preview does not create duplicate items.
Hard refresh or restart the server — scanned items persist in SQLite; an in-progress guided scan can be resumed from the banner.
- No auth, payments, or message sending
- No message draft generation
- No integration with WhatsApp, Meta, or Telegram APIs
- No cloud sync (SQLite is local only)
- Next.js (App Router)
- TypeScript
- Tailwind CSS
- Google Gemini 2.5 Flash (vision)
- SQLite (better-sqlite3) for local persistence