OmniComment - Universal Comments & AnnotationsUniversal commenting, inline highlight, and thread annotation system for editors (VS Code), embeddable web pages, browser extensions, and autonomous AI agents. Key Highlights
Supported VS Code Editor Modes & File TypesOmniComment works out of the box across all editor modes and all file types without requiring per-language configuration:
Screenshots1. In-Editor Comment Threads & Sidebar NavigationInteractive sidebar listing active and resolved comment threads, author attributions, thumbs-up counters, two-way cursor synchronization, and gutter comment indicators.
2. In-Situ Dynamic Annotation Zones (WYSIWYG & TextEditor)Comments embed directly beneath the annotated block with resolution workflows, collapsible threaded responses, and quick reply actions.
3. Live Markdown Preview HighlightingIn-situ highlight rendering in the VS Code Markdown preview with hover tooltips, comment count badges, and reaction indicators.
4. One-Click Configuration PresetsQuickly switch between pre-configured operational profiles via the VS Code Command Palette (
5. Autonomous AI Agent Review & Suggestion DiffHeadless Agent APIs (
Features
Built-in Configuration PresetsOmniComment provides 5 purpose-built presets to minimize configuration effort:
To switch presets:
Programmatic Agent APIsOmniComment exposes first-class VS Code commands for autonomous AI agents and automated scripting: 1. Retrieve Comments (
|
| Client | Configuration File / Command |
|---|---|
| Antigravity | ~/.gemini/antigravity/mcp_config.json (under "mcpServers", or via Agent Panel → ... → MCP Servers → Manage MCP Servers → View raw config) |
| Claude Code | claude mcp add --scope user omnicomment -- node ~/.vscode/extensions/benquike.omnicomment-0.3.8/bin/omnicomment-mcp (or .mcp.json / ~/.claude.json) |
| Claude Desktop | ~/.config/Claude/claude_desktop_config.json (Linux) or ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) |
| Cursor | ~/.cursor/mcp.json or .cursor/mcp.json |
| VS Code | .vscode/mcp.json (under "servers") |
Standard mcpServers JSON (~/.gemini/antigravity/mcp_config.json, .mcp.json, ~/.cursor/mcp.json, claude_desktop_config.json):
{
"mcpServers": {
"omnicomment": {
"command": "node",
"args": ["/home/<user>/.vscode/extensions/benquike.omnicomment-0.3.8/bin/omnicomment-mcp"]
}
}
}
(In a Remote-SSH workspace, point args to /home/<user>/.vscode-server/extensions/benquike.omnicomment-0.3.8/bin/omnicomment-mcp.)
VS Code .vscode/mcp.json:
{
"servers": {
"omnicomment": {
"type": "stdio",
"command": "node",
"args": ["/home/<user>/.vscode/extensions/benquike.omnicomment-0.3.8/bin/omnicomment-mcp"]
}
}
}
Exposed MCP Tools (7 Tools)
omnicomment_list_files— List all files in the workspace SQLite database with open/resolved counts and version status.omnicomment_get_comments— Read comments and file version drift status for any code, Markdown, plain text, or PDF file.omnicomment_get_file_version— InspectstoredVersionvs.currentVersion(fileHashSHA-256,fileSize,fileMtime,gitCommit,gitBlob).omnicomment_post_comment— Post a comment on any text/code/Markdown file (byanchorTextor 1-basedline) or PDF (bypageand optional normalizedrects).omnicomment_reply_comment— Reply to a thread (or a specific mid-thread message viainReplyTo).omnicomment_resolve_comment— Resolve, reopen, or toggle a comment thread.omnicomment_delete_comment— Delete an entire thread or a single reply (replyId).
8. Reading Comments Directly from SQLite (Python / Node.js / sqlite3)
Outside VS Code, any tool or script can read comments directly from OmniComment's SQLite database (omnicomment.db, WAL mode, read-safe while VS Code is running):
- Workspace open in VS Code:
~/.config/Code/User/workspaceStorage/<workspace-hash>/benquike.omnicomment/omnicomment.db - Single file opened without a workspace folder:
~/.config/Code/User/globalStorage/benquike.omnicomment/no-workspace/omnicomment.db(On macOS use~/Library/Application Support/Code/User/...; on Windows use%APPDATA%\Code\User\....)
Node.js (built-in node:sqlite, zero dependencies):
const { DatabaseSync } = require('node:sqlite');
const db = new DatabaseSync('/path/to/omnicomment.db');
// Read comments + version fingerprint for a specific file URI:
const row = db
.prepare(
'SELECT comments, file_hash, file_size, file_mtime, git_commit, git_blob, updated_at FROM file_comments WHERE file_key = ?'
)
.get('file:///abs/path/to/paper.pdf');
const comments = row ? JSON.parse(row.comments) : [];
console.log(row?.file_hash, comments);
Python (sqlite3 standard library):
import json, sqlite3
conn = sqlite3.connect("/path/to/omnicomment.db")
for file_key, raw_comments, file_hash, git_commit, updated_at in conn.execute(
"SELECT file_key, comments, file_hash, git_commit, updated_at FROM file_comments"
):
comments = json.loads(raw_comments)
print(file_key, f"sha256={file_hash[:12]}", len(comments), "threads")
Shell (sqlite3 CLI + jq):
sqlite3 ~/.config/Code/User/globalStorage/benquike.omnicomment/no-workspace/omnicomment.db \
"SELECT file_key, file_hash, file_size, git_commit, comments FROM file_comments;"
Keyboard Shortcuts
| Shortcut | Action |
|---|---|
Ctrl+Enter / Cmd+Enter |
Add comment to selection (or submit inside comment box) |
Ctrl+Shift+M / Cmd+Shift+M |
Add comment to selection or word at cursor |
Escape |
Cancel editing or dismiss active comment form |
Storage Specification
1. Extension-Managed SQLite Database ("omnicomment.storage": "database", default)
By default, OmniComment stores comments in an extension-managed SQLite database (omnicomment.db) inside VS Code's private storage directory so commented files stay completely clean on disk (no dirty editor indicator, no git diffs).
SQLite Schema (omnicomment.db, Schema Version 2)
CREATE TABLE meta (
key TEXT PRIMARY KEY,
value TEXT NOT NULL
);
CREATE TABLE file_comments (
file_key TEXT PRIMARY KEY, -- Document URI string, e.g. "file:///abs/path/to/paper.pdf"
comments TEXT NOT NULL, -- JSON-serialized Comment[] array
file_hash TEXT NOT NULL DEFAULT '', -- SHA-256 hex digest of the file when comments were saved
file_size INTEGER NOT NULL DEFAULT 0, -- File size in bytes
file_mtime TEXT, -- File last-modified timestamp on disk (ISO-8601)
git_commit TEXT, -- Git HEAD commit SHA if inside a Git repository
git_blob TEXT, -- Git blob SHA-1 ("git hash-object") of the file content
updated_at TEXT NOT NULL -- ISO 8601 timestamp of last write
);
- File Version Tracking & Carry-Forward:
- Every
file_commentsrow stores the current file version fingerprint (file_hash,file_size,file_mtime,git_commit,git_blob), and each individualCommentrecordscreatedFileHash(andfileVersion) for the exact version of the file it was originally written on. - When a text or Markdown file is modified externally (
storedVersion.fileHash !== currentVersion.fileHash), OmniComment carries existing comments forward by re-anchoringanchor.textin the updated document while preserving each comment's originalcreatedFileHash.
- Every
- When a file is renamed or moved inside VS Code, OmniComment automatically updates its
file_keyinfile_comments. - When all comments on a file are deleted, its row is removed from
file_comments.
How PDF Comments Are Saved
PDF files are binary documents opened in custom editors (mathematic.vscode-pdf / pdf.view or cweijan.vscode-office / cweijan.officeViewer), so PDF comments are always saved in omnicomment.db (keyed by the PDF's file:// URI), regardless of the omnicomment.storage setting. The PDF file itself is never modified.
Each PDF comment uses the same Comment structure as text comments, with an additional anchor.pdf object that stores page-relative normalized coordinates (0..1) so highlights and region boxes survive zoom and rotation:
[
{
"id": "b7c0d2a0-4e3a-4c6e-9c1a-8f5b9e2d1001",
"anchor": {
"text": "The cache layer needs a lock",
"startLine": 0,
"startChar": 0,
"endLine": 0,
"endChar": 0,
"pdf": {
"page": 1,
"kind": "text",
"rects": [
{ "x": 0.1176, "y": 0.1389, "w": 0.1842, "h": 0.0227 }
]
}
},
"content": "Which lock? A mutex or an RW lock?",
"author": "alex",
"createdAt": "2026-11-02T12:00:00.000Z",
"replies": [
{
"id": "r-91f2a3",
"content": "A mutex is enough here",
"author": "sam",
"createdAt": "2026-11-02T12:02:00.000Z",
"inReplyTo": "b7c0d2a0-4e3a-4c6e-9c1a-8f5b9e2d1001"
}
]
},
{
"id": "c4e91f88-1d2b-4a90-8b77-123456789abc",
"anchor": {
"text": "[Region on page 1]",
"startLine": 0,
"startChar": 0,
"endLine": 0,
"endChar": 0,
"pdf": {
"page": 1,
"kind": "region",
"rects": [
{ "x": 0.15, "y": 0.50, "w": 0.32, "h": 0.12 }
]
}
},
"content": "This figure area needs a caption",
"author": "alex",
"createdAt": "2026-11-02T12:01:00.000Z"
}
]
| Field | Type | Description |
|---|---|---|
anchor.text |
string |
Selected text snippet, or "[Region on page N]" for rectangular region comments |
anchor.startLine / endLine |
number |
0-based page index (page - 1) for compatibility with line-based views |
anchor.pdf.page |
number |
1-based PDF page number |
anchor.pdf.kind |
'text' \| 'region' |
'text' for text-selection highlights; 'region' for drawn rectangular boxes |
anchor.pdf.rects |
Array<{x, y, w, h}> |
Bounding boxes normalized to [0, 1] relative to the page's width and height |
2. In-File HTML Comment Block ("omnicomment.storage": "inFile" or omnicomment.exportCommentsToFile)
For text/Markdown files, you can optionally store or export comments directly inside the document in an HTML comment block at the end of the file (via "omnicomment.storage": "inFile" or the OmniComment: Export Comments to File command):
<!-- omnicomment
{
"version": 2,
"comments": [
{
"id": "5c903516-cf11-444e-9581-567a37228917",
"anchor": {
"text": "Universal commenting, inline highlight, and thread annotation system",
"startLine": 2,
"startChar": 0,
"endLine": 2,
"endChar": 70
},
"content": "Add integration test for browser extension web components.",
"author": "agent-reviewer",
"createdAt": "2026-10-28T12:00:00.000Z",
"resolved": false,
"replies": []
}
]
}
-->
Building & Packaging (VS Code Extension, Chrome Extension, Web Module Component)
OmniComment can be built from a single repository into three deployment targets:
| Target | Build Command | Output Artifact / Directory |
|---|---|---|
1. VS Code Extension (.vsix) |
npm run build:vscode |
omnicomment-0.3.8.vsix (out/extension.js, bin/omnicomment, bin/omnicomment-mcp) |
| 2. Chrome Extension (Manifest V3) | npm run build:chrome |
dist/chrome-extension/ (manifest.json, background.js, contentScript.js, popup.html) |
3. Web Module Component (<omni-comment>) |
npm run build:web |
dist/web/omnicomment-web.js (IIFE), dist/web/omnicomment-web.esm.js (ESM), dist/web/omnicomment-web.css |
| All Targets | npm run build:all |
Compiles TypeScript (out/) + builds dist/web/ and dist/chrome-extension/ |
1. Building & Installing the VS Code Extension (.vsix)
# 1. Install dependencies and compile TypeScript to out/
npm install
npm run compile
# 2. Package the VSIX archive
npm run build:vscode
# (Equivalent to: npx --yes @vscode/vsce package --allow-missing-repository -o omnicomment-0.3.8.vsix)
# 3. Install into local VS Code
code --install-extension omnicomment-0.3.8.vsix --force
2. Building & Loading the Chrome Extension (Manifest V3)
# Build the unpacked Manifest V3 Chrome Extension into dist/chrome-extension/
npm run build:chrome
To load in Google Chrome / Chromium / Brave / Edge:
- Open
chrome://extensions/in your browser. - Enable Developer mode (top-right toggle).
- Click Load unpacked and select the
dist/chrome-extension/directory. - (Optional) Click the OmniComment toolbar icon and enter your Python SQLite Server URL (e.g.
http://localhost:8000) to persist browser annotations directly into SQLite instead of local browser storage.
3. Building the Web Module Component (<omni-comment>)
# Build the standalone Web Component & ES Module bundle into dist/web/
npm run build:web
This produces:
dist/web/omnicomment-web.js— Zero-dependency browser bundle registering<omni-comment>andwindow.initOmniComment().dist/web/omnicomment-web.esm.js— Standard ES Module exportinginitOmniCommentandOmniCommentElementfor Vite / Webpack / Next.js / Rollup.dist/web/omnicomment-web.css— Stylesheet for text highlights, the floating💬 Add Commentselection chip, and the inline comment composer box.
How to Embed OmniComment into a Web App
You can embed OmniComment into any web application using either the declarative <omni-comment> custom HTML element or the programmatic initOmniComment() JavaScript/TypeScript API.
Method 1: Declarative <omni-comment> Custom Element (HTML / Static Sites / Server-Rendered Apps)
Include omnicomment-web.css and omnicomment-web.js, wrap your annotatable content in any selector (e.g. #article-content), and drop <omni-comment> onto the page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="/omnicomment-web.css" />
</head>
<body>
<!-- 1. The content container users can highlight and comment on -->
<article id="article-content">
<h1>System Design Proposal</h1>
<p>Select any text in this article to open the inline comment box.</p>
</article>
<!-- 2. Declarative <omni-comment> Web Component -->
<omni-comment
target="#article-content"
document-id="system-design-v1"
preset="team-collaboration"
storage="rest"
api-endpoint="http://localhost:8000/api/documents/system-design-v1/comments"
author="Alice"
></omni-comment>
<!-- 3. Load Web Component bundle -->
<script src="/omnicomment-web.js"></script>
</body>
</html>
Method 2: Programmatic ES Module API (initOmniComment) for SPAs (React, Vue, Svelte, Angular)
import { initOmniComment } from './dist/web/omnicomment-web.esm.js';
import './dist/web/omnicomment-web.css';
const omni = initOmniComment({
target: '#article-content',
documentId: 'system-design-v1',
author: 'Alice',
preset: 'team-collaboration',
storage: {
type: 'rest',
endpoint: 'http://localhost:8000/api/documents/system-design-v1/comments',
headers: {
'Content-Type': 'application/json'
}
},
panelContainer: document.getElementById('comments-sidebar'),
onCommentAdded: (comment) => console.log('Saved to SQLite:', comment),
onCommentResolved: (commentId) => console.log('Resolved thread:', commentId)
});
// Clean up listeners when unmounting component:
// omni.destroy();
React Wrapper Example (OmniCommentEmbed.tsx)
import React, { useEffect, useRef } from 'react';
import { initOmniComment } from './omnicomment-web.esm.js';
import './omnicomment-web.css';
export function OmniCommentEmbed({ target, docId, apiBaseUrl, author = 'Alice' }: {
target: string;
docId: string;
apiBaseUrl: string;
author?: string;
}) {
const panelRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const instance = initOmniComment({
target,
documentId: docId,
author,
apiEndpoint: `${apiBaseUrl}/api/documents/${encodeURIComponent(docId)}/comments`,
panelContainer: panelRef.current
});
return () => instance.destroy();
}, [target, docId, apiBaseUrl, author]);
return <div ref={panelRef} />;
}
Complete Example: Web App + Python SQLite Server
A complete, runnable, zero-dependency example is included in examples/python-sqlite-webapp/ (and an async FastAPI + aiosqlite implementation is in servers/python-fastapi/).
Run the Example in 2 Commands
# 1. Build the Web Component bundle (dist/web/omnicomment-web.js & .css)
npm run build:web
# 2. Launch the Python + SQLite server (uses only Python stdlib sqlite3 + http.server)
python3 examples/python-sqlite-webapp/server.py --port 8000 --db /tmp/comments.db
Now open http://127.0.0.1:8000 in your browser:
- Select any text inside the article → click the floating
💬 Add Commentbutton. - Type a comment inside the inline comment box and click Add Comment (or press
Ctrl+Enter). - Add replies, resolve/reopen threads, or delete comments — all persisted in
/tmp/comments.db.
Minimal Python + sqlite3 Backend (examples/python-sqlite-webapp/server.py)
Below is the core SQLite schema and REST handler logic used by examples/python-sqlite-webapp/server.py:
import json, sqlite3, uuid
from datetime import datetime, timezone
def init_db(db_path: str = "comments.db") -> None:
with sqlite3.connect(db_path) as conn:
conn.executescript("""
PRAGMA journal_mode = WAL;
CREATE TABLE IF NOT EXISTS comments (
id TEXT PRIMARY KEY,
document_id TEXT NOT NULL,
anchor_json TEXT NOT NULL,
content TEXT NOT NULL,
author TEXT NOT NULL,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
resolved INTEGER NOT NULL DEFAULT 0
);
CREATE TABLE IF NOT EXISTS replies (
id TEXT PRIMARY KEY,
comment_id TEXT NOT NULL,
content TEXT NOT NULL,
author TEXT NOT NULL,
created_at TEXT NOT NULL,
FOREIGN KEY(comment_id) REFERENCES comments(id) ON DELETE CASCADE
);
""")
def save_comment(db_path: str, doc_id: str, payload: dict) -> dict:
now = datetime.now(timezone.utc).isoformat()
comment_id = payload.get("id") or f"comment-{uuid.uuid4().hex[:12]}"
anchor = payload["anchor"]
with sqlite3.connect(db_path) as conn:
conn.execute(
"INSERT INTO comments VALUES (?, ?, ?, ?, ?, ?, ?, 0)",
(comment_id, doc_id, json.dumps(anchor), payload["content"], payload["author"], now, now),
)
conn.commit()
return {
"id": comment_id,
"documentId": doc_id,
"anchor": anchor,
"content": payload["content"],
"author": payload["author"],
"createdAt": now,
"updatedAt": now,
"resolved": False,
"replies": [],
}
Documentation
Comprehensive guides and tutorials are available in the docs/ directory:
- 🏠 Project Home Page: Product overview, value propositions, cross-surface feature matrix, and quickstarts.
- 🎓 Hands-on Tutorial: Step-by-step guide from zero to hero across VS Code, presets, web embedding, browser extensions, and AI reviewer agents.
- 💻 Web Applications Guide: React, Next.js, Vue 3, Nuxt, Svelte 5, SvelteKit, Web Component (
<omni-comment>), real-time sync (Supabase, WebSockets), and offline IndexedDB. - 🧩 Chrome Extension Guide: Manifest V3 browser extension, live web page annotation with W3C TextQuoteSelector, Shadow DOM style isolation, and local VS Code bridge.
- 📟 Terminal & TUI Apps Guide: Headless CLI commands (
omnicomment-cli), Neovim Lua plugin usingvirt_linesextmarks, Python Textual, Go Bubbletea, and Git pre-commit hooks. - 📝 VS Code Editor Modes Guide: Standard TextEditor, Vditor WYSIWYG Custom Editor, Jupyter Notebooks (
.ipynb), Git split/unified diff reviews, and split panes. - 📚 Comprehensive API Reference: Formal API specification for data structures (
Comment,Reply,CommentAnchor), commands, TypeScript core classes, and<omni-comment>. - 🤖 AI Agent API Guide: Programmatic APIs for AI agents, MCP tool schemas, automated review loops, and LLM prompt context builders.
- 🌐 Integration Guide: Embedding OmniComment into static site generators (Docusaurus, VitePress, Hugo), documentation hubs, and external frameworks.
- ⚙️ Configuration & Presets Guide: The 5 built-in presets (
documentation-site,git-file-review,browser-annotator,team-collaboration,ai-agent-reviewer), UI design tokens, and storage backends. - 🏗️ Architecture & Data Model: System design, W3C Web Annotation data models, and 3-tier robust anchoring engine.
Rendering the Documentation Website
OmniComment includes a built-in static site generator (scripts/render-docs.js) that compiles the Markdown guides into a responsive documentation website featuring sidebar navigation, Prism syntax highlighting, live Mermaid diagrams, GitHub callout alerts, and an active Table of Contents.
1. Build the Static Site
npm run docs:build
# or directly:
node scripts/render-docs.js
The compiled HTML site is output to dist/site/index.html.
2. Launch Local Preview Server
npm run docs:serve
# or with a custom port:
node scripts/render-docs.js --serve --port=8080
Open http://localhost:3000 in your browser to explore the rendered documentation portal.
3. Render a Single Markdown File
node scripts/render-docs.js path/to/file.md




