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 chatSessions JSONL/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

Session list Left sidebar listing all indexed sessions, filterable by name.
Message view Threaded message browser with Markdown rendering, model badge and JSONL line badge.
Global search Full-text search across all sessions; results link directly to the matching message.
DB status Quick stats panel showing session count, message count and index size.
Project on GitHub
The project is also published on GitHub. You can find release notes, checksums and older versions on the release page.
View on GitHub

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

Zero-install. No installer, no registry entries, no system dependencies. Just copy the exe and run it.
  1. Download kpsvibe-windows.zip from the Downloads section
  2. Extract the zip — you get kpsvibe.exe and config-example.json
  3. Copy config-example.json to config.json in the same folder
  4. Edit config.json: chat.chat_sessions_paths is optional — leave it empty and kpsVibe auto-detects VS Code, Cursor, VSCodium and Windsurf
  5. Open a terminal in that folder and run:
.\kpsvibe.exe
If you see 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
The service appears as kpsVibe Viewer in services.msc. On failure it restarts automatically after 5 s, 10 s, then 30 s.

Installation on Linux

  1. Download the Linux binary from the Downloads section
  2. Make it executable:
chmod +x kpsvibe
  1. Copy config-example.json to config.json in the same folder and edit it
  2. 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

The Linux binary bundles OpenSSL and SQLite statically. Only glibc (present in any modern Ubuntu/Debian) is required as a shared library.

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

FieldDefaultDescription
listen"0.0.0.0"Interface to bind. Use 127.0.0.1 for local-only access.
port8380HTTP port.
threads0Worker threads. 0 = auto (one per CPU core).

Logging options

FieldDefaultDescription
file"app.log"Log file path. Leave empty to write to stdout only.
consoletrueAlso print log entries to stdout.
jsonfalseEmit 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

FieldDefaultDescription
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_starttrueScan for new / changed session files every time the server starts.
background_sync_interval_min0Automatically re-sync in the background every N minutes while the server is running. Set to 0 to disable periodic sync.
content_preview_chars1000Characters 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).

FieldDefaultDescription
enabledfalseActivate 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).
Self-signed certificate for local / LAN use — browsers will warn; add an exception or use it only internally. Generate with:
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.

Do not expose kpsVibe Viewer to the public internet without first setting up a password. There is no rate-limiting or brute-force protection — it is designed for trusted local networks only.

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.

Never expose the private key (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 .jsonl file (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