Repository navigation
feat: add Letta Code detection and restore - #3107
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (21)
🚧 Files skipped from review as they are similar to previous changes (6)
Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review. 📝 WalkthroughWalkthroughHerdr adds Letta Code detection, session hooks, integration installation, native conversation restore, configuration entries, API and CLI support, localized documentation, and changelog entries. ChangesLetta Code support
Estimated code review effort: 4 (Complex) | ~45 minutes Merge Risk: 🔵 Low · up to The PR adds Letta session detection, conversation restore, and a user-level SessionStart hook. It is mergeable with explicit owner awareness because status may remain stale after approval, session identity reporting may fail if hook settings are rejected, and interrupted or concurrent setup changes could leave configuration inconsistent. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 36.07% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 61 functions across 17 files. (14 skipped: 14 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (2)
src/config/sound.rs (1)
47-47: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winAdd an explicit regression assertion for omitted
letta.
#[serde(default)]already preservesAgentSoundOverrides::default(). Add an assertion that an absentlettafield producesAgentSoundSetting::Default.src/detect/mod.rs (1)
629-640: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low valueThe bare
letta-code/lettapath match is broad.The
windows(2)check matches any path that contains aletta-codedirectory followed by alettacomponent, outsidenode_modules. A local checkout path such as/home/user/src/letta-code/letta/build.jswould be classified as Letta. The scopedwindows(4)match above already covers the published package layout. Theis_interactive_letta_processgate limits the damage, so this is a small risk only.Consider anchoring the fallback to a
node_modulesor.bincontext, or to a trailing component.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: aa59483c-24ca-4cc4-8592-87c045048df4
📒 Files selected for processing (39)
docs/next/CHANGELOG.mddocs/next/api/herdr-api.schema.jsondocs/next/website/src/content/docs/agent-automation.mdxdocs/next/website/src/content/docs/agents.mdxdocs/next/website/src/content/docs/cli-reference.mdxdocs/next/website/src/content/docs/integrations.mdxdocs/next/website/src/content/docs/ja/agent-automation.mdxdocs/next/website/src/content/docs/ja/agents.mdxdocs/next/website/src/content/docs/ja/cli-reference.mdxdocs/next/website/src/content/docs/ja/integrations.mdxdocs/next/website/src/content/docs/ja/session-state.mdxdocs/next/website/src/content/docs/session-state.mdxdocs/next/website/src/content/docs/zh-cn/agent-automation.mdxdocs/next/website/src/content/docs/zh-cn/agents.mdxdocs/next/website/src/content/docs/zh-cn/cli-reference.mdxdocs/next/website/src/content/docs/zh-cn/integrations.mdxdocs/next/website/src/content/docs/zh-cn/session-state.mdxdocs/next/website/src/data/config-reference.jsonsrc/agent_resume.rssrc/api/schema/integrations.rssrc/cli/integration.rssrc/config/model.rssrc/config/sidebar.rssrc/config/sound.rssrc/detect/manifest.rssrc/detect/manifests/letta.tomlsrc/detect/mod.rssrc/integration/actions.rssrc/integration/assets/letta/herdr-agent-session.ps1src/integration/assets/letta/herdr-agent-session.shsrc/integration/env.rssrc/integration/mod.rssrc/integration/registry.rssrc/integration/targets.rssrc/integration/tests.rssrc/integration/types.rssrc/main.rswebsite/agent-detection/index.tomlwebsite/agent-detection/letta.toml
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.
04c821e to
cfeed00
Compare
|
There was a problem hiding this comment.
🧹 Nitpick comments (3)
src/config/sound.rs (1)
226-226: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCover the Letta-specific lookup with a non-default test.
The current assertion verifies only the default value. It does not verify that a configured value reaches
AgentSoundOverrides::for_agentforAgent::Letta. Addletta = "on"to the fixture and assert both the parsed field and the lookup result.Suggested test extension
[ui.sound.agents] droid = "off" claude = "on" +letta = "on" ... - assert_eq!(config.ui.sound.agents.letta, AgentSoundSetting::Default); + assert_eq!(config.ui.sound.agents.letta, AgentSoundSetting::On); + assert_eq!( + config + .ui + .sound + .agents + .for_agent(Some(crate::detect::Agent::Letta)), + AgentSoundSetting::On + );src/detect/mod.rs (1)
692-735: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider normalizing the
--flag=valueform once.The list repeats each option twice: once as an exact match and once as a
--name=prefix. Splitting the argument at the first=and matching the name once removes the duplication and keeps both forms in sync when the option list changes.♻️ Possible simplification
- if cli_args.iter().any(|arg| { - matches!( - arg.as_str(), + if cli_args.iter().any(|arg| { + let name = arg.split_once('=').map_or(arg.as_str(), |(name, _)| name); + matches!( + name, "-p" | "--print"Then drop the
starts_with("--…=")chain.src/integration/targets.rs (1)
1209-1211: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueReuse a single
letta_dir()result.
letta_dir()is called twice. Bind it once and derive both paths from it.♻️ Proposed change
- let hook_path = letta_dir()?.join("hooks").join(LETTA_HOOK_INSTALL_NAME); - let settings_path = letta_dir()?.join("settings.json"); + let dir = letta_dir()?; + let hook_path = dir.join("hooks").join(LETTA_HOOK_INSTALL_NAME); + let settings_path = dir.join("settings.json");
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: a6b68c80-a89f-46f3-907b-3c80fcdc37c8
📒 Files selected for processing (6)
docs/next/website/src/data/config-reference.jsonsrc/config/sound.rssrc/detect/mod.rssrc/integration/assets/letta/herdr-agent-session.ps1src/integration/targets.rssrc/integration/tests.rs
Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.
0e6f70e to
6c0ff7b
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/integration/targets.rs (1)
1011-1018: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winUse a named millisecond timeout constant for the Letta hook. Letta Code v0.30.28 supports both
timeoutin milliseconds andquietas a boolean. Replace the unexplained10_000literal withLETTA_HOOK_TIMEOUT_MS.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 0a396887-ed40-43ca-91ce-80b4fa6492ca
📒 Files selected for processing (3)
src/config/sound.rssrc/detect/mod.rssrc/integration/targets.rs
Included review availability: Your plan provides up to 10 included reviews per hour; 6 remain after this review.
6c0ff7b to
e03e033
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 25b3509d-f279-4a69-94a2-22d181088986
📒 Files selected for processing (3)
src/integration/mod.rssrc/integration/targets.rssrc/integration/tests.rs
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.
e03e033 to
f96c294
Compare
|
hey @just-cameron could you verify if this branch works great with letta? |
|
Yeah, taking a look now. Thanks! |
|
Okay -- battletested and found one blocking bug. You can see my agent's fix in this commit. I have included my agent's report for your perusal. As a side note, one of our users added a lot of bells and whistles to improve the herdr/letta experience, but I think it is out of scope for this PR. Would you like me to open issues for some of the features I liked in his work? https://github.com/klittle32/letta-herdr-mod Agent reportTested this thoroughly against exact PR head What worked:
The 11 Letta-focused tests pass, as do strict Clippy, manifest validation, and the documentation builds. I found one startup edge case:
The PR currently conflicts with master. I rebased it locally onto One note on validation: the full Overall, the integration works well in real use. The false-ready profile-selector case is the only Letta-specific issue I found. |
f96c294 to
daf9d95
Compare
|
Agreed—the known-agent idle fallback could make startup succeed before Letta showed live composer evidence. I applied your manifest fix and regression coverage, then rebased the PR onto current master. |
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@just-cameron could you re-review please and verify if it works with letta? |
|
FWIW, tested |
|
Agent report attached after some back and forth. These two are both minor to be honest. The first about the conversation switching could be kind of annoying down the road so I would address it now, the other is about a relatively uncommon flag in Letta that is not used often. Otherwise I would say this is mergable. Review summaryI reviewed #3107 at commit The integration is largely working, and the earlier profile-selector false-ready fix is correctly included. I found one restore-correctness blocker and one smaller process-detection issue. What works
Blocker: conversation changes retain the stale restore IDThe Letta hook reports subsequent As a result:
I proved this with a temporary regression test against the unmodified PR. The test failed while retaining the old conversation ID, then passed with this additional allow-list arm: | ("herdr:letta", "letta", Some("new" | "resume"))Suggested fix:
I would fix this before merge because it affects the core restore behavior introduced by the PR. Smaller issue:
|
|
Is there any ETA to address the issues and merge the PR? It seems straightforward and I could make it work locally. |
Installing it Letta Code rn and will see if we can get this sorted |
refs #3106 Co-authored-by: Cameron <cameron@pfiffer.org>
daf9d95 to
5e54411
Compare
|
@greptileai review |
There was a problem hiding this comment.
This is adding Letta Code detection, native conversation restore and the SessionStart hook in a preview form so people can use Letta with Herdr right now.
Use herdr integration install letta to manually install the integration.
Note that this is not a first-class integration as the agent registry rework was started without Letta in-scope.
There should be a follow up once the registry PR is merged to fully integrate Letta V1 that way.
Until then, this is a reasonable usability compromise.
|
Thanks for picking this up. We got a locally patched Herdr + Letta 0.32.2 setup working on macOS, and these were the changes we made along the way. On the Herdr side, we applied the two fixes Cameron described:
We also encountered a few issues on the Letta side:
Our patched pair passed startup, conversation switching, and resume tests under Node and Bun on macOS. These results are from our local builds; we haven’t runtime-tested your latest rebased revision yet. |
* fix: disconnect stalled terminal observers (herdrdev#4039) * fix: order ui accent before nested config tables (herdrdev#2698) * fix: order ui accent before nested config tables refs herdrdev#2697 * test: reject duplicate ui accent examples refs herdrdev#2697 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix: decouple pixel mouse from pane graphics (herdrdev#4045) refs herdrdev#3295 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: restrict claude session hooks to native sources (herdrdev#4046) refs herdrdev#4018 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix(input): preserve super-modified pane keys (herdrdev#4044) refs herdrdev#3710 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * test: relax windows docs snapshot timeout (herdrdev#4049) Windows CI runs these documentation contract fixtures under variable load. A degraded runner pushed the preview and versions snapshot integration tests past their 30s ceiling, while a healthy run finishes in seconds. Keep 30s elsewhere and give Windows a 120s ceiling. * fix: retain validated split mouse reports across idle gaps (herdrdev#4048) refs herdrdev#3911 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix(server): transfer handoff descriptors in batches (herdrdev#3411) Live handoff refused any session with more than 64 panes. The pane count was checked twice against MAX_FDS_PER_HANDOFF, and the transfer itself put every pane's pty master into one SCM_RIGHTS control message, so the guard was the only thing keeping the send inside the kernel's per-message limit. A session past the limit could only be updated by closing panes or by a normal restart, which ends every pane process. Send the descriptors in batches of 64 instead and drop both guards. The receiving side accumulates across recvmsg calls until the expected count arrives, bounds every SCM_RIGHTS payload it reads by the control bytes the kernel returned, rejects a batch that carries more descriptors than it asked for, and closes the descriptors it already holds on any failure. A session of 64 panes or fewer still produces one batch, so the bytes on the wire are unchanged and HANDOFF_VERSION stays at 1. refs herdrdev#3393 Co-authored-by: kataokatsuki <kataokatsuki@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * test: deflake windows metadata ttl expiry assertion (herdrdev#4050) The clear-only metadata test used a 1 ms ttl, so on loaded Windows runners set_agent_metadata could see the entry as expired, drop it, and recreate it with a None ttl before next_agent_metadata_expiry() ran. Expiry is forced explicitly later in the test, so use a long ttl to keep the no-extension assertion independent of wall-clock scheduling. * fix: detect kimi npm shim on windows (herdrdev#4053) refs herdrdev#3317 * fix(remote): resolve ssh host aliases from git bash on windows (herdrdev#4054) Windows OpenSSH resolves drive-letter Include paths, but Git for Windows' MSYS OpenSSH does not, so the managed remote SSH config silently ignored the user's ~/.ssh/config when herdr ran under Git Bash. Include the user config through ~/.ssh/config, which both implementations expand to the same file. refs herdrdev#3947 * feat: add Letta Code detection and restore (herdrdev#3107) refs herdrdev#3106 Co-authored-by: Cameron <cameron@pfiffer.org> * fix(windows): disable host mouse reporting on terminal restore (herdrdev#4055) Windows skipped the xterm mouse-reporting reset because clear_host_mouse_reporting was a no-op there. Standalone Git Bash (mintty) keeps SGR mouse reporting enabled after detach, so mouse motion leaks escape sequences into the shell. Emit the reset sequence on Windows too and include the X10 mode. refs herdrdev#3748 * fix: keep hermes enabled list valid yaml (herdrdev#4056) * fix: keep hermes enabled list valid yaml refs herdrdev#3839 * fix: preserve hermes inline list quoting and comments refs herdrdev#3839 * fix(ui): keep muted sidebar and tab labels readable (herdrdev#4062) refs herdrdev#2692 * fix(windows): honor default_shell in login shell mode (herdrdev#4060) * fix(windows): honor default_shell in login shell mode Login-mode panes used portable-pty's default-program builder, which resolves to %ComSpec% (cmd.exe) on Windows and ignores the SHELL env override, so [terminal].default_shell was silently ignored. Build the launch command from the configured shell instead and append the shell's own login flag for POSIX-style shells that support one. refs herdrdev#1445 * fix(windows): add csh and tcsh to login shell flags refs herdrdev#1445 * fix(windows): keep powershell cwd reporting in login mode (herdrdev#4065) Windows login-mode PowerShell panes are now launched directly, but the PowerShell prompt-based cwd integration was still gated to non-login mode, leaving those panes without repository-owned cwd reporting after Set-Location. Enable the existing integration for login-mode PowerShell and build the integration args on the shared direct-shell path. Follow-up to herdrdev#4060. * fix: keep an agent name through a process-exit observation (herdrdev#3574) A process-exit observation is not proof the agent is gone: the same observation can be wrong while the agent keeps running, and the name is the only handle its owner has on the pane. Detection uncertainty already preserves the name, so releasing it on the observation alone contradicts that contract and leaves a live agent unreachable by name with a rename as the only recovery. Free the name at the point the agent actually leaves the pane - a recorded exit with no agent detected any more - so a wrong observation costs nothing and a real exit still releases the name for reuse. refs herdrdev#3225 Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: auto-expire worktree action error banners (herdrdev#4063) * fix: auto-expire worktree action error banners refs herdrdev#1827 * fix: restart endpoint error timeout on repeated errors Route every transient client-side action error through a setter that installs a fresh deadline, so an identical repeated message cannot inherit an older, nearly-expired deadline. refs herdrdev#1827 * test: derive endpoint error expiry assertions from stored deadline refs herdrdev#1827 * test: deflake federated local input race (herdrdev#4066) refs herdrdev#3670 * fix: recognize kitty CSI-u codepoints for F1 through F12 (herdrdev#2378) Codepoints 57364-57375 (F1-F12) were missing from the kitty-protocol codepoint table, so terminals that send function keys as full CSI-u sequences (e.g. Ghostty, which enables the kitty keyboard protocol by default) had those keys silently dropped. Confirmed live against a running herdr session: injecting the raw F3/F4 codepoint sequences did nothing before this fix and correctly triggered previous_tab/next_tab after. refs herdrdev#1809 Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix(input): accept parameterized CSI-tilde F1-F4 keys (herdrdev#4067) Terminals such as foot send F1-F4 as parameterized CSI-tilde sequences (for example F3 as `\x1b[13;1:1~`). `parse_xterm_modified_special_sequence` mapped codes 15-24 but not 11-14, so these presses were dropped before keybindings saw them. Map 11-14 to F1-F4, matching the unmodified `\x1b[11~`..`\x1b[14~` aliases already accepted. refs herdrdev#1809 * fix: clean up failed terminal observer setup (herdrdev#4071) refs herdrdev#3612 * chore: add jjliebig as approved contributor and maintainer * feat: install windows remote host packages (herdrdev#3687) * feat: install windows remote host packages refs herdrdev#3651 * docs: clarify windows saved reconnect package behavior refs herdrdev#3651 * fix: include windows installer in nix sources refs herdrdev#3651 * fix: preserve paths in windows scp transfers refs herdrdev#3651 * refactor: isolate windows remote package setup refs herdrdev#3651 * feat: add ctrl-hover highlighting and fix wrapped links (herdrdev#4074) refs herdrdev#1282 * fix(linux): bound the foreground process-tree scan (herdrdev#3674) refs herdrdev#3621 Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: keep plugins working after client-only updates (herdrdev#4077) * ci: migrate remaining pinned actions to node24 (herdrdev#4023) * ci: migrate remaining pinned actions to node24 actions/cache@v4 and mlugg/setup-zig@v2.2.1 still target Node 20, which GitHub removes from runners on 2026-09-23. Bump actions/cache to v6.1.0 and replace mlugg/setup-zig with vercel-labs/setup-zig@v1.0.2. vercel-labs/setup-zig takes only `version`, so the use-cache/cache-size-limit tuning and Zig global-cache reuse are dropped. See the PR for alternatives. * ci: restore zig caching for vercel setup-zig vercel-labs/setup-zig has no cache controls, so redirect the Zig global cache into the workspace .zig-cache and run the Zig build cache step on Linux too. Drop this commit if we switch to a setup action that owns Zig caching, e.g. step-security/setup-zig or xyzzylabs/setup-zig. * fix: clarify agent integration settings description * fix: scope agent views to the selected machine (herdrdev#3784) * fix: scope agent views to the selected machine refs herdrdev#3732 * fix: preserve stable agent view ordering refs herdrdev#3732 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix(windows): restore mouse reporting when reattaching (herdrdev#4080) * fix(client): re-assert host mouse modes after a terminal reconnect (herdrdev#4079) Co-authored-by: dengos <dengoswei@gmail.com> * test(windows): deflake media player invalid media assertion (herdrdev#4082) * test(windows): deflake media player invalid media assertion The Windows sound test required MediaPlayer's MediaFailed event for invalid media. Some runners never raise it, so the script exits through its playback timer and the test saw "sound playback timed out" instead, panicking on the MediaFailed assertion. Accept either terminal error and keep the timer short under test via HERDR_SOUND_TIMEOUT_SECONDS so a missed MediaFailed no longer waits out the production 15 second bound. * test(windows): keep media player timeout override test-only Generate the short-timer player script only in tests instead of reading a process environment override. This keeps the production script's fixed 15 second bound unchanged, and the script-content test now proves the test variant rewrites the timer. * fix: hide only kitty image placements overlapping overlays (herdrdev#4081) * fix: clean up idle ssh bridges and back off flapping connections (herdrdev#4083) * fix: clean up idle ssh bridges and back off flapping connections * chore: keep ssh liveness smoke tooling local * fix: preserve agent panel scroll when switching machines (herdrdev#4101) refs herdrdev#3937 Root cause: Activating another endpoint applies a snapshot with a different endpoint-qualified graphics scope. This triggers reset_endpoint_projection, which clears agent_scroll together with endpoint-local state even though the agent list aggregates all machines. The selected agent receives focus, but the list jumps back to the top. Fix: Save the client-owned agent scroll offset and restore it only when activation changes endpoints. Keep same-endpoint reboot resets, workspace/tab scroll resets, input cleanup and existing list bounds clamping unchanged. This adds constant-time work on endpoint activation, with no protocol, persisted-state or pane-scaled rendering changes. Validation: The new regression fails on the original implementation with scroll 0 instead of 6. Tests cover repeated bidirectional agent clicks, stable visible rows, shrinking lists and same-machine reboots. All 242 client shell tests pass. Real SSH A/B testing against the same two disposable 0.9.0 servers reproduces the reset with both the stable and current-master clients. The patched client preserves the visible rows through six cross-machine switches and two same-machine control clicks. Native just ci passes: 3535 Rust tests, six default skips, plus lint, maintenance, architecture and integration-asset checks. All seven docs contract tests pass. Windows cross-lint was not run because its SDK is not installed; native macOS and Windows UI behavior was not tested. * fix: remove stale maintainer username * fix: detect codex activity with static titles and queued inputs (herdrdev#4099) * fix: detect codex activity with static titles and queued inputs refs herdrdev#4092 Codex 0.154.0 can omit the activity bullet when tui.animations is false and replace the literal Working label with a task-specific label. Its terminal title can also remain static during an active turn, so the OSC spinner rule is not sufficient to identify work. The screen fallback required a bullet followed by Working in the last three non-empty lines. It therefore missed both the animation-disabled status line and dynamic labels. Queued follow-ups add a heading, input text, and an edit hint below the activity line, moving that line outside the three-line region. The lower-priority non-empty OSC title rule then reported idle while Codex still showed an active timer and interrupt control. Recognize the elapsed-time and esc-to-interrupt controls in the detection snapshot before the current composer. Allow an optional bullet, a dynamic activity label, and queued follow-ups below that line. Require that no later response, completion, or interruption marker supersedes the live activity. This excludes composer text and stale output without letting an earlier interruption suppress a subsequent active turn. Keep OSC state precedence and transcript-viewer skip behavior unchanged. Update the bundled and distributed manifests together to 2026.09.14.1. Add regression coverage for optional bullets, dynamic labels, queued inputs, resumed work after interruption, and stale or quoted controls. Avoid discarding Regex search caches on every detection poll. The loader previously cloned the entire compiled rule vector, and each Regex clone created a fresh search cache pool despite sharing compiled read-only state. Share the immutable rules through Arc instead. Reload publishes a new array while in-flight readers retain a valid old generation, without holding the global cache lock during matching. Add a cheap contains gate for the required interrupt text before running the multiline expression. Add a deterministic regression for compiled-rule sharing, reload replacement, retained old readers, and concurrent detection. Measure the baseline and optimized detector kernels in three alternating rounds on CPU 24 with NUMA node 0 and CPU 25 with NUMA node 1. Real queued detection falls from about 116 to 22 microseconds, and two evaluations per pane over 15 panes fall from about 3.45 to 0.65 milliseconds on both sockets, about 81 percent less time. No benchmark match results change. The cache improvement requires the updated binary, not just a manifest reload. Validate on the official Herdr 0.9.0 release with Codex 0.154.0 by toggling the old and new manifests during the same active queued task. Confirm working for active turns and idle after completion or interruption. Pass 86 captured-screen and semantic checks through the optimized source binary, 69 manifest/cache tests, CPU-pinned render scaling, and the full native CI suite: 3535 Rust tests passed, with six default skips. Run CI serially with inherited Herdr session context removed; no tests were excluded or expectations relaxed to make CI pass. * fix: detect codex pending follow-ups as working refs herdrdev#4092 * fix: handle wrapped codex follow-up hints refs herdrdev#4092 --------- Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com> * fix: detect pi working border (herdrdev#4113) refs herdrdev#3629 * ci: restore zig local build cache reuse (herdrdev#4118) * fix: default pane splits to the calling pane (herdrdev#4123) * fix: restore saved machine screens after reconnect (herdrdev#4126) refs herdrdev#3842 * fix: scope window titles to each client view (herdrdev#4130) refs herdrdev#4091 * fix(windows): avoid lossy native Win32 input mode (herdrdev#4133) refs herdrdev#3932 refs herdrdev#3702 refs herdrdev#3910 * fix: keep modified enter compatible with legacy panes (herdrdev#4110) * fix: keep modified enter compatible with legacy panes refs herdrdev#4103 * fix: synchronize modified key negotiation state refs herdrdev#4103 * test: cover windows legacy modified enter refs herdrdev#4103 --------- Co-authored-by: Jonathan Liebig <jonathan.liebig@gmail.com> * fix: avoid resending terminal cells for metadata updates (herdrdev#4137) * feat: add cursor-based editing to text inputs (herdrdev#3698) * feat: add cursor-based editing to text inputs refs herdrdev#1803 * fix: preserve dialog actions with associated text refs herdrdev#1803 * refactor: simplify text editor outcomes and tests refs herdrdev#1803 --------- Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: protect integration configs from failed writes (herdrdev#3973) * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: map pixel mouse by integer cell pitch (herdrdev#4140) refs herdrdev#3295 * fix: reject stale pane surfaces after reconnect (herdrdev#4141) * test: deflake recent CI failures (herdrdev#4139) * fix(windows): batch input trace diagnostics (herdrdev#4146) refs herdrdev#3932 * fix(windows): prefer VT input for SSH clients (herdrdev#4148) refs herdrdev#3932 * fix: reveal the full last tab in overflowing tab strips (herdrdev#4152) refs herdrdev#4151 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * chore: guard the ziki agent enum against future sync drops The 2026-09-15 sync showed the gap: both sides added an Agent variant and each bumped only its own array length in src/detect/mod.rs, so the union auto-merged one entry short and did not compile. Nothing in FORK_OWNED_FILES covered the file, so the marker guardrail could not see it. refs #50 * fix: address review comments on #52 refs #50 --------- Co-authored-by: Can Celik <ogulcancelik@gmail.com> Co-authored-by: akbash <akbash@herdr.dev> Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> Co-authored-by: Kataoka Katsuki <49934462+kataokatsuki@users.noreply.github.com> Co-authored-by: kataokatsuki <kataokatsuki@users.noreply.github.com> Co-authored-by: Cameron <cameron@pfiffer.org> Co-authored-by: caner-akca <94343893+caner-akca@users.noreply.github.com> Co-authored-by: Kakumanu Ashok Reddy <kakumanuashokreddyias2024@gmail.com> Co-authored-by: dengos <dengoswei@gmail.com> Co-authored-by: Eric Yue <jiacheng.yue@foxmail.com> Co-authored-by: Mark Jaquith <mark@jaquith.me> Co-authored-by: zuraffa-review[bot] <326983185+zuraffa-review[bot]@users.noreply.github.com>
|
Thanks y'all! Looking forward to the next release, our users are quite excited. |
|
@just-cameron @leonardschneider thanks for those, note that this is truly a) manual opt-in for now and b) has to wait until the registry PR is merged. When that's done, I'd invite you to send a patch and tag me so I can make sure we can get Letta Code added properly then |
* fix: disconnect stalled terminal observers (herdrdev#4039) * fix: order ui accent before nested config tables (herdrdev#2698) * fix: order ui accent before nested config tables refs herdrdev#2697 * test: reject duplicate ui accent examples refs herdrdev#2697 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix: decouple pixel mouse from pane graphics (herdrdev#4045) refs herdrdev#3295 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: restrict claude session hooks to native sources (herdrdev#4046) refs herdrdev#4018 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix(input): preserve super-modified pane keys (herdrdev#4044) refs herdrdev#3710 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * test: relax windows docs snapshot timeout (herdrdev#4049) Windows CI runs these documentation contract fixtures under variable load. A degraded runner pushed the preview and versions snapshot integration tests past their 30s ceiling, while a healthy run finishes in seconds. Keep 30s elsewhere and give Windows a 120s ceiling. * fix: retain validated split mouse reports across idle gaps (herdrdev#4048) refs herdrdev#3911 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix(server): transfer handoff descriptors in batches (herdrdev#3411) Live handoff refused any session with more than 64 panes. The pane count was checked twice against MAX_FDS_PER_HANDOFF, and the transfer itself put every pane's pty master into one SCM_RIGHTS control message, so the guard was the only thing keeping the send inside the kernel's per-message limit. A session past the limit could only be updated by closing panes or by a normal restart, which ends every pane process. Send the descriptors in batches of 64 instead and drop both guards. The receiving side accumulates across recvmsg calls until the expected count arrives, bounds every SCM_RIGHTS payload it reads by the control bytes the kernel returned, rejects a batch that carries more descriptors than it asked for, and closes the descriptors it already holds on any failure. A session of 64 panes or fewer still produces one batch, so the bytes on the wire are unchanged and HANDOFF_VERSION stays at 1. refs herdrdev#3393 Co-authored-by: kataokatsuki <kataokatsuki@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * test: deflake windows metadata ttl expiry assertion (herdrdev#4050) The clear-only metadata test used a 1 ms ttl, so on loaded Windows runners set_agent_metadata could see the entry as expired, drop it, and recreate it with a None ttl before next_agent_metadata_expiry() ran. Expiry is forced explicitly later in the test, so use a long ttl to keep the no-extension assertion independent of wall-clock scheduling. * fix: detect kimi npm shim on windows (herdrdev#4053) refs herdrdev#3317 * fix(remote): resolve ssh host aliases from git bash on windows (herdrdev#4054) Windows OpenSSH resolves drive-letter Include paths, but Git for Windows' MSYS OpenSSH does not, so the managed remote SSH config silently ignored the user's ~/.ssh/config when herdr ran under Git Bash. Include the user config through ~/.ssh/config, which both implementations expand to the same file. refs herdrdev#3947 * feat: add Letta Code detection and restore (herdrdev#3107) refs herdrdev#3106 Co-authored-by: Cameron <cameron@pfiffer.org> * fix(windows): disable host mouse reporting on terminal restore (herdrdev#4055) Windows skipped the xterm mouse-reporting reset because clear_host_mouse_reporting was a no-op there. Standalone Git Bash (mintty) keeps SGR mouse reporting enabled after detach, so mouse motion leaks escape sequences into the shell. Emit the reset sequence on Windows too and include the X10 mode. refs herdrdev#3748 * fix: keep hermes enabled list valid yaml (herdrdev#4056) * fix: keep hermes enabled list valid yaml refs herdrdev#3839 * fix: preserve hermes inline list quoting and comments refs herdrdev#3839 * fix(ui): keep muted sidebar and tab labels readable (herdrdev#4062) refs herdrdev#2692 * fix(windows): honor default_shell in login shell mode (herdrdev#4060) * fix(windows): honor default_shell in login shell mode Login-mode panes used portable-pty's default-program builder, which resolves to %ComSpec% (cmd.exe) on Windows and ignores the SHELL env override, so [terminal].default_shell was silently ignored. Build the launch command from the configured shell instead and append the shell's own login flag for POSIX-style shells that support one. refs herdrdev#1445 * fix(windows): add csh and tcsh to login shell flags refs herdrdev#1445 * fix(windows): keep powershell cwd reporting in login mode (herdrdev#4065) Windows login-mode PowerShell panes are now launched directly, but the PowerShell prompt-based cwd integration was still gated to non-login mode, leaving those panes without repository-owned cwd reporting after Set-Location. Enable the existing integration for login-mode PowerShell and build the integration args on the shared direct-shell path. Follow-up to herdrdev#4060. * fix: keep an agent name through a process-exit observation (herdrdev#3574) A process-exit observation is not proof the agent is gone: the same observation can be wrong while the agent keeps running, and the name is the only handle its owner has on the pane. Detection uncertainty already preserves the name, so releasing it on the observation alone contradicts that contract and leaves a live agent unreachable by name with a rename as the only recovery. Free the name at the point the agent actually leaves the pane - a recorded exit with no agent detected any more - so a wrong observation costs nothing and a real exit still releases the name for reuse. refs herdrdev#3225 Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: auto-expire worktree action error banners (herdrdev#4063) * fix: auto-expire worktree action error banners refs herdrdev#1827 * fix: restart endpoint error timeout on repeated errors Route every transient client-side action error through a setter that installs a fresh deadline, so an identical repeated message cannot inherit an older, nearly-expired deadline. refs herdrdev#1827 * test: derive endpoint error expiry assertions from stored deadline refs herdrdev#1827 * test: deflake federated local input race (herdrdev#4066) refs herdrdev#3670 * fix: recognize kitty CSI-u codepoints for F1 through F12 (herdrdev#2378) Codepoints 57364-57375 (F1-F12) were missing from the kitty-protocol codepoint table, so terminals that send function keys as full CSI-u sequences (e.g. Ghostty, which enables the kitty keyboard protocol by default) had those keys silently dropped. Confirmed live against a running herdr session: injecting the raw F3/F4 codepoint sequences did nothing before this fix and correctly triggered previous_tab/next_tab after. refs herdrdev#1809 Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix(input): accept parameterized CSI-tilde F1-F4 keys (herdrdev#4067) Terminals such as foot send F1-F4 as parameterized CSI-tilde sequences (for example F3 as `\x1b[13;1:1~`). `parse_xterm_modified_special_sequence` mapped codes 15-24 but not 11-14, so these presses were dropped before keybindings saw them. Map 11-14 to F1-F4, matching the unmodified `\x1b[11~`..`\x1b[14~` aliases already accepted. refs herdrdev#1809 * fix: clean up failed terminal observer setup (herdrdev#4071) refs herdrdev#3612 * chore: add jjliebig as approved contributor and maintainer * feat: install windows remote host packages (herdrdev#3687) * feat: install windows remote host packages refs herdrdev#3651 * docs: clarify windows saved reconnect package behavior refs herdrdev#3651 * fix: include windows installer in nix sources refs herdrdev#3651 * fix: preserve paths in windows scp transfers refs herdrdev#3651 * refactor: isolate windows remote package setup refs herdrdev#3651 * feat: add ctrl-hover highlighting and fix wrapped links (herdrdev#4074) refs herdrdev#1282 * fix(linux): bound the foreground process-tree scan (herdrdev#3674) refs herdrdev#3621 Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: keep plugins working after client-only updates (herdrdev#4077) * ci: migrate remaining pinned actions to node24 (herdrdev#4023) * ci: migrate remaining pinned actions to node24 actions/cache@v4 and mlugg/setup-zig@v2.2.1 still target Node 20, which GitHub removes from runners on 2026-09-23. Bump actions/cache to v6.1.0 and replace mlugg/setup-zig with vercel-labs/setup-zig@v1.0.2. vercel-labs/setup-zig takes only `version`, so the use-cache/cache-size-limit tuning and Zig global-cache reuse are dropped. See the PR for alternatives. * ci: restore zig caching for vercel setup-zig vercel-labs/setup-zig has no cache controls, so redirect the Zig global cache into the workspace .zig-cache and run the Zig build cache step on Linux too. Drop this commit if we switch to a setup action that owns Zig caching, e.g. step-security/setup-zig or xyzzylabs/setup-zig. * fix: clarify agent integration settings description * fix: scope agent views to the selected machine (herdrdev#3784) * fix: scope agent views to the selected machine refs herdrdev#3732 * fix: preserve stable agent view ordering refs herdrdev#3732 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix(windows): restore mouse reporting when reattaching (herdrdev#4080) * fix(client): re-assert host mouse modes after a terminal reconnect (herdrdev#4079) Co-authored-by: dengos <dengoswei@gmail.com> * test(windows): deflake media player invalid media assertion (herdrdev#4082) * test(windows): deflake media player invalid media assertion The Windows sound test required MediaPlayer's MediaFailed event for invalid media. Some runners never raise it, so the script exits through its playback timer and the test saw "sound playback timed out" instead, panicking on the MediaFailed assertion. Accept either terminal error and keep the timer short under test via HERDR_SOUND_TIMEOUT_SECONDS so a missed MediaFailed no longer waits out the production 15 second bound. * test(windows): keep media player timeout override test-only Generate the short-timer player script only in tests instead of reading a process environment override. This keeps the production script's fixed 15 second bound unchanged, and the script-content test now proves the test variant rewrites the timer. * fix: hide only kitty image placements overlapping overlays (herdrdev#4081) * fix: clean up idle ssh bridges and back off flapping connections (herdrdev#4083) * fix: clean up idle ssh bridges and back off flapping connections * chore: keep ssh liveness smoke tooling local * fix: preserve agent panel scroll when switching machines (herdrdev#4101) refs herdrdev#3937 Root cause: Activating another endpoint applies a snapshot with a different endpoint-qualified graphics scope. This triggers reset_endpoint_projection, which clears agent_scroll together with endpoint-local state even though the agent list aggregates all machines. The selected agent receives focus, but the list jumps back to the top. Fix: Save the client-owned agent scroll offset and restore it only when activation changes endpoints. Keep same-endpoint reboot resets, workspace/tab scroll resets, input cleanup and existing list bounds clamping unchanged. This adds constant-time work on endpoint activation, with no protocol, persisted-state or pane-scaled rendering changes. Validation: The new regression fails on the original implementation with scroll 0 instead of 6. Tests cover repeated bidirectional agent clicks, stable visible rows, shrinking lists and same-machine reboots. All 242 client shell tests pass. Real SSH A/B testing against the same two disposable 0.9.0 servers reproduces the reset with both the stable and current-master clients. The patched client preserves the visible rows through six cross-machine switches and two same-machine control clicks. Native just ci passes: 3535 Rust tests, six default skips, plus lint, maintenance, architecture and integration-asset checks. All seven docs contract tests pass. Windows cross-lint was not run because its SDK is not installed; native macOS and Windows UI behavior was not tested. * fix: remove stale maintainer username * fix: detect codex activity with static titles and queued inputs (herdrdev#4099) * fix: detect codex activity with static titles and queued inputs refs herdrdev#4092 Codex 0.154.0 can omit the activity bullet when tui.animations is false and replace the literal Working label with a task-specific label. Its terminal title can also remain static during an active turn, so the OSC spinner rule is not sufficient to identify work. The screen fallback required a bullet followed by Working in the last three non-empty lines. It therefore missed both the animation-disabled status line and dynamic labels. Queued follow-ups add a heading, input text, and an edit hint below the activity line, moving that line outside the three-line region. The lower-priority non-empty OSC title rule then reported idle while Codex still showed an active timer and interrupt control. Recognize the elapsed-time and esc-to-interrupt controls in the detection snapshot before the current composer. Allow an optional bullet, a dynamic activity label, and queued follow-ups below that line. Require that no later response, completion, or interruption marker supersedes the live activity. This excludes composer text and stale output without letting an earlier interruption suppress a subsequent active turn. Keep OSC state precedence and transcript-viewer skip behavior unchanged. Update the bundled and distributed manifests together to 2026.09.14.1. Add regression coverage for optional bullets, dynamic labels, queued inputs, resumed work after interruption, and stale or quoted controls. Avoid discarding Regex search caches on every detection poll. The loader previously cloned the entire compiled rule vector, and each Regex clone created a fresh search cache pool despite sharing compiled read-only state. Share the immutable rules through Arc instead. Reload publishes a new array while in-flight readers retain a valid old generation, without holding the global cache lock during matching. Add a cheap contains gate for the required interrupt text before running the multiline expression. Add a deterministic regression for compiled-rule sharing, reload replacement, retained old readers, and concurrent detection. Measure the baseline and optimized detector kernels in three alternating rounds on CPU 24 with NUMA node 0 and CPU 25 with NUMA node 1. Real queued detection falls from about 116 to 22 microseconds, and two evaluations per pane over 15 panes fall from about 3.45 to 0.65 milliseconds on both sockets, about 81 percent less time. No benchmark match results change. The cache improvement requires the updated binary, not just a manifest reload. Validate on the official Herdr 0.9.0 release with Codex 0.154.0 by toggling the old and new manifests during the same active queued task. Confirm working for active turns and idle after completion or interruption. Pass 86 captured-screen and semantic checks through the optimized source binary, 69 manifest/cache tests, CPU-pinned render scaling, and the full native CI suite: 3535 Rust tests passed, with six default skips. Run CI serially with inherited Herdr session context removed; no tests were excluded or expectations relaxed to make CI pass. * fix: detect codex pending follow-ups as working refs herdrdev#4092 * fix: handle wrapped codex follow-up hints refs herdrdev#4092 --------- Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com> * fix: detect pi working border (herdrdev#4113) refs herdrdev#3629 * ci: restore zig local build cache reuse (herdrdev#4118) * fix: default pane splits to the calling pane (herdrdev#4123) * fix: restore saved machine screens after reconnect (herdrdev#4126) refs herdrdev#3842 * fix: scope window titles to each client view (herdrdev#4130) refs herdrdev#4091 * fix(windows): avoid lossy native Win32 input mode (herdrdev#4133) refs herdrdev#3932 refs herdrdev#3702 refs herdrdev#3910 * fix: keep modified enter compatible with legacy panes (herdrdev#4110) * fix: keep modified enter compatible with legacy panes refs herdrdev#4103 * fix: synchronize modified key negotiation state refs herdrdev#4103 * test: cover windows legacy modified enter refs herdrdev#4103 --------- Co-authored-by: Jonathan Liebig <jonathan.liebig@gmail.com> * fix: avoid resending terminal cells for metadata updates (herdrdev#4137) * feat: add cursor-based editing to text inputs (herdrdev#3698) * feat: add cursor-based editing to text inputs refs herdrdev#1803 * fix: preserve dialog actions with associated text refs herdrdev#1803 * refactor: simplify text editor outcomes and tests refs herdrdev#1803 --------- Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: protect integration configs from failed writes (herdrdev#3973) * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: map pixel mouse by integer cell pitch (herdrdev#4140) refs herdrdev#3295 * fix: reject stale pane surfaces after reconnect (herdrdev#4141) * test: deflake recent CI failures (herdrdev#4139) * fix(windows): batch input trace diagnostics (herdrdev#4146) refs herdrdev#3932 * fix(windows): prefer VT input for SSH clients (herdrdev#4148) refs herdrdev#3932 * fix: reveal the full last tab in overflowing tab strips (herdrdev#4152) refs herdrdev#4151 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix: reveal newly focused workspaces in the machines sidebar * fix: propagate focused pane moves to attached clients (herdrdev#4159) refs herdrdev#4153 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * test: wait for runtime readiness in integration tests (herdrdev#4168) Root cause: The handoff test starts an agent immediately after workspace creation, before the new shell is necessarily ready. The reconnect test assumes a fixed sidebar row and searches raw ANSI output for text that can arrive as separate incremental cell updates. Fix: Wait for a shell builtin to write a readiness marker before sending the single raw agent.start request. Exercise the gap with a delayed shell. Locate the recovered workspace in the rendered sidebar and check the reconstructed screen for selection and input, including overlay borders. Do not extend existing timeouts or add retries that hide failures. Validation: All 25 affected group and helper tests pass. Ten repeated rounds of the two runtime tests and the row helper pass, for 30 test executions without retries. Standalone native just ci passes 3582 Rust tests with six default skips, formatting, all-target Clippy, 106 maintenance tests, six architecture tests and 39 integration-asset tests. Windows cross-lint was not run because its SDK is not installed. Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: reconcile client locations after no-focus pane moves (herdrdev#4171) refs herdrdev#4153 Root cause: A no-focus pane move can remove the source tab without changing the server's numeric workspace and tab coordinates. PaneMove is not classified as a topology change, so a client viewing that tab retains its deleted ID. Its target lookup falls back to the server default and can follow a later, unrelated focus change instead of staying in the source workspace. Fix: Include PaneMove in the existing client-location reconciliation path. Extend the existing focus-guard test with a client on the removed tab and verify that a later server-default change cannot move its view. Preserve the other client's view and existing error, no-op and zoom assertions. Validation: The minimized regression fails five times on PR herdrdev#4159's unchanged head and passes five times with the one-line fix. All 19 pane-move tests, native lint, maintenance, architecture and integration-asset checks pass. Full native just ci on the publication branch, including the unchanged prerequisites from herdrdev#4159 and herdrdev#4168, passes 3585 Rust tests with six default skips plus lint, 106 maintenance, six architecture and 39 integration-asset tests. All seven docs contract tests pass. Local Windows cross-lint was not run because its SDK is unavailable. No geometry policy, protocol or periodic rendering behavior is changed. * fix: preserve live selections during pane output (herdrdev#4193) refs herdrdev#3841 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix(windows): preserve sgr mouse encoding after native capture (herdrdev#4195) refs herdrdev#4155 * fix(windows): normalize pane launch cwd casing (herdrdev#4199) * fix(windows): reject dynamic msvc runtime in packaging (herdrdev#4200) The v0.8.2 Windows archive shipped an herdr.exe that imported VCRUNTIME140.dll and the api-ms-win-crt-* Universal CRT, none of which the archive provides. Static CRT linkage was restored for x86_64-pc-windows-msvc in .cargo/config.toml, but nothing verified the packaged executable, so the dependency could silently regress. Parse the PE import and delay-import tables and reject herdr.exe when it depends on the dynamic Microsoft C/C++ runtime, including release and debug variants. Check the input while staging and re-check the staged executable before archiving so a direct archive cannot bypass the guard. refs herdrdev#3129 * fix: preserve unloaded sessions before replacement (herdrdev#4190) refs herdrdev#4125 * fix: preserve macos services across logout (herdrdev#4202) refs herdrdev#4100 * chore: approve vinayshah1998 as contributor * fix: keep remote surface updates incremental (herdrdev#4209) refs herdrdev#3769 refs herdrdev#3745 * fix: keep local usable when remote machines stall (herdrdev#4234) refs herdrdev#3903 * fix: let local agent clicks cancel remote handoffs (herdrdev#4236) refs herdrdev#3903 * fix: require exact session names before deletion (herdrdev#4233) * fix: require exact session names before deletion refs herdrdev#3819 * test: isolate session deletion regression tests refs herdrdev#3819 --------- Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * test: wait for app readiness before late session injection (herdrdev#4224) Root cause: The API socket is bound before App evaluates session restore. Waiting only for that socket lets the late-session test inject its file during startup, so the server may load it normally instead of exercising late-file recovery. The missing backup then fails an otherwise correct persistence assertion. Fix: Wait for a read-only workspace-list request to pass through App and assert that the workspace list is still empty before injecting the session file. Keep the existing autosave deadline and byte-for-byte backup assertion. Add no sleeps, retries, longer timeouts or production changes. Validation: The original assertion fails with unchanged master. With the barrier, five independent runs pass. Full native just ci passes 3624 Rust tests with six default skips, formatting, all-target Clippy, 112 maintenance tests, six architecture tests and 39 integration-asset tests. All seven docs contract tests pass. Local Windows cross-lint was not run because its SDK is absent. Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: offer forced removal for worktrees with submodules (herdrdev#4238) refs herdrdev#1797 * ci: promote stable releases from protected previews (herdrdev#4241) * fix: address release promotion review findings * fix: avoid workstation sdk requirement in preview checks * docs: publish preview documentation * release: synchronize metadata for v0.9.1 * fix: respect opencode tui.json registrations (herdrdev#4250) refs herdrdev#4240 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: cache saved machine connection metadata (herdrdev#4256) refs herdrdev#4252 * fix(windows): preserve VT input during mouse refresh (herdrdev#4257) refs herdrdev#4251 * fix(windows): restore terminal after setup errors (herdrdev#4261) refs herdrdev#4251 * fix(windows): recover VT input without changing readers (herdrdev#4269) refs herdrdev#4251 * fix: address review comments on #55 --------- Co-authored-by: Can Celik <ogulcancelik@gmail.com> Co-authored-by: akbash <akbash@herdr.dev> Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> Co-authored-by: Kataoka Katsuki <49934462+kataokatsuki@users.noreply.github.com> Co-authored-by: kataokatsuki <kataokatsuki@users.noreply.github.com> Co-authored-by: Cameron <cameron@pfiffer.org> Co-authored-by: caner-akca <94343893+caner-akca@users.noreply.github.com> Co-authored-by: Kakumanu Ashok Reddy <kakumanuashokreddyias2024@gmail.com> Co-authored-by: dengos <dengoswei@gmail.com> Co-authored-by: Eric Yue <jiacheng.yue@foxmail.com> Co-authored-by: Mark Jaquith <mark@jaquith.me> Co-authored-by: kangal-bot <285672167+kangal-bot@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: zuraffa-review[bot] <326983185+zuraffa-review[bot]@users.noreply.github.com>
Absorbs upstream through v0.9.1 release metadata. Notable fixes: stable release promotion from protected previews (herdrdev#4241), windows VT input recovery and pwsh default shell (herdrdev#4269, herdrdev#4297), cursor-based text input editing (herdrdev#3698), ctrl-hover highlighting and wrapped links (herdrdev#4074), whole-word selection during drag (herdrdev#3969), client location reconciliation after pane moves (herdrdev#4171, herdrdev#4159), saved machine screen restore after reconnect (herdrdev#4126), overflowing tab strips reveal the full last tab (herdrdev#4152), muted sidebar/tab label readability (herdrdev#4062), machine connection metadata caching (herdrdev#4256), unloaded session preservation (herdrdev#4190, herdrdev#4125), kitty CSI-u/CSI-tilde F-keys (herdrdev#2378, herdrdev#4067), pixel mouse integer cell pitch (herdrdev#4140), ssh bridge cleanup and backoff (herdrdev#4083), Letta Code detection (herdrdev#3107). Conflicts resolved per FORK-CHANGELOG.md: justfile kept upstream's test_release/test_windows_input additions plus the fork's test_fork_changelog_check; tabs.rs took upstream's max_tab_scroll rework and muted tab-label style, keeping the vertical tab strip intact.
* docs: publish release distribution for v0.9.0 * fix: reduce idle ssh cpu without dropping final output (herdrdev#3728) * fix: stop polling idle ssh uploads on unix * fix: preserve ssh output during idle bridge cancellation * test: exercise active ssh upload cancellation * docs: publish preview documentation * fix: show ssh errors during machine setup (herdrdev#3733) refs herdrdev#3731 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * chore: move marketplace worker to website repository * fix: collapse worktree groups with saved machines (herdrdev#3781) * fix: collapse worktree groups with saved machines refs herdrdev#3778 * fix: scope worktree collapse by machine refs herdrdev#3778 * fix: collapse machines without switching focus refs herdrdev#3778 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com> * fix: support preinstalled windows remote hosts (herdrdev#3661) * fix: support windows hosts in saved ssh machines refs herdrdev#3651 * fix: keep windows ssh bridge writes blocking refs herdrdev#3651 * fix: close saved windows ssh bootstrap input refs herdrdev#3651 * refactor: simplify remote bridge helpers refs herdrdev#3651 * refactor: isolate remote bridge platform behavior refs herdrdev#3651 * fix: close captured ssh input under windows consoles refs herdrdev#3651 * test: remove redundant remote command assertions refs herdrdev#3651 refs herdrdev#3701 * test: handle framed ssh commands in machine setup refs herdrdev#3651 --------- Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com> * fix: restore autofocus when creating worktrees (herdrdev#3787) * fix: restore autofocus when creating worktrees refs herdrdev#3766 * fix: let the client focus newly created worktrees refs herdrdev#3766 * feat: navigate and highlight workspaces across machines (herdrdev#3755) * fix: highlight workspace navigation with saved machines refs herdrdev#3754 * feat: navigate workspaces across connected machines refs herdrdev#3754 * feat: navigate workspaces across machines refs herdrdev#3754 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com> * fix: avoid full-screen copies for retained client updates (herdrdev#3837) refs herdrdev#3822 * fix: restore plugin focus events for client navigation (herdrdev#3850) refs herdrdev#3824 * fix: retain double-click selections and make tests root-safe (herdrdev#3854) refs herdrdev#3847 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix: project public agent focus to attached clients (herdrdev#3764) refs herdrdev#3760 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix: restore connected session navigator tree glyphs (herdrdev#3861) refs herdrdev#3843 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix(pi): support Windows session paths (herdrdev#3729) refs herdrdev#3726 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix: stop token selection at CJK punctuation (herdrdev#3708) refs herdrdev#3706 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix: keep spaces sidebar stable during resize (herdrdev#3862) refs herdrdev#3817 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix: accept session names after option terminator (herdrdev#3222) refs herdrdev#3220 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix(linux): identify Herdr desktop notifications (herdrdev#3639) refs herdrdev#3638 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix(windows): preserve legacy mouse reports over ssh (herdrdev#3742) * fix(windows): preserve legacy mouse reports over ssh refs herdrdev#3735 * fix(windows): preserve input after missing mouse release refs herdrdev#3735 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: use host background for pane selection highlights (herdrdev#3894) refs herdrdev#3798 * fix: preserve focused viewer geometry during activation (herdrdev#3746) * fix: preserve focused viewer geometry during activation refs herdrdev#3744 * fix: preserve geometry through activation sync refs herdrdev#3744 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix(input): accept WezTerm control key reports (herdrdev#3592) * fix(input): accept WezTerm control key reports refs herdrdev#3589 * fix(input): preserve WezTerm tab and escape reports refs herdrdev#3589 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix: accept machine add options before the SSH target (herdrdev#3897) refs herdrdev#3883 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix: bound mouse selection repaint cadence (herdrdev#3901) refs herdrdev#3895 * chore: upgrade libghostty and preserve terminal behavior (herdrdev#3906) * feat: route cli commands to saved ssh machines (herdrdev#3918) * feat: support conditional sidebar token hiding (herdrdev#3925) * fix: keep terminal snapshots consistent while scrolling (herdrdev#3928) refs herdrdev#3900 * fix: explain zig version requirement on build failure (herdrdev#3931) * fix: preserve plugin registry symlinks (herdrdev#3927) refs herdrdev#3922 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * ci: trigger nix updates after stable releases * chore: add one-time windows cross-check setup * test: make windows cross-check path assertions portable (herdrdev#3954) * fix: recognize claude unicode spinner during active turns (herdrdev#3953) refs herdrdev#3949 * fix: preserve local direct kitty graphics transport (herdrdev#3957) refs herdrdev#3785 * fix: detect cline launchers and idle states (herdrdev#3959) refs herdrdev#2396 * fix: flush Windows Codex paste burst before prompt submit (herdrdev#3961) Codex's Windows input reader does not surface bracketed paste. It buffers the prompt as a paste burst and rewrites a following Enter into a newline until the burst idles out, so the previous size-based delay only reduced the chance of losing the submit. Append a non-character key after the paste so Codex flushes the burst synchronously, giving every prompt a deterministic submit boundary. refs herdrdev#3187 * fix: lint all targets on windows (herdrdev#3963) Native Windows lint and check only clippy-checked the herdr binary, while macOS and Linux run clippy across all targets. Enable --all-targets on Windows and gate the Unix-only test helpers that this exposed so Windows check matches the Unix one. * fix(config): keep utf8 bom from breaking config reads and writes (herdrdev#3962) * fix(config): keep utf8 bom from breaking config reads and writes refs herdrdev#3678 * fix(config): only strip displaced boms when config is invalid refs herdrdev#3678 * fix(config): strip only boms the toml parser rejects refs herdrdev#3678 * fix(remote): show SSH authentication output (herdrdev#3609) * fix(remote): show SSH authentication output refs herdrdev#3606 * test(remote): stabilize SSH authentication output regression refs herdrdev#3606 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * ci: reuse compiler state across validation runs (herdrdev#3956) * ci: retain zig build caches across validation runs * ci: reduce debug information in validation builds * ci: build only the ghostty test target for scalar checks * ci: measure debug profiles and remove duplicate macos caching * ci: compare scalar build scopes on one runner * ci: keep the zig compiler path stable across runs * ci: run macos and windows lint alongside tests * ci: inspect remaining zig cache misses * ci: remove completed measurement probes * ci: compare windows linkers without changing release builds * ci: test linux incremental reuse and correct the linker probe * ci: measure windows incremental state reuse * test: verify incremental reuse after a source change * ci: finalize measured compiler cache optimizations * fix: preserve whole-word selection while dragging (herdrdev#3969) refs herdrdev#1836 * docs: enable nesting in throwaway repro setup * fix: opencode v2 lifecycle reporting (herdrdev#3757) * fix: support opencode v2 lifecycle reporting * fix: repair Japanese docs * fix: ignore payload-less OpenCode events * fix: harden opencode v2 integration install and reporting Follow-ups on top of the V2 lifecycle support: - create `cli.json` when OpenCode has no V1 TUI preferences (`tui.json` or `kv.json`) to migrate, instead of only registering into an existing file - settle stalled socket attempts with a plain connect timer, and resend the latest lifecycle state after a failed delivery so the pane cannot get stuck - resolve the OpenCode state directory from `XDG_STATE_HOME` - remove the managed `herdr-opencode` directory on uninstall - document failed executions reporting `blocked`, keep the integration test environment independent of an inherited `XDG_STATE_HOME`, and simplify `reconcileBlockers` to reassign its map --------- Co-authored-by: Jonathan Liebig <jonathan.liebig@gmail.com> * fix: suppress Windows dead-key fallback characters in remote panes (herdrdev#3972) refs herdrdev#3948 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix: preserve complete alternate-screen history reads (herdrdev#3979) * fix: ignore nested OMP session reports (herdrdev#3994) refs herdrdev#2593 * fix: finish windows ssh setup after bridge exit (herdrdev#3719) refs herdrdev#3651 * fix: keep windows endpoint writes progressing (herdrdev#3721) refs herdrdev#3651 * fix: batch queued endpoint input frames (herdrdev#4004) refs herdrdev#3833 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix: allow retrying partial worktree removal (herdrdev#3315) refs herdrdev#3314 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix: recognize codex composer sparkles (herdrdev#4015) refs herdrdev#3988 * fix: honor space row gaps across machines (herdrdev#3740) * fix: honor space row gaps across machines refs herdrdev#3738 * test: cover scrolling with machine space gaps refs herdrdev#3738 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix: restore alternate-screen pane width (herdrdev#4016) refs herdrdev#3329 * fix: update grok session after new (herdrdev#2683) * fix: update grok session after new refs herdrdev#2681 * fix: avoid powershell args shadowing refs herdrdev#2681 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix: deflake windows endpoint flush drain test (herdrdev#4021) The polling peer drains at production's 2ms Windows read cadence, so a 1 MiB frame took ~5.5s locally and exceeded the test's 10s flush deadline under CI load. Use a 256 KiB frame, still well above the 64 KiB batch limit, and a 30s deadline so the assertion no longer depends on CI scheduling. * fix(linux): avoid blocking proc reads for wsl agents (herdrdev#2179) Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: disconnect stalled terminal observers (herdrdev#4039) * fix: order ui accent before nested config tables (herdrdev#2698) * fix: order ui accent before nested config tables refs herdrdev#2697 * test: reject duplicate ui accent examples refs herdrdev#2697 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix: decouple pixel mouse from pane graphics (herdrdev#4045) refs herdrdev#3295 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: restrict claude session hooks to native sources (herdrdev#4046) refs herdrdev#4018 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix(input): preserve super-modified pane keys (herdrdev#4044) refs herdrdev#3710 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * test: relax windows docs snapshot timeout (herdrdev#4049) Windows CI runs these documentation contract fixtures under variable load. A degraded runner pushed the preview and versions snapshot integration tests past their 30s ceiling, while a healthy run finishes in seconds. Keep 30s elsewhere and give Windows a 120s ceiling. * fix: retain validated split mouse reports across idle gaps (herdrdev#4048) refs herdrdev#3911 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix(server): transfer handoff descriptors in batches (herdrdev#3411) Live handoff refused any session with more than 64 panes. The pane count was checked twice against MAX_FDS_PER_HANDOFF, and the transfer itself put every pane's pty master into one SCM_RIGHTS control message, so the guard was the only thing keeping the send inside the kernel's per-message limit. A session past the limit could only be updated by closing panes or by a normal restart, which ends every pane process. Send the descriptors in batches of 64 instead and drop both guards. The receiving side accumulates across recvmsg calls until the expected count arrives, bounds every SCM_RIGHTS payload it reads by the control bytes the kernel returned, rejects a batch that carries more descriptors than it asked for, and closes the descriptors it already holds on any failure. A session of 64 panes or fewer still produces one batch, so the bytes on the wire are unchanged and HANDOFF_VERSION stays at 1. refs herdrdev#3393 Co-authored-by: kataokatsuki <kataokatsuki@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * test: deflake windows metadata ttl expiry assertion (herdrdev#4050) The clear-only metadata test used a 1 ms ttl, so on loaded Windows runners set_agent_metadata could see the entry as expired, drop it, and recreate it with a None ttl before next_agent_metadata_expiry() ran. Expiry is forced explicitly later in the test, so use a long ttl to keep the no-extension assertion independent of wall-clock scheduling. * fix: detect kimi npm shim on windows (herdrdev#4053) refs herdrdev#3317 * fix(remote): resolve ssh host aliases from git bash on windows (herdrdev#4054) Windows OpenSSH resolves drive-letter Include paths, but Git for Windows' MSYS OpenSSH does not, so the managed remote SSH config silently ignored the user's ~/.ssh/config when herdr ran under Git Bash. Include the user config through ~/.ssh/config, which both implementations expand to the same file. refs herdrdev#3947 * feat: add Letta Code detection and restore (herdrdev#3107) refs herdrdev#3106 Co-authored-by: Cameron <cameron@pfiffer.org> * fix(windows): disable host mouse reporting on terminal restore (herdrdev#4055) Windows skipped the xterm mouse-reporting reset because clear_host_mouse_reporting was a no-op there. Standalone Git Bash (mintty) keeps SGR mouse reporting enabled after detach, so mouse motion leaks escape sequences into the shell. Emit the reset sequence on Windows too and include the X10 mode. refs herdrdev#3748 * fix: keep hermes enabled list valid yaml (herdrdev#4056) * fix: keep hermes enabled list valid yaml refs herdrdev#3839 * fix: preserve hermes inline list quoting and comments refs herdrdev#3839 * fix(ui): keep muted sidebar and tab labels readable (herdrdev#4062) refs herdrdev#2692 * fix(windows): honor default_shell in login shell mode (herdrdev#4060) * fix(windows): honor default_shell in login shell mode Login-mode panes used portable-pty's default-program builder, which resolves to %ComSpec% (cmd.exe) on Windows and ignores the SHELL env override, so [terminal].default_shell was silently ignored. Build the launch command from the configured shell instead and append the shell's own login flag for POSIX-style shells that support one. refs herdrdev#1445 * fix(windows): add csh and tcsh to login shell flags refs herdrdev#1445 * fix(windows): keep powershell cwd reporting in login mode (herdrdev#4065) Windows login-mode PowerShell panes are now launched directly, but the PowerShell prompt-based cwd integration was still gated to non-login mode, leaving those panes without repository-owned cwd reporting after Set-Location. Enable the existing integration for login-mode PowerShell and build the integration args on the shared direct-shell path. Follow-up to herdrdev#4060. * fix: keep an agent name through a process-exit observation (herdrdev#3574) A process-exit observation is not proof the agent is gone: the same observation can be wrong while the agent keeps running, and the name is the only handle its owner has on the pane. Detection uncertainty already preserves the name, so releasing it on the observation alone contradicts that contract and leaves a live agent unreachable by name with a rename as the only recovery. Free the name at the point the agent actually leaves the pane - a recorded exit with no agent detected any more - so a wrong observation costs nothing and a real exit still releases the name for reuse. refs herdrdev#3225 Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: auto-expire worktree action error banners (herdrdev#4063) * fix: auto-expire worktree action error banners refs herdrdev#1827 * fix: restart endpoint error timeout on repeated errors Route every transient client-side action error through a setter that installs a fresh deadline, so an identical repeated message cannot inherit an older, nearly-expired deadline. refs herdrdev#1827 * test: derive endpoint error expiry assertions from stored deadline refs herdrdev#1827 * test: deflake federated local input race (herdrdev#4066) refs herdrdev#3670 * fix: recognize kitty CSI-u codepoints for F1 through F12 (herdrdev#2378) Codepoints 57364-57375 (F1-F12) were missing from the kitty-protocol codepoint table, so terminals that send function keys as full CSI-u sequences (e.g. Ghostty, which enables the kitty keyboard protocol by default) had those keys silently dropped. Confirmed live against a running herdr session: injecting the raw F3/F4 codepoint sequences did nothing before this fix and correctly triggered previous_tab/next_tab after. refs herdrdev#1809 Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix(input): accept parameterized CSI-tilde F1-F4 keys (herdrdev#4067) Terminals such as foot send F1-F4 as parameterized CSI-tilde sequences (for example F3 as `\x1b[13;1:1~`). `parse_xterm_modified_special_sequence` mapped codes 15-24 but not 11-14, so these presses were dropped before keybindings saw them. Map 11-14 to F1-F4, matching the unmodified `\x1b[11~`..`\x1b[14~` aliases already accepted. refs herdrdev#1809 * fix: clean up failed terminal observer setup (herdrdev#4071) refs herdrdev#3612 * chore: add jjliebig as approved contributor and maintainer * feat: install windows remote host packages (herdrdev#3687) * feat: install windows remote host packages refs herdrdev#3651 * docs: clarify windows saved reconnect package behavior refs herdrdev#3651 * fix: include windows installer in nix sources refs herdrdev#3651 * fix: preserve paths in windows scp transfers refs herdrdev#3651 * refactor: isolate windows remote package setup refs herdrdev#3651 * feat: add ctrl-hover highlighting and fix wrapped links (herdrdev#4074) refs herdrdev#1282 * fix(linux): bound the foreground process-tree scan (herdrdev#3674) refs herdrdev#3621 Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: keep plugins working after client-only updates (herdrdev#4077) * ci: migrate remaining pinned actions to node24 (herdrdev#4023) * ci: migrate remaining pinned actions to node24 actions/cache@v4 and mlugg/setup-zig@v2.2.1 still target Node 20, which GitHub removes from runners on 2026-09-23. Bump actions/cache to v6.1.0 and replace mlugg/setup-zig with vercel-labs/setup-zig@v1.0.2. vercel-labs/setup-zig takes only `version`, so the use-cache/cache-size-limit tuning and Zig global-cache reuse are dropped. See the PR for alternatives. * ci: restore zig caching for vercel setup-zig vercel-labs/setup-zig has no cache controls, so redirect the Zig global cache into the workspace .zig-cache and run the Zig build cache step on Linux too. Drop this commit if we switch to a setup action that owns Zig caching, e.g. step-security/setup-zig or xyzzylabs/setup-zig. * fix: clarify agent integration settings description * fix: scope agent views to the selected machine (herdrdev#3784) * fix: scope agent views to the selected machine refs herdrdev#3732 * fix: preserve stable agent view ordering refs herdrdev#3732 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix(windows): restore mouse reporting when reattaching (herdrdev#4080) * fix(client): re-assert host mouse modes after a terminal reconnect (herdrdev#4079) Co-authored-by: dengos <dengoswei@gmail.com> * test(windows): deflake media player invalid media assertion (herdrdev#4082) * test(windows): deflake media player invalid media assertion The Windows sound test required MediaPlayer's MediaFailed event for invalid media. Some runners never raise it, so the script exits through its playback timer and the test saw "sound playback timed out" instead, panicking on the MediaFailed assertion. Accept either terminal error and keep the timer short under test via HERDR_SOUND_TIMEOUT_SECONDS so a missed MediaFailed no longer waits out the production 15 second bound. * test(windows): keep media player timeout override test-only Generate the short-timer player script only in tests instead of reading a process environment override. This keeps the production script's fixed 15 second bound unchanged, and the script-content test now proves the test variant rewrites the timer. * fix: hide only kitty image placements overlapping overlays (herdrdev#4081) * fix: clean up idle ssh bridges and back off flapping connections (herdrdev#4083) * fix: clean up idle ssh bridges and back off flapping connections * chore: keep ssh liveness smoke tooling local * fix: preserve agent panel scroll when switching machines (herdrdev#4101) refs herdrdev#3937 Root cause: Activating another endpoint applies a snapshot with a different endpoint-qualified graphics scope. This triggers reset_endpoint_projection, which clears agent_scroll together with endpoint-local state even though the agent list aggregates all machines. The selected agent receives focus, but the list jumps back to the top. Fix: Save the client-owned agent scroll offset and restore it only when activation changes endpoints. Keep same-endpoint reboot resets, workspace/tab scroll resets, input cleanup and existing list bounds clamping unchanged. This adds constant-time work on endpoint activation, with no protocol, persisted-state or pane-scaled rendering changes. Validation: The new regression fails on the original implementation with scroll 0 instead of 6. Tests cover repeated bidirectional agent clicks, stable visible rows, shrinking lists and same-machine reboots. All 242 client shell tests pass. Real SSH A/B testing against the same two disposable 0.9.0 servers reproduces the reset with both the stable and current-master clients. The patched client preserves the visible rows through six cross-machine switches and two same-machine control clicks. Native just ci passes: 3535 Rust tests, six default skips, plus lint, maintenance, architecture and integration-asset checks. All seven docs contract tests pass. Windows cross-lint was not run because its SDK is not installed; native macOS and Windows UI behavior was not tested. * fix: remove stale maintainer username * fix: detect codex activity with static titles and queued inputs (herdrdev#4099) * fix: detect codex activity with static titles and queued inputs refs herdrdev#4092 Codex 0.154.0 can omit the activity bullet when tui.animations is false and replace the literal Working label with a task-specific label. Its terminal title can also remain static during an active turn, so the OSC spinner rule is not sufficient to identify work. The screen fallback required a bullet followed by Working in the last three non-empty lines. It therefore missed both the animation-disabled status line and dynamic labels. Queued follow-ups add a heading, input text, and an edit hint below the activity line, moving that line outside the three-line region. The lower-priority non-empty OSC title rule then reported idle while Codex still showed an active timer and interrupt control. Recognize the elapsed-time and esc-to-interrupt controls in the detection snapshot before the current composer. Allow an optional bullet, a dynamic activity label, and queued follow-ups below that line. Require that no later response, completion, or interruption marker supersedes the live activity. This excludes composer text and stale output without letting an earlier interruption suppress a subsequent active turn. Keep OSC state precedence and transcript-viewer skip behavior unchanged. Update the bundled and distributed manifests together to 2026.09.14.1. Add regression coverage for optional bullets, dynamic labels, queued inputs, resumed work after interruption, and stale or quoted controls. Avoid discarding Regex search caches on every detection poll. The loader previously cloned the entire compiled rule vector, and each Regex clone created a fresh search cache pool despite sharing compiled read-only state. Share the immutable rules through Arc instead. Reload publishes a new array while in-flight readers retain a valid old generation, without holding the global cache lock during matching. Add a cheap contains gate for the required interrupt text before running the multiline expression. Add a deterministic regression for compiled-rule sharing, reload replacement, retained old readers, and concurrent detection. Measure the baseline and optimized detector kernels in three alternating rounds on CPU 24 with NUMA node 0 and CPU 25 with NUMA node 1. Real queued detection falls from about 116 to 22 microseconds, and two evaluations per pane over 15 panes fall from about 3.45 to 0.65 milliseconds on both sockets, about 81 percent less time. No benchmark match results change. The cache improvement requires the updated binary, not just a manifest reload. Validate on the official Herdr 0.9.0 release with Codex 0.154.0 by toggling the old and new manifests during the same active queued task. Confirm working for active turns and idle after completion or interruption. Pass 86 captured-screen and semantic checks through the optimized source binary, 69 manifest/cache tests, CPU-pinned render scaling, and the full native CI suite: 3535 Rust tests passed, with six default skips. Run CI serially with inherited Herdr session context removed; no tests were excluded or expectations relaxed to make CI pass. * fix: detect codex pending follow-ups as working refs herdrdev#4092 * fix: handle wrapped codex follow-up hints refs herdrdev#4092 --------- Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com> * fix: detect pi working border (herdrdev#4113) refs herdrdev#3629 * ci: restore zig local build cache reuse (herdrdev#4118) * fix: default pane splits to the calling pane (herdrdev#4123) * fix: restore saved machine screens after reconnect (herdrdev#4126) refs herdrdev#3842 * fix: scope window titles to each client view (herdrdev#4130) refs herdrdev#4091 * fix(windows): avoid lossy native Win32 input mode (herdrdev#4133) refs herdrdev#3932 refs herdrdev#3702 refs herdrdev#3910 * fix: keep modified enter compatible with legacy panes (herdrdev#4110) * fix: keep modified enter compatible with legacy panes refs herdrdev#4103 * fix: synchronize modified key negotiation state refs herdrdev#4103 * test: cover windows legacy modified enter refs herdrdev#4103 --------- Co-authored-by: Jonathan Liebig <jonathan.liebig@gmail.com> * fix: avoid resending terminal cells for metadata updates (herdrdev#4137) * feat: add cursor-based editing to text inputs (herdrdev#3698) * feat: add cursor-based editing to text inputs refs herdrdev#1803 * fix: preserve dialog actions with associated text refs herdrdev#1803 * refactor: simplify text editor outcomes and tests refs herdrdev#1803 --------- Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: protect integration configs from failed writes (herdrdev#3973) * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 * fix: atomically write integration configs refs herdrdev#3970 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: map pixel mouse by integer cell pitch (herdrdev#4140) refs herdrdev#3295 * fix: reject stale pane surfaces after reconnect (herdrdev#4141) * test: deflake recent CI failures (herdrdev#4139) * fix(windows): batch input trace diagnostics (herdrdev#4146) refs herdrdev#3932 * fix(windows): prefer VT input for SSH clients (herdrdev#4148) refs herdrdev#3932 * fix: reveal the full last tab in overflowing tab strips (herdrdev#4152) refs herdrdev#4151 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix: reveal newly focused workspaces in the machines sidebar * fix: propagate focused pane moves to attached clients (herdrdev#4159) refs herdrdev#4153 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * test: wait for runtime readiness in integration tests (herdrdev#4168) Root cause: The handoff test starts an agent immediately after workspace creation, before the new shell is necessarily ready. The reconnect test assumes a fixed sidebar row and searches raw ANSI output for text that can arrive as separate incremental cell updates. Fix: Wait for a shell builtin to write a readiness marker before sending the single raw agent.start request. Exercise the gap with a delayed shell. Locate the recovered workspace in the rendered sidebar and check the reconstructed screen for selection and input, including overlay borders. Do not extend existing timeouts or add retries that hide failures. Validation: All 25 affected group and helper tests pass. Ten repeated rounds of the two runtime tests and the row helper pass, for 30 test executions without retries. Standalone native just ci passes 3582 Rust tests with six default skips, formatting, all-target Clippy, 106 maintenance tests, six architecture tests and 39 integration-asset tests. Windows cross-lint was not run because its SDK is not installed. Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: reconcile client locations after no-focus pane moves (herdrdev#4171) refs herdrdev#4153 Root cause: A no-focus pane move can remove the source tab without changing the server's numeric workspace and tab coordinates. PaneMove is not classified as a topology change, so a client viewing that tab retains its deleted ID. Its target lookup falls back to the server default and can follow a later, unrelated focus change instead of staying in the source workspace. Fix: Include PaneMove in the existing client-location reconciliation path. Extend the existing focus-guard test with a client on the removed tab and verify that a later server-default change cannot move its view. Preserve the other client's view and existing error, no-op and zoom assertions. Validation: The minimized regression fails five times on PR herdrdev#4159's unchanged head and passes five times with the one-line fix. All 19 pane-move tests, native lint, maintenance, architecture and integration-asset checks pass. Full native just ci on the publication branch, including the unchanged prerequisites from herdrdev#4159 and herdrdev#4168, passes 3585 Rust tests with six default skips plus lint, 106 maintenance, six architecture and 39 integration-asset tests. All seven docs contract tests pass. Local Windows cross-lint was not run because its SDK is unavailable. No geometry policy, protocol or periodic rendering behavior is changed. * fix: preserve live selections during pane output (herdrdev#4193) refs herdrdev#3841 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> * fix(windows): preserve sgr mouse encoding after native capture (herdrdev#4195) refs herdrdev#4155 * fix(windows): normalize pane launch cwd casing (herdrdev#4199) * fix(windows): reject dynamic msvc runtime in packaging (herdrdev#4200) The v0.8.2 Windows archive shipped an herdr.exe that imported VCRUNTIME140.dll and the api-ms-win-crt-* Universal CRT, none of which the archive provides. Static CRT linkage was restored for x86_64-pc-windows-msvc in .cargo/config.toml, but nothing verified the packaged executable, so the dependency could silently regress. Parse the PE import and delay-import tables and reject herdr.exe when it depends on the dynamic Microsoft C/C++ runtime, including release and debug variants. Check the input while staging and re-check the staged executable before archiving so a direct archive cannot bypass the guard. refs herdrdev#3129 * fix: preserve unloaded sessions before replacement (herdrdev#4190) refs herdrdev#4125 * fix: preserve macos services across logout (herdrdev#4202) refs herdrdev#4100 * chore: approve vinayshah1998 as contributor * fix: keep remote surface updates incremental (herdrdev#4209) refs herdrdev#3769 refs herdrdev#3745 * fix: keep local usable when remote machines stall (herdrdev#4234) refs herdrdev#3903 * fix: let local agent clicks cancel remote handoffs (herdrdev#4236) refs herdrdev#3903 * fix: require exact session names before deletion (herdrdev#4233) * fix: require exact session names before deletion refs herdrdev#3819 * test: isolate session deletion regression tests refs herdrdev#3819 --------- Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * test: wait for app readiness before late session injection (herdrdev#4224) Root cause: The API socket is bound before App evaluates session restore. Waiting only for that socket lets the late-session test inject its file during startup, so the server may load it normally instead of exercising late-file recovery. The missing backup then fails an otherwise correct persistence assertion. Fix: Wait for a read-only workspace-list request to pass through App and assert that the workspace list is still empty before injecting the session file. Keep the existing autosave deadline and byte-for-byte backup assertion. Add no sleeps, retries, longer timeouts or production changes. Validation: The original assertion fails with unchanged master. With the barrier, five independent runs pass. Full native just ci passes 3624 Rust tests with six default skips, formatting, all-target Clippy, 112 maintenance tests, six architecture tests and 39 integration-asset tests. All seven docs contract tests pass. Local Windows cross-lint was not run because its SDK is absent. Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> * fix: offer forced removal for worktrees with submodules (herdrdev#4238) refs herdrdev#1797 * ci: promote stable releases from protected previews (herdrdev#4241) * fix: address release promotion review findings * fix: avoid workstation sdk requirement in preview checks * docs: prepare 0.9.1 release documentation * release: v0.9.1 * ci: fetch upstream release tags for documentation checks * test: remove obsolete hidden-client help assertion --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Can Celik <ogulcancelik@gmail.com> Co-authored-by: kangal-bot <285672167+kangal-bot@users.noreply.github.com> Co-authored-by: akbash <akbash@herdr.dev> Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com> Co-authored-by: Mark Jaquith <mark.jaquith@gusto.com> Co-authored-by: Rhett CfZhuang <dark.momo985@gmail.com> Co-authored-by: Kataoka Katsuki <49934462+kataokatsuki@users.noreply.github.com> Co-authored-by: kataokatsuki <kataokatsuki@users.noreply.github.com> Co-authored-by: Cameron <cameron@pfiffer.org> Co-authored-by: caner-akca <94343893+caner-akca@users.noreply.github.com> Co-authored-by: Kakumanu Ashok Reddy <kakumanuashokreddyias2024@gmail.com> Co-authored-by: dengos <dengoswei@gmail.com> Co-authored-by: Eric Yue <jiacheng.yue@foxmail.com> Co-authored-by: Mark Jaquith <mark@jaquith.me>
|
Implementation and testing were performed with Letta Code. We tested registry draft We could still reproduce both Herdr-side cases discussed earlier:
Our local Herdr adjustments made both cases pass. Default → new A → new B → resume A The two fixes and regression coverage are isolated in |
refs herdrdev#3106 Co-authored-by: Cameron <cameron@pfiffer.org>
Summary
herdr integration install|uninstall letta, config, and release docsBuilds on the initial integration work from @just-cameron in https://github.com/just-cameron/herdr/tree/letta-code-integration.
Endpoint compatibility note
Letta is deliberately not added to the frozen generation-1 client endpoint
IntegrationTargetenum. Adding a variant there changes theintegration.installmethod shape shipped in stable 0.9.0 (the endpoint contract added in #3509), so it would break the published v1 contract.Instead Letta is an experimental, CLI-only target:
herdr integration install letta/herdr integration uninstall lettawork through a dedicated local path, andherdr integration statusreports it asletta (experimental). It is intentionally absent from the JSON API schema and the TUI integration list.The agent registry (
architecture/agent-registry) should be merged before we finish the full v1 fixture, so a new target can be registered and negotiated without touching the frozen enum.Validation
cargo fmt --checkcargo clippy --all-targets --locked -- -D warningscargo nextest run --locked(2975 passed), plus maintenance, integration-asset, and docs-contract checksintegration install/status/uninstall, and session hook reportingRefs #3106