v0.17.0Dernière
Durable agent status and sessions
Agent status that survives the window
Paneflow 0.17.0 moves agent status out of the window and out of the terminal host into a third process, a per-home worker started as paneflow serve run. The worker owns no terminal. It reads the lifecycle hooks Claude Code and Codex report, reduces them to one state per session (thinking, needs input, finished, errored), rebuilds that state from disk when it restarts, and decides which desktop notifications fire. The desktop follows it, the new paneflow sessions verb reads it without a window, and stopping or replacing it never touches a running shell.
Hooks are installed once per machine instead of on every launch. The shim no longer writes hook files into project directories or agent configs at each start; Claude Code and Codex get a global integration that stays inert outside a Paneflow pane. Until it is installed, those agents report no hook status, so read the upgrade notes below.
The same release hardens persistent sessions: a session keeps owning every process it started until their fate is proven, a finished shell leaves its final output on screen, restoring a layout never starts a process on its own, and quitting or updating stops everything under one bounded, reported pass. The terminal gains automatic text contrast on by default and a palette derived from the theme, and the command palette is rebuilt around about a hundred context-aware commands.
The worker
- The desktop starts, adopts or replaces the worker at every launch: a worker of the same build is adopted, any other is drained and replaced. It runs detached, one per
PANEFLOW_HOME, and outlives the window likepaneflow-hostdoes. - New files under the state home:
serve/owner.lock,serve/instance.json,serve/serve.log, and on Windowsserve/runtime/<sha256>/, a copy of the executable the worker runs from so the installed binary stays replaceable by the updater. The endpoint ispaneflow-serve-<fingerprint>.sockin the runtime directory, or\\.\pipe\paneflow-serve-<fingerprint>on Windows, owner-only on both. - When the worker cannot start, the Workspaces sidebar shows the error with a Retry button. Session rows dim while the worker stream is disconnected.
paneflow serve start # start or adopt the worker for this PANEFLOW_HOME
paneflow serve status # pid, protocol, home, session count, capabilities
paneflow serve stop [--drain-ms 5000]
paneflow sessions [--json] [--follow]
paneflow sessions ack <session-id>...
paneflow sessions prints the same projection the sidebar shows, and --follow prints one line per transition and reconnects on its own when the worker restarts. ack lowers the unread flag a finished turn raises; the desktop lowers it too when the pane is in view.
One-time hook integrations
- Claude Code and Codex are the two runtimes with an installer. Install from Settings > Agents (the Install hooks button on the agent's row; a green check marks it installed, and clicking it removes the hooks), or from the CLI:
paneflow integrations list
paneflow integrations install claude-code # or: claude, codex
paneflow integrations remove codex
paneflow hooks setup # installs every detected runtime that has an installer
- Claude Code hooks go to
$CLAUDE_CONFIG_DIR/settings.json(default~/.claude/settings.json), Codex hooks to$CODEX_HOME/hooks.json(default~/.codex/hooks.json). Installing also registers thepaneflowMCP server in~/.claude.jsonor in Codexconfig.toml, and writes a marker under<home>/integrations/. Codex asks you once to trust the new hooks with/hooks. - The hooks exit immediately outside a Paneflow-hosted pane. The worker refreshes installed integrations when it starts and adopts Paneflow hook entries a previous
paneflow hooks setupleft in the global config. - Installing or removing now edits only Paneflow's own handlers inside a hook group, so a handler of yours that shares the group is kept. Before, the whole group was deleted.
How status is decided
- A session becomes hook-owned at its first hook: busy on prompt submit, idle on Stop, needs input on a permission request. Output alone never starts a busy state, and agent state is no longer guessed from terminal progress (OSC 9;4) or notification text.
- Pressing Esc to interrupt Claude Code, Gemini CLI or Muse Code in a pane Paneflow launched settles the pane to idle as canceled, with no "finished" notification. A lone Esc counts after 150 ms with no following byte.
- A Claude Code pane stays busy while subagents run after the main turn stops, and settles when the last one ends.
- A turn whose Stop hook never arrives returns to idle after 5 minutes without a screen change, silently. Events from a runtime generation the session has left are refused.
- Claude Code and Codex numbered approval menus, which fire no hook, mark the session as needing input in the sidebar.
menu_attention_detection(defaulttrue) turns this off; the worker reads it when it starts. - Desktop notifications: " finished" fires only for a turn that completed, never for a failure, an interrupt, an expiry or an exit. " needs input" fires at most once per 10 s. The body is the agent's last message, up to 200 characters.
Upgrade notes
- Agent hooks need a one-time install. 0.16.0 injected Claude Code and Codex hooks on every launch through the shim; 0.17.0 does not. Until you install the integration (Settings > Agents,
paneflow integrations install, orpaneflow hooks setup), Claude Code and Codex panes show no hook-driven status. If you already ranpaneflow hooks setup, the worker adopts those entries on its first start and nothing else is needed. Gemini CLI, Cursor, Qoder, CodeBuddy, OpenCode, Hermes Agent, Grok, Muse Code, Pi and DeepSeek Harness lose their per-launch hooks with no replacement and are detection only. paneflow hookschanges meaning.setupnow installs the integrations above, MCP server included;uninstallalso removes thepaneflowMCP entry, including onepaneflow mcp installwrote;statusprints one<runtime>: <state>line for all 18 runtimes and always exits 0.- A finished terminal stays open. A shell or command that exits, with any exit code, now leaves its pane, detached window or Changes dock tab in place as a read-only final view. Typing
exitno longer closes the pane; close it like any other. - Nothing restarts on its own. Restoring a layout or clicking an ended session in the sidebar attaches to it and never starts a process. The pane bar offers Restart (was Resume), New terminal when the record is gone, Attach or Retry; Enter triggers it. From the sidebar, an ended session restarts through its Resume session menu item.
- A 0.16.0 host that outlives the upgrade is left running. 0.16.0 retired a host from another build at launch; 0.17.0 keeps it and its sessions. If you quit 0.16.0 with Keep running, or upgraded through a package manager while sessions ran, panes open on "The running local host is incompatible with this build and keeps its sessions" with Retry and Stop host and restart, which ends that host's sessions and starts a fresh one. An in-app update from 0.16.0 stops the sessions and the host first and is not affected.
- Terminal contrast is on by default.
terminal.minimum_contrastnow defaults to Auto, APCA Lc 60, and corrects only the colors a program chose (truecolor and palette indices 16 to 255), never the theme's sixteen ANSI colors, foreground or background. Set"terminal": {"minimum_contrast": 0}to keep program colors verbatim. An explicit value now applies to program colors instead of the theme's ANSI colors, and a negative or non-numeric value means Auto instead of Off. - Palette indices 16 to 255 follow the theme. They come from a palette generated from the active theme instead of the fixed xterm cube, on screen and in OSC 4 replies. On light presets the cube runs from the background to the foreground, so index 16 is the background and 231 the foreground. This is not configurable.
- Windows launch surfaces list five agents. The pane palette, the New pane menu and the welcome screen offer Claude Code, Codex, Amp, Gemini and Copilot, the runtimes that declare Windows support, and hide
agent_profilesentries based on the others. Linux and macOS keep all 18. - Without a window,
paneflow psandpaneflow statusreportunknownfor hooked agents andpaneflow send --submitcannot confirm through hook state. Usepaneflow sessions, which reads the worker. - Launch Pad is gone, with its
open_launch_padaction andCmd/Ctrl+Shift+L. Use New branch… in the New pane palette or the tab context menu; there is no prompt pre-fill there. Ashortcutsentry namingopen_launch_padis skipped with a log warning and has to be removed frompaneflow.jsonby hand. - Removed config keys
agent_panel.max_content_width,agent_panel.thinking_display,agent_panel.profiles,agent_panel.default_profileandtool_permissionswere never read. A config that sets them still loads, but editors that validate against the published schema now flag them. - The
contextfield ofsurface.splitandworkspace.createpane specs is ignored andPANEFLOW_CONTEXT_FILEis no longer set. Pass values throughenv. - A custom
PANEFLOW_HOMEgets its own IPC endpoint,paneflow-ipc-<fingerprint>. Clients that export the samePANEFLOW_HOMEfind it; a desktop given both a custom home and aPANEFLOW_SOCKET_PATHof another instance ignores the socket unlessPANEFLOW_ALLOW_SOCKET_OVERRIDE=1. - macOS
option_as_meta: truenow takes effect: Option plus a letter sends Meta (ESC prefix) instead of composing a character, and a config reload applies it to open terminals. The macOS default staysfalse. - Direct
agent.eventsenders on the host endpoint must passruntime_generation. The shipped hook helper does.
Added
- Automatic terminal contrast. Corrections keep their hue: lightness moves in OKLCH and chroma is clipped to sRGB, and a color whose saturation has to drain snaps to the nearest theme color instead of turning grey. Box drawing, blocks, Braille, Powerline and Legacy Computing glyphs, and text drawn in its own background color, are never corrected. Settings > Terminal > Minimum contrast and a Minimum contrast palette command both offer Auto, Off, 45, 60, 75 and 90. The default correction costs about 6 percent on a full 220 by 60 layout pass (
scripts/bench-terminal, Windows x86_64 release build). - Command palette rebuilt. 104 commands in a fixed catalog, shown when the focused pane can run them: terminal, search and Markdown commands appear on the matching surface. Nested pickers for theme, theme mode, workspace, tab, layout, Settings section, open in editor, terminal font, size, weight, line height, cell width, cursor shape, shell, editor, quit behavior and ended sessions apply a preference as you arrow through it and write it to
paneflow.json; Escape leaves the picker without reverting. Toggles flip in place. The query is a real text field, matches are highlighted, the panel sizes to its content between 420 and 640 px, rows are 29 px with 14 px labels, and 26 commands carry a glyph. Closing the palette returns focus where it was. - Reopen a closed tab. Closing a tab shows "Tab closed. Press Ctrl+Shift+T to reopen it." (⌘⇧T on macOS) with an Undo button, and the shortcut restores the most recently closed tab or pane with its split layout, working directories, scrollback, names and font sizes. The terminals come back as new shells.
- Keyboard navigation in the Workspaces sidebar.
focus_workspaces_sidebar(Ctrl+Alt+S, ⌘⌥S on macOS) focuses the list; arrows, Home and End move, Enter opens, Space folds, Left and Right fold or step in, F2 renames, Delete closes a tab, Alt+Up and Alt+Down reorder, Escape returns to the pane. The list exposes a tree to screen readers. - Final output of ended sessions. When a hosted shell exits, the host keeps up to 512 KiB of its final screen and scrollback in
<home>/host/session-data/<id>/final-output.txt, within a 64 MiB budget per home evicted oldest first. Reopening the ended session shows that text read-only, with a note when it was incomplete or has been evicted. - Other sessions. Sessions no open workspace claims are listed once under an Other sessions group, even with no workspace open; opening one attaches it without starting a shell.
paneflow host statusreports aresourcesobject: persistence queue, checkpoint captures, live runtimes, pending launches, connections and per-session buffer usage.- Settings > Agents lists the agents found on PATH with their hook state inline, folds the others into a Not installed card showing three before Show more, and gives Profiles a description and a + New profile row.
Changed
- Session ownership. The host tracks every process of a session, its process group and its descendants, and reports it exited only when all of them are gone. A background job that outlives its shell keeps the session unverified until the job ends, and Stop terminates tracked descendants: through pidfd on Linux, audit-token signals on macOS, and retained handles on Windows. A stop the host cannot confirm now reads unverified instead of lost.
- Stop everything on quit or update also stops owned sessions no pane shows, under one 5 s budget. When a stop cannot be confirmed the window stays open with Retry, Keep running and quit and Cancel; when only the final save failed it offers Quit with unsaved final state. An update restart first checks that the replacement is staged and the host answered, and says why in a toast when it defers.
- Windows updates. The MSI update goes through the same stop dialog. The relay waits up to 30 s for the host to let go, and when the host still serves or its binary is locked it relaunches the current version and keeps the staged MSI instead of running msiexec. msiexec runs with
MSIRESTARTMANAGERCONTROL=Disable, so Restart Manager cannot kill a retained host. - Host durability. Session records are written by a dedicated thread off the terminal path. Creation, restart and accepted agent events wait for their write, exit and final states are synced to disk and retried until storage recovers, and an older queued write can no longer overwrite a newer record. Hard limits now answer with explicit errors: 4,194,304 cells per terminal, 2 MiB of input queued for a child that stopped reading, 2 concurrent checkpoint captures within 256 MiB, 120 streaming connections with 8 reserved for control, 64 KiB control replies.
- Idle cost. Output followers wait on a condition variable instead of polling every 15 ms, the session runtime blocks on deadlines instead of a 20 ms tick, and the viewport scan skips a quiet session. On Linux glibc builds the host caps malloc arenas at 2 unless
MALLOC_ARENA_MAXis set and returns freed memory when a session retires. - Hosts from another build are kept. The client build is logged, not enforced: a host that matches the protocol and the terminal engine is attached, and an incompatible one is left running with Retry and Stop host and restart on its panes.
- Codex rows in the Sessions sidebar come from Paneflow-hosted sessions reported by the integration, within the host retention window, titled with the last tool name or a short session id. Codex sessions run outside Paneflow no longer appear.
- Gemini sessions are read from the trailing
[<session-id>]of eachgemini --list-sessionsline and resumed with that id; the index and age are stripped from the title. - Light themes darken their added, deleted and error hues and their muted text to clear 4.5:1, and the sidebar Input and Done colors and the match highlight get light-theme values. 38 preset colors are retuned to clear APCA tiers, notably red, blue, magenta and bright black on the dark presets and the Claude Dark and Tailwind Dark accents.
- Workspaces sidebar. Folding a workspace animates its tab rows over 180 ms and crossfades the folder icon; the active tab rests on the active tint; workspace groups are 10 px apart; titles and branches longer than 13 characters show in full in a tooltip; menu labels use sentence case; the thinking indicator holds still under Reduce motion.
- Changes dock slides closed over 280 ms from the pane toggle and its collapse buttons, and snaps under Reduce motion or when maximized.
- Help > System Info puts the build line beside the app icon, groups the report into System and Rendering panels and makes Copy the primary action; Escape closes, Enter copies. Help > About Paneflow follows the active theme and links the website, the source code and the release notes of the running version. The copied report is unchanged.
- Tailwind Dark paints Settings and dialog cards in its own zinc neutral (
#1f2023) and liftssurfaceto#212225andsubtleto#2b2c30. - Settings cards use 16 px horizontal padding and toggle rows 12 px vertical padding.
- Terminal file links open in the editor chosen in Settings (
external_editor), with Auto keeping the$VISUAL,$EDITOR, known-editor chain;visual_studiois accepted by the schema. - Changes dock file tabs use the same icons as the Files sidebar, which now also recognizes
.scss,.sass,.less,.jsoncand.text. - Shell integration no longer emits OSC 133 D after each command, and the PowerShell prompt no longer calls
Get-Historyon every prompt. Nothing in Paneflow read it. - Terminals no longer answer Glyph Protocol queries, and a Linux middle-click paste reaches the engine as the primary selection.
- A tab title saved with the retired
autosource restores as a title you set, and the repair that moves a workspace rooted at/now runs only when a version 1session.jsonis migrated. - Secondary, destructive and solid buttons report the Button role and their label to assistive technology.
- A desktop started from inside a Paneflow pane keeps its own home and socket instead of taking over the running instance, and no longer passes that pane's session markers to its own terminals.
Removed
- The Launch Pad, the
contextpane-spec field and the five unread config keys listed in the upgrade notes. - Per-launch hook injection by the shim, and the 400 ms poll of
~/.claude/sessionsthat stood in for Claude Code hooks. - The Hermes Agent and Cursor readers of the Sessions sidebar, which never produced a resumable session for the current directory.
Fixed
- The host no longer crashes on hook text over 4 KiB that contains accented, CJK or emoji characters.
- The first keystroke after a minute of idle in a persistent terminal is no longer lost: control connections no longer time out after 60 s.
- macOS: IPC replies larger than 8 KiB, such as
surface.listwith many panes or a longsurface.read, were cut at 8192 bytes. They arrive whole. - macOS: a background process started just before a session's shell exits stays owned by the session, so stopping the session stops it.
- Windows: a recycled process id can no longer make an unrelated or system process count as a session descendant and hold the session unverified.
- Unix: a host started on a socket another live host serves refuses instead of unlinking it and stranding that host's sessions.
surface.renameaccepts the documentednameparameter; before, a documented call cleared the pane name.- With no window running,
paneflowCLI and MCP calls that address a pane bysurface_idreach the listed pane. - Hovering command palette rows no longer lags: only the rows in view are laid out.
- Windows: the Gemini CLI, Kiro, Grok and OpenCode session lists find
.cmdshims throughPATHEXT.
Security
- On Windows the host pipe is owner-only: its ACL drops the SYSTEM and Administrators grants. The worker endpoint is owner-only on every platform.
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 36247383226.
Legs that passed:
- Build:
x86_64-unknown-linux-gnu,aarch64-unknown-linux-gnu,aarch64-apple-darwin,x86_64-pc-windows-msvc, each gated bycargo fmt --checkandcargo clippy --workspace --locked -- -D warnings - Release test gate on Linux x86_64:
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.16.0...v0.17.0