{"id":51070659,"url":"https://github.com/asaf-kali/narrative","last_synced_at":"2026-06-23T10:01:40.076Z","repository":{"id":351755514,"uuid":"1201575916","full_name":"asaf-kali/narrative","owner":"asaf-kali","description":"A local analytics dashboard for exploring the narrative hidden in your WhatsApp chat history.","archived":false,"fork":false,"pushed_at":"2026-05-13T21:07:47.000Z","size":2674,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-13T21:33:18.600Z","etag":null,"topics":["fastapi","react","whatsapp"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/asaf-kali.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-04T21:34:54.000Z","updated_at":"2026-05-13T21:07:52.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/asaf-kali/narrative","commit_stats":null,"previous_names":["asaf-kali/narrative"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/asaf-kali/narrative","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asaf-kali%2Fnarrative","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asaf-kali%2Fnarrative/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asaf-kali%2Fnarrative/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asaf-kali%2Fnarrative/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/asaf-kali","download_url":"https://codeload.github.com/asaf-kali/narrative/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asaf-kali%2Fnarrative/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34684686,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-23T02:00:07.161Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fastapi","react","whatsapp"],"created_at":"2026-06-23T10:01:39.327Z","updated_at":"2026-06-23T10:01:40.071Z","avatar_url":"https://github.com/asaf-kali.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"frontend/src/assets/large.png\" alt=\"Narrative logo\" width=\"250px\" /\u003e\n\u003c/p\u003e\n\n[![CI](https://github.com/asaf-kali/narrative/actions/workflows/ci.yml/badge.svg)](https://github.com/asaf-kali/narrative/actions/workflows/ci.yml)\n[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)\n[![Type checked: mypy](https://img.shields.io/badge/type%20check-mypy-22aa11)](http://mypy-lang.org/)\n\nA local analytics dashboard for exploring the narrative hidden in your WhatsApp chat history. Reads decrypted SQLite databases directly, unlocking insights text exports cannot provide.\n\n- **All processing is local** — No network calls, no telemetry, no cloud\n- **No message data is sent anywhere** — Server binds to `127.0.0.1` only\n- **Database files never committed** — `data/` directory is gitignored\n\n---\n\n## What It Does\n\nReads the encrypted-then-decrypted SQLite databases (`msgstore.db` + `wa.db`) that WhatsApp stores on your Android device. Visualize activity heatmaps, explore your contact network, analyze messaging patterns, and browse conversations with full metadata and reaction history.\n\n---\n\n## Getting the Database Files\n\n\u003e **Android only.** iOS stores WhatsApp data in a proprietary format not currently supported by this tool.\n\nWhatsApp encrypts its local backup as `.crypt15` files. To decrypt them, you need a **64-digit encryption key** that you generate once in WhatsApp settings and must keep safe forever.\n\n### 1. Generate your encryption key\n\n1. In WhatsApp: **Settings → Chats → Chat Backup → End-to-end Encrypted Backup**\n2. Tap **Turn On**, then choose **Use 64-digit encryption key** (not a password)\n3. WhatsApp displays your 64-digit key — **copy it and store it in a safe place immediately**\n4. Tap **Create** to enable encrypted backups\n\n\u003e ⚠️ **Do not lose your key.** It cannot be recovered from WhatsApp. Without it, your backup files are permanently unreadable. Store it in a password manager and never share it.\n\n### 2. Back up and copy the files\n\n1. Trigger a backup: **Settings → Chats → Chat Backup → Back Up Now**\n2. Copy these files from your device to the `data/` directory (via USB cable, ADB, or a file manager app):\n   - `Android/media/com.whatsapp/WhatsApp/Databases/msgstore.db.crypt15` — all messages\n   - `Android/media/com.whatsapp/WhatsApp/Backups/wa.db.crypt15` *(optional — for contact names)*\n\n### 3. Decrypt\n\n```bash\njust decrypt \u003cyour-64-digit-key\u003e\n```\n\n\u003e Your decrypted `.db` files contain all your messages in plain text. Keep them secure and never share them.\n\n---\n\n## Prerequisites\n\n- [uv](https://docs.astral.sh/uv/) `\u003e= 0.9`\n- [just](https://github.com/casey/just) command runner\n- Node.js 20+ (only needed for frontend development)\n\n---\n\n## Setup\n\n```bash\n# 1. Clone and install dependencies\ngit clone https://github.com/asaf-kali/narrative\ncd narrative\njust install\n\n# 2. Copy encrypted backup files into data/ and decrypt (see \"Getting the Database Files\" above)\njust decrypt \u003ckey\u003e\n\n# 3. Start the server (builds frontend automatically)\njust run\n\n# Opens at http://127.0.0.1:8050\n```\n\n---\n\n## Development\n\n```bash\n# Terminal 1 — backend with auto-reload\njust run-dev --msgstore data/msgstore.db\n\n# Terminal 2 — Vite dev server (proxies /api → :8050)\njust frontend-dev\n# Open http://localhost:5173\n```\n\nOther useful commands:\n\n```bash\njust lint          # format + ruff fix + pre-commit\njust check-ruff    # ruff format + lint check (CI)\njust check-mypy    # mypy type check (CI)\njust frontend-build  # build React app into frontend/dist/\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasaf-kali%2Fnarrative","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fasaf-kali%2Fnarrative","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasaf-kali%2Fnarrative/lists"}