Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
fc44f61
fix: disconnect stalled terminal observers (#4039)
ogulcancelik Sep 13, 2026
f48cd6a
fix: order ui accent before nested config tables (#2698)
akbash-bot Sep 13, 2026
9631f8e
fix: decouple pixel mouse from pane graphics (#4045)
akbash-bot Sep 13, 2026
a5e1c94
fix: restrict claude session hooks to native sources (#4046)
akbash-bot Sep 13, 2026
858ad4e
fix(input): preserve super-modified pane keys (#4044)
akbash-bot Sep 13, 2026
540b20f
test: relax windows docs snapshot timeout (#4049)
JJLiebig Sep 13, 2026
7505c08
fix: retain validated split mouse reports across idle gaps (#4048)
akbash-bot Sep 13, 2026
d66c39d
fix(server): transfer handoff descriptors in batches (#3411)
kataokatsuki Sep 13, 2026
5c0ecc6
test: deflake windows metadata ttl expiry assertion (#4050)
JJLiebig Sep 13, 2026
63ea231
fix: detect kimi npm shim on windows (#4053)
JJLiebig Sep 13, 2026
3be3523
fix(remote): resolve ssh host aliases from git bash on windows (#4054)
JJLiebig Sep 13, 2026
fc1cb77
feat: add Letta Code detection and restore (#3107)
ogulcancelik Sep 13, 2026
cb06df6
fix(windows): disable host mouse reporting on terminal restore (#4055)
JJLiebig Sep 13, 2026
981fe83
fix: keep hermes enabled list valid yaml (#4056)
JJLiebig Sep 13, 2026
5f26879
fix(ui): keep muted sidebar and tab labels readable (#4062)
JJLiebig Sep 13, 2026
38bc172
fix(windows): honor default_shell in login shell mode (#4060)
JJLiebig Sep 13, 2026
ff32bd4
fix(windows): keep powershell cwd reporting in login mode (#4065)
JJLiebig Sep 13, 2026
f0cb0e0
fix: keep an agent name through a process-exit observation (#3574)
caner-akca Sep 13, 2026
3834fd3
fix: auto-expire worktree action error banners (#4063)
JJLiebig Sep 13, 2026
1e3c625
test: deflake federated local input race (#4066)
JJLiebig Sep 13, 2026
0305fdb
fix: recognize kitty CSI-u codepoints for F1 through F12 (#2378)
ashokDevs Sep 13, 2026
a7a1410
fix(input): accept parameterized CSI-tilde F1-F4 keys (#4067)
JJLiebig Sep 13, 2026
8d213f8
fix: clean up failed terminal observer setup (#4071)
ogulcancelik Sep 13, 2026
8be8bff
chore: add jjliebig as approved contributor and maintainer
ogulcancelik Sep 13, 2026
5916765
feat: install windows remote host packages (#3687)
JJLiebig Sep 13, 2026
f8e5922
feat: add ctrl-hover highlighting and fix wrapped links (#4074)
ogulcancelik Sep 13, 2026
b847e6c
fix(linux): bound the foreground process-tree scan (#3674)
caner-akca Sep 13, 2026
6075d25
fix: keep plugins working after client-only updates (#4077)
ogulcancelik Sep 13, 2026
2746ac7
ci: migrate remaining pinned actions to node24 (#4023)
JJLiebig Sep 13, 2026
4e1096b
fix: clarify agent integration settings description
ogulcancelik Sep 13, 2026
c91349e
Merge remote-tracking branch 'upstream/master' into sync/upstream-master
geril07 Sep 13, 2026
3b478e6
fix: scope agent views to the selected machine (#3784)
akbash-bot Sep 13, 2026
aa961df
fix(windows): restore mouse reporting when reattaching (#4080)
JJLiebig Sep 13, 2026
247f6d1
fix(client): re-assert host mouse modes after a terminal reconnect (#…
JJLiebig Sep 13, 2026
add3dd2
test(windows): deflake media player invalid media assertion (#4082)
JJLiebig Sep 13, 2026
21c1f8c
fix: hide only kitty image placements overlapping overlays (#4081)
ogulcancelik Sep 14, 2026
c77af18
fix: clean up idle ssh bridges and back off flapping connections (#4083)
ogulcancelik Sep 14, 2026
be03b7a
fix: preserve agent panel scroll when switching machines (#4101)
minatoaquaMK2 Sep 14, 2026
970b926
fix: remove stale maintainer username
ogulcancelik Sep 14, 2026
a291af9
Merge remote-tracking branch 'upstream/master' into sync/upstream-master
geril07 Sep 14, 2026
17e63c7
Merge branch 'master' into sync/upstream-master
geril07 Sep 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/APPROVED_CONTRIBUTORS
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,4 @@ aneym
dhh
caner-akca
markjaquith
JJLiebig
2 changes: 1 addition & 1 deletion .github/MAINTAINERS
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# GitHub usernames with Herdr maintainer authority, one per line.
# Maintainers must also use the canonical repository and have write access.
ogulcancelik
Pimpmuckl
kangal-bot
JJLiebig
6 changes: 3 additions & 3 deletions .github/workflows/build-artifacts-manual.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ jobs:
targets: ${{ matrix.target }}

- name: Install Zig
uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
uses: vercel-labs/setup-zig@83c1594f26b86da8a9a8ddd9b5ee5f3af0f96943 # v1.0.2
with:
version: 0.16.0

Expand Down Expand Up @@ -154,7 +154,7 @@ jobs:
targets: ${{ matrix.target }}

- name: Install Zig
uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
uses: vercel-labs/setup-zig@83c1594f26b86da8a9a8ddd9b5ee5f3af0f96943 # v1.0.2
with:
version: 0.16.0

Expand Down Expand Up @@ -207,7 +207,7 @@ jobs:
targets: x86_64-pc-windows-msvc

- name: Install Zig
uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
uses: vercel-labs/setup-zig@83c1594f26b86da8a9a8ddd9b5ee5f3af0f96943 # v1.0.2
with:
version: 0.16.0

Expand Down
20 changes: 10 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ env:
# Keep file/line backtraces without generating type and variable debug information.
CARGO_PROFILE_DEV_DEBUG: "1"
CARGO_PROFILE_TEST_DEBUG: "1"
# vercel-labs/setup-zig does not cache the Zig global cache, so redirect it into the
# workspace .zig-cache that the Zig build cache steps persist. Remove this (and the
# widened condition on "Restore Zig build cache") if we switch to a setup action that
# owns Zig caching, e.g. step-security/setup-zig. See PR #4023.
ZIG_GLOBAL_CACHE_DIR: ${{ github.workspace }}/.zig-cache

concurrency:
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
Expand Down Expand Up @@ -89,12 +94,9 @@ jobs:
bun-version: 1.3.14

- name: Install Zig
uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
uses: vercel-labs/setup-zig@83c1594f26b86da8a9a8ddd9b5ee5f3af0f96943 # v1.0.2
with:
version: 0.16.0
use-cache: ${{ runner.os == 'Linux' }}
# Linux builds both SIMD/ReleaseFast and scalar/ReleaseSafe variants.
cache-size-limit: 4096

# Zig's C-header cache keys include the compiler installation path.
- name: Stabilize Zig installation path on Unix
Expand All @@ -116,8 +118,7 @@ jobs:
"ZIG=$(Join-Path $stable 'zig.exe')" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

- name: Restore Zig build cache
if: runner.os == 'macOS' || matrix.kind == 'windows'
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .zig-cache
key: zig-build-v1-${{ runner.os }}-${{ runner.arch }}-0.16.0-${{ github.run_id }}-${{ github.run_attempt }}
Expand All @@ -134,7 +135,7 @@ jobs:
# rebuilds workspace targets; only rustc's validated query state is retained.
- name: Restore Windows incremental compiler state
if: matrix.kind == 'windows'
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: target/debug/incremental
key: ci-incremental-v1-${{ runner.os }}-${{ runner.arch }}-${{ env.RUST_TOOLCHAIN_VERSION }}-${{ env.CARGO_PROFILE_DEV_DEBUG }}-${{ env.CARGO_PROFILE_TEST_DEBUG }}-${{ hashFiles('Cargo.lock', 'Cargo.toml', '.cargo/config.toml', 'build.rs') }}-${{ github.sha }}
Expand Down Expand Up @@ -192,10 +193,9 @@ jobs:
targets: x86_64-pc-windows-msvc

- name: Install Zig
uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
uses: vercel-labs/setup-zig@83c1594f26b86da8a9a8ddd9b5ee5f3af0f96943 # v1.0.2
with:
version: 0.16.0
use-cache: false

- name: Stabilize Zig installation path
shell: pwsh
Expand All @@ -207,7 +207,7 @@ jobs:
"ZIG=$(Join-Path $stable 'zig.exe')" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

- name: Restore Zig build cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .zig-cache
key: zig-build-v1-conpty-package-windows-2022-${{ runner.arch }}-0.16.0-${{ github.run_id }}-${{ github.run_attempt }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ jobs:

- name: Install Zig
if: steps.plan.outputs.should_publish == 'true'
uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
uses: vercel-labs/setup-zig@83c1594f26b86da8a9a8ddd9b5ee5f3af0f96943 # v1.0.2
with:
version: 0.16.0

Expand Down Expand Up @@ -161,7 +161,7 @@ jobs:
targets: ${{ matrix.target }}

- name: Install Zig
uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
uses: vercel-labs/setup-zig@83c1594f26b86da8a9a8ddd9b5ee5f3af0f96943 # v1.0.2
with:
version: 0.16.0

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ jobs:
targets: ${{ matrix.target }}

- name: Install Zig
uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
uses: vercel-labs/setup-zig@83c1594f26b86da8a9a8ddd9b5ee5f3af0f96943 # v1.0.2
with:
version: 0.16.0

Expand Down
4 changes: 4 additions & 0 deletions distribution/agent-detection/index.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ path = "kimi.toml"
id = "kiro"
path = "kiro.toml"

[[agents]]
id = "letta"
path = "letta.toml"

[[agents]]
id = "maki"
path = "maki.toml"
Expand Down
95 changes: 95 additions & 0 deletions distribution/agent-detection/letta.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
id = "letta"
version = "2026.08.24.1"
min_engine_version = 3
updated_at = "2026-08-24T00:00:00Z"
aliases = ["letta-code", "letta code"]

# Letta keeps completed tool rows and spinners in the transcript. A standalone
# screen spinner is not working evidence. Prefer its live OSC title/progress
# signals, with visible status chrome and running tool rows as fallbacks.
[[rules]]
id = "osc_progress_blocked"
state = "blocked"
priority = 1400
region = "osc_progress"
visible_blocker = true
regex = ['^4;3(?:;|$)']

[[rules]]
id = "osc_title_blocked"
state = "blocked"
priority = 1300
region = "osc_title"
visible_blocker = true
regex = ['^\[ [!.] \] Action Required(?: \| |$)']

[[rules]]
id = "command_approval"
state = "blocked"
priority = 1200
region = "bottom_non_empty_lines(20)"
visible_blocker = true
contains = ["Run this command?", "Enter to select · Esc to cancel"]

[[rules]]
id = "osc_title_working"
state = "working"
priority = 900
region = "osc_title"
visible_working = true
regex = ['(?:^| )[⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏](?: |$)']

[[rules]]
id = "active_status"
state = "working"
priority = 850
region = "bottom_non_empty_lines(8)"
visible_working = true
line_regex = ['^\s*(?:\S+\s+)+is(?: \S+)*… \((?:esc to interrupt(?: · .*)?|interrupting)\)\s*$']

[[rules]]
id = "running_tool"
state = "working"
priority = 800
region = "bottom_non_empty_lines(8)"
visible_working = true
line_regex = ['^\s*(?:└\s*)?Running\.\.\.\s*(?:\(.*\))?$']

[[rules]]
id = "profile_selector"
state = "unknown"
priority = 700
region = "bottom_non_empty_lines(12)"
contains = ["Create a new agent (--new)", "Enter select · Esc exit"]

[[rules]]
id = "composer_input"
state = "unknown"
priority = 150
region = "bottom_non_empty_lines(8)"
line_regex = ['^\s*›\s+\S.*$']
not = [
{ line_regex = ['^\s*›\s+Try\s+"'] },
]

[[rules]]
id = "composer_idle"
state = "idle"
priority = 100
region = "bottom_non_empty_lines(8)"
visible_idle = true
any = [
{ line_regex = ['^\s*›\s*$'] },
{ line_regex = ['^\s*›\s+Try\s+"'] },
]
not = [
{ line_regex = ['^\s*(?:\S+\s+)+is(?: \S+)*… \((?:esc to interrupt(?: · .*)?|interrupting)\)\s*$'] },
{ line_regex = ['^\s*(?:└\s*)?Running\.\.\.\s*(?:\(.*\))?$'] },
]

[[rules]]
id = "no_live_state_evidence"
state = "unknown"
priority = 0
region = "whole_recent"
regex = ['(?s)^.*$']
64 changes: 64 additions & 0 deletions docs/next/api/herdr-api.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -5867,6 +5867,22 @@
],
"type": "object"
},
{
"properties": {
"method": {
"const": "pane.link.resolve",
"type": "string"
},
"params": {
"$ref": "#/schemas/request/$defs/PaneLinkActivateParams"
}
},
"required": [
"method",
"params"
],
"type": "object"
},
{
"properties": {
"method": {
Expand Down Expand Up @@ -8162,6 +8178,35 @@
],
"type": "object"
},
"PaneLinkRegion": {
"description": "Inclusive display-cell columns on a pane's current viewport.",
"properties": {
"end_col": {
"format": "uint16",
"maximum": 65535,
"minimum": 0,
"type": "integer"
},
"row": {
"format": "uint16",
"maximum": 65535,
"minimum": 0,
"type": "integer"
},
"start_col": {
"format": "uint16",
"maximum": 65535,
"minimum": 0,
"type": "integer"
}
},
"required": [
"row",
"start_col",
"end_col"
],
"type": "object"
},
"PaneMoveReason": {
"enum": [
"same_tab",
Expand Down Expand Up @@ -10374,6 +10419,25 @@
],
"type": "object"
},
{
"properties": {
"regions": {
"items": {
"$ref": "#/schemas/success_response/$defs/PaneLinkRegion"
},
"type": "array"
},
"type": {
"const": "pane_link_resolved",
"type": "string"
}
},
"required": [
"type",
"regions"
],
"type": "object"
},
{
"properties": {
"handled": {
Expand Down
2 changes: 1 addition & 1 deletion docs/next/website/src/content/docs/agent-automation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Agent commands accept either a unique live name or the pane ID that currently ho

An available shell pane is at its interactive shell prompt: the shell itself owns the foreground, with no foreground command, editor, or agent running. Return the pane to its prompt before calling `agent start`.

`--kind` selects a supported agent and its canonical executable. Supported kinds are `pi`, `claude`, `codex`, `gemini`, `cursor`, `devin`, `agy`, `cline`, `omp`, `mastracode`, `opencode`, `copilot`, `kimi`, `kiro`, `droid`, `amp`, `grok`, `hermes`, `kilo`, `qodercli`, `qwen`, `maki`, and `muse`. Arguments after `--` are passed unchanged to that executable.
`--kind` selects a supported agent and its canonical executable. Supported kinds are `pi`, `claude`, `codex`, `gemini`, `cursor`, `devin`, `agy`, `cline`, `omp`, `mastracode`, `opencode`, `copilot`, `kimi`, `kiro`, `droid`, `amp`, `grok`, `hermes`, `kilo`, `qodercli`, `qwen`, `letta`, `maki`, and `muse`. Arguments after `--` are passed unchanged to that executable.

Successful `agent start` returns only after Herdr detects the expected agent in the same terminal and marks it ready for interactive input. If detection reports `blocked` during startup, the command returns `agent_not_ready` immediately. The name remains available for `agent read` and `agent send-keys`, and becomes ready for prompts after detection reports `idle`. Startup waits for 30 seconds by default; `--timeout` must be greater than 3000 and no more than 300000 milliseconds.

Expand Down
1 change: 1 addition & 0 deletions docs/next/website/src/content/docs/agents.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Automatic detection works out of the box for common coding agents. The table sho
| Hermes Agent | screen manifest | session |
| Qoder CLI | screen manifest | session |
| Qwen Code | screen manifest | session |
| Letta Code | screen manifest | session |
| Droid | screen manifest | session |
| OpenCode | lifecycle plugin when installed; otherwise screen manifest | state and session |
| Kilo Code CLI | lifecycle plugin when installed; otherwise screen manifest | state and session |
Expand Down
7 changes: 6 additions & 1 deletion docs/next/website/src/content/docs/cli-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ herdr agent explain --file PATH --agent LABEL [--json|--verbose]

Agent targets are either a unique live agent name or the pane ID that currently hosts the agent. Terminal IDs and bare agent-kind labels are not agent targets. Agents started through `agent start` require a name; manually launched agents remain unnamed and use their pane ID.

`agent start` activates an existing available shell pane: the pane's interactive shell must own the foreground, with no foreground command, editor, or agent running. Topology must be created separately. Names are unique among live agents and must match `[a-z][a-z0-9_-]{0,31}`. The kind selects Herdr's canonical interactive executable, while arguments after `--` are passed to that executable. Supported kinds are `pi`, `claude`, `codex`, `gemini`, `cursor`, `devin`, `agy`, `cline`, `omp`, `mastracode`, `opencode`, `copilot`, `kimi`, `kiro`, `droid`, `amp`, `grok`, `hermes`, `kilo`, `qodercli`, `qwen`, `maki`, and `muse`. A name follows the current pane occupant and is cleared when that agent exits, is released, or is replaced. Temporary detection uncertainty does not clear it.
`agent start` activates an existing available shell pane: the pane's interactive shell must own the foreground, with no foreground command, editor, or agent running. Topology must be created separately. Names are unique among live agents and must match `[a-z][a-z0-9_-]{0,31}`. The kind selects Herdr's canonical interactive executable, while arguments after `--` are passed to that executable. Supported kinds are `pi`, `claude`, `codex`, `gemini`, `cursor`, `devin`, `agy`, `cline`, `omp`, `mastracode`, `opencode`, `copilot`, `kimi`, `kiro`, `droid`, `amp`, `grok`, `hermes`, `kilo`, `qodercli`, `qwen`, `letta`, `maki`, and `muse`. A name follows the current pane occupant and is cleared when that agent exits, is released, or is replaced. Temporary detection uncertainty does not clear it.

A successful start returns only after the expected agent owns the same terminal and is ready for interactive input. If detection reports `blocked` during startup, the command returns `agent_not_ready` immediately. The name remains available for `agent read` and `agent send-keys`, and becomes ready for prompts after detection reports `idle`. The default startup timeout is 30000 milliseconds; explicit values must be greater than 3000 and no more than 300000.

Expand Down Expand Up @@ -380,6 +380,9 @@ terminal, or agent target. It prints newline-delimited JSON `terminal.frame`
records with base64-encoded ANSI bytes, then a `terminal.closed` record when
the server closes the stream. Multiple observers can watch the same terminal
without taking input, resize, scroll, or takeover authority.
On Linux and macOS, an observer is disconnected if a socket write makes no progress
for 30 seconds. A stalled stream can end without a final `terminal.closed` record;
the pane and other clients keep running. Quiet panes do not trigger this timeout.
`terminal title clear` hands the outer terminal window title back to `ui.window_title`.

## Output waits
Expand Down Expand Up @@ -414,6 +417,7 @@ herdr integration install kilo
herdr integration install hermes
herdr integration install qodercli
herdr integration install qwen
herdr integration install letta
herdr integration install cursor
herdr integration install mastracode
herdr integration install grok
Expand All @@ -430,6 +434,7 @@ herdr integration uninstall kilo
herdr integration uninstall hermes
herdr integration uninstall qodercli
herdr integration uninstall qwen
herdr integration uninstall letta
herdr integration uninstall cursor
herdr integration uninstall mastracode
herdr integration uninstall grok
Expand Down
4 changes: 3 additions & 1 deletion docs/next/website/src/content/docs/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,9 @@ Search the [Config reference](/docs/config-reference/) for scrollback limits, ne

## Kitty graphics

Herdr renders pane images by default in compatible outer terminals. To disable graphics rendering and the pane graphics API:
Herdr renders pane images by default in compatible outer terminals. Popups, menus, and notifications temporarily hide only the image placements they overlap. Uncovered images stay visible, and hidden placements return when uncovered. Images do not dim with dialog backgrounds.

To disable graphics rendering and the pane graphics API:

```toml
[terminal]
Expand Down
Loading