mnml-rs 0.2.22

A NvChad-style terminal IDE in Rust — vim or standard editing, LSP, git, and an embedded HTTP client. Final Rust release; the project continues in Zig at the same repository.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
# mnml — Features

The complete, organised feature inventory. For the front-door overview see
[README.md](README.md); for design rationale see [`CLAUDE.md`](CLAUDE.md).

---

## Editing & input

- **Pluggable input layer** — a modal **vim** keymap and a modeless **standard**
  (VS Code-style) keymap, both first-class and both fully remappable. Switch at
  runtime (`:set input=vim` / `editor.toggle_keymap`). Input handlers translate
  keys into a closed set of edit operations; the editor, buffer, and render
  layers never branch on which handler is active.
- **Vim modal editing** — Normal / Insert / Visual / Visual-Block / Replace
  modes; operators + motions + text objects (`iw`, `ip`, `i(`, `if`/`ic`/`ia`
  tree-sitter objects, indent objects); registers (named, numbered delete-ring,
  yank); macros (named, persisted); marks (buffer-local + global, persisted);
  the `.` repeat; jumplist & change-list; `f`/`t` find-char; vim-surround;
  multi-cursor; abbreviations. Charwise VISUAL is inclusive of the cell
  under the cursor, as vim's is, and folds follow vim's directions —
  `za` toggles while `zo` opens and `zc` closes, each idempotent.
- **Flash-motion jumps** — `s` plus two characters labels every match on
  screen (mnml gives `s` to flash rather than vim's substitute); press a
  label to jump, Esc to cancel. The overlay says so while it is armed.
- **Ex-command line** — `:w`/`:q`/`:e`, `:%s/old/new/flags` with ranges and
  marks, `:g/`/`:v/` global commands, `:norm`, `:sort`, `:!cmd`, `:r`, line-range
  ops, user-defined `:command`s, history with completion — a deep `:` surface.
- **Standard keymap** — modeless VS Code-style editing with multi-cursor
  (`Ctrl-D` add-next-occurrence, `Ctrl-Alt-↑/↓` column cursors), familiar
  chords, and the same config-driven rebinding.
- **Editor essentials** — undo/redo (persisted per file), system clipboard,
  word-wrap, auto-indent, auto-pairs, bracket-match highlight, code folding
  (manual + LSP-suggested), `.editorconfig` support, snippets with tab-stops,
  trailing-whitespace tools.

## Panes, splits & tab pages

- **Recursive split tree** — editors, terminals, diffs, and every tool view are
  `Pane`s laid out in a binary split tree. Split side-by-side or stacked.
- **Window management** — vim `Ctrl-W` chords (focus, move, resize, rotate,
  equalize, maximize), mouse click-to-focus and drag-to-resize dividers.
- **Tab pages** — vim-style `:tab*` pages, each with an independent split tree;
  a bufferline tab strip; session-persisted across launches.
- **Buffer management** — a tabline of open buffers, MRU buffer switching,
  reopen-closed-buffer, recent-files picker, alternate-file jump.

## File manager

- **Files pane** — a directory listing as a first-class `Pane`
  (`files.open`), so a browser is just another thing you can split, tab,
  and arrange; `files.open_split` opens a second one beside it for a
  Commander-style dual layout. Navigation, three sort orders
  (dirs-first-name / size / modified), a hidden-file toggle, a clickable
  breadcrumb with a destinations picker (Home / Downloads / volumes /
  workspaces / recents), per-row git status badges, `p` to preview a file
  without leaving the listing, and a `/`-filter. The same `file.*`
  operations that work from tree focus (below) also act from a focused
  Files pane. `src/file_browser.rs` + `src/ui/file_browser_view.rs` +
  `src/app/file_actions.rs`.
- **Multi-select** — `Space` marks the row under the cursor, `a` marks
  all, `Esc` clears; every file operation acts on the marked set.
  Ctrl/Cmd-click toggles one row, Shift-click extends a range; the
  right-click menu acts on the marks rather than the row under the
  cursor. Marks are keyed by path (not index), so they survive a
  re-sort, a reload, a hidden-file toggle, or navigating away and back.
- **Background transfers** — copy and move run on a worker thread
  (`src/transfer.rs`) instead of the render thread, so a large directory
  no longer freezes the editor. A statusline chip shows progress and
  speed while a transfer is running (hidden when idle);
  `transfer.cancel_all` cancels every in-flight transfer from the
  palette; `:qa` refuses to quit mid-transfer.
- **Undoable delete / workspace trash** — a delete moves the entry to
  `<workspace>/.mnml/trash` instead of removing it outright; the confirm
  modal also offers "Delete permanently" to skip the trash. `files.trash`
  opens the trash as a Files pane; `files.restore_from_trash` puts the
  selected entry back where it came from. Bounded: entries older than 7
  days are pruned, the trash is capped at 512 MB total (oldest evicted
  first above that), and anything at least 256 MB skips the trash and is
  deleted directly rather than trashing something the size cap would
  immediately evict.
- **Editor breadcrumb** — a directory-path row above the buffer; each
  path segment is clickable and opens a Files pane at that directory
  (parity with the Files pane's own breadcrumb, which was already
  clickable).

## Navigation & search

- **Fuzzy pickers** — file finder, command palette, buffer switcher, symbol
  picker, marks/clipboard/recent-commands pickers — all over one fuzzy core.
- **Which-key leader popup** — a discoverable trie of leader-key chords.
  Root groups: `f` find, `b` buffer, `t` toggle (explorer, right panel,
  hidden files, vim⇄standard, theme picker), `g` git, `h` http, `T` test,
  `L` lang-run (`c` cargo / `n` npm / `p` pytest / `g` go, each its own
  subgroup), `P` PR (cross-host picker + refresh), `i` integrations
  (detail pane, `htop`/`iftop`/`btop` launchers, icon picker,
  enable/disable), `a` AI/term, `s` split, `l` LSP, `I` snippet insert, `H`
  harpoon (plus `1`–`9` direct jumps), `c` cheatsheet. Root-level leaves
  (no second key): `/` toggle comment, `n` line-number gutter, `?`
  cheatsheet, `w` save, `B` open browser, `q` close buffer, `e` explorer,
  `m` markdown preview, `p` command palette, `o` run task. The per-forge
  chords that used to live under `i` (one letter per Bitbucket / GitHub /
  S3 / Lambda / … sibling) were dropped 2026-08-03 — each marketplace
  integration now registers its own command and chord via its manifest
  instead of a hardcoded binding here.
- **Find & replace** — in-buffer find (literal + regex, smart-case,
  incremental), replace, find history.
- **Workspace grep** — ripgrep-backed project search into a results pane, with
  cross-file replace and a per-hit toggle.
- **Quickfix & location lists** — vim-style `:cnext`/`:cprev` navigation.
- **Multi-root workspaces** — several workspace roots and multiple git repos in
  one session, with a repo switcher. The "Open folder…" (`AddWorkspace`) prompt
  shows a live-filtered directory listing (up to 12 suggestions): `↑↓` navigate,
  `Tab` autocomplete from focused row, `Enter` accept. Tilde expansion; dotfiles
  hidden unless the typed prefix asks for them. Other prompt kinds are unaffected.

## Language intelligence (LSP)

- **Completion** — as-you-type popup with documentation, lazy
  `completionItem/resolve`, snippet-format items.
- **Navigation** — go-to definition / declaration / type-definition /
  implementation, find references, document & workspace symbols, an Outline pane.
- **Diagnostics** — inline gutter signs, a Problems pane, `]d`/`[d` navigation,
  external-linter integration (eslint, ruff, shellcheck, …).
- **Code actions** — quick-fix, refactors, organize-imports, with a picker.
- **Rename** — with an inline preview and a cross-file confirmation pane.
- **Hover, signature help, inlay hints, semantic tokens, document colors,
  code lens, document links** — the standard LSP surface.
- **Hierarchies** — call hierarchy (incoming/outgoing) and type hierarchy
  (super/sub-types).
- **Formatting** — LSP formatting, format-on-save, on-type formatting,
  `willSaveWaitUntil`, plus external formatters (rustfmt, prettier, gofmt, …).
- **Tools picker** — a Mason-style installer view listing every LSP / formatter
  / linter mnml looks for, with install hints.

## Git

- **Gutter & statusline** — per-line add/modify/remove signs, a branch chip with
  ahead/behind and file-status counts, a clickable provider badge.
- **Diff pane** — Hunk / Inline / Split views, per-hunk stage / unstage /
  discard, intraline highlighting, a `/`-filter, change-density minimap.
- **Staging view** — `git status` unstaged/staged lists, stage/unstage whole
  files or dive into hunks, commit from inside the IDE.
- **Commit graph** — a coloured-lane commit DAG with a
  right-side detail panel, sortable columns, branch/date/author/subject filters,
  hash-jump, and a working-tree (WIP) row with interactive staging buttons.
- **Branch rail** — a collapsible rail of branches / worktrees / open PRs;
  checkout, create, delete, and worktree management.
- **Sync** — fetch / pull (ff-only) / push, cherry-pick, revert, tags, stash
  list & reflog pickers, an operation-level undo/redo stack.
- **Blame** — a per-line `<sha> <author>` gutter.
- **AI commit messages** — summarise the staged diff into a conventional-commit
  message, recompose `HEAD`'s message, via the `claude` CLI or Codex.
- **Browse** — open the current file / commit on the remote (GitHub, GitLab,
  Bitbucket, Azure DevOps).
- **Cross-host PR picker** — `pr.picker` fans out to whichever
  `mnml-forge-*` integration siblings (Bitbucket / GitHub / GitLab /
  Azure DevOps) are installed, merges their open PRs into one picker
  (Enter opens the PR URL, Tab jumps to its pipeline run), backed by a
  background-refreshed cache (`pr.refresh`). Per-host Pipelines/builds
  dashboards, PR reviewer/approval detail, and CI log viewers live in
  those standalone `mnml-forge-*` binaries, not in mnml core — the SCM
  hosts were split out of core in June 2026 (`src/scm.rs`).

## TODOs, notes & findings

Three activity-bar list panels sharing one design (`src/ui/{todos,notes,
findings}_panel.rs`, `src/ui/list_sort.rs`).

- **TODOS panel** — scans `TODO`/`FIXME`/`XXX`/`HACK`/`REVIEW` markers from
  source-code comments AND markdown list items (a bare `- TODO: …` line
  counts) across the workspace, plus Playwright/Jest `.fixme(`/`.fail(`/
  `.skip(` call sites. Rescans on filesystem changes, throttled to one
  scan per 2 seconds. `+ New todo` (`todos.new`) appends a line under a
  `## Inbox` heading in the workspace's `TODO.md` (creating both if
  absent). Right-click a hit for an action menu that hands it to
  whatever agents/commands/skills the workspace's own `.claude/`
  directory declares, or falls back to "Fix with Claude Code" / "Fix
  with Codex".
- **NOTES / FINDINGS panels** — the same list shape over `.mnml/notes/`
  and `.mnml/findings/`. `+ New note` (`notes.new`) / `+ New finding`
  (`findings.new`) open a NewFile prompt pre-seeded with the next
  auto-numbered filename (`note-N.md` / `finding-N.md`), so Enter is
  fast and typing over it is still possible.
- **Shared panel chrome** — a caps header with a live count (`(N)`, or
  `(M of N)` while filtered; a trailing `+` means the TODOS scan hit its
  1000-marker cap and the count is a floor), a `/`-focus filter row, a
  focused-row accent bar, a scrollbar, and keyboard/wheel/drag
  scrolling. Right-click the `⟳` chip (shared with the Git / Agents /
  Cloud Agents / HTTP panels) for "Refresh now" and "Auto-refresh:
  on/off" (persisted per panel via `[ui] auto_refresh_off`).
- **Sort chip** — a `sort: <mode>` chip in the header of TODOS / NOTES /
  FINDINGS / SESSIONS, styled like the Cloud Agents `view:` chip. Click
  cycles; right-click lists every mode with a `✓` on the current one.
  Narrow panels drop to an icon-only form rather than losing the chip.
  The three list panels share four modes — Newest first, Oldest first,
  Name (A–Z), Name (Z–A) — persisted as `[ui] todos_sort` /
  `notes_sort` / `findings_sort`, and reachable from the palette as
  `todos.sort` / `notes.sort` / `findings.sort`. SESSIONS sorts on its
  own axis (State vs Manual, `[ui] sessions_sort`,
  `sessions.sort_auto` / `sessions.sort_manual`).
- **Row context menus** — right-click a NOTES / FINDINGS / SEARCH /
  AGENTS row for Open, Open in split, Reveal in tree, Reveal in
  Finder/Explorer, Copy path, Rename and Delete as applicable. "Reveal
  in tree" expands the rail to the file and selects it; the OS reveal is
  a separate row.

## AI

> mnml *integrates with* AI tooling — it does not bundle a model. These
> features describe what mnml does; you bring your own CLI / API key.

- **AI panes** — run the `claude` CLI or Codex as embedded panes; tail their
  session transcripts; promote a one-shot answer into an interactive session.
  `ai.claude_code_focus` focuses the running Claude Code session (starting one
  if none is open) rather than always spawning a new one.
- **On-selection actions** — explain / fix / refactor / write-tests on a
  selection; a free-text "ask"; results stream into a pane and a fix/refactor can
  be applied as a reviewed diff.
- **Two backends** — drive the `claude` CLI in print mode, or talk to the
  Anthropic Messages API directly (with an agentic read-only tool loop). The
  backend, model name, system prompt, and token cap are all config knobs.
- **Inline suggestions** — opt-in Copilot-style ghost text: an API backend, or a
  fully local, in-process FIM model via the bundled `mnml-fim-engine` crate (no API
  key, offline after a one-time download). Off until you turn it on — via the
  first-launch wizard, `ai.setup_suggestions`, or Settings → AI. The remote
  backends send buffer context around the cursor, so files whose names look
  secret-bearing (`.env`, `id_rsa`, `*.pem`, `*credentials*`, …) are never sent
  regardless of the setting; the local backend is exempt since nothing leaves
  the machine.
- **Context-aware chat** — a claude-chat.nvim-style wrapper that seeds a prompt
  with the active file and selection.
- **Launch profiles** — multiple named launch commands per Claude/Codex chip
  (`[[launch_profile]]` + `default_profile` in the integration manifest,
  user-global or workspace-scoped). Right-click the chip to fire a one-off
  session with any profile or to persist a new default; the legacy
  "Set launcher script…" single override still works as the `wrapper` profile.

## Terminal & process panes

- **Pty panes** — a shell, the `claude` CLI, Codex, or any task as live terminal
  panes, with a multi-session tab strip and `:rename`.
- **Pty tabs in bufferline** — terminal and Claude Code sessions get bufferline
  tabs with a `$` suffix and a close button. `:bn` / `:bp` skip Pty tabs so vim
  users don't get trapped cycling through terminal sessions.
- **Scratch terminal** — a quick docked terminal strip.
- **External tool launchers** — `tools.htop`, `tools.iftop`, `tools.btop` (also
  `term.htop` / `term.iftop` / `term.btop` aliases) probe `$PATH`, open the tool
  in a Pty pane if found, or fire a platform-aware install hint toast (Homebrew on
  macOS, apt on Linux, winget on Windows) if not.
- **Tasks** — `[tasks.*]` config + a task launcher; startup tasks.

## Dock widgets

- **Three-tier UI** — full panes (split-tree) / dock widgets (corner-pinned
  mini-panels in the editor body) / status chrome. The middle tier is for
  things you want visible next to the buffer rather than instead of it.
- **Four corners** — `BottomLeft` / `BottomRight` / `TopLeft` / `TopRight`.
  Widgets sharing a corner stack inward (bottom corners upward, top corners
  downward); per-corner stack capped at 50 % of the editor height.
- **Content variants** — `Text` (static, via `dock.new_text*`) and `LogTail`
  (per-frame re-read of a file's last N lines, via `dock.new_log_tail`;
  default path `<workspace>/.mnml/run.log`). The title bar shows a `▼N`
  chip when the file has more lines than fit.
- **Size presets** — Small (0.25 × 0.15) / Medium (0.5 × 0.25, default) /
  Large (0.5 × 0.4) / Wide (0.9 × 0.25) / Tall (0.5 × 0.5). Fractions clamped
  to `0.15..=0.9`.
- **Layout modes** — `Overlay` (default; paints on top of the editor) and
  `Inline` (claims a strip at the top/bottom edge; editor reflows around it).
  Multiple inline widgets at the same edge tile horizontally; combined strip
  heights capped at 50 % of editor height.
- **Opacity modes** — `Solid` (default; full bg) and `Translucent` (skips body
  bg so editor text shows through; title + border keep their bg).
- **Kebab menu** — `⋮` glyph at the right end of the title bar (also right-click
  the widget body). Sections: Resize / Move to / Layout / Opacity / Rename… /
  Close. Current values get a `●` marker; the highlight pre-positions on the
  row that matches the widget's current state. Drops up when it would clip
  into the statusline.
- **Drag-to-move** — click + hold the title bar; a cyan ghost chip `⇲ <title>`
  follows the cursor, and a translucent `░` overlay paints on the actual
  landing rect (with a `⤴ Top-left` / `⤵ Top-right` label) so the drop target
  is unambiguous. Magnetic snap within 8 cells of another widget's body
  center: the dragged widget inherits the target's corner and reorders in
  the vec to sit adjacent (above if cursor was above the target's center,
  below otherwise).
- **New dock note lives in the `+` menu.** An earlier faint ` + dock `
  chip painted over the bottom-right of the editor body — on top of
  whatever pane's last row was there, so clicking a file in a Files pane
  could spawn a sticky note. Removed 2026-08; "New dock note" is a row
  in the shared `+` menu instead, which covers nothing and is always in
  the same place.
- **Session persistence** — the widget vec (positions, sizes, corners,
  content, layout, opacity) round-trips through `.mnml/session.json`. Older
  session files without the layout / opacity fields default to `Overlay` /
  `Solid` cleanly via serde.

## HTTP request client

- **Request files** — send `.http` / `.rest` / `.curl` files, with multi-block
  files, `{{variable}}` templating, environments, and pre/post-request scripts
  (`@set-*`, `@assert`, `@capture`).
- **Request pane** — an editable, form-style pane (method / URL / headers /
  body), re-send, copy-as-curl, and write-back to the source file. The Edit
  view is **tabbed** — Body / Headers / Params / Vars / Source — with
  `Ctrl+]` / `Ctrl+[` cycling and `Ctrl+1..5` for direct jumps.
- **Side-by-side edit split** — the `[⇔]` chip on the Request block's border
  row opens a two-pane view of the edit area. Left = current primary tab,
  right = a secondary tab you pick (any of Body / Params / Headers / Auth /
  Vars / Source). Both sides operate on the same underlying request, so
  edits in one are visible in the other. Right side has its own clickable
  tab strip so any combination works (Body|Vars, Params|Body, Auth|Headers).
  Click the 1-cell divider to cycle the ratio 30 / 50 / 70. Palette command
  `http.toggle_edit_split`.
- **`{{VAR}}` highlighting + click-to-def + hover** — variable tokens across
  the URL, Body (JSON + plain), Params values, and Headers values render
  cyan-bold when resolved, red-bold when the active env is missing them.
  Left-click a token jumps to its definition line in
  `.mnml/env/<active>.env` (falls back to `.rqst/env/<active>.env`; opens
  at end-of-file when undefined so you can append). Right-click opens a
  quick-fix menu: "Set value…" seeds the env-edit prompt (accept upserts
  into the active env file), "Jump to definition", "Copy variable name".
  Hover shows the resolved value or "not defined in active env" so you can
  scan a request for missing envs at a glance. Dynamic vars like
  `{{$uuid}}` / `{{$timestamp}}` render as resolved but skip the Set-value
  menu since they're built-ins.
- **HTTP activity-bar panel with `/` filter** — the seven-section HTTP
  sidebar (COLLECTIONS / FILES / ENVS / CHAINS / MOCKS / RECENT / CAPTURED)
  gains a `/`-focus filter row at the top, matching the Agents / Cloud
  Agents idiom. Typing narrows across every section; for COLLECTIONS a
  matching request-name keeps its collection visible and force-expands the
  chevron so hits show without an extra click.
- **Blank request scratch** — `:http.new` (or the green `+` chip in the
  INTEGRATIONS rail) opens an empty Request pane in Edit mode, no file
  backing. Postman-style entry point.
- **Paste curl** — `:http.paste_curl` (also `Ctrl+Shift+V` in Edit view, or
  right-click a field → "Paste curl from clipboard") reads the clipboard,
  parses it as curl / `.http` / `.rest`, and overwrites the active pane's
  Method / URL / Headers / Body. Opens a blank pane first if none active.
- **Field-aware right-click menu** — Send / Paste curl / Copy as curl /
  Switch to Response, with per-field title (`Request · URL` / `· Method` /
  etc) and an extra "Cycle method" entry on the Method row. Same menu
  fires from every tab's content area.
- **Cycle method** — `:http.cycle_method` (also Space when Method field is
  focused) walks through GET → POST → PUT → PATCH → DELETE → HEAD → OPTIONS.
- **SSE streaming** — `:http.send_streaming` opens the request over an SSE
  reader (per-event newline buffering, no overall timeout for SSE servers
  that hold the socket).
- **Cookies normalizer** — `:cookies.normalize_clipboard` collapses any of
  the three DevTools cookie-paste shapes (`name=val` per line,
  `name: val` per line, or canonical `name=val; name=val`) into the
  on-the-wire `name=v; name=v` form, written back to clipboard.
- **Env files** — `.mnml/env/<name>.env` (preferred) and `.rqst/env/<name>.env`
  (legacy, ported from rqst). `.mnml/` overrides on the same key; resolution
  chain is `--env` → `$MNML_ENV` → `.rqst/config`'s `default_env`.
- **Chains** — run a `.chain.json` of dependent requests, extracting values
  between steps.
- **Discover** — turn an OpenAPI / Swagger spec into one `.curl` stub per
  operation.
- **Sources sync** — `.mnml/sources.json` (or `.rqst/sources.json`) lists
  swagger sources; `:http.sync` regenerates every `.curl` stub from upstream
  on a background thread.
- **Bench** — `:http.bench` fires the active request 10× concurrent on a
  background thread, full p50/p95/p99/max trace to the clipboard, summary
  headline toasts.
- **Mocks** — `:http.save_mock` writes the active Done response to a sibling
  `<source>.curl.mock.json`; `:http.replay_mock` serves it back as if it were
  a live send (no network call).
- **History** — every send (Ok or Err) appends to `.rqst/history.jsonl`;
  `:http.history` opens a picker over the last 100 entries, Enter scratches a
  re-fire-ready `.curl` buffer.
- **Captured browser traffic** — when a Browser pane is open, every network
  request auto-appends to `.rqst/captured/log.jsonl` (default on; toggle with
  `[browser] autocapture_to_log` or `:browser.autocapture_toggle`).
  `:http.view_captured` opens a picker, Enter scratches a `.curl` for re-fire.
  `:http.capture_now` also dumps the pane's current NetEntry list on demand.
- **Lookup picker** — `:http.lookup` walks a multi-stage UI: pick a `.curl`
  under `.rqst/lookups/` → fire it → pick an item from the response list →
  type a var name → writes `<var>=<id>` to the active env file.
- **Env editor** — `:http.edit_env` opens a structured picker over every
  `KEY=VALUE` row in the active env file plus a `+ Add new variable…` row.
  Reads both `.mnml/env/` and `.rqst/env/` files (with `.mnml/` precedence);
  writes back to whichever file the key currently lives in.
- **Helpers** — `:jwt.decode` (clipboard JWT → claims + EXPIRED flag);
  `:auth.extract_bearer` (clipboard text → bare token);
  `:sse.parse_active_response` (parse Done body as SSE events + summarize).
- **CLI mode** — `mnml run FILE`, `mnml chain run FILE`, `mnml discover SPEC`,
  `mnml sync [--workspace DIR]`, `mnml proxy --url URL [--seconds N]`
  (headless Chrome CDP capture into `.rqst/captured/log.jsonl`),
  `mnml export-config-zon [--out PATH] [--workspace DIR] [--in PATH] [--force]`
  (convert a 0.2.x `config.toml` to the `config.zon` mnml 0.3 / mnml-zig reads —
  only the keys you set, a `//` doc per key, enums as `.literals`, string-or-list
  and `custom:` forms normalised, unknown keys kept in a trailing
  `// unmigrated:` block).

## Browser & CDP capture

- **Browser pane** — launch Chrome over the DevTools Protocol; a live console,
  filtered network log, and navigation log.
- **Inspectors** — network requests (copy-as-curl, re-send as a request pane),
  a DOM tree with live highlight, cookies, web storage, and a performance panel
  — all with type-to-narrow filters.
- **Capture** — full-page and per-node screenshots, print-to-PDF, snapshot
  diffs, device emulation, multi-target and headless support.

## Debugging (DAP)

- **Debug Adapter Protocol** — launch or attach a debug adapter; breakpoints
  (incl. conditional & hit-count), step controls, an exception-breakpoints
  picker.
- **Inspection** — a call-stack pane, a variables tree with set-variable, watch
  expressions, and a REPL pane with lazy-expand. Reverse-debugging where the
  adapter supports it.

## Testing & quality

- **Playwright runner** — run tests, a grouped results pane, jump-to-source, a
  trace timeline viewer, a flaky-test dashboard with run history.
- **`.test` E2E format** — a line-based DSL (`open`, `key`, `type`, `command`,
  `click`, `expect screen …`) that drives the real `App` against a virtual
  backend. Runs via `mnml test` and under `cargo test`.

## UI & theming

- **NvChad-style chrome** — file-tree rail, bufferline, powerline statusline,
  cmdline bar, which-key, indent guides, sticky scope context.
- **Local file actions** — `file.cut` / `file.copy` / `file.paste` /
  `file.duplicate` / `file.move_to` cover the standard file-manager surface
  from tree focus (Ctrl+X / C / V / D chords, plus the right-click menu).
  Cut+Paste renames (move, clipboard clears); Copy+Paste duplicates (recursive
  for directories, symlinks preserved on Unix; clipboard sticks so the same
  set can paste elsewhere); same-dir Copy bumps to `-copy` / `-copy-N` instead
  of clobbering. Move-to opens a path prompt with autocomplete and `~`
  expansion. Tree drag-and-drop works too — plain drag prompts "Move to X?"
  before renaming, and `Alt`-drag copies immediately without a confirmation
  (Finder / VS Code convention).
- **Optional right side panel** — a collapsible panel on the right edge; toggle
  with `Ctrl+Shift+B` or click the EC00 icon in the palette bar, or `:set
  rightpanel` (idempotent enable) / `:set rightpanel!` (toggle) / `:set
  norightpanel` (disable). Drag the left-edge grip to resize. State (visible +
  width) persists to `session.json`; defaults configurable via `[ui]
  right_panel_visible` and `[ui] right_panel_width`. Palette command:
  `view.toggle_right_panel`. Which-key chord: `<leader>tr`.
  When visible, `outline.show` and `lsp.diagnostics` host their pane inside
  the panel instead of splitting the editor body — the editor keeps full
  width and the panel header switches between OUTLINE / DIAGNOSTICS. A `×`
  on the header evicts the hosted pane (panel stays open, returns to the
  empty-state copy that teaches the two commands).
- **Keyboard right-click** — `Shift+F10` opens the context menu for the
  focused element. Routes Focus::Tree → tree-row menu, Focus::Pane →
  bufferline tab menu, and falls back to the cursor's most-recent hovered
  chip (integration / launcher / activity-bar gear). Palette command:
  `view.context_menu_at_focus`. Mirrors VS Code + macOS convention.
- **Palette bar redesign** — sidebar toggle (EC02 codicon) + right-panel toggle
  (EC00 codicon) + flat-rendered integration chips between the workspace chip and
  the right cluster + add-integration `+` (EA7C codicon). At narrow widths the
  right cluster drops TABS rather than vanishing entirely.
- **Menu glyphs** — every context-menu row draws an icon by default
  (`src/ui/menu_glyph.rs`); `[ui] ascii_icons = true` blanks them all so
  the menu is pure text. `menu.glyph_audit` writes and opens a
  spacing/icon audit covering every menu in the app.
- **Context-menu submenus + a curated `+` menu** — a context-menu row can
  open a nested submenu. The `+` chip's "new thing" menu is organised
  into five sections rather than ~15 flat rows; each row carries a kebab
  to pin, hide, or copy its command id, and the layout persists
  (`[ui] plus_menu_pinned` / `plus_menu_hidden`).
- **External browser override** — `[ui] external_browser = "Google
  Chrome"` opens external links (git remote browse, etc.) in a named
  application instead of the OS default; an untrusted workspace cannot
  set this key for you.
- **94 themes** — the full NvChad base46 set (onedark, gruvbox, catppuccin,
  kanagawa, tokyonight, nord, dracula, …); switch at runtime.
- **Discoverability** — an F1 click-discovery overlay, hover tooltips on every
  chip (hover any chip for a description; right-click for a context menu with
  actions), right-click context menus throughout, a first-launch welcome, About &
  Settings overlays.
- **Markdown** — a live preview pane with inline image embedding, and
  optional inline-rendered markdown in the editor (`render_markdown`,
  off by default; `view.toggle_render_markdown`). `[ui]
  markdown_opens_rendered` (default on) opens `.md` files straight into
  the rendered preview pane rather than the raw editor.
- **Preview tabs** — opening a markdown file, an image/GIF, or an
  `.http`/`.curl`/`.rest` request from a single click (tree, Files pane,
  a jump) reuses a *preview* tab that the next glance replaces, instead
  of piling up permanent tabs for things you were only looking at.
  Typing edits the tab permanent; on a rendered markdown preview, typing
  first swaps it to the raw editor and lands the keystroke there — under
  the standard keymap only, vim input does not auto-swap on the first key.
- **Image rendering** — inline images via the Kitty / iTerm2 graphics protocols.
- **Now-playing transport chip** — the statusline's right-side cluster splits
  into `[play/pause]` + `[ffwd]` + `[track]` adjacent segments when any source
  is playing. Source-aware dispatch — mixr uses its `~/.mixr/command` IPC
  (`pause`, `teleport`); Apple Music and Spotify use AppleScript via
  `osascript` (`playpause`, `next track`, `activate`) with a hardcoded source
  whitelist. macOS sources combine `artist - title` in the track text. A 10-s
  stickiness layer papers over mixr's mid-transition empty reads so the chip
  doesn't flicker. Idle collapses to one `♪ <app>` chip — label and click
  destination follow `[ui] preferred_music_app` (`mixr` / `music` / `spotify`,
  default `mixr`).
- **Mixr panel size chips** — the `♪ mixr` panel's header carries three
  right-aligned chips for snapping between size states: `⤢` grow (to
  `Full`), `⤡` shrink (to `BottomStrip`, only from `Full`), `–` minimize.
  Click handlers run before the header's drag detector so the chips don't
  get eaten by a window-drag start. The minimize chip releases focus back
  to the editor; grow and shrink keep focus on the panel.
- **Stress meter** — a small 4-block bar in both the top-right
  bufferline cluster and the bottom-right statusline that fills as
  mnml's p95 frame time climbs (green under 20/100, yellow to 40,
  orange to 70, red above). Hidden when idle. Hover shows exact
  `p50 / p95 / max` in ms plus the sample count; right-click opens
  Reset / Copy summary / Toast the numbers. Backed by a rolling
  120-sample window (`App.frame_times_ms`) populated by the main
  loop after each tick+draw+event-wait cycle.
- **Click-to-dismiss toasts** — click a toast to remove it; right-
  click for a menu with dismiss-this / dismiss-all / copy-text.
  The Undo chip beside the toast stack commits on left-click and
  cancels on right-click.
- **Notification history** — every toast is recorded to `:messages`
  (`messages.show` opens a picker over recent entries; `:Messages!`
  dumps the full log into a scratch buffer) and now persists per
  workspace across restarts. A bell chip sits immediately left of the
  clock in the statusline, always drawn, in three states: quiet/idle
  colours when nothing is unread, yellow with a count for unread
  warnings, red with a count when any unread entry is an error — info
  messages don't light it.
- **Zen mode**, a clickable statusline.

## Workspace trust

- **Repo-supplied config is gated before it can run anything.** A workspace's
  own `.mnml/config.toml` can name programs mnml would execute — language
  servers (`[lsp.*] cmd`), formatters and linters, debug adapters,
  `[ui] md_preview_engine = "custom:…"`, `[[startup.layout]] kind = "pty"` —
  and `.mnml/integrations/*.toml` can register commands, launch profiles, and
  spawn `[env]`. mnml scans for exactly those keys on open and asks before
  honouring any of them, so cloning a repo and opening it can't run code.
- **Quiet by default.** The scan means an ordinary repo — no `.mnml/`, or one
  with only themes and keymaps — never prompts. You see the dialog only when a
  workspace actually declares something executable, which is what keeps it
  worth reading rather than reflexively dismissing.
- **The dialog shows the actual commands**, what each one is, and when it would
  fire ("runs when you open a file", "runs immediately, on open"). "Don't
  trust" is focused by default.
- **Untrusted is restricted, not broken.** Only the exec-bearing keys are
  dropped; the same file's theme, keymaps, and editor settings still apply, and
  your global language servers and formatters keep working. A `RESTRICTED` chip
  in the statusline says why something isn't running.
- **Trust is fingerprinted**, so approving a workspace today doesn't bless
  whatever a later `git pull` adds — if the declared commands change, mnml asks
  again. Cosmetic config edits don't re-prompt. Decisions live in
  `~/.config/mnml/trusted_workspaces.toml`, keyed by canonical path (never in
  the workspace, which the repo itself could write). `workspace.review_trust`
  reviews or revokes.

## Headless, IPC & extensibility

- **Headless mode** — `mnml --headless` renders to a virtual screen, driven over
  a file-IPC channel (`command` in, `screen.txt` / `status.json` /
  `events.jsonl` out) — the same `App` and draw path as the terminal UI.
- **Plugins** — out-of-process helpers over the IPC channel can register
  commands that appear in the palette and resolve as keybindings.
- **Integration tools** — `:term <binary>` spawns an integration
  (`mnml-tracker-jira`, `mnml-aws-cloudwatch-logs`, `mnml-aws-amplify`,
  `mnml-db`, `mnml-aws-lambda`, `mnml-aws-eventbridge`, and ~25 more in
  the `mnml-integrations` monorepo) as a Pty pane.

  Each integration declares its own palette command in the manifest its
  `--install` writes, so the ids live with the integration, not in mnml
  core: `lambda.open`, `amplify.open`, `cloudwatch_logs.open`,
  `eventbridge.open`, `db.open`. They resolve as dynamic commands once
  that integration is installed, and `integrations.refresh` re-scans
  without a restart.

  Add a custom integration by dropping a `[[ui.integration_icon]]` entry
  in config — no code changes to mnml required.
- **Settings overlay** — `:settings` / `view.settings` opens a keyboard-driven
  overlay (centered, ~60 % × 70 %) for everyday config toggles. Rows are
  `▸ <label>: [active] / other  *`; section headers `── UI ──` etc. Keys:
  `←→` adjust, `↑↓` move, `r` reset row, `R` reset all, `Enter` save, `Esc`
  cancel. Includes rows for right panel visible (default on) and right panel
  width.
- **Config-driven launcher-icon strip** — the bufferline's right cluster is
  driven by `[[ui.launcher_icon]]` TOML entries (`id`, `glyph`, `fallback`,
  `command`, `color`, `tooltip`). The `command` field accepts a registered
  command id or a colon-prefixed ex-cmdline string (`:term binary`).
  Setting the key replaces the built-in Claude Code + Codex defaults.
- **Config-driven integration-icon rail** — the file-tree rail's icon strip is
  driven by `[[ui.integration_icon]]` TOML entries (same fields as
  `[[ui.launcher_icon]]`). Each icon launches its sibling binary on click.
  Default entries ship for all first-party siblings; extras can be added via
  TOML or the Marketplace tab — no code changes to mnml required.
- **`+` "Add integration" chip** — the `+` chip in the palette bar opens the
  Marketplace tab (`integrations.show_marketplace`), which lists published
  apps plus any `mnml-<class>-<name>` binaries auto-discovered on `$PATH`,
  with per-row install / update actions.

  The separate centered "discovery overlay" this chip used to open was
  dropped on 2026-07-03 — the activity-bar side panel (Installed /
  Marketplace tabs, filter, per-row Enable / Edit / Move-up / Remove menu)
  already covered browse + enable + edit + install, so the overlay was a
  redundant second copy.
- **Integration `enabled` opt-in** — each integration chip in the palette bar
  carries an `enabled` flag (default `false`; `browser` is enabled by default).
  Right-click a chip → Enable / Disable toggles the flag and persists the change
  to TOML. Palette command: `integrations.toggle_enabled`. Which-key chord:
  `<leader>iE`. Disabled chips are rendered visually dim and do not launch on
  click; they can still be edited or removed via the kebab menu
  (`integrations.edit` / `integrations.remove`). `<leader>ip` (icon picker) and
  `<leader>id` (detail pane) round out the integrations which-key group.
- **Icon picker** — `integrations.icon_picker` (palette command; `<leader>ip`)
  opens a browsable overlay of ~70 Nerd Font glyphs organized by category.
  Accepting a glyph copies the character and its `\u{XXXX}` escape to the
  clipboard. Used when adding or editing an integration icon.
- **Startup workspace picker** — `--startup-picker` (or `MNML_STARTUP_PICKER=1`)
  shows a chooser overlay on launch: [1] New file, [2] Open file…, [3–9]
  configured `[[workspaces]]` rows. Keys: `↑↓`/`jk` move, `Enter` commit,
  `1`–`9` direct jump, `Esc`/`q` skip. The `mnml.app` launcher enables this by
  default so Finder launches land on the chooser rather than `$HOME`.
- **Update-available check** — on launch, a background thread queries
  `api.github.com/repos/chris-mclennan/mnml/releases/latest` and fires a
  one-shot toast when a newer release tag is found. Opt out with
  `[ui] check_updates = false`. Skipped in headless mode.

## Languages

Tree-sitter syntax highlighting for **39+ languages** — Rust, JavaScript / TSX,
Python, Go, C / C++, Ruby, Java, C#, Lua, HTML / CSS, JSON, YAML, TOML, Markdown,
Bash, Scala, Elixir, Haskell, PHP, Swift, Zig, Nix, OCaml, Dart, SQL, Kotlin,
Dockerfile, HCL / Terraform, Protobuf, Vue, Svelte, Astro, diff, and more — with
**language injection** so fenced code blocks, embedded `<script>` / `<style>`,
and other nested grammars are highlighted too.