Skip to content

Changelog

Get an email when a new version of mnml ships — no spam, just release notes.

Or watch the repo on GitHub for a notification on every release:

View all releases on GitHub

Already subscribed? Every issue carries a manage/unsubscribe link in its footer — that link is personal to your subscription, so there is no generic portal URL to send you to.


Versions auto-tagged at github.com/chris-mclennan/mnml/releases — this page summarizes the user-facing changes. For commit-level history, see the GitHub release notes.

Big two-day rollup: first-launch wizard + per-integration auth SDK (both landed 8/11), plus 8/12’s L2 demo mode + AI ghost-text via Claude Code subscription + wizard/hover-help polish.

  • L2 demo mode (mnml --demo / ./run.sh demo). Screenshot-ready mnml without exposing real work. Boots against a bundled Notely / Bloom Labs sample workspace (copied to a per-user cache dir, fictional 10-commit git history seeded from a shipped tarball). Auto-spawns a Python mock HTTP server on localhost:7071 that serves ~40 JSON fixtures under demo/fixtures/{jira,bitbucket,github}/ — populated Jira boards + sprints + tickets, Bitbucket repos + PRs + pipelines, GitHub PRs + Actions runs. Env-injects the sibling env vars so integration panes route through the mock; clears extra workspaces from the in-memory config so the tree rail doesn’t leak workspace favorites.
  • AI ghost-text via Claude Code subscription. New SuggestBackend::ClaudeCode reuses the OAuth access token Claude Code caches so ghost-text bills against your Max/Pro plan instead of requiring $ANTHROPIC_API_KEY. Wizard auto-selects it when claude CLI + ~/.claude/ are both present. Grey-area vs. Anthropic TOS — flagged in the code + docs.
  • First-launch wizard (first_launch.show). Modal that auto-opens on first-ever launch, walks new users through AI ghost-text backend / input style / Nerd Font check / Claude Code + Codex install / VSCode code shim. Install sections spawn a Pty pane running the actual command. Numbered sections + horizontal rules; input-style row shows recommended-vs-current without silent overwrite.
  • Per-integration Settings pane + [[auth]] manifest schema. Integration authors declare auth fields via mnml-bridge 0.7.0’s AuthField; mnml drives a Configure pane, first-hit auth guard, and Pty env-injection. Cross-integration sharing — configure bitbucket once, jira’s Fix Versions view gets $BITBUCKET_ACCESS_TOKEN for free.
  • Hover-help debounce (120ms). Dragging the mouse across tree rows no longer flickers the info-box copy rapid-fire.
  • hover_tooltip opt-out. view.toggle_hover_tooltip palette command + :set [no]hovertooltip + Settings row.
  • ./run.sh demo subcommand + interactive-menu entry, mirroring the standalone loop shape.

Same-day rollup on top of v0.2.8. Two SEV-1 fixes plus a full morning of menu-bar / hover-help / integration-audit polish.

  • SEV-1 fix — Headers-tab typing no longer corrupts the wire. Any keystroke while the Request pane’s Headers tab was focused was landing INSIDE the last header’s value — silently mangling Auth Bearer tokens on the wire. The tab now reloads with a fresh newline; typing starts on an empty row.
  • SEV-1 fix — :qa / :qall / :quitall no longer discards unsaved work silently. Vim’s :qa requires :qa! to force; mnml’s :qa was setting quit unconditionally. Now walks every pane; any dirty pane refuses with unsaved changes — use :qa! to discard.
  • Menu bar keyboard reachability fixed at typical terminal widths. Alt+V / G / R / T / W / H had been silently no-oping (or worse: opening an invisible input trap) when the parent chip was clipped by the workspace cluster. Dropdown now paints at a fallback origin — every menu is keyboard-reachable at any width.
  • Alt+letter is inert while a picker, prompt, or cmdline is open. Prior behavior stacked the dropdown on top and swallowed keys between them.
  • Menu-open + top-level chord (Ctrl+P / F1 / etc.) closes the menu and runs the chord instead of silently no-oping.
  • F10 during a DAP session fires dap.next (step over), not the menu-summon.
  • Quit-confirm dialog defaults keyboard focus to [Cancel] — Enter is safe.
  • view.toggle_workspace_dots — opt-out for the ● / ○ workspace-root markers. Reachable via config key [ui] show_workspace_dots, palette command, :set wsdots / :set nowsdots ex-commands, and right-click on any workspace row.
  • integrations.audit_glyphs palette diagnostic — reports three drift classes without repairing: manifests whose glyph won’t render in your ghostty font-codepoint-map, id-alias duplicates in integration-glyphs.toml, orphan glyph_meta.toml entries. Writes a full report to .mnml/findings/glyph-audit-<timestamp>.md.
  • Left panel renamed from “file tree” throughout the UI — palette title, menu label, hover-help — since the panel actually hosts Git / Integrations / Agents / HTTP / Findings in addition to files.
  • Hover-help repositioned as an Ableton-style info box docked to the bottom of the left panel (was a 1-row footer strip). Word-wrapped, 6 rows tall, with a ? Info header. Tree rows show file language (.tsx → “TypeScript (JSX)”), Agents-dashboard rows get their own description, keyboard focus takes precedence over the always-active-pane fallback.
  • Menu-bar left-column glyphs on every menu (File / Edit / Selection / View / Go / Run / Terminal / Window / Help + Brand). Icons where a widely-recognized Nerd Font glyph matches; 3-space spacer preserves alignment where nothing fits.
  • HTTP panel MOCKS section discovers .mock.json sidecar files produced by :http.save_mock (was always showing (0)).
  • view.toggle_bufferline deleted — it only affected the launcher-cluster row on the empty welcome screen, which is duplicated in the welcome body anyway.
  • Sibling published: mnml-msg-slack 0.1.2 — canvases → boards rename, \u{F07D2} mdi-slack glyph (renders as the classic Slack logo in ghostty’s routed range), channels = white / boards = yellow.
  • Deleted ~640 lines of legacy family_catalog install-path scaffolding (CATALOG was &[] for months — every entry point was a silent no-op).

First actually-published release in eight tags. v0.2.1 through v0.2.7 all had tags pushed, but the Release workflow’s Windows build silently failed on use std::os::unix::process::CommandExt in src/main.rs — nothing shipped. Root-caused, cfg-gated, cross-checked with cargo check --target x86_64-pc-windows-gnu. Rollup of the eight-tag arc below.

  • Marketplace install is now upgrade-safe. Two overlapping bugs made “click Install on a sibling that’s already at an older version” a silent no-op: (a) cargo install without --force skips when the binary already exists, and (b) even when the fresh binary lands in ~/.cargo/bin/, a shell resolve of <sibling> --install would run whichever copy PATH found first — a stale ~/.local/bin/<sibling> could win and write its old manifest. Fixed by passing --force and by targeting $HOME/.cargo/bin/<name> explicitly. Added palette command integrations.audit_shadowed_binaries to move existing stale copies into a quarantine dir so they stop shadowing.
  • Legacy family_catalog install path deleted. −680 lines. The compiled-in registry was &[] for months while the whole cargo-install + prompt + IPC + AI-tool + Mount-picker pipeline sat around as silent no-ops. Marketplace is the only install path. Follow-up cruft sweep removed another handful of dead types + palette commands + config structs.
  • Bake-on-install glyph pipeline. Each sibling ships its SVG via mnml-bridge::ChipSpec::glyph_svg_bytes; mnml bakes it into MnmlSymbols.ttf at a codepoint it owns, preserving user-baked glyphs across rebakes.
  • Auto-refresh Claude Code OAuth tokens. No more “re-link every 8h” prompt — mnml POSTs the on-disk refresh token to Anthropic’s OAuth endpoint on the first 401/403 and persists the new blob.
  • Claude thinking-spinner glyphs. Five mnml-owned frames (F1E10..F1E14) baked at cap-mid height for the animated Claude Code tab.
  • Menu-bar submenus. MenuItem::Submenu variant with hover-open — File menu already has glyphs; Edit/Selection/View/etc coming next.
  • Findings activity-bar section. Live viewer over .mnml/findings/*.md; icon swapped to nf-md-file-search.
  • Verified marketplace chip. Curated allow-list surfaces a green ✓ Verified badge alongside the Official/Community authorship chip.
  • AI usage meter. Claude + Codex quota chip on the statusline.
  • Tree / integrations chevrons. Swapped from Unicode BLACK triangles to nf-oct-chevron-right/down (F460 / F47C) so collapsible groups match the VS Code / IntelliJ tree convention.
  • Shared text-input helper. Ctrl+U/W/K/V + word-nav uniform across every text surface (vim cmdline, prompt overlays, request-pane fields).
  • bake_ai_glyphs no longer wipes user-custom glyphs. The bake path seeds from glyph_meta.toml first, then adds the builtins.
  • Write-then-chmod race fixed on secret files. ai_token + ai_last_response.json now use OpenOptions::mode(0o600) atomically. Also: redact-before-write on ai_last_response.json (previously wrote raw HTTP body before restricting perms).

Session-length UX polish around the Claude Code integration, plus a small ergonomic gap in the : cmdline. The headline is that Claude Code OAuth tokens now auto-refresh — no more “re-link every 8h” prompt.

  • Auto-refresh of Claude Code OAuth tokens. Claude Code tokens expire roughly every 8h; before v0.2.3 the usage chip would show token rejected — re-link via :ai.link_claude_token and users had to re-paste the token from the keychain every day. mnml now POSTs the on-disk refreshToken to console.anthropic.com/v1/oauth/token on the first 401/403, persists the new {accessToken, refreshToken, expiresAt} blob back to ~/.config/mnml/ai_token, and re-issues the usage GET with the fresh bearer. Requires that you paste the full claudeAiOauth JSON blob (from security find-generic-password -s 'Claude Code-credentials' -w) into :ai.link_claude_token, not just the bare sk-ant-oat… access token — the plain-string path has no refresh token to swap. See AI panes → Claude Code OAuth token.
  • Paste into the : cmdline. Cmd+V (macOS, bracketed-paste) and Ctrl+V (other platforms, raw key event) now route into the : gutter cmdline buffer. Previously both silently dropped — you couldn’t paste a command id or a snippet of ex-cmdline into : without going through the prompt overlay. Multi-line paste is flattened to single-line (newlines stripped) so pasting a JSON blob doesn’t accidentally fire multiple commands. See Cmdline popup → Paste.
  • Anthropic brand color for Claude Code chips. The Claude Code integration icon’s default color switched from the orange theme slot to the exact Anthropic brand #D97757. Applied consistently across the installed-list row, palette-bar chip, split-cluster AI chip, and the Pty tab glyph (including the animated spinner) — regardless of your active theme. IntegrationIcon.color fields now accept literal #RRGGBB hex strings alongside the existing theme slot names (orange, cyan, …), so community manifests can carry brand hexes without waiting for a new theme slot to be added upstream.
  • Integrations panel refresh chip. Nudged 1 cell in from the panel edge so the refresh glyph is no longer jammed against the vertical separator.
  • macOS .dmg / .pkg retired. The install page’s macOS row is now brew install chris-mclennan/tap/mnml, cargo install mnml-rs, or the .tar.xz — the .dmg bundle and mnml.app scaffolding were dropped as part of this release. mnml is a TUI editor; macOS developers already have Homebrew, cargo, and the tarball path. Windows .msi stays as a plumbing artifact because winget requires it as the download source, but the featured Windows install remains winget install mnml. See Platform support.

0.2.0 — 2026-07-03 — The Integration SDK

Section titled “0.2.0 — 2026-07-03 — The Integration SDK”

The big release. Integration SDK ships: siblings self-install into mnml via <sibling> --install (mnml-bridge 0.3), the community-default IntegrationIcons for 37 siblings move out of mnml core into sibling-owned manifests, and mnml gains a runtime helper surface for level-tagged toasts, persistent toasts, progress spinners, dynamic statusline segments, and OS notifications via OSC 9 / 777 terminal escapes.

The Integration SDK install flow — cargo install a sibling, then <sibling> --install writes a manifest that mnml picks up on integrations.refresh, adding a rail chip + palette command + chord binding.

Before 0.2, mnml core carried default IntegrationIcon entries for every community sibling — bitbucket, github, slack, datadog, and 33 more. Users installed the sibling binary and the chip was already in the rail (disabled), because mnml shipped the metadata. That worked but had three costs:

  1. Internal-only stragglers. A private company-internal sibling shipped as a default chip visible to every crates.io user, tooltip and all. Removed as part of the arc.
  2. mnml core carried release cycles for every sibling. Change a sibling’s tooltip → mnml core needed a release.
  3. No first-class registration story. Community authors couldn’t publish a chip; they had to send a PR to mnml.

The SDK inverts that:

  • Each sibling ships a --install subcommand using mnml-bridge 0.3’s install_integration(). Writes ~/.config/mnml/integrations/<id>.toml.
  • mnml scans that directory on startup + on the new integrations.refresh palette command. Rail chip + palette command + chord binding land automatically.
  • Precedence rules keep user config on top: user config > manifest > built-in default. A sibling manifest can never clobber a user’s own [[ui.integration_icon]] override.

Install helpers (fs-based, no IPC needed):

mnml_bridge::install_integration(spec) -> io::Result<PathBuf>
mnml_bridge::uninstall_integration(id) -> io::Result<bool>
mnml_bridge::list_installed_integrations() -> io::Result<Vec<String>>

Runtime IPC helpers (tier-2 JSONL channel):

// Toasts (level-tagged + persistent)
toast_info(msg) / toast_warn(msg) / toast_error(msg)
toast_persistent(id, msg, level) / toast_dismiss(id)
// Progress notifications (animated Braille spinner)
progress_start(id, label)
progress_update(id, label?, percent?)
progress_end(id, ProgressStatus)
// Dynamic statusline segments (hybrid packing)
statusline_set_segment(id, side, text, color?, click?, priority, min_width, max_width)
statusline_clear_segment(id)
// OS notifications (OSC 9 + OSC 777 → Ghostty/iTerm2/kitty/WezTerm banners)
notify(title, body, NotifyOpts { level, sound, source })

Every helper is fire-and-forget — silent no-op when MNML_IPC_DIR isn’t set, so siblings can call them freely even when running standalone outside mnml.

  • File-based integration manifests~/.config/mnml/integrations/<id>.toml (workspace override at <ws>/.mnml/integrations/<id>.toml). Mirrors the mount manifest pattern.
  • integrations.refresh palette command — re-scan without restart.
  • Level-tagged toastsApp::toast_info / toast_warn / toast_error. Info + warn share the standard comment border (calm ambient); error gets a red border so failures stand out.
  • Persistent toasts — pinned until an explicit dismiss by id. Repeat calls with the same id update in place.
  • Progress notifications — animated Braille spinner with terminal-status glyph on end (✓ / ✗ / ⊘). Failed status auto-fires toast_error.
  • Dynamic statusline segments — sibling-authored chips with priority-based overflow (drop lowest-priority when the lane is tight; never push the canonical mode / line-col / workspace chips off screen).
  • OS notifications via OSC 9 + OSC 777 — Ghostty / iTerm2 / kitty / WezTerm / Windows Terminal route to native banners. Per-integration [notifications] policy: never / error_only / always + rate limit.
  • [jira] + [cloud_agents] config — org-specific Jira wiring (domain + ticket_prefix) and full config-driven ECS runner for cloud agents. Both empty by default; the whole feature no-ops without config. See Cloud agents runner.

The AWS-Fargate cloud-agent runner was hardcoded against one company’s private infra; it’s now a generic config-driven feature (AgentSource::Ecs). Existing users populate [cloud_agents] config to keep the feature; empty config = no-op.

The family — 37 siblings, all self-installing

Section titled “The family — 37 siblings, all self-installing”

Everything under the mnml-* prefix from forges (bitbucket, github, gitlab, azdevops) through trackers (jira, linear), messaging (slack, teams, gmail, gcal, buttondown, mandrill), AWS (11 services), databases (7), cloud filesystems (s3, azure-blob), observability (datadog), CDN (cloudflare), containers (docker), and testing (playwright, cypress). Each ships --install + --uninstall. See Community integrations for the directory.

Users on 0.1.x who had community sibling chips visible:

  • If you’d already installed the sibling binary: run <sibling> --install once. Chip stays working; now driven by the sibling’s own manifest instead of mnml’s built-in default. integrations.refresh picks it up.
  • If you had a custom [[ui.integration_icon]] in ~/.config/mnml/config.toml: untouched. User config wins over manifests.
  • If you were relying on the built-in default without having the sibling installed: the chip continues to show (built-in defaults still ship as discovery hints); clicking still fires :term <sibling> which errors “not installed” until you run cargo install <sibling> and <sibling> --install.

No breaking changes for the shipped user experience — every 0.1.x flow continues working. The SDK is additive.

Add mnml-bridge = "0.3" to your Cargo.toml, add --install / --uninstall CLI flags backed by install_integration() / uninstall_integration(). See Building integrations for the full walkthrough.


User-facing changes landed on main since v0.2.0 and waiting for the next tag:

  • Startup picker — JetBrains-style chooser overlay shown on launch when invoked with --startup-picker (or MNML_STARTUP_PICKER=1). Rows: New file · Open file… · 1-9 entries from [[workspaces]]. Keys: ↑↓ / jk move · Enter / 1-9 select · Esc / q skip. See the Startup picker manual.
  • Update-check toast — on launch, mnml pings api.github.com/repos/chris-mclennan/mnml/releases/latest in a background thread and shows a one-shot toast with the release URL if a newer tag is available. Opt out with [ui] check_updates = false. Skipped automatically in --headless mode. See the Update check section in Settings.
  • Docs: new manual page for the Startup picker, new Troubleshooting page, and an Update check subsection in Settings.
  • macOS .dmg artifact now ships with cargo-dist’s standard naming (mnml-rs-<triple>.dmg)
  • Install page’s macOS download button points at the DMG (drag-to-install)
  • Smaller fixes (release pipeline cleanup)
  • First .app bundle + DMG artifacts shipping with releases
  • Refactor: build-app.sh / build-dmg.sh accept --bin-path so CI can package the cargo-dist-built binary directly

First tagged release. cargo-dist pipeline goes live (shell installer, PowerShell installer, MSI, per-arch tar.xz / .pkg).

Day-to-day capabilities prior to v0.1.0: see CLAUDE.md and FEATURES.md on the repo.