v0.12.0Neueste
Review rails and word diffs
Review is a pane grid
Paneflow 0.12.0 rebuilds Review around two rails and the same pane grid Agents uses: the Workspaces rail lists every repository open in Agents with its checkouts and worktrees, the Changes rail follows the focused pane, and a diff is a pane card you split, close, zoom and drag like a terminal. The Changes tab and the editor gain a word-level diff ported from IntelliJ, gutter markers against HEAD, a Revert chip, a minimap, and highlighting queries taken from Zed, on top of an editor pipeline that now colors the viewport without dropping a frame.
The terminal grid is now measured on the font the way Ghostty measures it, box drawing and Powerline glyphs are drawn as sprites, and the bundled font is the regular JetBrainsMono Nerd Font. That is the one place an existing paneflow.json can change what you see: line_height and cell_width are now multipliers of the measured font strides and default to 1.0, so a value carried over from an older config needs a second look.
The session format stays at v2, the terminal engine is still libghostty on every target, and the packaging contract, the IPC and MCP method names, and the CLI are unchanged. One configuration key is removed and ignored, one is added, and two change meaning; all three are in the upgrade notes.
Behavior changes
The terminal grid is measured on the font
The cell is the font's widest advance by its own line height, each rounded to whole device pixels, and the baseline lands on a pixel row. The default JetBrains Mono at 13 pt used to be squeezed into a cell 8% shorter than its face, with descenders crossing into the next row; it now gets its designed spacing. Underlines and strikethroughs are placed and sized from the font's own tables, double, dotted, dashed and curly underlines each have their own shape and are painted under the glyphs, and the bar, underline and hollow cursors take their thickness from the font metrics.
line_height and cell_width are multipliers of those measured strides and default to 1.0. They used to be 1.2 and 0.6 of the font size, so a config that still carries the old defaults makes the grid taller and narrower than before. Remove the two keys or set them to 1.0:
- "line_height": 1.2,
- "cell_width": 0.6,
+ "line_height": 1.0,
+ "cell_width": 1.0,
The accepted ranges are now 0.8 to 2.5 for line_height and 0.8 to 2.0 for cell_width.
Box drawing, shades, braille and Powerline are sprites
The renderer draws the whole box-drawing block itself (heavy, double, dashed and mixed-weight joins, arcs, diagonals), the ░ ▒ ▓ shades, braille patterns and the geometric Powerline symbols, at one font-derived stroke thickness on the device-pixel grid. Adjacent cells meet with no seam at any scale factor, which is what the font's own glyphs could not guarantee.
The bundled font is JetBrainsMono Nerd Font, not the Mono variant
Icons keep their designed size and the renderer constrains them to their cell, borrowing the empty cell after them when there is one, which is Ghostty's Nerd Font rule. A config naming JetBrainsMono Nerd Font Mono or JetBrainsMono NFM keeps resolving to the bundled family, so nothing needs to change in font_family.
Bold uses the Bold face, faint halves the opacity, the contrast floor is off
SGR bold uses the Bold face rather than SemiBold, and SGR faint halves the foreground opacity where it used to keep 70%. The APCA contrast floor applied to the theme's ANSI colors is off by default, so themes render their colors as designed. It is configurable as terminal.minimum_contrast, an APCA Lc value from 0 to 90, hot-reloaded; Zed's floor is 45:
{
"terminal": {
"minimum_contrast": 45
}
}
Desktop notifications follow the pane under your eye
Every desktop notification used to be muted whenever the Paneflow window was active, so an agent asking for permission in another workspace never reached you while you worked elsewhere in Paneflow. The test is now the one the completion dot already uses: a notification is dropped only when its pane's workspace and tab are on screen in the active window. The four agent notifications (needs input, turn finished, agent exited, stalled) and OSC 9 / OSC 777 program notifications all take the same answer, which is where cmux draws the line too.
The Changes tab is opt-in and every dock tab closes
The editor dock no longer opens with a permanent Changes tab in first position. Changes is an entry of the dock's + menu, next to the file picker, and opens once; every tab, Changes included, closes like any other. A workspace that only ever needed a file open no longer carries a diff it did not ask for.
The service port badge leaves the workspace row
The workspace meta line only ever carried the detected dev-server port, so the line is gone and folder rows are single line like tab rows. The service list stays reachable from the workspace context menu.
Review
Two rails and a pane grid
The Workspaces rail lists every repository open in Agents as a folder row that folds its checkouts and git worktrees and remembers the folded rows across restarts. Clicking a checkout shows its diff in the focused pane, dragging one onto a pane edge opens it side by side, and dropping it on the center replaces that pane's subject. The Changes rail follows the focused pane and carries the base branch picker.
Diff panes are regular pane cards: split, close, zoom, focus navigation and header drag work as in Agents, the grid persists across restarts, and it is capped at six panes. Their header replaces the split buttons with the ... options menu of the Changes tab (layout, highlight, whitespace, collapse or expand all, refresh), applied to that pane's diff. The grid and the fold state are stored in the session as review_layout and review_collapsed; the old diff_scope field is dropped. The schema stays at v2, a session written by 0.11.0 restores with an empty grid, and a 0.11.0 build ignores the two new fields. See the Review page.
What left with the toolbar
The toolbar above the Review diff is gone, along with the Multi-project and Worktree scopes, the repo tabs, the hunk counter, the cost badge, the Unified | Split segment, Collapse all and the cross-column scroll sync (s). u still toggles unified and split, [ and ] still walk the hunks, collapse all lives in the Changes rail header, and the agent attribution is a tooltip on the pane header diffstat. A pane shows one worktree, so the per-column headers and the internal column arrangement left with the toolbar.
Changes and the editor
A word-level diff, with Highlight and Whitespace options
The Changes tab highlights the words that differ inside a modified block, on top of the line wash, so a one-word edit on a long line reads at a glance. The comparison is a port of IntelliJ's pipeline on imara-diff: lines carrying three or more non-blank characters are matched first, short lines are paired in the gaps between them, block boundaries slide onto empty lines, and each modified block gets a word pass with punctuation matching. Two submenus join the dock Options menu next to Layout: Highlight (Words, Lines, None) and Whitespace (Default, Trim, Ignore), so an agent's reformat can be read with the indentation changes muted. Both last for the session, a block whose two sides differ only by whitespace is painted muted, and switching either option repaints the diff in place instead of rebuilding it.
Gutter markers and a Revert chip
A file opened in a dock tab shows its changes against HEAD in the gutter: a bar for an added or modified block, a dot for a deletion. Typing shifts the blocks without a diff, and only the touched blocks are re-diffed off the render thread after a short pause. Clicking a marker opens a popup with the block's previous text, syntax highlighted, with Copy and Revert; a revert is a single undo step. Escape, a click outside, or an agent rewriting the file closes the popup.
Hovering a block of a modified file in the Changes tab shows a Revert chip. It writes the HEAD lines back through the atomic save path and refreshes the dock, and refuses when the file has unsaved changes in a dock tab or changed on disk since the dock was built.
Minimap, scrollbars, and the file tree in the dock
An Editor Controls button on the editor opens a menu that toggles a Zed-style minimap and the scrollbar; the choice lasts for the session. The Changes tab gets a permanent editor-style scrollbar of its own. The Files tree now lives inside the editor dock next to the file tabs, at 250 px, rather than in a sidebar of its own: toggling Files opens the dock on the active file tab, or on the file picker when no file is open, and closes it again from a file tab.
Highlighting aligned with Zed
The code editor and diff view use Zed's highlighting queries for Rust, JSON/JSONC, shell, Python, TypeScript/TSX/JavaScript, Markdown, Go, YAML, CSS, C and C++. Calls, parameters, fields, macros and attributes receive the query's specific classes, variables and namespaces use editor text, punctuation is neutral, and constructors use the function color in all eight palettes. Overlapping captures follow Zed's last-active-capture rule; the stock priority audit records every conflicting node on the regression corpus. Vendored queries carry a pinned source manifest, hashes and cross-platform sync checks.
The editor colors the viewport without losing a frame
Ten increments on the editor pipeline, each measured on the reproducible suite in scripts/bench-editor.sh and recorded under bench/results:
| What | Before | After |
|---|---|---|
| 2 MB Rust file, time to first text | 45 ms, after the parse | 1.3 ms, parse off the render thread |
| Highlight cap | 300 KB | 2 MB (Markdown 1 MB), set by a measured tree-memory probe |
| Keystroke to colored runs, 300 KB Rust, p95 | 1.77 ms | 0.71 ms |
| Retained bytes after 200 reloads | 5.15 MiB | 2.19 MiB |
| Warm prepaint of 60 rows | 60 allocations | 6 allocations, 19.9 us median |
| Reload of 10 hunks in a 100 000 line file, on the UI thread | 22.6 us; the line diff runs off-thread | |
| Terminal snapshots per editor wheel notch, 6 panes | 720 | 0 |
A starved fill asks for its own follow-up frame instead of notifying from render, so a PageDown no longer drops the frame that would have colored it. A wheel notch moves exactly three rows, a horizontal notch whole columns, and the last row of a 300 000 line file lands on the viewport floor and stays there. A synchronous reparse that cannot fit its budget is skipped rather than burned on every keystroke, an initial parse past 5 s gives up and says so in a banner under the file name, and reloads from disk diff the common prefix and suffix off-thread and apply one batch. Idle terminal panes are cached during an editor scroll, and the Files tree rebuilds from cached snapshots.
Removed
Review with agentand the terminal panel it opened under a Review diff, along with thereview_prefill_delay_mssetting; the key is ignored if it is still present inpaneflow.json. The Review rail menu no longer offersOpen Shell in Worktree. Launch agents from Agents mode; there is no replacement flow.- The in-pane peek overlay that painted an agent's question over the terminal. The attention ring, the header dot, the sidebar row and the attention queue keep carrying it.
Fixed
- The sidebar bell rings only for agent-initiated requests. Two hook-free channels promoted things nobody had to act on to waiting-for-input. Claude Code's session registry writes
waitingFor: "dialog open"while you sit in a local slash command such as/resumeor/model; that is your own UI, not the agent asking, and it now reads as idle. OSC 9 was promoted whenever the text was non-empty; it is now classified the way cmux's fallback does it, so wording that asks for permission, approval, input or confirmation is a request, Claude Code'sidle_promptis idle, and anything else, a build's notify-send included, says nothing. - Switching Highlight or Whitespace no longer rebuilds the diff. The options apply to the existing diff and repaint in place.
Under the hood
- The libghostty archives leave git. The four
libghostty-vtarchives are assets of thelibghostty-vt-<sha>pre-release thatnative/libghostty/manifest.tomlnames, placed byscripts/fetch-libghostty.shor.ps1after a manifest hash check and by.github/actions/fetch-libghosttyin every job that runs cargo. Building from source now needs that script once per pin; Cargo still performs no downloads. The Windows formatter determinism patch is retired: the Windows archive is built once by the bump workflow and its provenance is the build-provenance attestation that run publishes, while Linux and macOS keep their two-build reproducibility proof. 455be37b, 11f8a3ef. - A reproducible editor benchmark.
scripts/bench-editor.shand.ps1run the suite insrc-app/src/app/diff_dock/code/perf_bench.rswith a counting allocator and compare againstbench/editor-baseline.json, sharing the harness of the terminal suite. See bench/README.md. - The source tree carries no comments and the internal docs tree is gone; intent lives in names, types, tests,
ARCHITECTURE.mdandDESIGN.md, which now states the native UI contract.
Upgrade notes
Install over 0.11.x and launch. No manual step is required unless your paneflow.json sets line_height or cell_width.
line_heightandcell_widthchanged meaning: multipliers of the measured font strides, default1.0, ranges0.8to2.5and0.8to2.0. A config still carrying1.2and0.6renders a taller, narrower grid than 0.11.0; remove both keys, which is also what keeps a later downgrade sane, or set them to1.0.review_prefill_delay_msis removed and ignored when present.terminal.minimum_contrastis added, default0; set45for the 0.11.0 look.- The session schema stays at v2.
review_layoutandreview_collapsedare added anddiff_scopeis dropped; a 0.11.0 session restores with an empty Review grid. - The bundled font is
JetBrainsMono Nerd Font;JetBrainsMono NFMandJetBrainsMono Nerd Font Monoinfont_familykeep resolving to it. - The terminal engine, the packaging contract, the IPC and MCP method names, and the
paneflowCLI are unchanged. - Downgrading to 0.11.0 works. An older build ignores the two new session fields and
terminal.minimum_contrast, and readsline_heightandcell_widthagainst the font size again, so a pinned"cell_width": 1.0renders very wide on 0.11.0 where a removed key does not.
Install and validation
Download the signed artifacts from this release or use the installation instructions.
Every primary artifact carries a .sha256 sidecar and a minisign .minisig; each AppImage also ships an .AppImage.zsync for delta updates. 35 assets in total.
Pipeline: run 34024098604.
Legs that passed:
- Build:
x86_64-unknown-linux-gnu,aarch64-unknown-linux-gnu,aarch64-apple-darwin,x86_64-pc-windows-msvc - Release test gate on Linux x86_64:
cargo fmt --check,cargo clippy --workspace --locked -- -D warnings,cargo test --workspace --locked - Package smoke tests: Debian 12 and Ubuntu 22.04 (
.debpostinst), Fedora 40 and openSUSE Tumbleweed (.rpmpostinst), Arch Linux (tar.gzbinary), Windows MSI install and relay - Auto-update end to end on Linux x86_64
Full Changelog: https://github.com/arthjean/paneflow/compare/v0.11.0...v0.12.0