This batches the in-flight [Unreleased] block from CHANGELOG.md into a single commit. Highlights: - Real MCP protocol layer (initialize / tools/list / tools/call) so vendor MCP clients can complete the handshake against the per-PID socket. Legacy direct-dispatch preserved for the harness. - New mcp_injection kinds — cli_override for codex, config_env for opencode — joining the existing env-var and config_file paths so patterm can slot into more agents without touching their real config or auth. - Ctrl+A/D and Ctrl+W/S focus navigation across tabs and intra-tab process lists, recognised in legacy / kitty CSI u / xterm modifyOtherKeys encodings. - Palette macros (sw / k / sp ) and reordering so open sessions surface above spawn-new entries. - Two-row tab bar, sidebar/tabbar/status chrome cache, viewport-wipe on agent spawn, CR-terminated orchestrator injections, and split- Enter PTY writes so paste-detecting TUIs see Enter as a key event. Also fixes the bug logged in TODO: claude's Ctrl+O tool-call expansion emits CSI 0 J, which the viewport renderer was forwarding verbatim — wiping the sidebar to the right of the cursor and leaving the chrome cache convinced nothing had changed. CSI 0 J and CSI 1 J are now translated into per-row ECH sequences clamped to the viewport, same as CSI 2 J and CSI K already were. Agent guides (CLAUDE.md / AGENTS.md) now spell out the TODO->CHANGELOG workflow so completed items land in the changelog rather than as ticked entries left behind in TODO.
5.0 KiB
5.0 KiB
Changelog
All notable changes to patterm are tracked in this file. Format follows Keep a Changelog and the project loosely follows Semantic Versioning.
[Unreleased]
Added
- Ctrl+A / Ctrl+D step focus between top-level tabs; Ctrl+W / Ctrl+S step through processes (root + sub-agents) inside the current tab. Recognised in legacy, kitty CSI u, and xterm modifyOtherKeys encodings. The chord shadows the corresponding raw byte for the focused pane — pressing Ctrl+D no longer sends EOF to the underlying shell, for instance.
- MCP protocol layer (
internal/mcp/protocol.go) implementinginitialize,tools/list,tools/call,ping, and MCP notifications. Tool catalog with input schemas is advertised viatools/list. Real MCP clients (claude, etc.) can now complete the handshake against patterm's per-PID socket. Legacy direct-tool dispatch is preserved so the harness keeps working unchanged. mcp_injection.kind = "cli_override"for agents that accept inlinekey=valueconfig overrides on the command line. The default codex preset uses it to emit-c mcp_servers.patterm.command=…and-c mcp_servers.patterm.args=[…]— zero files written, noCODEX_HOMEoverride.mcp_injection.kind = "config_env"for agents that read their config from an env var. The default opencode preset uses it to pass a mergedopencode.jsoninline throughOPENCODE_CONFIG_CONTENT, so auth/agents/tui.json/skills resolve from the user's real$HOMEwith no XDG override.- Palette macros: typing
sw,k, orspfilters the list to switch / kill / spawn entries respectively. Footer shows the available macros.
Changed
- Palette ordering: open agents/processes (
Switch to …) now appear above the option to spawn new ones, with kill entries pushed down toward the end of the list. - Tab bar trimmed from three rows (label / subtitle / underline) to
two (label / underline). Tabs flex to fill the available host width
evenly with leftover columns distributed to the leftmost tabs; the
+ newhint sits in a reserved slot on the right. Layout'smainTopconsequently drops from 4 to 3, giving each pane one extra row of viewport.
Fixed
- Killed agents no longer linger in the command palette. Agent entries that aren't running are filtered out of the switch list; session-persistent commands (which can be restarted) stay visible.
tools/listnow emits a concretepropertiesobject ({}) for parameterless tools instead ofnull. Claude rejected thenull-properties form with "tools fetch failed" even though the initialize handshake had succeeded.- Sidebar no longer flickers on every PTY chunk. The tab bar, sidebar, and status line now cache their last rendered byte string and skip the write when the new frame matches; full repaint paths (resize / focus change / palette close / screen clear) invalidate the cache so the next draw fires unconditionally.
- Spawning a child agent now clears the viewport area before it paints, so the previous focused child's PTY output no longer bleeds through underneath the new pane.
- Orchestrator-injected input (initial agent prompts, MCP
send_inputwithsubmit: true,send_message,timer_waitcallbacks) now ends with CR (\r) instead of LF (\n). Claude treated\nas "newline in textarea"; with CR the prompt actually submits, matching what the host terminal sends when a user presses Enter directly. - Enter is now written to a child PTY as its own
write()call, separated from the preceding text by a short delay. BothInjectAsUser(user typing forwarded through patterm) andInjectAsOrchestrator(MCP / send_message / initial-prompt paths) share the split. Without it, claude — and other paste-detecting TUIs — coalesced"hello\r"into one read and inserted the CR as literal text instead of treating it as the Enter keystroke. - Sidebar (and tab bar) no longer get wiped when the focused child
issues
CSI 0 J/CSI 1 J(clear-to-cursor). The viewport renderer already clampedCSI 2 JandCSI Kto viewport columns, but the partial-screen variants were forwarded verbatim, so any tool-call expansion in claude (Ctrl+O) would erase every cell to the right of the cursor — including the right rail. Both forms are now translated into per-row ECH sequences that stop at the viewport's right edge. - Sidebar left border no longer vanishes when the viewport repaints.
The border column was the same column as the viewport's rightmost
cell, so any child write to that column (or
clearViewport's ECH) would erase it. The viewport is now one column narrower so the border has a dedicated column.
Conventions
- This file is the single record of user-visible changes; the TODO is scratch space, not history.
- One bullet per change, written in the past tense from the user's point of view. Reference the package or preset name when it helps a reader find the code.