Releases: chris-mclennan/tmnl
0.2.0 — 2026-06-16
Release Notes
This release is the deferred-polish + audit sweep — a session built on
four explicit phases: ship the open backlog, drive multi-persona testing
through the headless harness, fix every verified finding, and audit the
public site against ghostty.org. Across 36 commits, shell.rs split
from 4135 → 561 lines (-86%) via 10 sibling-module extractions; 21
persona-testing findings shipped (4 modifier-guard families, 4
per-window scope inconsistencies, 5 mouse-access via context menu, 4
modal-stacking, 3 headless quirks, plus the help-overlay.gif regression
re-record); 5 ghostty-comparison doc edits landed (landing reorder,
themes quickstart, install per-OS routing, About page, shell-integration
bash/fish). Final state: 544 lib tests pass, Starlight build clean at
28 pages, every audit finding adversarially verified.
Highlights:
- Shell.rs split — extracted into 8 method submodules (resize,
scroll, io, queries, render, spawn, accessors, reader) + 9 sibling
helper crates (shell_cell_attrs, shell_color, shell_config,
shell_context, shell_keys, shell_mouse, shell_osc1337, shell_prompt,
shell_pty). Submodule visibility lets each slice touch private
ShellSession fields withoutpub(crate)leakage. - Persona-testing fixes — keyboard chords no longer get eaten by
overlay filter buffers (Cmd+Shift+R no longer wipes recents), per-
window cfg overrides honored by toggle_sidebar / toggle_tab_bar,
pane management reachable from the right-click menu (Split / Close /
Zoom / Equalize), pane divider gets a hover cursor, Cmd+W closes
the topmost overlay from inside palette/find/etc., view.help no
longer stacks on other overlays, headless--appno longer
persists user config when toggle buttons are clicked. - Render perf — apply_to_grid drops the parser Mutex before the
rustybuzz ligature pass; sync-depth (DECSET 2026) early return
reads a cached cursor instead of leaking the live one; per-frame
~4KB palette_override.indexed clone replaced with a lock-held
borrow; per-framelink_grid/underline_grid/
underline_color_gridclones now gated on sticky-true*_active
flags so sessions that never see OSC 8 / extended underlines /
CSI 58 skip the clones entirely. - Settings save-failure inline error banner — Save now happens
before the overlay closes; failure stays the dialog open with a
red! save failed: <reason>banner instead of silently losing
the user's edits. - Type-to-filter the help overlay — start typing while ⌘⇧/ is
open to narrow the binding list. - 20 demos shipped across the manual — 3 layout demos
(many-tabs-horizontal / bottom-tab-bar / tab-layout-toggle), help-
filter, attention-dot, palette-filter, settings-window-scope,
discovery-install, help-themes, plus the existing 13. - Site audit fixes vs ghostty.org — landing reordered so the
plain-English value pitch precedes the jargon grid, themes
quickstart added, install page gains per-OS jump table + version
banner + Gatekeeper escape hatch, new /about page, shell-
integration grew bash + fish recipes + verification step.
Menu bar
- New Edit > Find… menu item (⌘F). Standard macOS slot, mirrors the
existing chord. Opens the in-pane find bar in the focused pane. - New Edit > Find Next and Edit > Find Previous menu items.
Work whether the find bar is visible or not — as long as a find
session is active, they advance through matches. Same match-
advance logic Enter / Shift+Enter use inside the find bar.
Intentionally no chord — ⌘G / ⌘⇧G stay reserved for the
fwd.cmd_gforwarder that sends ⌘G as ⌃G to native mnml panes
(goto-line in the editor). - New Shell > New Tab (⌘T) and Shell > Close Tab (⌘W) menu
items. Standard slots that were previously chord-only. - New View > Recents… (⌘R) menu item. Opens the recents picker —
the same overlay the welcome screen used to surface on startup.
Mirrors the existing chord; gives the recents flow a discoverable
menu-bar entry point. - New View > Search Tabs… menu item. Toggles the
tab-search overlay (filter tab chips by name). Intentionally
no chord — ⌘⇧T is reserved at the chord-registry layer for
tab.reopen_closed(browser convention). - Help > tmnl Help now opens the in-app help overlay (same surface
⌘⇧/ opens) instead of logging a placeholder. The overlay lists every
registered command + its current chord — the discoverable answer to
"what does tmnl do?" for new users.
Multi-window
- ⌘W on the last tab of one of N windows now closes only that
window, instead of quitting tmnl and dropping every other open
window with it. When the focused window's last tab closes and at
least one background window is open, swap a background window in
as the new focused window (dropping the previous one's winit
handle closes the OS window). When no background windows are
open, the historical "quit the app" behavior still fires. - ⌘W no longer cascades through every open window in one
press. Dropping aWindowStatecauses AppKit to queue a
CloseRequestedfor the just-closed window. The handler used to
process that stale event against the new focused window and
cascade-close. Now the dispatcher ignoresWindowEvents whose
WindowIddoesn't match any window we still own. - Persistence stays in sync with what's actually open —
closing one of N windows (via the red close button or via the
last-tab ⌘W path) now writes the smaller window-state immediately,
so the next launch doesn't resurrect the closed window.
Chrome strip
- Back / forward arrows on Shell panes now jump to the previous /
next OSC 133 prompt in scrollback (same as ⌘↑ / ⌘↓). They used to
forward Ctrl+PgUp / Ctrl+PgDn to the focused pane — useful on
Native (mnml) panes, no-op in bare zsh. The chord stays in place;
the arrows give it a discoverable click target.
Selection
- Shift+click now extends the existing body-selection — anchor stays
put, focus moves to the click position — instead of starting a fresh
single-cell selection. Falls back to a fresh selection when there's
no existing one on the same tab + pane. Matches the macOS Terminal /
iTerm / VS Code convention. - The selection highlight now paints during drag, not only on
release. EachCursorMovedwhile dragging force-pushes the live
bounds togpu.selection_boundsso the next frame paints them even
if the redraw chain lagged.
Modal overlay accessibility
Every modal overlay — palette, palette overlay (chip-clicked),
welcome, discovery, settings, help, right-click context menu, and
both confirm dialogs (close + paste) — now has full mouse +
keyboard parity:
- Click a row to activate / focus it (palette dispatches the
command, welcome opens the entry, discovery toggles in-rail,
settings focuses the row; second click on the focused settings
row cycles its value). - Wheel scrolls the row selection on welcome / discovery /
settings / help. - Click outside the panel dismisses (palette / palette overlay /
welcome / discovery / help / context menu); settings is
intentionally excluded to avoid silently discarding unsaved
row edits. - Confirm-close and confirm-paste dialogs grow visible
[Close] / [Cancel]and[Paste] / [Cancel]buttons. Click-outside
also cancels. - Hover pre-selects rows on welcome + discovery — standard menu
UX, lets users hover-then-Enter without a click. - Help overlay click-outside dismiss covers chrome / chip clicks
that previously slipped past the body-click-dismiss path.
Keyboard chords (closing the persona-report gaps)
- F2 — rename the focused tab. VS Code parity. Same modal as
the right-click rename path; first-class menu item lives under
Window > Rename Tab. - ⌘⇧1 … ⌘⇧9 — open launcher rail icons. Closes the "rail is
mouse-only" gap. Out-of-range indices silently no-op. - ⌘Home / ⌘End — jump to top / bottom of scrollback. Pairs
with the existing ⇧PgUp / ⇧PgDn row-by-row paging. - ↑ / ↓ in ⌘F find bar and ⌘⇧T tab-search step matches
forward / backward. Was Enter / Shift+Enter only. - ⌘⇧P palette and ⌘R recents now supersede transient input
overlays — welcome / tab_search / find / palette_overlay /
discovery / context_menu auto-dismiss as the new one opens.
The "destructive" modals (settings / help / rename / confirm
dialogs) still block. Closes the 06-10 hybrid SEV-4 #7 design
call. - ⌘D in a Browser pane forwards as ⌃D instead of unconditionally
splitting right, so mnml's multi-cursor "select next
occurrence" chord works when the editor's a Native pane. - ⌘Z / X / S / N / P / B / G / / no longer silently eat keys in
Shell context. Thefwd.cmd_*chords now gate on Native
focus; in Shell context they fall through to the pty's char
path as the user expects.
Browser pane chord coverage
Safari conventions, all gated on Browser-pane focus:
⌘[/⌘]— history back / forward.⌘L— focus the URL bar (seeds the chrome edit buffer with
the current URL).⌘R— reload (rides onview.recents's wire; falls through
to opening recents when no Browser pane is focused).
Maximize Pane (zoom)
The Shell > Splits > Maximize Pane (⌘⇧↩) verb shipped in
0.1.5 but was substantially broken — composite painted via
tab.layout.leaf_rects instead of effective_leaf_rects, so
the zoomed pane's full-area grid only painted at its small
underlying split-tree rect; pane_under_cursor mis-routed
clicks; divider drag still fired through the zoomed pane;
close / split paths left zoomed_pane stale across id shifts.
All fixed; the menu label now flips between Maximize Pane ↔
Restore Pane in sync with the state (across toggle / chord /
menu click / tab switch / window swap / close / split paths).
Active chip in the strip also gains a leading ⤢ badge while
zoomed.
Multi-window state drift
Several latent state-drift bu...
v0.0.5
Install tmnl-rs 0.0.5
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/chris-mclennan/tmnl/releases/download/v0.0.5/tmnl-rs-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/chris-mclennan/tmnl/releases/download/v0.0.5/tmnl-rs-installer.ps1 | iex"Download tmnl-rs 0.0.5
| File | Platform | Checksum |
|---|---|---|
| tmnl-rs-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| tmnl-rs-aarch64-apple-darwin.pkg | Apple Silicon macOS | checksum |
| tmnl-rs-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| tmnl-rs-x86_64-apple-darwin.pkg | Intel macOS | checksum |
| tmnl-rs-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| tmnl-rs-x86_64-pc-windows-msvc.msi | x64 Windows | checksum |
| tmnl-rs-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| tmnl-rs-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
v0.0.4
Install tmnl-rs 0.0.4
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/chris-mclennan/tmnl/releases/download/v0.0.4/tmnl-rs-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/chris-mclennan/tmnl/releases/download/v0.0.4/tmnl-rs-installer.ps1 | iex"Download tmnl-rs 0.0.4
| File | Platform | Checksum |
|---|---|---|
| tmnl-rs-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| tmnl-rs-aarch64-apple-darwin.pkg | Apple Silicon macOS | checksum |
| tmnl-rs-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| tmnl-rs-x86_64-apple-darwin.pkg | Intel macOS | checksum |
| tmnl-rs-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| tmnl-rs-x86_64-pc-windows-msvc.msi | x64 Windows | checksum |
| tmnl-rs-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| tmnl-rs-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
v0.0.3
Install tmnl-rs 0.0.3
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/chris-mclennan/tmnl/releases/download/v0.0.3/tmnl-rs-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/chris-mclennan/tmnl/releases/download/v0.0.3/tmnl-rs-installer.ps1 | iex"Download tmnl-rs 0.0.3
| File | Platform | Checksum |
|---|---|---|
| tmnl-rs-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| tmnl-rs-aarch64-apple-darwin.pkg | Apple Silicon macOS | checksum |
| tmnl-rs-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| tmnl-rs-x86_64-apple-darwin.pkg | Intel macOS | checksum |
| tmnl-rs-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| tmnl-rs-x86_64-pc-windows-msvc.msi | x64 Windows | checksum |
| tmnl-rs-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| tmnl-rs-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
v0.0.2
Install tmnl-rs 0.0.2
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/chris-mclennan/tmnl/releases/download/v0.0.2/tmnl-rs-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/chris-mclennan/tmnl/releases/download/v0.0.2/tmnl-rs-installer.ps1 | iex"Download tmnl-rs 0.0.2
| File | Platform | Checksum |
|---|---|---|
| tmnl-rs-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| tmnl-rs-aarch64-apple-darwin.pkg | Apple Silicon macOS | checksum |
| tmnl-rs-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| tmnl-rs-x86_64-apple-darwin.pkg | Intel macOS | checksum |
| tmnl-rs-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| tmnl-rs-x86_64-pc-windows-msvc.msi | x64 Windows | checksum |
| tmnl-rs-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| tmnl-rs-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
0.0.1
Release Notes
Added
- Shell mode — hosts a real pty, output parsed into cells with
vt100;
mouse input (click, drag, move, scroll). - Native mode — the
tmnl-protocolwire format over a Unix socket; apps
send structuredFrames of cells, with partial-frameDiffRunupdates and
app-set tab titles. - GPU rendering — a
wgpucell pipeline plus a chrome-strip pipeline;
true-color cells, cursor shape and visibility. - Window & chrome — native tabs, a native macOS menu bar, Mac-style editing
chords, and an in-grid settings modal persisted to
~/.config/tmnl/config.toml. - OSC 133 shell integration — command-lifecycle tracking and a command-line
anchor. - Local AI command completion —
⌘Icontinuation and⌘K
natural-language → command, offline via the embeddedfim-enginemodel. - Headless mode (
--headless) — scriptable cell-grid dumps for tests, plus
fake_server/fake_clientexamples that exercise the protocol without a
GPU window.
Install tmnl-rs 0.0.1
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/chris-mclennan/tmnl/releases/download/v0.0.1/tmnl-rs-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/chris-mclennan/tmnl/releases/download/v0.0.1/tmnl-rs-installer.ps1 | iex"Download tmnl-rs 0.0.1
| File | Platform | Checksum |
|---|---|---|
| tmnl-rs-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| tmnl-rs-aarch64-apple-darwin.pkg | Apple Silicon macOS | checksum |
| tmnl-rs-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| tmnl-rs-x86_64-apple-darwin.pkg | Intel macOS | checksum |
| tmnl-rs-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| tmnl-rs-x86_64-pc-windows-msvc.msi | x64 Windows | checksum |
| tmnl-rs-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| tmnl-rs-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |