You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Reopened 2026-06-30 — the trigger this issue named ("adopt CM6 when autocomplete becomes a priority") is now met: #84 (schema-aware autocomplete) is a 1.0 feature, and #88 settled the foundation (signals-core + imperative adapters behind seams, no UI framework). CM6 is now scheduled, behind an EditorPort seam.
Goal
Replace the hand-rolled <textarea> editor (src/ui/editor.js + editor-* modules) with CodeMirror 6 behind an injected EditorPort seam — unlocking schema-aware autocomplete (#84), inline docs (#60), bracket matching, search and folding, without breaking the single self-contained artifact (CM6 bundles + inlines via esbuild, like Chart.js).
Sequencing
After the signals migration (#88); before #84/#60. See the #68 build order (Phase 3).
src/editor/textarea-adapter.js — the current editor behind the port (temporary, so the swap is reversible).
src/editor/codemirror-adapter.js — CM6 (@codemirror/lang-sql + schemaCompletionSource on the live schema). SQL knowledge — keywords/funcs/schema and the FROM-scope resolver from Column-name autocompletion: FROM-driven column loading + alias/scope awareness #84 — stays pure in src/core/; the CM6 wrapper is integration-tested and gated like app.js/Chart/dagre so the per-file gate holds.
If the measured bundle delta is unacceptable, fall back to the textarea + the "middle path" schema-driven completion dropdown (kept zero-dep) — see the survey below.
Tracking
Part of #68 (Phase 3). Enables #84, #60. Foundation: #88 / docs/ADR-0001-reactivity.md (rule 5).
Original survey + rationale (2026-06-23, when this issue recommended deferring)
Context
The SQL editor is written from scratch, zero-dependency (src/ui/editor.js, ~125 lines): a <textarea> overlaid on a syntax-highlighted <pre> with a line-number gutter, fed by a hand-rolled ~100-line pure tokenizer (src/core/sql-highlight.js). It's fully covered by the 100% test gate and adds nothing to the bundle.
It nails the 90% case — write, highlight, line numbers, Tab-indent, drag-drop schema identifiers, undo, save/share/run wiring. What it lacks: autocomplete (especially schema-aware table/column completion), bracket matching, auto-indent, in-editor search, folding, multi-cursor, error squiggles.
Options surveyed
Library
Size
Fit for this app
Monaco (VS Code editor)
~5–10 MB + web workers
❌ Disqualified. We ship one self-contained HTML file with zero third-party requests (served from ClickHouse user_files); Monaco's size + worker model can't be cleanly inlined and would bloat the ~316 KB artifact ~20×. Unusable on mobile.
✅ Only realistic candidate. Tree-shakeable, no workers, bundles+inlines with esbuild like Chart.js, good on mobile. Used by Prisma Studio, Observable, Replit, Firefox DevTools.
The case for CM6
One real reason: schema-aware autocomplete. It's the single capability that matters for a SQL browser and that the hand-rolled editor can't reasonably match. @codemirror/lang-sql's schemaCompletionSource turns the schema tree we already load into live table.column completion (plus keyword/function completion, bracket matching, search, folding for free). Reimplementing a decent completion engine on the textarea is most of the work of adopting CM6 anyway, with worse results.
The editor DOM wrapper drops below the 100% coverage gate → move it behind an injected seam (app.Editor, exactly the Chart.js precedent), keeping the SQL knowledge (keywords/funcs/schema) pure in core/.
CM6's transaction/extension API is a real integration surface — selection, undo, drag-drop, and the share/save wiring all get rewritten.
Recommendation
Don't migrate now. The current editor is well-matched to the constraints and migrating is a net loss unless we're buying a feature it structurally can't provide.
Adopt CM6 when autocomplete becomes a priority (or we want folding/search/multi-cursor as a set). At that point CM6 is clearly the right pick — not Monaco (size/worker/single-file killer) or Ace — bundled and inlined behind an injected seam like Chart.js, keeping the artifact self-contained.
Middle path (if we only want completion and want to avoid a second dep): keep the textarea and build a small schema-driven completion dropdown ourselves — we already have the schema + tokenizer. Stays zero-dep and on-gate, but won't match CM6's polish and is more maintenance.
Suggested next step
Prototype the CM6 route on a branch behind a seam (lang-sql + schemaCompletionSource wired to the live schema) to measure the real bundle delta and the autocomplete UX before committing.
Reopened 2026-06-30 — the trigger this issue named ("adopt CM6 when autocomplete becomes a priority") is now met: #84 (schema-aware autocomplete) is a 1.0 feature, and #88 settled the foundation (signals-core + imperative adapters behind seams, no UI framework). CM6 is now scheduled, behind an
EditorPortseam.Goal
Replace the hand-rolled
<textarea>editor (src/ui/editor.js+editor-*modules) with CodeMirror 6 behind an injectedEditorPortseam — unlocking schema-aware autocomplete (#84), inline docs (#60), bracket matching, search and folding, without breaking the single self-contained artifact (CM6 bundles + inlines via esbuild, like Chart.js).Sequencing
After the signals migration (#88); before #84/#60. See the #68 build order (Phase 3).
Key implementation —
EditorPort+ dual adapter (reversible swap)src/editor/editor-port.js— interface:mount/destroy/getValue/setValue/getSelection/replaceSelection/replaceDocument/revealOffset/setSchema/setReferenceData/onChange/onRun/onSelectionChange. (Selection +setSchemaare shaped by Multiquery + run-selection: execute a ;-separated script (DDL / INSERT / single-row SELECT) with per-statement output #83 run-selection and Column-name autocompletion: FROM-driven column loading + alias/scope awareness #84 completion.)src/editor/textarea-adapter.js— the current editor behind the port (temporary, so the swap is reversible).src/editor/codemirror-adapter.js— CM6 (@codemirror/lang-sql+schemaCompletionSourceon the live schema). SQL knowledge — keywords/funcs/schema and the FROM-scope resolver from Column-name autocompletion: FROM-driven column loading + alias/scope awareness #84 — stays pure insrc/core/; the CM6 wrapper is integration-tested and gated likeapp.js/Chart/dagre so the per-file gate holds.Acceptance criteria
EditorPort; the bundle delta is measured + recorded (CLAUDE.md rule 4 — the deliberate 4th runtime dep).core/at 100%; the CM6 wrapper is gated likeapp.js.Re-evaluation trigger
If the measured bundle delta is unacceptable, fall back to the textarea + the "middle path" schema-driven completion dropdown (kept zero-dep) — see the survey below.
Tracking
Part of #68 (Phase 3). Enables #84, #60. Foundation: #88 /
docs/ADR-0001-reactivity.md(rule 5).Original survey + rationale (2026-06-23, when this issue recommended deferring)
Context
The SQL editor is written from scratch, zero-dependency (
src/ui/editor.js, ~125 lines): a<textarea>overlaid on a syntax-highlighted<pre>with a line-number gutter, fed by a hand-rolled ~100-line pure tokenizer (src/core/sql-highlight.js). It's fully covered by the 100% test gate and adds nothing to the bundle.It nails the 90% case — write, highlight, line numbers, Tab-indent, drag-drop schema identifiers, undo, save/share/run wiring. What it lacks: autocomplete (especially schema-aware table/column completion), bracket matching, auto-indent, in-editor search, folding, multi-cursor, error squiggles.
Options surveyed
user_files); Monaco's size + worker model can't be cleanly inlined and would bloat the ~316 KB artifact ~20×. Unusable on mobile.The case for CM6
One real reason: schema-aware autocomplete. It's the single capability that matters for a SQL browser and that the hand-rolled editor can't reasonably match.
@codemirror/lang-sql'sschemaCompletionSourceturns the schema tree we already load into livetable.columncompletion (plus keyword/function completion, bracket matching, search, folding for free). Reimplementing a decent completion engine on the textarea is most of the work of adopting CM6 anyway, with worse results.Costs (these cut against the project's grain)
app.Editor, exactly the Chart.js precedent), keeping the SQL knowledge (keywords/funcs/schema) pure incore/.Recommendation
Don't migrate now. The current editor is well-matched to the constraints and migrating is a net loss unless we're buying a feature it structurally can't provide.
Adopt CM6 when autocomplete becomes a priority (or we want folding/search/multi-cursor as a set). At that point CM6 is clearly the right pick — not Monaco (size/worker/single-file killer) or Ace — bundled and inlined behind an injected seam like Chart.js, keeping the artifact self-contained.
Middle path (if we only want completion and want to avoid a second dep): keep the textarea and build a small schema-driven completion dropdown ourselves — we already have the schema + tokenizer. Stays zero-dep and on-gate, but won't match CM6's polish and is more maintenance.
Suggested next step
Prototype the CM6 route on a branch behind a seam (
lang-sql+schemaCompletionSourcewired to the live schema) to measure the real bundle delta and the autocomplete UX before committing.References
🤖 Generated with Claude Code