Skip to content
| Marketplace
Sign in
Visual Studio Code>AI>SeshNew to Visual Studio Code? Get it now.
Sesh

Sesh

Michael Ogundare

|
3 installs
| (0) | Free
Browse, annotate, and resume saved Claude Code and Codex CLI sessions.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Sesh

Browse, annotate, and resume saved Claude Code and Codex CLI sessions — without leaving VSCode.

Tests TypeScript License: MIT VSCode

Sesh indexes the JSONL transcripts that Claude Code and Codex CLI already write to disk, gives you a fast filterable session list, full-text search across every transcript, structured rendering of tool calls and diffs, and one-click resume — all in a single VSCode panel.

Source data is read-only. Annotations live in Sesh's own SQLite. Your CLI's session files are never modified.


Why Sesh

Claude Code and Codex CLI both quietly accumulate a long tail of sessions. After a few months you've got hundreds of transcripts in ~/.claude/ and ~/.codex/, none of them browsable, searchable, or recoverable. The CLIs themselves give you --resume <id> but no way to find the id you want. Sesh fills that gap.

  • Find any past conversation. Search by title, body, tag, category, or folder. Hits highlight inline.
  • Make sense of long sessions. Tool calls, thinking blocks, and tool results render as collapsible cards. Edit/Write blocks become colored diffs. Code fences get Prism syntax highlighting. Screenshots inline.
  • Don't lose history when CLIs prune. Sesh imports Claude Code's sessions-index.json ledger, so titles + metadata survive even after transcripts are deleted. Opt in to gzipped transcript archiving and the bodies stick around too.
  • Resume in the right place. A click runs claude --resume <id> or codex resume <id> in a terminal opened in the session's original cwd. For Claude sessions in your current workspace, resume in the editor panel directly.

Sources supported

Source Storage location Resume command
Claude Code ~/.claude/projects/<encoded-cwd>/<id>.jsonl claude --resume <id>
Codex CLI ~/.codex/sessions/<year>/<month>/<day>/rollout-<ts>-<id>.jsonl codex resume <id>

Schema is source-pluggable — adding another source means a parser + a source value, not a migration.

Features in detail

Session list. Virtualized 3-line rows with title (custom or auto-derived), category pill, tags, message count, source badge, last-active relative time. Orphaned (pruned-transcript) sessions render in muted italics.

Detail pane. Sectioned layout: header, annotations, transcript. Folder pulled into its own labeled row. Tag input is inline, category dropdown supports inline create. Resume buttons hide when they'd be invalid (cross-workspace panel resume, codex panel resume).

Search. SQLite FTS5 across annotations and transcript bodies. Matches highlight in titles and the transcript body via <mark> tags. Auto-expands collapsed tool blocks when the body matches.

Scope. Three modes: current folder, all projects, or pick a specific folder from the dropdown (groups all known projects). Honors project remaps so renamed folders surface their legacy sessions.

Transcript rendering.

  • Markdown + GFM via react-markdown for assistant text.
  • Prism syntax highlighting for fenced code (theme-aware: vsLight on .vscode-light, vsDark otherwise).
  • Default-collapsed <details> cards for tool_use / tool_result / thinking blocks, each with a per-tool codicon (Bash → terminal, Read → file, Edit → edit, Grep → search, etc.).
  • Line-by-line diff for Edit / Write tool calls, derived via diff.diffLines and tinted with VSCode's diff editor colors.
  • Inline images for screenshot-bearing messages.

Project remap. When the workspace path doesn't match any indexed project_path but a folder with the same basename does, Sesh suggests merging them. One click writes a project_remap row and legacy sessions show up under the new path.

Annotations. Custom titles, colored categories, free-form tags, notes, favorited, archived. All overlay-only — never written to source JSONL.

Settings

Key Default Effect
sesh.openOnActivation false Auto-open the panel on VSCode startup.
sesh.transcriptLimit 10000 Max recent messages loaded into the detail pane. Lower this if very long transcripts feel slow to open.
sesh.archiveTranscripts false Keep a gzipped sidecar of each transcript at ~/.sesh/transcripts/<id>.jsonl.gz so pruned sessions stay readable. Roughly 1/6 the raw JSONL size after gzip.

Commands

  • Sesh: Open — opens or focuses the panel.
  • Sesh: Show stats — info message with the indexed session count.
  • Sesh: Rescan all projects — re-scan + reimport ghosts + reindex FTS.
  • Sesh: Show archive size — disk size of the opt-in archive directory.

Sesh: Open is wired to the activity-bar entry, the secondary-sidebar entry (right strip, alongside Claude / Codex), the editor-title button (history icon), and the welcome-view links — pick whichever fits your layout.

Storage

Path Purpose
~/.sesh/db.sqlite Session metadata, annotations, FTS5 index. WAL mode.
~/.sesh/transcripts/<id>.jsonl.gz Optional gzipped archive (only when sesh.archiveTranscripts: true).
~/.claude/projects/**/*.jsonl Claude Code source. Read-only.
~/.codex/sessions/**/rollout-*.jsonl Codex CLI source. Read-only.

Deleting ~/.sesh/db.sqlite rebuilds from source on next activation. You only lose annotations.

Development

Sesh is a TypeScript-strict, esbuild-bundled extension with a Vite-bundled React 18 webview. Tests are Vitest, manifest is in package.json.

npm install
npm run typecheck                                    # tsc --noEmit on host
npm test                                             # 101 tests pass (host Node binary)
npm run build                                        # bundles extension + webview
npx @electron/rebuild -f -w better-sqlite3 -v 39.8.8 # before pressing F5

Then open this directory in VSCode and press F5 to launch the Extension Development Host.

Native binary toggling

better-sqlite3 is a native module — its prebuilt binary at node_modules/better-sqlite3/build/Release/better_sqlite3.node targets one runtime at a time:

Use case Command
Run vitest (host Node) npm rebuild better-sqlite3
Run extension in dev host (VSCode's Electron) npx @electron/rebuild -f -w better-sqlite3 -v 39.8.8

The 39.8.8 matches the Electron version VSCode currently bundles. Re-check /Applications/Visual Studio Code.app/Contents/Resources/app/package.json if VSCode updates and the rebuild fails.

To minimize flips during a dev session: finish all code changes, then rebuild → test → rebuild → build in one chain. When changing package.json, do a full F5 restart of the dev host — Cmd+R only reloads the webview.

Architecture

src/
├── extension.ts              activate() — output channel, host start, command + view registration
├── host/
│   ├── seshHost.ts           DB + scan + ghost import + content indexer + watcher + archive
│   ├── seshPanel.ts          singleton WebviewPanel, message dispatcher, light/dark iconPath
│   └── transcriptArchive.ts  opt-in gzipped sidecar (sesh.archiveTranscripts)
├── messaging.ts              typed protocol (TranscriptBlock, scope, totalInScope)
├── db/
│   ├── connection.ts, migrate.ts, migrations/
│   ├── sessions.ts, tags.ts, categories.ts
│   └── search.ts             searchSessions + countSessionsInScope
└── scanner/
    ├── jsonl.ts              streaming reader — handles .jsonl.gz transparently
    ├── extract.ts            metadata extractor (Claude Code shape)
    ├── transcript.ts         transcript reader (Claude Code shape)
    ├── scan.ts               walks ~/.claude/projects/, top-level *.jsonl only
    ├── sessionsIndex.ts      imports ghost (pruned-transcript) sessions
    ├── systemTags.ts         shared SYSTEM_TAG_RE
    ├── contentIndexer.ts     background FTS populate, source-aware
    ├── watcher.ts            chokidar add/change/unlink (Claude Code only for now)
    └── codex/                Codex CLI source adapter (extract + scan + transcript + sessionText)

webview/src/
├── App.tsx                   PanelGroup wrapping list/detail with persisted size
├── messaging.ts              MIRROR of host messaging.ts
├── styles.css                --sesh-* design tokens, theme-decoupled muted text
├── components/               Toolbar, SessionList, DetailPane, Transcript,
│                             MessageBlocks, CodeBlock, Highlight, SourceBadge, Icon, RemapBanner
└── hooks/                    useSessions, useSessionDetail, useCategories, useAllTags, useProjects

Design invariants

These are intentionally load-bearing — don't refactor them away without thinking hard:

  • Top-level JSONL only counts as a session. <encoded-cwd>/<id>.jsonl is a session; <encoded-cwd>/<id>/subagents/agent-*.jsonl is not — it's a subagent invocation inside the parent session.
  • sessions-index.json is the ghost ledger. Claude Code keeps it as a permanent record. After pruning, the JSONL is gone but the entry remains. Sesh imports those as orphaned=1 rows so the user keeps title + metadata even though the transcript is gone.
  • Annotations live in Sesh's DB only. Editing a title/category/tag/notes never touches the source JSONL.
  • Project / folder is intrinsic. Every session has a cwd field in its first JSONL record — that's the "Folder" value.
  • Panel resume needs cwd match. Claude Code's bundled extension.js resolves the panel resume command against workspaceFolders[0] only — there's no API path to resume cross-workspace.

Contributing

Issues and PRs welcome. The project follows a tight TDD-discipline pattern — every meaningful behavior change ships with a unit test next to the file it touches. See the commit history for the cadence.

Before opening a PR:

npm run typecheck
npm rebuild better-sqlite3 && npm test
npx @electron/rebuild -f -w better-sqlite3 -v 39.8.8
npm run build

All four must pass.

License

MIT © Michael Bluman.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft