perf: SQLite-backed session loading for Copilot CLI (~15x faster startup)#93
Conversation
…tup) - Add copilot-session-db.ts: reads ~/.copilot/session-store.db (read-only, lazy-loaded) - Session list loads from SQLite in ~200ms vs ~3-4s filesystem scan - FTS5 full-text search across ALL sessions (not just loaded 314) - AND/OR operator support in session and prompt search - Prompt search (Ctrl+Shift+Y) searches all historical sessions via SQLite - Graceful fallback to filesystem when DB unavailable (Claude Code, fresh installs) - WSL: derives DB path from basePath, no cross-contamination with host DB - Search skips lifecycle tab filter (shows all matching results) - Load-more hidden when SQLite active (all sessions queryable instantly) - Fixed archived tooltip to match actual auto-archive criteria - Search placeholder shows AND/OR hints when SQLite active - Debounce increased to 500ms for IPC-backed search - Version bump to 1.7.3 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…rtion in E2E test Two fixes for workspaces-multi-select E2E test failures: 1. createWorkspace() now clears selectedTerminalIds when switching to the new workspace, matching setActiveWorkspace behavior (TASK-72). Without this, selection from workspace A leaked across because createWorkspace already sets activeWorkspaceId to the new ws, making the subsequent setActiveWorkspace(wsB) a no-op. 2. The 'showSelectedPanes is a no-op' test asserted viewMode !== 'grid', but the default viewMode IS 'grid'. Since showSelectedPanes is a no-op (< 2 selected), viewMode stays unchanged. Fixed the assertion to check viewMode is unchanged rather than not-grid. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Thanks @meni-braun - this is a thoughtful proposal with real benchmarks. The hybrid (SQLite cold + chokidar hot) shape and the graceful filesystem fallback are exactly the right design. Review notes before merging: Native module compat. Concurrency with the CLI writer. The DB is opened read-only, but Copilot CLI writes to it during sessions. SQLite WAL mode + a busy timeout would smooth this; please confirm the open path uses Schema-drift defense. If a future Copilot CLI release adds/renames columns, the queries should fall back gracefully rather than throw. The code path that sets WSL. The constructor passes a path under Conflicts with main. The PromptSearchDialog touches conflicting territory after a recent change (AND-syntax tokenization + match-count badge). Both the SQLite query path and the client-side AND filter want to handle the user's typed query - they need to compose: when SQLite-active, use the DB query for the haystack; when SQLite-inactive (Claude Code, fallback), use the client-side AND filter. The merge will need a hand-resolved hunk in that file. I'd like to defer the merge until there's confidence on the cross-platform native install and the conflict resolution. Happy to walk through either with you - or you can rebase on current main and confirm the PromptSearchDialog merge yourself, and I'll re-review. |
|
Thanks @meni-braun - merged in 158849a. The SQLite path + filesystem fallback + native install all worked cleanly on this Windows machine. The PromptSearchDialog merge composed your SQLite query path with the AND-syntax client-side filter that landed in the meantime - SQLite-active queries use the DB directly, Claude Code entries continue to flow through the client-side AND filter, and the match-count badge stays. Will pick up real-world CLI write-during-read concurrency feedback once it's in users' hands. Closing alongside the merge. |
Use Copilot CLI's local SQLite DB (
session-store.db) for session loadingProblem
tmax currently loads Copilot CLI sessions by scanning the filesystem:
readdirSyncon~/.copilot/session-state/(6,000+ directories on heavy-use machines)stateach dir'sevents.jsonlfor mtime sortingworkspace.yamlper session for metadata (cwd, branch, repo, summary)events.jsonlincrementally for activity data (messageCount, latestPrompt, etc.)This was optimized in v1.7.1 (cap to 314 sessions, cached candidate list, incremental parsing), but the initial scan still takes ~300ms for the directory enumeration alone, plus ~3 seconds to parse 314 sessions. On machines with thousands of sessions, startup remains noticeably slow.
Opportunity
Copilot CLI maintains a local SQLite database at
~/.copilot/session-store.dbthat already contains most of the data tmax needs. This DB is updated by the CLI after each session and includes:sessionsturnssearch_indexsession_filessession_refscheckpointsBenchmarks
Tested on a machine with 6,931 sessions (224 MB database):
Proposed hybrid architecture
SQLite for cold data (session list, metadata, search), filesystem watcher for hot data (live status of active sessions).
Field mapping
CopilotSessionSummaryfieldidsessions.idcwdsessions.cwdrepositorysessions.repositorybranchsessions.branchsummarysessions.summarylastActivityTimesessions.updated_atmessageCountCOUNT(turns)latestPromptturns.user_messagelatestPromptTimeturns.timestamptoolCallCounttotalTokensstatus(live)pendingToolCallsThe missing fields (
toolCallCount,totalTokens,status,pendingToolCalls) are only meaningful for active sessions - exactly the ones the chokidar watcher already monitors. For the session list sidebar, all key display fields are available from SQLite.SQLite schema
Example queries
Considerations
Copilot CLI only - Claude Code doesn't use this SQLite DB (different session format). The filesystem approach must remain for Claude Code sessions. This optimization is Copilot CLI-specific.
SQLite locking - The CLI writes to this DB while tmax reads. SQLite handles concurrent readers well, but tmax should open with
SQLITE_OPEN_READONLYand use WAL mode awareness. Since Electron already hasbetter-sqlite3available (or can use the built-insql.js), this should be straightforward.DB availability - The
session-store.dbfile may not exist on fresh installs or if the user has a very old CLI version. Fall back to the filesystem approach gracefully.Data freshness - The SQLite DB is updated at session boundaries (not in real-time during a session). For the session list this is fine - the live status comes from the events.jsonl watcher. For search, SQLite data may lag by one session but FTS5 coverage of all historical sessions far outweighs this.
No additional dependency - The SQLite file is already maintained by the CLI. tmax just needs to read it.
How these were measured
SQLite benchmarks were measured by running timed Python/sqlite3 queries against the actual
~/.copilot/session-store.dbon a machine with 6,931 sessions (224 MB database). Each query was timed withtime.time()around the execute + fetchall.Filesystem benchmarks come from two sources:
copilot-session-monitor.tsline 44: "Uses sync stat - fast (~300ms) and only runs once (cached after)"readFileSynconworkspace.yaml+ incrementalreadSynconevents.jsonl+ JSON parsing per line. On a cold start with 314 sessions to parse, this takes ~3 seconds based on observed startup behavior (the motivation for the v1.7.1 perf fix).Impact