Know what you've shared with AI. OmniGraph is an open-source AI interaction tracker that gives you a timeline and knowledge graph of every message you send to ChatGPT, Claude, Gemini, Copilot, and other AI tools.
A browser extension silently captures outbound messages. A dashboard classifies them by sensitivity, maps data subjects, and visualizes your cumulative AI exposure — so you always know what went where.
AI tools are everywhere. You paste code into ChatGPT, share financials with Claude, drop resumes into Copilot. But nobody tracks the cumulative picture:
- What sensitive data have you shared?
- With which services?
- When did it happen?
- How exposed are specific people, projects, or credentials?
OmniGraph answers these questions with a passive browser extension and a visual dashboard. No proxies, no browser profile changes — just install and browse.
┌─────────────────────────────────────────────────────────────────┐
│ BROWSER EXTENSION (MV3) │
│ │
│ ┌─────────────┐ ┌──────────┐ ┌──────────────────────────┐ │
│ │ Interceptor │ │ Bridge │ │ Background Worker │ │
│ │ (MAIN world) │──▶│(ISOLATED)│──▶│ Dedup · Batch · Retry │ │
│ │ fetch / XHR │ │ relay │ │ IndexedDB persistence │ │
│ │ WebSocket │ │ │ │ │ │
│ └─────────────┘ └──────────┘ └───────────┬──────────────┘ │
│ ┌─────────────┐ │ │
│ │ DOM Observer │───────────────────────────────┘ │
│ │ Input / Paste│ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
POST /api/ingest
│
┌─────────────────────────────────────────────────────────────────┐
│ NEXT.JS BACKEND │
│ │
│ ┌─────────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ Ingest API │ │ Classifier │ │ Graph API │ │
│ │ Zod validation │──▶│ OpenAI │──▶│ CRUD + Search │ │
│ │ Rate limiting │ │ Queue │ │ Timeline │ │
│ │ Bearer auth │ │ Retry │ │ Stats │ │
│ └─────────────────┘ └──────────────┘ └──────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ FalkorDB │ │
│ │ Service ← SENT_TO ← Disclosure → MENTIONS → DataSubject │ │
│ │ │ │ │
│ │ CONTAINS → DataCategory │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
Dashboard UI
│
┌─────────────────────────────────────────────────────────────────┐
│ DASHBOARD │
│ │
│ Dashboard Timeline Exposure Graph │
│ Stats & trends Chronological Interactive knowledge graph │
│ Service breakdown Search & filter Node inspector │
│ Sensitivity bars CSV export Zoom & pan │
└─────────────────────────────────────────────────────────────────┘
OmniGraph uses dual-layer capture for reliability:
- Network interception — Monkey-patches
fetch,XMLHttpRequest, andWebSocketin the page'sMAINworld to capture outbound API calls to AI services. - DOM observation — A
MutationObserverwatches for editable elements (textareas, contenteditable divs) and captures input/paste events as a fallback.
Events from both layers are deduplicated by content hash within a 3-second window, batched, persisted to IndexedDB, and sent to the backend with exponential-backoff retry.
| Service | Network Capture | DOM Capture |
|---|---|---|
| ChatGPT (chat.openai.com, chatgpt.com) | ✅ | ✅ |
| Claude (claude.ai) | ✅ | ✅ |
| Gemini (gemini.google.com) | ✅ | ✅ |
| Copilot (copilot.microsoft.com) | ✅ | ✅ |
| Perplexity (perplexity.ai) | ✅ | ✅ |
| Harvey (app.harvey.ai) | ✅ | ✅ |
| Clay (app.clay.com) | ✅ | ✅ |
| Jasper (app.jasper.ai) | ✅ | ✅ |
| Notion AI (notion.so) | ✅ | ✅ |
Adding a new service requires a small entry in extension/src/services/registry.js.
| Tool | Version | Check |
|---|---|---|
| Node.js | 20+ | node --version |
| Docker | 24+ | docker --version |
| Chrome/Chromium | Latest | — |
| OpenAI API Key | — | platform.openai.com |
git clone https://github.com/ASR4/omni-graph.git
cd omni-graph
npm installdocker compose up -dVerify:
docker exec omnigraph-falkordb redis-cli -a omnigraph-dev-password ping
# Expected: PONGcp .env.example .envSet your OpenAI API key in .env:
OPENAI_API_KEY=sk-proj-your-key-here
Everything else has working defaults. See Environment Variables for the full reference.
npm run devDashboard is at http://localhost:3001.
- Open
chrome://extensionsin Chrome - Enable Developer mode (top-right toggle)
- Click Load unpacked
- Select the
extension/directory from this repo
The OmniGraph icon appears in your toolbar. Click it to see the popup with status and controls.
Open ChatGPT, Claude, or any supported service and send a message. Within seconds, it appears on your OmniGraph dashboard timeline.
| Variable | Purpose | Required | Default |
|---|---|---|---|
OPENAI_API_KEY |
Classification via OpenAI | Yes | — |
INGEST_API_KEY |
Shared secret for extension auth | No | (auth disabled) |
FALKORDB_HOST |
Graph database host | No | localhost |
FALKORDB_PORT |
Graph database port | No | 6379 |
FALKORDB_PASSWORD |
FalkorDB/Redis password | No | omnigraph-dev-password |
FALKORDB_GRAPH_NAME |
Graph name in FalkorDB | No | omnigraph |
AUTH_SECRET |
NextAuth JWT signing secret | Yes (prod) | change-me-to-a-random-secret |
OMNIGRAPH_PASSWORD |
Dashboard login password | No | (auth disabled) |
LOG_LEVEL |
Pino log level | No | info |
Generate secrets with: openssl rand -base64 32
If INGEST_API_KEY is set, the extension must send it as a Bearer token. If unset, the ingest endpoint accepts all requests (suitable for local dev).
omni-graph/
├── extension/ # Chrome MV3 browser extension
│ ├── manifest.json # Extension config and permissions
│ ├── icons/ # Extension icons (16, 48, 128px)
│ └── src/
│ ├── interceptor.js # MAIN world: fetch/XHR/WS monkey-patching
│ ├── bridge.js # ISOLATED world: relay to service worker
│ ├── background.js # Service worker: dedup, batch, retry, IndexedDB
│ ├── popup.html # Toolbar popup UI
│ ├── popup.js # Popup logic and state
│ ├── services/
│ │ └── registry.js # AI service definitions and body parsers
│ └── content/
│ ├── element-discovery.js # DOM observer for input detection
│ └── adapters/ # Service-specific DOM adapters
│ ├── chatgpt.js
│ ├── claude.js
│ └── gemini.js
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── page.tsx # Dashboard: stats, breakdowns, recent activity
│ │ ├── timeline/page.tsx # Timeline: chronological feed, search, export
│ │ ├── graph/page.tsx # Graph: interactive exposure map
│ │ ├── login/page.tsx # Authentication
│ │ └── api/
│ │ ├── ingest/route.ts # Extension → server ingestion
│ │ ├── graph/route.ts # Graph data, search, timeline, stats
│ │ ├── health/route.ts # System health check
│ │ └── auth/[...nextauth]/ # NextAuth handlers
│ ├── components/
│ │ ├── graph/
│ │ │ ├── GraphCanvas.tsx # Graph visualization container
│ │ │ ├── CosmographWrapper.tsx # Cosmograph WebGL renderer
│ │ │ └── NodeDetail.tsx # Node inspector panel
│ │ └── ui/ # shadcn/ui primitives
│ ├── lib/
│ │ ├── types.ts # TypeScript type definitions
│ │ ├── falkordb.ts # FalkorDB client and Cypher helpers
│ │ ├── classifier.ts # OpenAI-based content classification
│ │ ├── classifier-queue.ts # Async classification queue with retry
│ │ ├── rate-limit.ts # Token bucket rate limiter
│ │ ├── auth.ts # NextAuth configuration
│ │ ├── logger.ts # Pino structured logging
│ │ ├── api-error.ts # Safe error responses
│ │ ├── constants.tsx # UI constants (icons, colors)
│ │ └── graph/
│ │ ├── schema.ts # Node/edge types, colors, sizes
│ │ └── operations.ts # Graph CRUD, search, timeline, stats
│ ├── middleware.ts # Route protection
│ ├── instrumentation.ts # Startup: re-queue unclassified disclosures
│ └── __tests__/ # Vitest test suite
│ ├── rate-limit.test.ts
│ ├── classifier.test.ts
│ └── ingest-validation.test.ts
├── docker-compose.yml # FalkorDB with persistence and auth
├── Dockerfile # Multi-stage production build
├── vitest.config.ts
├── .env.example # Environment variable reference
└── package.json
OmniGraph stores disclosures in a property graph with four node types and four edge types:
(Service) ←[SENT_TO]← (Disclosure) →[MENTIONS]→ (DataSubject)
│
[CONTAINS]
↓
(DataCategory)
(DataSubject) ←[EXPOSED_TO]→ (Service)
| Node | Description | Example |
|---|---|---|
| Service | An AI tool or SaaS product | ChatGPT, Claude, Gemini |
| Disclosure | A single message sent to a service | "Here's our Q4 revenue..." |
| DataSubject | A person, company, project, or product mentioned | "John Smith", "Acme Corp" |
| DataCategory | Type of sensitive data contained | PII, Financial, Code, Credentials |
Sensitivity levels: LOW, MEDIUM, HIGH, CRITICAL — assigned by the OpenAI classifier.
Receives disclosure batches from the browser extension. Validates with Zod, stores in FalkorDB, queues for classification.
{
"disclosures": [
{
"id": "uuid",
"service": "ChatGPT",
"serviceUrl": "https://chatgpt.com",
"endpointUrl": "https://chatgpt.com/backend-api/f/conversation",
"messageText": "Here is our Q4 revenue breakdown...",
"timestamp": 1710000000000,
"contentType": "text",
"inputMethod": "typed",
"captureSource": "network",
"metadata": {
"messageLength": 42,
"tabUrl": "https://chatgpt.com/c/abc123"
}
}
]
}Headers: Authorization: Bearer <INGEST_API_KEY> (if configured)
Returns graph nodes and edges for visualization.
Search nodes by keyword.
Chronological disclosures with optional filters: service, sensitivity, search.
Aggregate stats: totals, weekly count, service breakdown, sensitivity distribution, most-exposed subjects, recent activity.
Delete a node with cascade (removes connected edges and orphaned nodes).
System health check (FalkorDB connectivity).
# Run the full suite
npm test
# Watch mode
npm run test:watch
# Full CI pipeline (typecheck + lint + test)
npm run ci| File | Tests | Covers |
|---|---|---|
src/__tests__/rate-limit.test.ts |
8 | Token bucket: burst, refill, per-client isolation, key expiry |
src/__tests__/classifier.test.ts |
6 | Zod schema validation, category/sensitivity/subject parsing, edge cases |
src/__tests__/ingest-validation.test.ts |
6 | Ingest payload validation, required fields, bounds checking |
| Command | What It Does |
|---|---|
npm run dev |
Start dev server with hot reload (port 3001) |
npm run build |
Next.js production build |
npm run start |
Start production server (port 3001) |
npm run typecheck |
TypeScript type checker |
npm run lint |
ESLint |
npm run test |
Run Vitest suite |
npm run test:watch |
Vitest in watch mode |
npm run ci |
Typecheck + lint + test |
| Layer | Technology |
|---|---|
| Frontend | Next.js 15, React 19, Tailwind CSS 4, shadcn/ui |
| Graph Visualization | Cosmograph (WebGL) |
| Graph Database | FalkorDB (Cypher queries over Redis protocol) |
| Classification | OpenAI API with Zod-validated structured output |
| Auth | NextAuth v5 |
| Validation | Zod |
| Logging | Pino |
| Testing | Vitest |
| Extension | Chrome Manifest V3 |
- Port 6379 in use. Another Redis instance will conflict with FalkorDB. Stop it or change
FALKORDB_PORT. - Extension not capturing. Make sure the extension is enabled and the page was loaded after the extension was installed. Reload the AI service tab.
- No data on dashboard. Check the extension popup — it shows a count of captured disclosures and connection status. If the count is zero, try sending a message on a supported AI service.
- CORS errors. The ingest API includes CORS headers for the extension. If you move the backend to a different origin, update
host_permissionsinmanifest.json. - Docker Compose V2. Use
docker compose(no hyphen). Older Linux installations may needdocker-compose. - Auth is off by default. Set
OMNIGRAPH_PASSWORDin.envto enable dashboard authentication. - Classification requires OpenAI. An
OPENAI_API_KEYis required for sensitivity classification. Without it, disclosures are stored but remain unclassified.
Contributions are welcome. Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Make your changes
- Run
npm run cito verify (typecheck + lint + test) - Submit a pull request
To add support for a new AI service:
- Add the service's URL patterns to
extension/manifest.json(matchesarrays andhost_permissions) - Add a service entry in
extension/src/services/registry.jswith endpoint patterns and a body parser - Optionally add a DOM adapter in
extension/src/content/adapters/
MIT License. See LICENSE for details.