T-FG8R-editor-settings-toolbar-and-vim
State: planning/proposed · Impact: medium · Complexity: medium
The markdown editor has no vim mode, and every MdSurface mount hardcodes its toolbar as
toolbar="fixed" rather than reading a user preference. This task makes both a real settings
choice — a vim extension slot in the CodeMirror engine, and one editor settings section every
markdown and code surface reads from — so a user picks modal editing and toolbar visibility once.
| Location | Role today |
|---|---|
packages/ts/obsidian-editor/src/extensions.ts | Compiles the fixed extension stack (plugins, keymaps, theme); no vim extension slot |
packages/ts/obsidian-editor/package.json | Dependency list; no @replit/codemirror-vim |
packages/ts/markdown-ui/app/components/MdSurface.vue#toolbar | toolbar?: boolean | 'fixed' prop, default false; no vim prop |
solutions/determined/experiences/notes/app/components/NotesNoteView.vue | Mounts MdSurface with toolbar="fixed" hardcoded |
solutions/determined/experiences/agent-pants/app/components/ApNewComponentWizard.vue | Mounts MdSurface with toolbar="fixed" hardcoded |
solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/index.vue | Same |
solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/notes/[...path].vue | Same |
solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/plugins/[...path].vue | Same |
packages/ts/app-frame/app/plugins/settings.client.ts | Registers the shell’s own sections (shell.general zod, shell.appearance/icons/effects component-based) through registerSettings |
packages/ts/app-frame/app/composables/useSettingsSection.ts | Declarative/zod settings persistence keyed by namespace; fires the settings:saved hook on save |
solutions/augmented/apps/vimit_prototype/app/components/VimEditor/VimEditor.vue | Prototype CM6 + vim integration; comments the ordering rule “key filter MUST come before vim()“ |
Proposed
Section titled “Proposed”An editor zod settings section (vimMode: boolean, showToolbar: boolean), default
vimMode: false / showToolbar: true, registered through registerSettings following
settings.client.ts’s pattern. @replit/codemirror-vim ^6.3.0 is an opt-in extension in
obsidian-editor’s stack, installed ahead of the editor’s own keymaps — the vimit_prototype’s
ordering note generalizes to: vim must sit before any keymap it needs to intercept. The same slot
exists in code-editor-package. Every MdSurface mount binds toolbar and a new vim prop from
useSettingsSection('editor') instead of the toolbar="fixed" literal. A status-bar indicator
shows the active vim mode when enabled.
Approach
Section titled “Approach”- Add
@replit/codemirror-vim^6.3.0topackages/ts/obsidian-editor/package.json. - In
extensions.ts, addvim?: booleantoObsidianEditorOptionsand, when set, prependvim()to the returned extension array ahead of thekeymap.of([...pluginKeys, ...structuralKeymap, ...])block. - Add the matching
vimslot tocode-editor-package(depends on T-MVW5-code-editor-package existing). - Register an
editorzod settings section (vimMode,showToolbar) viaregisterSettings, followingsettings.client.ts’sshell.generalpattern. - Add a
vimprop toMdSurface.vuealongside the existingtoolbarprop, threaded toobsidianEditorExtensions. - Bind
toolbarandvimon all fivetoolbar="fixed"mounts (NotesNoteView.vueand the four agent-pants mounts) touseSettingsSection('editor')instead of the literal. - Add a status-bar mode indicator (normal/insert/visual) that reads vim state when
vimModeis on. - Cover the toggle and a vim smoke test (enter insert mode, type, escape) in the playground or an experience e2e spec.
| Area | Note |
|---|---|
packages/ts/obsidian-editor/package.json | Add @replit/codemirror-vim |
packages/ts/obsidian-editor/src/extensions.ts | Prepend vim() extension when enabled |
packages/ts/obsidian-editor/src/types.ts | vim?: boolean on ObsidianEditorOptions |
packages/ts/markdown-ui/app/components/MdSurface.vue | vim prop, status-bar mode indicator |
packages/ts/app-frame/app/plugins/settings.client.ts | Register the editor zod section |
solutions/determined/experiences/notes/app/components/NotesNoteView.vue | Bind toolbar/vim from useSettingsSection('editor') |
solutions/determined/experiences/agent-pants/app/components/ApNewComponentWizard.vue | Same |
solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/index.vue | Same |
solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/notes/[...path].vue | Same |
solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/plugins/[...path].vue | Same |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: Toggling
showToolbaroff in Settings hidesMdSurface’s toolbar on all five mounts without a page reload. - AC-2: Toggling
vimModeon enables normal/insert/visual modal editing; a test drivesEscape,iand a motion, and asserts the resulting buffer. - AC-3: The vim extension installs ahead of the editor’s own keymaps, verified by a test that a vim-mapped key is not swallowed by a plugin chord.
- AC-4: A status-bar indicator shows the current vim mode when
vimModeis on and is absent when it is off. - AC-5:
code-editor-package’s vim slot compiles and has at least one passing test.
Out of scope
Section titled “Out of scope”- Vim key-filtering or an allowlist (
vimit_prototype’sallowedKeys); this task ships plain vim, not a restricted subset. - An ex-command surface (
:w,:q) beyond what@replit/codemirror-vimprovides. - Creating
code-editor-packageitself (T-MVW5-code-editor-package); this task only adds a vim slot once that package exists.
Dependencies
Section titled “Dependencies”- T-MVW5-code-editor-package: the code editor package must exist before this task adds its vim slot.
Discovery context
Section titled “Discovery context”From the user’s Agent Manager planning request (2026-09-07), grouped with tables, styling and mermaid as the markdown-ecosystem stage. M-BMFD’s Stage 6 row cites the vimit_prototype ordering note directly; the CodeMirror-6 editor engine (confirmed in the plan’s direct-answers section — there is no ProseMirror anywhere in the repo) is why vim support and the future code editor share one extension.