コンテンツにスキップ

v0.12.0最新

Review rails and word diffs

GitHub で見る

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 agent and the terminal panel it opened under a Review diff, along with the review_prefill_delay_ms setting; the key is ignored if it is still present in paneflow.json. The Review rail menu no longer offers Open 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 /resume or /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's idle_prompt is 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-vt archives are assets of the libghostty-vt-<sha> pre-release that native/libghostty/manifest.toml names, placed by scripts/fetch-libghostty.sh or .ps1 after a manifest hash check and by .github/actions/fetch-libghostty in 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.sh and .ps1 run the suite in src-app/src/app/diff_dock/code/perf_bench.rs with a counting allocator and compare against bench/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.md and DESIGN.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_height and cell_width changed meaning: multipliers of the measured font strides, default 1.0, ranges 0.8 to 2.5 and 0.8 to 2.0. A config still carrying 1.2 and 0.6 renders a taller, narrower grid than 0.11.0; remove both keys, which is also what keeps a later downgrade sane, or set them to 1.0.
  • review_prefill_delay_ms is removed and ignored when present.
  • terminal.minimum_contrast is added, default 0; set 45 for the 0.11.0 look.
  • The session schema stays at v2. review_layout and review_collapsed are added and diff_scope is dropped; a 0.11.0 session restores with an empty Review grid.
  • The bundled font is JetBrainsMono Nerd Font; JetBrainsMono NFM and JetBrainsMono Nerd Font Mono in font_family keep resolving to it.
  • The terminal engine, the packaging contract, the IPC and MCP method names, and the paneflow CLI are unchanged.
  • Downgrading to 0.11.0 works. An older build ignores the two new session fields and terminal.minimum_contrast, and reads line_height and cell_width against the font size again, so a pinned "cell_width": 1.0 renders 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 (.deb postinst), Fedora 40 and openSUSE Tumbleweed (.rpm postinst), Arch Linux (tar.gz binary), 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

コントリビューター