kpsVibe Viewer
kpsVibe Viewer is a lightweight, self-hosted web server that indexes all your VS Code Copilot Chat sessions stored locally on disk and serves them through a clean browser interface.
What it does
- Auto-discovers VS Code
chatSessionsJSONL/JSON files - Indexes messages into a local SQLite database
- Full-text search across all sessions and messages
- Renders messages with Markdown and syntax highlighting
- Shows the exact JSONL line number of each message for easy file tracking
- Per-session or global re-sync without restarting the server
What it is NOT
- Not a cloud service — everything runs locally, your chat data never leaves your machine
- Not a VS Code extension — it is a standalone binary you run separately
- Not a chat client — it only reads and displays existing session files
How it works
The viewer scans your workspaceStorage folder for Copilot JSONL session files, parses and indexes each message into SQLite, then serves a single-page web app on a local HTTP/HTTPS port. Incremental sync keeps the index up-to-date without re-reading the entire history every time.
Main views
The project is also published on GitHub. You can find release notes, checksums and older versions on the release page.
System Requirements
Windows 10 / 11 (64-bit)
- VS Code, VSCodium, Cursor or Windsurf with the Copilot/AI chat extension installed and at least one chat session
- No additional runtime dependencies — SQLite is bundled in the binary
- Any modern browser (Chrome, Edge, Firefox)
Linux (Ubuntu 20.04+ / Debian 11+ or compatible)
- VS Code, VSCodium, Cursor or Windsurf with Copilot/AI chat extension
- glibc 2.31+ (included in Ubuntu 20.04 and later)
- Any modern browser
Finding your chatSessions folder
kpsVibe automatically detects all installed editors (VS Code, VS Code Insiders, VSCodium, Cursor, Windsurf) on startup — no configuration needed. You can also set chat.chat_sessions_paths in config.json to a specific path or an array of paths. Typical locations:
- Windows VS Code:
%APPDATA%\Code\User\workspaceStorage - Windows Cursor:
%APPDATA%\Cursor\User\workspaceStorage - Windows VSCodium:
%APPDATA%\VSCodium\User\workspaceStorage - Linux VS Code:
~/.config/Code/User/workspaceStorage - macOS VS Code:
~/Library/Application Support/Code/User/workspaceStorage
Installation on Windows
- Download
kpsvibe-windows.zipfrom the Downloads section - Extract the zip — you get
kpsvibe.exeandconfig-example.json - Copy
config-example.jsontoconfig.jsonin the same folder - Edit
config.json:chat.chat_sessions_pathsis optional — leave it empty and kpsVibe auto-detects VS Code, Cursor, VSCodium and Windsurf - Open a terminal in that folder and run:
.\kpsvibe.exe
Listening on 0.0.0.0:8380 in the console, the server is running. Open http://localhost:8380 in your browser.Auto-start as a Windows Service (optional)
kpsVibe Viewer has a built-in Windows Service installer — no third-party tools needed. Run the commands below from an Administrator prompt:
Install and start automatically with Windows:
kpsvibe.exe --install-service
Or install as manual start (you start it yourself):
kpsvibe.exe --install-service --demand
Once installed, manage the service with:
kpsvibe.exe --start-service # start the service
kpsvibe.exe --stop-service # stop the service
kpsvibe.exe --uninstall-service # remove from Windows
services.msc. On failure it restarts automatically after 5 s, 10 s, then 30 s.Installation on Linux
- Download the Linux binary from the Downloads section
- Make it executable:
chmod +x kpsvibe
- Copy
config-example.jsontoconfig.jsonin the same folder and edit it - Run the server:
./kpsvibe --config config.json
Run as a systemd service (recommended)
Create /etc/systemd/system/kpsvibe.service:
[Unit]
Description=kpsVibe Viewer
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/kpsvibe
ExecStart=/opt/kpsvibe/kpsvibe --config /opt/kpsvibe/config.json
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Statically linked — no extra packages needed
Basic Configuration (config.json)
The single configuration file config.json covers the server, logging and chat-indexing settings. Copy config-example.json to config.json and edit as needed.
Complete structure with defaults
{
"server": {
"listen": "0.0.0.0",
"port": 8380,
"threads": 0,
"tls": {
"enabled": false,
"cert_file": "cert.pem",
"key_file": "key.pem"
}
},
"logging": {
"file": "kpsvibe.log",
"json": false,
"console": true
},
"chat": {
"chat_sessions_path": "",
"db_path": "chat_viewer.db",
"web_root": "web",
"resync_on_start": true,
"content_preview_chars": 1000,
"index_fields": ["role","timestamp","model","has_tool_calls","has_references"]
}
}
Server options
| Field | Default | Description |
|---|---|---|
listen | "0.0.0.0" | Interface to bind. Use 127.0.0.1 for local-only access. |
port | 8380 | HTTP port. |
threads | 0 | Worker threads. 0 = auto (one per CPU core). |
Logging options
| Field | Default | Description |
|---|---|---|
file | "app.log" | Log file path. Leave empty to write to stdout only. |
console | true | Also print log entries to stdout. |
json | false | Emit structured JSON log lines instead of plain text. |
quiet_paths | ["/api/poll"] | Array of path prefixes silenced from the access log. The default hides the high-frequency /api/poll heartbeat. Set to [] to log every request. |
Chat indexing options
| Field | Default | Description |
|---|---|---|
chat_sessions_paths | "" | Path (string) or array of paths to editor workspaceStorage directories. Auto-detects VS Code, Cursor, VSCodium and Windsurf when empty. chat_sessions_path (singular) also accepted for backward compatibility. |
db_path | "chat_viewer.db" | SQLite database file. Relative to the binary or absolute. |
web_root | "web" | Folder containing the web app assets (index.html, app.js, style.css). |
resync_on_start | true | Scan for new / changed session files every time the server starts. |
background_sync_interval_min | 0 | Automatically re-sync in the background every N minutes while the server is running. Set to 0 to disable periodic sync. |
content_preview_chars | 1000 | Characters of message content to store in SQLite for full-text search. |
TLS / HTTPS
Enable HTTPS by setting server.tls.enabled = true and providing a certificate + key. HTTP continues to work on server.port; HTTPS listens on a separate port (default 8381).
| Field | Default | Description |
|---|---|---|
enabled | false | Activate the HTTPS listener. |
cert_file | "cert.pem" | Path to the PEM certificate chain (e.g. fullchain.pem). |
key_file | "key.pem" | Path to the PEM private key (e.g. privkey.pem). |
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/CN=localhost"Using the Viewer
Session list (left sidebar)
All indexed sessions appear in the left sidebar, ordered by last activity. Use the filter input to narrow down by session name. Click a session to open it.
Message view
Each message shows the role badge (user/assistant), model name, a timestamp, and — for JSONL-backed sessions — an L:N badge indicating the line number of that message inside the source JSONL file.
Global search
Type in the top search bar and press Enter (or click the 🔍 button). Results are ranked by relevance and link directly to the matching message context.
Syncing
Click the global ⟳ Sync button (top-right) to re-index all changed session files. Within an open session, use the per-session Sync button to force a full re-index of only that file.
Sharing a session
Click Share in the session toolbar to copy a direct URL to the current session to the clipboard. Anyone with network access to the server can open it.
API Endpoint Reference
All HTTP endpoints exposed by the viewer. The server binds to http://localhost:8380 by default.
| Endpoint | Method | Description |
|---|---|---|
/ |
GET |
Serves the web app (index.html). |
/api/sessions |
GET |
JSON array of all indexed sessions with metadata (id, label, file_path, message_count, last_activity). |
/api/messages?id=<session_id> |
GET |
JSON array of all messages for the given session, including role, content preview, model, timestamp, file_offset and byte_length. |
/api/search?q=<query> |
GET |
Full-text search across all indexed messages. Returns matching messages with session context. |
/api/db_status |
GET |
JSON object with session count, message count and DB file size in bytes. |
/api/sync |
POST |
Re-scan all known session files and update the index. Returns {status, sessions, messages}. |
/api/sync/session?id=<id> |
POST |
Force a full re-index of a single session file (deletes existing messages first). Returns {status, session_id, messages}. |
curl quick reference
| List all sessions | curl http://localhost:8380/api/sessions |
| Messages for a session | curl 'http://localhost:8380/api/messages?id=<session-uuid>' |
| Search | curl 'http://localhost:8380/api/search?q=how+to+use+docker' |
| Global sync | curl -X POST http://localhost:8380/api/sync |
| Per-session sync | curl -X POST 'http://localhost:8380/api/sync/session?id=<uuid>' |
Security & Authentication
kpsVibe Viewer binds to all interfaces (0.0.0.0) by default so you can access it from other devices on your local network. This is convenient but means that anyone on the same network can browse your entire AI chat history.
Optional username/password login
If you want to require a login before anyone can view the chat history, set credentials via the command line. Once set, every browser visit will show a sign-in page. The credentials are stored in the SQLite database and survive a DB reset (only chat data is cleared — credentials are kept).
Set credentials
kpsvibe --set-auth <username> <password>
The password is stored as a SHA-256 hash — it is never saved in plain text. Run this command again to change the password.
Remove credentials
kpsvibe --clear-auth
After clearing, the viewer returns to open-access mode. Existing browser sessions are invalidated immediately.
DB reset and credentials
The Reset DB button in the viewer (or POST /api/db/reset) only deletes indexed chat messages and sessions. It never touches the auth_config table, so your credentials are preserved across resets.
Security banner
When no password is configured and the viewer is accessed from a hostname other than localhost or 127.0.0.1, a red warning banner is shown at the top of the page reminding you to secure the installation.
HTTPS with a Self-signed Certificate
kpsVibe Viewer supports HTTPS out of the box. You can point it at a commercially-signed certificate or generate a quick self-signed one for local/intranet use.
Generate a self-signed certificate
The command below uses OpenSSL (pre-installed on Linux and macOS; available via Win32 OpenSSL or winget install ShiningLight.OpenSSL on Windows) to create a 4096-bit RSA certificate valid for 365 days:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/CN=localhost"
This produces two files: cert.pem (the certificate) and key.pem (the private key). Store them somewhere safe and accessible to the kpsvibe process.
Point kpsvibe at the certificate
Add the tls_cert, tls_key, and tls_port fields to your config.json:
{
"server": {
"port": 8380,
"tls_cert": "cert.pem",
"tls_key": "key.pem",
"tls_port": 8443
}
}
Trusting the certificate in your browser
Because the certificate is self-signed, your browser will show a security warning the first time you open https://<host>:8443. This is expected. In Chrome/Edge choose Advanced → Proceed to <host>; in Firefox choose Accept the Risk and Continue. You only need to do this once per browser profile.
key.pem) to other users or commit it to version control. If the key is compromised, regenerate the certificate pair and restart kpsvibe.Other Use Cases
Beyond browsing recent sessions, kpsVibe is also useful in these less-obvious scenarios.
Browsing Archived Chats
VS Code Copilot moves older conversations to an archived/ subfolder when a workspace accumulates many sessions. kpsVibe indexes those too, so you can:
- Browse sessions that VS Code has moved to its
archived/folder alongside active ones - Search across both active and archived conversations from a single view
- Read the full history of a project without having to restore anything in VS Code
Repairing a Bloated Chat Session
Accidentally pasting a very large file or data dump into a Copilot message bloats the .jsonl entry and can make the entire session extremely slow or unresponsive. You can use kpsVibe to locate the problem and then fix the raw file:
- Identify the exact message that contains the oversized context by inspecting it in the viewer
- Open the underlying
.jsonlfile (path shown in session details), find the entry, and remove or truncate the bloated field - Hit the per-session Sync button in kpsVibe to re-index immediately — the cleaned session loads instantly