Skip to content

fix: preserve claude settings key order - #2089

Merged
ogulcancelik merged 3 commits into
masterfrom
akbash/2066-preserve-claude-settings
Aug 2, 2026
Merged

fix: preserve claude settings key order#2089
ogulcancelik merged 3 commits into
masterfrom
akbash/2066-preserve-claude-settings

Conversation

@akbash-bot

@akbash-bot akbash-bot commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • update Claude settings through a strict, lossless CST instead of reserializing the whole file
  • preserve key order, whitespace, compact layouts, line endings, scalar spelling, and trailing suffixes outside Herdr-owned hook edits
  • keep install and uninstall byte-idempotent while verifying the edited file matches the existing semantic migration behavior

Checks

  • just check

refs #2066

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Claude hook installation and removal now use dedicated CST-based helpers. The implementation validates settings, preserves formatting and unchanged bytes, updates managed hooks selectively, and routes target operations through the new helpers.

Changes

Claude settings migration

Layer / File(s) Summary
CST rewrite and validation
Cargo.toml, src/integration/mod.rs, src/integration/claude_settings.rs
Adds jsonc-parser support, strict JSON validation, duplicate-key detection, and formatting-preserving CST edits.
Hook transformation and integration
src/integration/claude_settings.rs, src/integration/targets.rs
Adds separate install and uninstall operations. Claude target operations use these helpers and write settings only when content changes.
Hook transformation validation
src/integration/claude_settings.rs
Tests formatting preservation, compact and multiline containers, idempotence, selective removal, uninstallation, duplicate keys, and invalid input.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant targets
  participant claude_settings
  participant settings_content
  targets->>claude_settings: call install or uninstall
  claude_settings->>settings_content: parse and edit settings through CST
  claude_settings-->>targets: return original or updated content
  targets->>settings_content: write only when content changed
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: preserving key order in Claude settings.
Description check ✅ Passed The description accurately explains the lossless CST changes and preservation behavior for Claude settings.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch akbash/2066-preserve-claude-settings

Comment @coderabbitai help to get the list of available commands.

@kangal-bot kangal-bot added the ai-review Trigger automated AI reviews for pull requests admitted by the PR gate label Jul 30, 2026
@greptile-apps

greptile-apps Bot commented Jul 30, 2026

Copy link
Copy Markdown

Greptile Summary

This PR replaces whole-file Claude settings serialization with targeted CST-based edits.

  • Preserves key order, formatting, scalar spelling, line endings, and trailing content outside Herdr-owned hook changes.
  • Keeps install and uninstall byte-idempotent when no semantic update is required.
  • Adds jsonc-parser for strict CST parsing and routes Claude integration updates through the new editor.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
src/integration/claude_settings.rs Introduces strict CST-based Claude hook migration with semantic verification and formatting-preservation tests.
src/integration/targets.rs Routes Claude installation and removal through the lossless settings editor and avoids unchanged writes.
Cargo.toml Adds jsonc-parser with only the CST and serde_json features required by the new editor.
Cargo.lock Locks jsonc-parser 0.33.1 and its existing serde_json dependency.
src/integration/mod.rs Registers the new Claude settings module.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Read Claude settings.json] --> B[Parse semantic JSON]
    B --> C[Compute desired hook migration]
    C --> D{Semantic change needed?}
    D -- No --> E[Return original bytes]
    D -- Yes --> F[Parse strict CST]
    F --> G[Edit Herdr-owned hook nodes]
    G --> H[Verify semantic result]
    H --> I[Write only when bytes changed]
Loading

Reviews (7): Last reviewed commit: "Merge branch 'master' into akbash/2066-p..." | Re-trigger Greptile

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/integration/claude_settings.rs (1)

189-261: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add unit tests for the structural-validation error paths.

ensure_hooks_object and ensure_command_hook have distinct error branches (root not an object, hooks not an object, hook entries not an array) that aren't exercised by any test — the current tests only cover top-level JSON parse failure and success paths. A #[cfg(test)] mod tests block co-located here (testing update_claude_settings directly rather than only via install_claude) would catch regressions in these branches cheaply.

src/integration/targets.rs (1)

126-134: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Consider an atomic write for settings.json.

fs::write(&settings_path, updated_settings)? overwrites the file directly; an interruption mid-write (crash, kill) can leave settings.json truncated or corrupted, requiring the user to manually repair Claude's config. Writing to a temp file in the same directory and renaming over settings_path would make this update atomic.

♻️ Suggested atomic-write pattern
-    fs::write(&settings_path, updated_settings)?;
+    let tmp_path = settings_path.with_extension("json.tmp");
+    fs::write(&tmp_path, updated_settings)?;
+    fs::rename(&tmp_path, &settings_path)?;

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: dab25f02-86f1-42ed-a509-238d2aecbb56

📥 Commits

Reviewing files that changed from the base of the PR and between 9135ffe and e1b14c5.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • Cargo.toml
  • src/integration/claude_settings.rs
  • src/integration/mod.rs
  • src/integration/targets.rs
  • src/integration/tests.rs

Comment thread Cargo.toml Outdated
@akbash-bot
akbash-bot force-pushed the akbash/2066-preserve-claude-settings branch from 02ca4a6 to 5b1ab96 Compare July 30, 2026 16:23
@ogulcancelik
ogulcancelik force-pushed the akbash/2066-preserve-claude-settings branch from 5b1ab96 to e5481af Compare July 31, 2026 15:52

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6cc76234-efd3-486f-b92b-58005a0a5eff

📥 Commits

Reviewing files that changed from the base of the PR and between 5b1ab96 and e5481af.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • Cargo.toml
  • src/integration/claude_settings.rs
  • src/integration/mod.rs
  • src/integration/targets.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/integration/mod.rs

Comment thread src/integration/claude_settings.rs Outdated
@ogulcancelik
ogulcancelik force-pushed the akbash/2066-preserve-claude-settings branch from e5481af to f26cc4a Compare July 31, 2026 16:02

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
src/integration/claude_settings.rs (4)

280-293: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Rename the return value to describe what it reports.

remove_event_commands returns canonical_preserved, not a removal flag. The near-identical remove_value_event_commands at line 144 returns removed. The mismatched meanings of two same-shaped functions invite misuse in future edits. Rename this function or add a doc comment that states the return meaning.

♻️ Proposed doc comment
+/// Removes Herdr-owned commands for `event` from the CST.
+///
+/// Returns `true` when the canonical `SessionStart` entry was found and
+/// preserved in place, so the caller must not append it again.
 fn remove_event_commands(
     hooks: &CstObject,
     event: &str,
     commands: &[String],
     installing: bool,
     canonical: &Value,
 ) -> io::Result<bool> {

515-520: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Derive the compact canonical JSON from one source.

The canonical hook entry is now defined three times: canonical_hook_value at line 346, canonical_hook_input at line 357, and this hand-written string. A change to timeout, the matcher, or the command action must be applied to all three. If one drifts, verify_updated turns the mismatch into a runtime "failed to safely update claude settings" error instead of a compile error.

Build the compact string from canonical_hook_value so the values have a single owner.

♻️ Proposed consolidation
 fn canonical_hook_json(hook_path: &Path) -> io::Result<String> {
-    let command = serde_json::to_string(&hook_command(hook_path, Some("session")))?;
-    Ok(format!(
-        "{{\"matcher\":\"*\",\"hooks\":[{{\"type\":\"command\",\"command\":{command},\"timeout\":10}}]}}"
-    ))
+    // `canonical_hook_value` is the single owner of the canonical entry, so the
+    // compact form cannot drift from the semantic form used by `verify_updated`.
+    Ok(serde_json::to_string(&canonical_hook_value(hook_path))?)
 }

serde_json::to_string emits no insignificant whitespace, so the output stays compact. Because preserve_order is not enabled, the emitted key order becomes alphabetical (hooks, matcher), which changes the written bytes but not the semantics. Update the expected strings in install_keeps_compact_containers_compact accordingly, or keep the literal and add a test that asserts canonical_hook_json and canonical_hook_value parse equal.

Based on learnings, serde_json's preserve_order feature is intentionally not enabled in this repository, so Value comparison in verify_updated stays order-insensitive.

Source: Learnings


797-803: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Correct the test name to match the assertion.

The name says the content is kept unchanged. The body asserts install returns Err. Rename the test so a future failure report describes the real contract.

♻️ Proposed rename
-    fn install_keeps_structurally_invalid_content_unchanged() {
+    fn install_rejects_structurally_invalid_content() {

750-781: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for the uninstall no-op and event-key removal paths.

The current uninstall test covers only the partial-removal case, where a foreign command keeps the entry alive. Two uninstall branches stay untested:

  • Line 111: uninstall returns the original content when no Herdr command is present. This is the byte-idempotence guarantee stated in the PR objectives.
  • Line 177: hooks.remove(event) in the value path, and line 332 event_property.remove() in the CST path, run when the last entry for an event is removed. These two paths must agree, otherwise verify_updated fails.
💚 Proposed tests
#[test]
fn uninstall_is_a_byte_exact_noop_without_herdr_hooks() {
    let (settings_path, hook_path) = paths();
    let input = "{\"hooks\":{\"SessionStart\":[{\"matcher\":\"keep\",\"hooks\":[{\"type\":\"command\",\"command\":\"echo keep\"}]}]}}\r\n";

    assert_eq!(uninstall(input, settings_path, hook_path).unwrap(), input);
}

#[test]
fn uninstall_removes_the_event_key_when_the_last_entry_is_removed() {
    let (settings_path, hook_path) = paths();
    let canonical = canonical_hook_json(hook_path).unwrap();
    let input = format!("{{\"before\":1,\"hooks\":{{\"SessionStart\":[{canonical}]}},\"after\":2}}");

    let updated = uninstall(&input, settings_path, hook_path).unwrap();

    let parsed: Value = serde_json::from_str(&updated).unwrap();
    assert!(parsed["hooks"].get("SessionStart").is_none());
    assert_eq!(parsed["before"], 1);
    assert_eq!(parsed["after"], 2);
}

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d85ccfae-7451-444e-af00-5574419154b3

📥 Commits

Reviewing files that changed from the base of the PR and between e5481af and f26cc4a.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • Cargo.toml
  • src/integration/claude_settings.rs
  • src/integration/mod.rs
  • src/integration/targets.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/integration/mod.rs
  • src/integration/targets.rs
  • Cargo.toml

@ogulcancelik
ogulcancelik merged commit d742e51 into master Aug 2, 2026
9 checks passed
abhijit-s pushed a commit to abhijit-s/herdr that referenced this pull request Aug 3, 2026
Range 9a4ce5e..10eb0bc (8 commits): host color-scheme propagation to
pane apps (herdrdev#2214), preserve hover during extended-button drags, older-git
snapshot-check support, publish only released docs, non-blocking foreground
cwd checks (herdrdev#2213), non-UTF-8 CLI arg reporting (herdrdev#2207), host cell-size
query when ioctl reports no pixels (herdrdev#2160), preserve claude settings
formatting (herdrdev#2089).

Resolutions: Cargo.toml/Cargo.lock both-add reconciled to keep fork's jiff
alongside upstream's jsonc-parser. justfile install-local recipe preserved
while adopting upstream justfile changes. Fork status strip, StatusConfig,
and herdrdev#1876 non-US shifted-keybinding revert (3c15069) all preserved; input
and terminal_theme fixes adopted additively.
brchue-ux added a commit to brchue-ux/herdr that referenced this pull request Aug 5, 2026
#53)

* fix(windows): restore system notifications and sound playback (herdrdev#2019)

* test(windows): remove flaky sound timing assertion

refs herdrdev#1330

* fix: preserve windows path variables during install

refs herdrdev#1947

* fix(windows): preserve parent agent ownership

refs herdrdev#1514

* docs: update preview manifest

* fix: scope agent skill installation

refs herdrdev#2022

* ci: allow repository organization migration

* chore: update repository links after organization transfer

* Update rose pine surface_dim colour to "Overlay" (herdrdev#2002)

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* chore: finish repository organization migration

* fix: preserve kitty associated text (herdrdev#2051)

refs herdrdev#2020

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>

* fix: add opt-in child-group process detection (herdrdev#2052)

* fix: add opt-in child-group process detection

refs herdrdev#1982

* fix: preserve lifecycle probes without foreground groups

refs herdrdev#1982

* fix: launch argument-free agents on windows (herdrdev#2075)

refs herdrdev#2072

* ci: consolidate ai review trigger label

* fix: resume agents after headless restore (herdrdev#2088)

refs herdrdev#2064

* fix(omp): support Windows session paths (herdrdev#2092)

* fix: preserve windows sessions after ssh logout (herdrdev#2098)

* fix: preserve windows sessions after ssh logout

refs herdrdev#2008

* chore: document windows wmi safety

refs herdrdev#2008

* fix(client): restore terminal on sighup and sigterm

Enable termination-signal handling so SIGHUP and SIGTERM follow the graceful
quit path and restore terminal state. Log handler registration failures and
add PTY coverage for direct SIGHUP and server EOF restoration

Co-authored-by: Matt Coles <macols@amazon.com>

* fix(sidebar): keep worktree groups packed

* fix: read alternate-screen agent history

* chore: update agentmd for protocol changes

* feat: support bottom tab bar placement (herdrdev#2118)

* feat: support bottom tab bar placement

* fix: preserve mouse cleanup under bottom mode bar

refs herdrdev#2117

* chore: remove experiments from settings tui

* fix(input): preserve native key lifecycle across routing (herdrdev#2142)

refs herdrdev#2077

Co-authored-by: Jonathan Liebig <jonathan.liebig@gmail.com>

* fix(windows): preserve semantic escape key taps

* fix: report a clear cli error when no herdr server is running (herdrdev#1963)

* fix: report a clear cli error when no herdr server is running

socket cli commands surfaced a raw io::Error debug string
(`Error: Os { code: 2, ... }`) when nothing was listening on the
api socket, which read like a bad --cwd path. map dead-socket
connect failures to a `server_not_running` json error carrying the
resolved socket path, printed once at the edge that surfaces the
error; recovering callers (plugin offline registry fallback, agent
start polling) recognize the marker and keep their existing
behavior.

refs herdrdev#1941

* fix: map dead-socket errors on the unchecked cli request path

refs herdrdev#1941

* fix: make server-not-running guidance session-aware

refs herdrdev#1941

* fix: expand copy-mode word-end window past a final wide glyph (herdrdev#2145)

point_is_final_atom compared an atom's terminating column against a
word-motion target's starting column. The two are equal for narrow
cells but never for wide ones, so the read window stopped expanding
and copy-mode `e` halted at the soft-wrap boundary on CJK text.

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* feat(ui): make pane scrollbars optional (herdrdev#2166)

refs herdrdev#2167

* fix(ci): skip pr gate in forks

* feat: add antigravity-cli integration (herdrdev#2087)

* feat: add antigravity_cli integration harness

Register the `antigravity_cli` target, resolve its configuration
directory to `~/.gemini/antigravity-cli/`, wire target actions,
and add lifecycle hook scripts for Unix and Windows.

* feat: support session resume for antigravity-cli

* fix: correct antigravity-cli hook config path, shape, and agent label

Antigravity CLI reads global customizations from ~/.gemini/config, keys
hooks.json by hook name, and only accepts the matcher/hooks wrapper for
the tool events. The previous install wrote event arrays at the top level
of ~/.gemini/antigravity-cli/hooks.json, which agy never reads and would
reject anyway, so no Herdr hook ever ran.

Session reports were dropped for a third reason: the hooks reported the
agent as antigravity-cli, but the server normalizes that to the canonical
label agy before matching, so is_official_agent_source never matched and
agy --conversation resume was unreachable.

- Resolve the config dir to ~/.gemini/config
- Nest Herdr entries under a Herdr-owned "herdr" block that install
  rewrites and uninstall removes, leaving other named hooks untouched
- Emit grouped entries for PreToolUse/PostToolUse and flat handler lists
  for PreInvocation/PostInvocation/Stop
- Report the canonical agy label from both hook assets and match it in
  agent_resume
- Compile-gate the hook asset constants and stop shadowing $args in the
  PowerShell hook
- Document the real directory, that it must already exist, and the
  named-block behavior

refs herdrdev#1011
refs herdrdev#1571

* fix: make antigravity-cli integration session-only

antigravity cli cannot express lifecycle safely: there is no blocked
event, postinvocation is skipped on interruption, and stop fires at the
end of a turn rather than on process exit, which left stale state and
released authority at the wrong time.

report only the conversation on preinvocation and let screen detection
own agent state. resume via `agy --conversation <id>` is unchanged.

* fix: update antigravity session after conversation switch

---------

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix(input): decode 0x1f as Ctrl+_ not Ctrl+- per ASCII standard (herdrdev#2165)

* fix(input): decode 0x1f as Ctrl+_ not Ctrl+- per ASCII standard

refs herdrdev#2164

* fix(input): update control-byte matrix test for 0x1f -> Ctrl+_

* fix(socket_paths): remove dead if-branch in derive_client_socket_from_api_socket (herdrdev#2157)

* fix(windows): detect agents across git bash exec boundaries (herdrdev#2170)

refs herdrdev#2107

* fix: route vscode remote copies through osc52 (herdrdev#2173)

refs herdrdev#2015

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>

* fix(detect): recognize opencode2 as opencode

refs herdrdev#2169

* fix: stop advertising worktree json flag (herdrdev#2174)

refs herdrdev#2171

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>

* fix: preserve claude settings formatting (herdrdev#2089)

refs herdrdev#2066

Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com>

* fix(client): query host cell size when the ioctl reports no pixels (herdrdev#2160)

* fix(cli): report non-UTF-8 arguments instead of panicking (herdrdev#2207)

* fix(cli): report non-UTF-8 arguments instead of panicking

* fix(cli): avoid echoing malformed arguments

---------

Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com>

* fix: avoid blocking on foreground cwd checks (herdrdev#2213)

refs herdrdev#2206

* fix(docs): publish only released documentation

* fix(docs): support older git in snapshot checks

* fix(input): preserve hover during extended-button drags

* fix: propagate host color scheme to pane apps (herdrdev#2214)

refs herdrdev#714

* fix(pi): restrict state reporting to tui sessions (herdrdev#2159)

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix: page keys scroll pane scrollback at zsh and REPL prompts (herdrdev#2191)

* fix: page keys scroll pane scrollback at zsh and REPL prompts

PageUp/PageDown were forwarded to the pane whenever DECCKM (application
cursor) was on, assuming only primary-screen pagers enable it, but zsh's
line editor also enables DECCKM, as do REPLs such as python3. The result
was PageUp scrolling shell history instead of Herdr scrollback.

Bracketed paste discriminates the two: it means the app accepts typed or
pasted text at a prompt, so line editors enable it and pagers do not.

* test: update page key state fixture

---------

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* feat(website): rebuild marketing pages on new brand chassis

* docs: finalize 0.8.0 release documentation

* release: v0.8.0

* docs: update website manifest for v0.8.0

* docs: refine cpu optimization blog post

* fix(ui): keep collapsed workspace status visible (herdrdev#2239)

refs herdrdev#2216

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* docs: publish preview documentation

* feat(plugins): index marketplace manifests

* fix(docs): allow corrections to published versions

refs herdrdev#916

* fix(input): preserve shift-tab in pane automation (herdrdev#2259)

refs herdrdev#1561

* fix(ui): preserve sidebar scroll across clients (herdrdev#2280)

refs herdrdev#2255

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>

* fix(website): copy heading links to clipboard

* fix: detect claude confirmation prompts

refs herdrdev#2268

* feat(ui): add distinct status indicators (herdrdev#2282)

refs herdrdev#2260

* fix(input): keep pending url clicks across host focus loss (herdrdev#2291)

Opening a URL raises the browser, which takes focus away from the host
terminal before the mouse release arrives. release_input_source(_headless)
cleared pending_url_click_sources on that focus loss, so the release was
forwarded to the pane and the agent opened the same URL again.

Clear the set in clear_input_source instead, whose only production caller
is remove_client.

refs herdrdev#2290

Co-authored-by: kataokatsuki <kataokatsuki@users.noreply.github.com>

* fix(cli): resolve pane query --current from caller (herdrdev#2298)

refs herdrdev#2297

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>

* fix(input): parse default mouse reports (herdrdev#2312)

* fix(input): parse default mouse reports

refs herdrdev#2309

* fix(input): preserve split default mouse reports

refs herdrdev#2309

---------

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix(ui): search single-tab names in navigator (herdrdev#2320)

* fix(layout): return focus to the pane a split was opened from (herdrdev#2266)

Closing a focused pane handed focus to the next pane in tree order.
For a pane opened beside another one -- a plugin split, a file viewer,
any transient tool pane -- that is rarely where the user was: it lands
on some unrelated neighbour rather than the pane that opened it.

Track the pane focus came from in TileLayout and prefer it when the
focused pane closes, falling back to tree order when there is no
history, when it points at the pane being closed, or when it points at
a pane that has since gone away. The history lives in the layout, so it
can only ever name a pane in the same tab.

A one-slot history is only sound if internal focus excursions never
write it, so the tree edits that used to bounce focus around now go
through target-taking primitives instead. close_pane removes a
background pane directly, so detach_pane and take_pane_for_move stop
focus-close-refocusing. split_pane splits a target without moving
focus: the runtime split path only focuses the new pane once the spawn
succeeds, which makes a failed split a pure rollback, and the targeted
and unfocused workspace split paths stop fabricating history.
insert_pane_near now takes the focus intent, so an unfocused pane move
leaves the target tab's history alone. The layout-level focused-split
helpers become test-only; production splits all flow through the
target-taking path.

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix(terminal): render halfwidth katakana voiced marks (herdrdev#2257)

Co-authored-by: oyoguhito <oyoguhito@kamatanoMacBook-Pro.local>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix(ci): make issue gate structural

* fix(input): preserve modifyOtherKeys key releases (herdrdev#2303)

refs herdrdev#2302

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix(config): accept retired agent panel scope (herdrdev#2295)

refs herdrdev#2292

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* feat(theme): add optional sidebar background

* docs: refresh readme and sponsors

* test(graphics): pin the shrinking-cell symptom against upstream's fix

Upstream's cell-size fix prefers the ioctl whenever it reports any nonzero
pixels, so a stale SSH ws_xpixel is still divided by a growing column count.
HostCellSize::is_plausible is what keeps that off the card path. The sweep
covers the widths the defect was measured at and states the bound it does
not claim: a stale pty at a low column count is still believed.

Also corrects the AGENTS.md cell-size principle, which named the retired
HOST_CELL_SIZE_QUERY_SEQUENCE, and records the state-alphabet dispatch.

* no-mistakes(review): clamp client cell size at ingress and address review findings

* no-mistakes(review): floor sidebar ink separately from shared palette tokens

* no-mistakes(review): cache the sidebar palette per frame

* no-mistakes(review): resolve sidebar animation ink against the panel's own fill

* no-mistakes(review): route every sidebar ground through one panel-fill helper

* no-mistakes(document): document sidebar panel-fill palette floor, fix clippy clone-on-copy

* no-mistakes: apply CI fixes

---------

Co-authored-by: Can Celik <ogulcancelik@gmail.com>
Co-authored-by: kangal-bot <285672167+kangal-bot@users.noreply.github.com>
Co-authored-by: Bradley <67018167+brabli@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: Wiedzmin <56316383+art-wiedzmin@users.noreply.github.com>
Co-authored-by: Matt Coles <mattjcoles@outlook.com>
Co-authored-by: Matt Coles <macols@amazon.com>
Co-authored-by: Jonathan Liebig <jonathan.liebig@gmail.com>
Co-authored-by: Season Saw <season.saw@gmail.com>
Co-authored-by: Akira TSURUDA <jas39.gripen@gmail.com>
Co-authored-by: Ludovico Magnocavallo <ludo@qix.it>
Co-authored-by: serhat dolmaci <srhtsrht17@gmail.com>
Co-authored-by: WakaTaira <50697207+WakaTaira@users.noreply.github.com>
Co-authored-by: Florian <13469873+VialFlorian@users.noreply.github.com>
Co-authored-by: Rhys <105699450+rhjoh@users.noreply.github.com>
Co-authored-by: Michael Hackner <mhackner@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Kataoka Katsuki <49934462+kataokatsuki@users.noreply.github.com>
Co-authored-by: kataokatsuki <kataokatsuki@users.noreply.github.com>
Co-authored-by: Jon Kinney <jonkinney@gmail.com>
Co-authored-by: Kazunari Kamata <14287197+kazunari-kamata@users.noreply.github.com>
Co-authored-by: oyoguhito <oyoguhito@kamatanoMacBook-Pro.local>
Co-authored-by: Bchue <bchue@homeserver.tail25a02d.ts.net>
yjuyjuy added a commit to yjuyjuy/herdr that referenced this pull request Aug 5, 2026
* fix: preserve claude settings formatting (herdrdev#2089)

refs herdrdev#2066

Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com>

* fix(client): query host cell size when the ioctl reports no pixels (herdrdev#2160)

* fix(cli): report non-UTF-8 arguments instead of panicking (herdrdev#2207)

* fix(cli): report non-UTF-8 arguments instead of panicking

* fix(cli): avoid echoing malformed arguments

---------

Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com>

* fix: avoid blocking on foreground cwd checks (herdrdev#2213)

refs herdrdev#2206

* fix(docs): publish only released documentation

* fix(docs): support older git in snapshot checks

* fix(input): preserve hover during extended-button drags

* fix: propagate host color scheme to pane apps (herdrdev#2214)

refs herdrdev#714

* fix(pi): restrict state reporting to tui sessions (herdrdev#2159)

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix: page keys scroll pane scrollback at zsh and REPL prompts (herdrdev#2191)

* fix: page keys scroll pane scrollback at zsh and REPL prompts

PageUp/PageDown were forwarded to the pane whenever DECCKM (application
cursor) was on, assuming only primary-screen pagers enable it, but zsh's
line editor also enables DECCKM, as do REPLs such as python3. The result
was PageUp scrolling shell history instead of Herdr scrollback.

Bracketed paste discriminates the two: it means the app accepts typed or
pasted text at a prompt, so line editors enable it and pagers do not.

* test: update page key state fixture

---------

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* feat(website): rebuild marketing pages on new brand chassis

* docs: finalize 0.8.0 release documentation

* release: v0.8.0

* docs: update website manifest for v0.8.0

* docs: refine cpu optimization blog post

* fix(ui): keep collapsed workspace status visible (herdrdev#2239)

refs herdrdev#2216

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* docs: publish preview documentation

* feat(plugins): index marketplace manifests

* fix(docs): allow corrections to published versions

refs herdrdev#916

* fix(input): preserve shift-tab in pane automation (herdrdev#2259)

refs herdrdev#1561

* fix(ui): preserve sidebar scroll across clients (herdrdev#2280)

refs herdrdev#2255

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>

* fix(website): copy heading links to clipboard

* fix: detect claude confirmation prompts

refs herdrdev#2268

* feat(ui): add distinct status indicators (herdrdev#2282)

refs herdrdev#2260

* fix(input): keep pending url clicks across host focus loss (herdrdev#2291)

Opening a URL raises the browser, which takes focus away from the host
terminal before the mouse release arrives. release_input_source(_headless)
cleared pending_url_click_sources on that focus loss, so the release was
forwarded to the pane and the agent opened the same URL again.

Clear the set in clear_input_source instead, whose only production caller
is remove_client.

refs herdrdev#2290

Co-authored-by: kataokatsuki <kataokatsuki@users.noreply.github.com>

* fix(cli): resolve pane query --current from caller (herdrdev#2298)

refs herdrdev#2297

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>

* fix(input): parse default mouse reports (herdrdev#2312)

* fix(input): parse default mouse reports

refs herdrdev#2309

* fix(input): preserve split default mouse reports

refs herdrdev#2309

---------

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix(ui): search single-tab names in navigator (herdrdev#2320)

* fix(layout): return focus to the pane a split was opened from (herdrdev#2266)

Closing a focused pane handed focus to the next pane in tree order.
For a pane opened beside another one -- a plugin split, a file viewer,
any transient tool pane -- that is rarely where the user was: it lands
on some unrelated neighbour rather than the pane that opened it.

Track the pane focus came from in TileLayout and prefer it when the
focused pane closes, falling back to tree order when there is no
history, when it points at the pane being closed, or when it points at
a pane that has since gone away. The history lives in the layout, so it
can only ever name a pane in the same tab.

A one-slot history is only sound if internal focus excursions never
write it, so the tree edits that used to bounce focus around now go
through target-taking primitives instead. close_pane removes a
background pane directly, so detach_pane and take_pane_for_move stop
focus-close-refocusing. split_pane splits a target without moving
focus: the runtime split path only focuses the new pane once the spawn
succeeds, which makes a failed split a pure rollback, and the targeted
and unfocused workspace split paths stop fabricating history.
insert_pane_near now takes the focus intent, so an unfocused pane move
leaves the target tab's history alone. The layout-level focused-split
helpers become test-only; production splits all flow through the
target-taking path.

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix(terminal): render halfwidth katakana voiced marks (herdrdev#2257)

Co-authored-by: oyoguhito <oyoguhito@kamatanoMacBook-Pro.local>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix(ci): make issue gate structural

* fix(input): preserve modifyOtherKeys key releases (herdrdev#2303)

refs herdrdev#2302

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix(config): accept retired agent panel scope (herdrdev#2295)

refs herdrdev#2292

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* feat(theme): add optional sidebar background

* docs: refresh readme and sponsors

* chore: remove project-local worktree extension

refs herdrdev#2325

* fix(website): update author X profile

* chore: keep fork docs release metadata at 0.7.5

The upstream merge advanced docs/versions/manifest.json to the snapshot
stable source with current 0.8.0 and coupled website/latest.json to the
v0.8.0 release. Our fork has no v0.8.0 release tag, so the Website
workflow's published-documentation validator failed resolving
v0.8.0^{commit}, and manifest.current no longer matched latest.json.

Revert both release-metadata files to the pre-merge 0.7.5 legacy state so
the fork advertises only releases it actually publishes. This needs no
v0.8.0 tag and fires no release workflow. All other upstream merge content,
including the docs/versions/0.8.0 snapshot tree, is left intact.

* chore: pin fork stable docs snapshot to 0.7.5

The pure legacy-metadata revert could not build: the upstream merge also
deleted the committed legacy stable docs source tree
(website/src/content/docs and website/src/data/config-reference.json), so
docs-versions legacy mode has no source to render and the astro build fails
resolving config-reference.json.

Keep upstream's snapshot docs machinery but pin current to 0.7.5, the
newest release the fork actually publishes. The 0.7.5 entry gains snapshot
provenance from the existing v0.7.5 tag (commit ef4c23f) and its committed
docs/versions/0.7.5 snapshot tree. This needs no v0.8.0 tag and fires no
release workflow, and website/latest.json already advertises 0.7.5, so the
manifest current and latest version stay consistent.

Validated end to end: docs-versions check, docs-preview check, prepare-docs
in published and draft modes, a full astro build (946 pages), and
check-built-docs all pass locally.

---------

Co-authored-by: akbash <akbash@herdr.dev>
Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com>
Co-authored-by: WakaTaira <50697207+WakaTaira@users.noreply.github.com>
Co-authored-by: Florian <13469873+VialFlorian@users.noreply.github.com>
Co-authored-by: Rhys <105699450+rhjoh@users.noreply.github.com>
Co-authored-by: Michael Hackner <mhackner@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: kangal-bot <285672167+kangal-bot@users.noreply.github.com>
Co-authored-by: Kataoka Katsuki <49934462+kataokatsuki@users.noreply.github.com>
Co-authored-by: kataokatsuki <kataokatsuki@users.noreply.github.com>
Co-authored-by: Jon Kinney <jonkinney@gmail.com>
Co-authored-by: Kazunari Kamata <14287197+kazunari-kamata@users.noreply.github.com>
Co-authored-by: oyoguhito <oyoguhito@kamatanoMacBook-Pro.local>
vietairs pushed a commit to vietairs/herdr that referenced this pull request Aug 7, 2026
refs herdrdev#2066

Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com>
matthias-scale added a commit to matthias-scale/herdr that referenced this pull request Aug 7, 2026
* fix(windows): restore system notifications and sound playback (herdrdev#2019)

* test(windows): remove flaky sound timing assertion

refs herdrdev#1330

* fix: preserve windows path variables during install

refs herdrdev#1947

* fix(windows): preserve parent agent ownership

refs herdrdev#1514

* docs: update preview manifest

* fix: scope agent skill installation

refs herdrdev#2022

* ci: allow repository organization migration

* chore: update repository links after organization transfer

* Update rose pine surface_dim colour to "Overlay" (herdrdev#2002)

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* chore: finish repository organization migration

* fix: preserve kitty associated text (herdrdev#2051)

refs herdrdev#2020

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>

* fix: add opt-in child-group process detection (herdrdev#2052)

* fix: add opt-in child-group process detection

refs herdrdev#1982

* fix: preserve lifecycle probes without foreground groups

refs herdrdev#1982

* fix: launch argument-free agents on windows (herdrdev#2075)

refs herdrdev#2072

* ci: consolidate ai review trigger label

* fix: resume agents after headless restore (herdrdev#2088)

refs herdrdev#2064

* fix(omp): support Windows session paths (herdrdev#2092)

* fix: preserve windows sessions after ssh logout (herdrdev#2098)

* fix: preserve windows sessions after ssh logout

refs herdrdev#2008

* chore: document windows wmi safety

refs herdrdev#2008

* fix(client): restore terminal on sighup and sigterm

Enable termination-signal handling so SIGHUP and SIGTERM follow the graceful
quit path and restore terminal state. Log handler registration failures and
add PTY coverage for direct SIGHUP and server EOF restoration

Co-authored-by: Matt Coles <macols@amazon.com>

* fix(sidebar): keep worktree groups packed

* fix: read alternate-screen agent history

* chore: update agentmd for protocol changes

* feat: support bottom tab bar placement (herdrdev#2118)

* feat: support bottom tab bar placement

* fix: preserve mouse cleanup under bottom mode bar

refs herdrdev#2117

* chore: remove experiments from settings tui

* fix(input): preserve native key lifecycle across routing (herdrdev#2142)

refs herdrdev#2077

Co-authored-by: Jonathan Liebig <jonathan.liebig@gmail.com>

* fix(windows): preserve semantic escape key taps

* fix: report a clear cli error when no herdr server is running (herdrdev#1963)

* fix: report a clear cli error when no herdr server is running

socket cli commands surfaced a raw io::Error debug string
(`Error: Os { code: 2, ... }`) when nothing was listening on the
api socket, which read like a bad --cwd path. map dead-socket
connect failures to a `server_not_running` json error carrying the
resolved socket path, printed once at the edge that surfaces the
error; recovering callers (plugin offline registry fallback, agent
start polling) recognize the marker and keep their existing
behavior.

refs herdrdev#1941

* fix: map dead-socket errors on the unchecked cli request path

refs herdrdev#1941

* fix: make server-not-running guidance session-aware

refs herdrdev#1941

* fix: expand copy-mode word-end window past a final wide glyph (herdrdev#2145)

point_is_final_atom compared an atom's terminating column against a
word-motion target's starting column. The two are equal for narrow
cells but never for wide ones, so the read window stopped expanding
and copy-mode `e` halted at the soft-wrap boundary on CJK text.

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* feat(ui): make pane scrollbars optional (herdrdev#2166)

refs herdrdev#2167

* fix(ci): skip pr gate in forks

* feat: add antigravity-cli integration (herdrdev#2087)

* feat: add antigravity_cli integration harness

Register the `antigravity_cli` target, resolve its configuration
directory to `~/.gemini/antigravity-cli/`, wire target actions,
and add lifecycle hook scripts for Unix and Windows.

* feat: support session resume for antigravity-cli

* fix: correct antigravity-cli hook config path, shape, and agent label

Antigravity CLI reads global customizations from ~/.gemini/config, keys
hooks.json by hook name, and only accepts the matcher/hooks wrapper for
the tool events. The previous install wrote event arrays at the top level
of ~/.gemini/antigravity-cli/hooks.json, which agy never reads and would
reject anyway, so no Herdr hook ever ran.

Session reports were dropped for a third reason: the hooks reported the
agent as antigravity-cli, but the server normalizes that to the canonical
label agy before matching, so is_official_agent_source never matched and
agy --conversation resume was unreachable.

- Resolve the config dir to ~/.gemini/config
- Nest Herdr entries under a Herdr-owned "herdr" block that install
  rewrites and uninstall removes, leaving other named hooks untouched
- Emit grouped entries for PreToolUse/PostToolUse and flat handler lists
  for PreInvocation/PostInvocation/Stop
- Report the canonical agy label from both hook assets and match it in
  agent_resume
- Compile-gate the hook asset constants and stop shadowing $args in the
  PowerShell hook
- Document the real directory, that it must already exist, and the
  named-block behavior

refs herdrdev#1011
refs herdrdev#1571

* fix: make antigravity-cli integration session-only

antigravity cli cannot express lifecycle safely: there is no blocked
event, postinvocation is skipped on interruption, and stop fires at the
end of a turn rather than on process exit, which left stale state and
released authority at the wrong time.

report only the conversation on preinvocation and let screen detection
own agent state. resume via `agy --conversation <id>` is unchanged.

* fix: update antigravity session after conversation switch

---------

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix(input): decode 0x1f as Ctrl+_ not Ctrl+- per ASCII standard (herdrdev#2165)

* fix(input): decode 0x1f as Ctrl+_ not Ctrl+- per ASCII standard

refs herdrdev#2164

* fix(input): update control-byte matrix test for 0x1f -> Ctrl+_

* fix(socket_paths): remove dead if-branch in derive_client_socket_from_api_socket (herdrdev#2157)

* fix(windows): detect agents across git bash exec boundaries (herdrdev#2170)

refs herdrdev#2107

* fix: route vscode remote copies through osc52 (herdrdev#2173)

refs herdrdev#2015

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>

* fix(detect): recognize opencode2 as opencode

refs herdrdev#2169

* fix: stop advertising worktree json flag (herdrdev#2174)

refs herdrdev#2171

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>

* fix: preserve claude settings formatting (herdrdev#2089)

refs herdrdev#2066

Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com>

* fix(client): query host cell size when the ioctl reports no pixels (herdrdev#2160)

* fix(cli): report non-UTF-8 arguments instead of panicking (herdrdev#2207)

* fix(cli): report non-UTF-8 arguments instead of panicking

* fix(cli): avoid echoing malformed arguments

---------

Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com>

* fix: avoid blocking on foreground cwd checks (herdrdev#2213)

refs herdrdev#2206

* fix(docs): publish only released documentation

* fix(docs): support older git in snapshot checks

* fix(input): preserve hover during extended-button drags

* fix: propagate host color scheme to pane apps (herdrdev#2214)

refs herdrdev#714

* fix(pi): restrict state reporting to tui sessions (herdrdev#2159)

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix: page keys scroll pane scrollback at zsh and REPL prompts (herdrdev#2191)

* fix: page keys scroll pane scrollback at zsh and REPL prompts

PageUp/PageDown were forwarded to the pane whenever DECCKM (application
cursor) was on, assuming only primary-screen pagers enable it, but zsh's
line editor also enables DECCKM, as do REPLs such as python3. The result
was PageUp scrolling shell history instead of Herdr scrollback.

Bracketed paste discriminates the two: it means the app accepts typed or
pasted text at a prompt, so line editors enable it and pagers do not.

* test: update page key state fixture

---------

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* feat(website): rebuild marketing pages on new brand chassis

* docs: finalize 0.8.0 release documentation

* release: v0.8.0

* docs: update website manifest for v0.8.0

* docs: refine cpu optimization blog post

* fix(ui): keep collapsed workspace status visible (herdrdev#2239)

refs herdrdev#2216

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* docs: publish preview documentation

* feat(plugins): index marketplace manifests

* fix(docs): allow corrections to published versions

refs herdrdev#916

* fix(input): preserve shift-tab in pane automation (herdrdev#2259)

refs herdrdev#1561

* fix(ui): preserve sidebar scroll across clients (herdrdev#2280)

refs herdrdev#2255

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>

* fix(website): copy heading links to clipboard

* fix: detect claude confirmation prompts

refs herdrdev#2268

* feat(ui): add distinct status indicators (herdrdev#2282)

refs herdrdev#2260

* fix(input): keep pending url clicks across host focus loss (herdrdev#2291)

Opening a URL raises the browser, which takes focus away from the host
terminal before the mouse release arrives. release_input_source(_headless)
cleared pending_url_click_sources on that focus loss, so the release was
forwarded to the pane and the agent opened the same URL again.

Clear the set in clear_input_source instead, whose only production caller
is remove_client.

refs herdrdev#2290

Co-authored-by: kataokatsuki <kataokatsuki@users.noreply.github.com>

* fix(cli): resolve pane query --current from caller (herdrdev#2298)

refs herdrdev#2297

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>

* fix(input): parse default mouse reports (herdrdev#2312)

* fix(input): parse default mouse reports

refs herdrdev#2309

* fix(input): preserve split default mouse reports

refs herdrdev#2309

---------

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix(ui): search single-tab names in navigator (herdrdev#2320)

* fix(layout): return focus to the pane a split was opened from (herdrdev#2266)

Closing a focused pane handed focus to the next pane in tree order.
For a pane opened beside another one -- a plugin split, a file viewer,
any transient tool pane -- that is rarely where the user was: it lands
on some unrelated neighbour rather than the pane that opened it.

Track the pane focus came from in TileLayout and prefer it when the
focused pane closes, falling back to tree order when there is no
history, when it points at the pane being closed, or when it points at
a pane that has since gone away. The history lives in the layout, so it
can only ever name a pane in the same tab.

A one-slot history is only sound if internal focus excursions never
write it, so the tree edits that used to bounce focus around now go
through target-taking primitives instead. close_pane removes a
background pane directly, so detach_pane and take_pane_for_move stop
focus-close-refocusing. split_pane splits a target without moving
focus: the runtime split path only focuses the new pane once the spawn
succeeds, which makes a failed split a pure rollback, and the targeted
and unfocused workspace split paths stop fabricating history.
insert_pane_near now takes the focus intent, so an unfocused pane move
leaves the target tab's history alone. The layout-level focused-split
helpers become test-only; production splits all flow through the
target-taking path.

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix(terminal): render halfwidth katakana voiced marks (herdrdev#2257)

Co-authored-by: oyoguhito <oyoguhito@kamatanoMacBook-Pro.local>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix(ci): make issue gate structural

* fix(input): preserve modifyOtherKeys key releases (herdrdev#2303)

refs herdrdev#2302

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix(config): accept retired agent panel scope (herdrdev#2295)

refs herdrdev#2292

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* feat(theme): add optional sidebar background

* docs: refresh readme and sponsors

* chore: remove project-local worktree extension

refs herdrdev#2325

* fix(website): update author X profile

* feat(windows): support remote attach to unix hosts (herdrdev#2329)

* feat(windows): support remote attach to unix hosts

* fix(remote): preserve unix bridge behavior

* fix(sidebar): highlight active agent in collapsed sidebar (herdrdev#2382)

The collapsed sidebar renders agent rows with an unconditional
Style::default().fg(p.overlay0), so the active agent is
indistinguishable from the others. The workspace list directly above
it, and render_agent_detail in the expanded sidebar, both mark the
active entry.

Reuse the existing active treatment: resolve the active entry with the
same is_active_pane call the expanded agent panel uses, then paint the
row background with surface_dim and the position number with text, the
same tokens the collapsed workspace rows already use.

Assisted-By: devx/717e5259-915f-4a7b-af07-6abe46da5b90

* ci: restore approved contributor gate

* chore: update canonical repository references

* fix(ci): repair contributor gate handling

* fix: avoid ctrl-tab escape sequences in legacy panes

refs herdrdev#2296

* fix: render OSC 4 palette overrides instead of forwarding the index (herdrdev#2162)

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix: keep plugin marketplace counts current

* fix(cli): accept --flag=value and reordered options in pane read/wait-output (herdrdev#2183)

* fix(cli): accept --flag=value and reordered options in pane read/wait-output

* test(cli): trim redundant pane parser coverage

---------

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* docs: document custom agent integrations

* fix(detect): recognize versioned Python agent wrappers (herdrdev#2188)

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix(terminal): restore keyboard reporting on detach (herdrdev#2395)

refs herdrdev#2393

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>

* feat(copy-mode): add big-word motions (herdrdev#2270)

Co-authored-by: Ubuntu <ubuntu@ip-172-31-252-234.ca-west-1.compute.internal>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix: add positive idle detection for kiro-cli prompt (herdrdev#2301)

* fix: add positive idle detection for kiro-cli prompt

refs discussion herdrdev#982

* fix: remove manifest integration tests per reviewer request

---------

Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix(detect): ignore Cursor Run Everything status (herdrdev#2220)

* fix(detect): ignore Cursor Run Everything status

refs herdrdev#1763

* fix(detect): constrain Cursor approval controls

refs herdrdev#1763

* test(detect): remove cursor manifest behavior fixture

---------

Co-authored-by: Ogulcan Celik <ogulcancelik@gmail.com>

* fix(theme): refresh host appearance on focus (herdrdev#2417)

* fix(theme): refresh host appearance on focus

refs herdrdev#2416

* fix(input): preserve split appearance replies

refs herdrdev#2416

* fix(input): retain fragmented appearance reports

refs herdrdev#2416

---------

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: Can Celik <ogulcancelik@gmail.com>

* fix(client): restore terminal query and windows config behavior

* fix(ui): restore configurable status indicators

* test(multi-client): adapt flattened spaces scroll fixture

* fix(client): align remote image paste config across targets

* test(multi-client): preserve interactive tab scroll across renders

Retarget the flattened-sidebar regression at the live tab_scroll field and drive it through the client tab-bar scroll control.

Mutation proof: removing tab_scroll from the preserved_scroll save/restore tuple produced: test non_foreground_render_preserves_interactive_tab_scroll ... FAILED (0 passed; 1 failed). Restoring it produced: test non_foreground_render_preserves_interactive_tab_scroll ... ok (1 passed; 0 failed).

---------

Co-authored-by: Can Celik <ogulcancelik@gmail.com>
Co-authored-by: kangal-bot <285672167+kangal-bot@users.noreply.github.com>
Co-authored-by: Bradley <67018167+brabli@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: Wiedzmin <56316383+art-wiedzmin@users.noreply.github.com>
Co-authored-by: Matt Coles <mattjcoles@outlook.com>
Co-authored-by: Matt Coles <macols@amazon.com>
Co-authored-by: Jonathan Liebig <jonathan.liebig@gmail.com>
Co-authored-by: Season Saw <season.saw@gmail.com>
Co-authored-by: Akira TSURUDA <jas39.gripen@gmail.com>
Co-authored-by: Ludovico Magnocavallo <ludo@qix.it>
Co-authored-by: serhat dolmaci <srhtsrht17@gmail.com>
Co-authored-by: WakaTaira <50697207+WakaTaira@users.noreply.github.com>
Co-authored-by: Florian <13469873+VialFlorian@users.noreply.github.com>
Co-authored-by: Rhys <105699450+rhjoh@users.noreply.github.com>
Co-authored-by: Michael Hackner <mhackner@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Kataoka Katsuki <49934462+kataokatsuki@users.noreply.github.com>
Co-authored-by: kataokatsuki <kataokatsuki@users.noreply.github.com>
Co-authored-by: Jon Kinney <jonkinney@gmail.com>
Co-authored-by: Kazunari Kamata <14287197+kazunari-kamata@users.noreply.github.com>
Co-authored-by: oyoguhito <oyoguhito@kamatanoMacBook-Pro.local>
Co-authored-by: Ian Ker-Seymer <i.kerseymer@gmail.com>
Co-authored-by: Mo <77584024+hamidi-dev@users.noreply.github.com>
Co-authored-by: Kyle Corbeille <kcorbeille76@gmail.com>
Co-authored-by: Phil Larson <hello@phillarson.xyz>
Co-authored-by: JP Lew <462836+jplew@users.noreply.github.com>
Co-authored-by: Ubuntu <ubuntu@ip-172-31-252-234.ca-west-1.compute.internal>
Co-authored-by: Sam Biggins <sambiggins@gmail.com>
Co-authored-by: Jesse Zhang <j3ssezhang102@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Trigger automated AI reviews for pull requests admitted by the PR gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants