Audit performed: 2026-03-18
-
2026-03-18UnboundedlineBufferstring accumulation — added 1 MB cap with truncation (src/main/claude.ts) -
2026-03-18UnboundedpendingEventBufferarray — added 500-event cap (src/main/claude.ts) -
2026-03-18BlockingreadFileSync/writeFileSync/unlinkSyncon main thread — replaced with asyncfs/promises(src/main/claude.ts) -
2026-03-18SynchronousappendFileSyncdebug logging in hot loop — replaced with buffered async logger that flushes every 200ms (src/main/claude.ts) -
2026-03-18Recursivereaddirwithout timeout/limit — replaced with shallowreaddir(no recursive), added 5s timeout to git ls-files (src/main/index.ts) -
2026-03-18Messages list rendered without virtualization — replaced with@tanstack/react-virtualvirtualizer with dynamic measurement (Chat.tsx)
-
2026-03-18xterm eagerly imported (~6.1 MB) — lazy-loaded viaReact.lazy, split into 426 KB chunk (TerminalPanel.tsx,App.tsx) -
2026-03-18Shiki preloaded with 28 languages — reduced to 9 initial langs, remaining 16 loaded on demand (MarkdownRenderer.tsx) -
import * as monacoin 3 components prevents tree-shaking (~412 KB each) (DiffViewer.tsx:3,FilePreviewModal.tsx:2,SkillEditorModal.tsx:2) -
2026-03-18reactflowandreact-arboristin dependencies but never imported — removed from package.json -
2026-03-18NoReact.lazy()/ code-splitting — added React.lazy for TerminalPanel + 4 modals (App.tsx) -
2026-03-18NorollupOptions.outputchunk splitting — added manualChunks for monaco, xterm, shiki; main bundle 9.3 MB → 8.9 MB (electron-vite.config.ts)
- Zustand selectors return new object references on every call — no
useShallow(Chat.tsx:87,Sidebar.tsx:13,RightPanel.tsx:75) - Sessions stored as array — every selector does O(n)
.find()lookups (store/sessions.ts:169,177,204,212...) -
2026-03-18componentsobject passed to ReactMarkdown created inline every render — memoized withuseMemo(MarkdownRenderer.tsx) -
2026-03-18buildDiffFromToolInput()called every render withoutuseMemo— wrapped inuseMemo(ToolCallCard.tsx) -
2026-03-18findMatches()for in-session search computed every render — wrapped inuseMemo(Chat.tsx) -
allHistoryItemsrecomputed on any session change, not just messages (ChatInput.tsx:33-53) -
2026-03-18NoReact.memoon frequently-rendered children — addedReact.memotoCodeBlock,SkillRow(MarkdownRenderer.tsx,Sidebar.tsx) -
2026-03-18Inline arrays recreated every render — extracted to module-levelMODELS,EFFORT_LEVELS,BOUNCE_DOTSconstants (Chat.tsx)
-
2026-03-18Dynamicawait import('child_process')in hot IPC paths — moved to top-level import (src/main/index.ts) -
2026-03-18mcp:listreads 3 JSON files sequentially — replaced withPromise.all(src/main/index.ts) -
2026-03-18Terminal PTY sends every data chunk as separate IPC message — added 16ms batching buffer (src/main/terminal.ts) -
2026-03-18mkdir(recursive: true)called on every image save — cached withensureDir()set (src/main/index.ts) -
2026-03-18PTY Map entries may not be deleted on error paths — added.catch()to async processToolBlocks (src/main/claude.ts) - XLSX/PPTX read entirely into memory synchronously up to 10 MB (
src/main/fileExtractor.ts:84,104)
-
2026-03-18xterm CSS imported twice — verified: global CSS is only custom overrides (scrollbar), not a duplicate. Non-issue. - Status color/border class conditionals computed inline instead of memoized (
ToolCallCard.tsx:101-117) -
2026-03-18Sidebar skill list handlers created inline per-item — extracted touseCallbackhandlers, addedReact.memotoSkillRow(Sidebar.tsx) -
2026-03-18Timeline interval cleanup race condition on unmount — fixed explicitreturn undefinedpath (RightPanel.tsx)