Skip to content

revert(cli): revert headless agent session control (#5784) - #5837

Merged
Kitenite merged 2 commits into
mainfrom
revert-5784-headless-sessions
Jul 21, 2026
Merged

Kitenite merged 2 commits into
mainfrom
revert-5784-headless-sessions

Conversation

@Kitenite

@Kitenite Kitenite commented Jul 21, 2026 •

Copy link
Copy Markdown
Member

Summary

Reverts #5784 (squash commit 8386961b5) to isolate a deterministic regression: existing terminals stop accepting input, and automation-launched terminals break the same way, reliably on every run. Prod (desktop-v1.16.0, daemon 0.2.5) is unaffected; the regression exists only in post-1.16.0 builds carrying daemon 0.2.6.

#5784 is the prime suspect because it is the only recent merge on every input path shared by both broken surfaces:

  • rewrote host-service DaemonClient (carries all writes: desktop keystrokes and automation prompt delivery)
  • bumped the daemon protocol to v3 (snapshots), with v2 negotiation
  • replaced interactive prompt writes with the prompt-file/POSIX launcher + launch acknowledgement for argv/stdin agents

Changes

  • Clean git revert of 8386961b5 — daemon back to protocol v2-only, CLI agents sessions list/read/send/wait removed, launch path restored
  • pty-daemon bumped 0.2.5 → 0.2.7 (not back to 0.2.5): isVersionUpdatePending only updates daemons running < EXPECTED_DAEMON_VERSION, so restoring 0.2.5 would leave already-upgraded 0.2.6 daemons running the suspect binary forever. 0.2.7 makes them hand off onto the reverted build. fix(pty-daemon): release macOS PTY master descriptors #5795 (fd disposal) merged before feat(cli): add headless agent session control #5784 and is intentionally not reverted.

Validation

If the automation repro passes on this branch, #5784 is confirmed as the cause and can be re-landed piecewise (DaemonClient rewrite, protocol v3, prompt launcher) to find the specific culprit.


Summary by cubic

Reverts headless agent session control and protocol v3 snapshots to fix a regression where terminals stopped accepting input in post-1.16 builds. Restores the prior agent launch path and v2-only daemon protocol; bumps @superset/pty-daemon to 0.2.7 so hosts on 0.2.6 converge to the reverted build.

  • Bug Fixes
    • Restore v2-only daemon protocol; remove snapshot messages and terminal snapshot rendering.
    • Revert prompt-file/argv agent launcher and drop CLI session commands (superset agents sessions list/read/send/wait), tests, and CDP runbook; docs updated.
    • @superset/pty-daemon bumped to 0.2.7 to replace existing 0.2.6 daemons with the reverted binary.
    • @superset/cli-framework arg parser no longer treats - as a stdin sentinel for string options.

Written for commit efa6d3c. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Changes

    • Removed CLI commands for listing, reading, sending prompts to, and waiting on running agent sessions.
    • Workspace creation no longer reports failures when requested agents do not start.
    • CLI option parsing now requires values that do not begin with a hyphen.
  • Documentation

    • Updated workspace and agent command examples and session-opening guidance.
    • Removed obsolete CLI end-to-end testing runbooks and instructions.
  • Maintenance

    • Simplified terminal communication and session handling.

@linear-code

linear-code Bot commented Jul 21, 2026

Copy link
Copy Markdown

@coderabbitai

coderabbitai Bot commented Jul 21, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR removes CLI terminal-agent session controls and E2E harnesses, simplifies host workspace discovery and agent launching, removes PTY snapshot protocol support, restores protocol v2, updates CLI/deep-link documentation, and revises desktop CDP authentication guidance.

Changes

PTY protocol and snapshot removal

Layer / File(s) Summary
PTY protocol and snapshot handling
packages/pty-daemon/src/..., packages/pty-daemon/test/...
Protocol v2 is restored as the sole supported version; snapshot messages, truncation metadata, snapshot handlers, and related tests are removed.
Host-service daemon and terminal clients
packages/host-service/src/daemon/..., packages/host-service/src/terminal/DaemonClient/...
Daemon handshakes advertise only the current protocol, while client snapshot APIs and legacy negotiation tests are removed.

Host-service agent simplification

Layer / File(s) Summary
Agent command construction and lifecycle
packages/host-service/src/trpc/router/agents/..., packages/host-service/src/trpc/router/terminal-agents/...
Agent commands are built directly for argv or stdin transport, launches no longer wait for startup, and terminal-agent listing returns raw store entries while get/read/send APIs are removed.
Terminal adoption and exports
packages/host-service/src/terminal/..., packages/host-service/src/terminal-agents/index.ts
Terminal attachment calls the session creation path directly, and terminal-agent exports are narrowed.

CLI and documentation reduction

Layer / File(s) Summary
CLI commands and workspace discovery
packages/cli/..., packages/cli-framework/..., package.json
Agent-session commands and CLI E2E infrastructure are removed, option parsing rejects - as a value sentinel, agent-start assertions are removed, and host workspace discovery uses direct host listing with per-host warnings.
CLI and desktop guidance
apps/docs/content/docs/cli/..., skills/superset/SKILL.md, AGENTS.md, apps/desktop/AGENTS.md
Documentation switches deep-link examples to agents run, simplifies workspace and agent behavior descriptions, removes the CLI CDP runbook references, and documents credentialed local CDP sign-in.

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

Possibly related PRs

Suggested reviewers: saddlepaddle

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.77% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise, conventional, and accurately reflects the main change: reverting headless agent session control.
Description check ✅ Passed The description covers what changed, why, and how it was validated, though it does not mirror the template’s exact headings or checklist format.
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 revert-5784-headless-sessions

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.

❤️ Share

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

@github-actions

github-actions Bot commented Jul 21, 2026 •

Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch

Thank you for your contribution! 🎉

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/docs/content/docs/cli/cli-reference.mdx (1)

634-649: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use agents create consistently here. superset only defines agents create and agents list; agents run/#superset-agents-run don’t exist. Revert the deep-link section to agents create/#superset-agents-create, and change the skill doc references to agents create as well.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/docs/content/docs/cli/cli-reference.mdx` around lines 634 - 649, The
deep-link documentation must consistently use the existing agents create command
and anchor. Update apps/docs/content/docs/cli/cli-reference.mdx lines 634-649
and 719-726 to replace agents run and `#superset-agents-run` references with
agents create and `#superset-agents-create`, and update skills/superset/SKILL.md
lines 63 and 74-76 to reference agents create as well. Preserve the existing
deep-link guidance and session fields.
packages/cli-framework/src/parser.ts (1)

147-156: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep "-" working for fromFile packages/cli/src/commands/automations/prompt/set/command.ts still documents Use '-' to read from stdin and branches on options.fromFile === "-"; the new startsWith("-") check will reject that path before stdin can be read. Preserve the "-" exception here, or change the command contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli-framework/src/parser.ts` around lines 147 - 156, Adjust the
missing-value check in the parser’s String/number option handling to allow the
exact argument "-" through as a valid value, while continuing to reject other
arguments beginning with "-". Preserve the existing fromFile stdin behavior
consumed by the command’s options.fromFile handling.
🧹 Nitpick comments (2)
packages/pty-daemon/test/helpers/client.ts (1)

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

Use CURRENT_PROTOCOL_VERSION in these handshake tests. Replace the hardcoded 2/[2, 99] literals in packages/pty-daemon/test/helpers/client.ts, packages/pty-daemon/test/control-plane.test.ts, and packages/pty-daemon/test/integration.test.ts so the suite stays aligned with the exported protocol constant.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/pty-daemon/test/helpers/client.ts` at line 228, Replace hardcoded
handshake protocol values with the exported CURRENT_PROTOCOL_VERSION constant in
packages/pty-daemon/test/helpers/client.ts:228,
packages/pty-daemon/test/control-plane.test.ts:109-117 and :999, and
packages/pty-daemon/test/integration.test.ts:29-33; preserve any additional
protocol values such as 99 where they test unsupported versions.
packages/host-service/src/trpc/router/agents/agents.ts (1)

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

Minor: inline type import instead of top-level import.

import("../../../events").EventBus works but is inconsistent with the top-level import type { HostDb } pattern already used in this file. Consider hoisting it to a top-level type import for readability.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/host-service/src/trpc/router/agents/agents.ts` at line 231, Hoist
EventBus into a top-level type import alongside HostDb, then update the ctx type
in the affected router definition to reference EventBus directly instead of
import("../../../events").EventBus.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/cli/src/lib/host-workspaces/listHostWorkspaces.ts`:
- Around line 63-84: Update the host-selection logic in listHostWorkspaces so
that when discovery returns hosts but the online-host Set is empty after the
local manifest check, it adds a warning explaining that no discovered hosts are
reachable and falls back to localHostId. Preserve the existing targetHostIds
behavior when reachable hosts are present and retain the discovery-error
fallback in the sibling branch.

---

Outside diff comments:
In `@apps/docs/content/docs/cli/cli-reference.mdx`:
- Around line 634-649: The deep-link documentation must consistently use the
existing agents create command and anchor. Update
apps/docs/content/docs/cli/cli-reference.mdx lines 634-649 and 719-726 to
replace agents run and `#superset-agents-run` references with agents create and
`#superset-agents-create`, and update skills/superset/SKILL.md lines 63 and 74-76
to reference agents create as well. Preserve the existing deep-link guidance and
session fields.

In `@packages/cli-framework/src/parser.ts`:
- Around line 147-156: Adjust the missing-value check in the parser’s
String/number option handling to allow the exact argument "-" through as a valid
value, while continuing to reject other arguments beginning with "-". Preserve
the existing fromFile stdin behavior consumed by the command’s options.fromFile
handling.

---

Nitpick comments:
In `@packages/host-service/src/trpc/router/agents/agents.ts`:
- Line 231: Hoist EventBus into a top-level type import alongside HostDb, then
update the ctx type in the affected router definition to reference EventBus
directly instead of import("../../../events").EventBus.

In `@packages/pty-daemon/test/helpers/client.ts`:
- Line 228: Replace hardcoded handshake protocol values with the exported
CURRENT_PROTOCOL_VERSION constant in
packages/pty-daemon/test/helpers/client.ts:228,
packages/pty-daemon/test/control-plane.test.ts:109-117 and :999, and
packages/pty-daemon/test/integration.test.ts:29-33; preserve any additional
protocol values such as 99 where they test unsupported versions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0ac99e3b-485c-49ba-899c-235230c1097d

📥 Commits

Reviewing files that changed from the base of the PR and between ac090c2 and efa6d3c.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (65)
  • AGENTS.md
  • apps/desktop/AGENTS.md
  • apps/desktop/docs/CLI_CDP_E2E.md
  • apps/docs/content/docs/cli/cli-reference.mdx
  • package.json
  • packages/cli-framework/src/parser.test.ts
  • packages/cli-framework/src/parser.ts
  • packages/cli/package.json
  • packages/cli/src/commands/agents/sessions/list/command.ts
  • packages/cli/src/commands/agents/sessions/meta.ts
  • packages/cli/src/commands/agents/sessions/read/command.ts
  • packages/cli/src/commands/agents/sessions/send/command.test.ts
  • packages/cli/src/commands/agents/sessions/send/command.ts
  • packages/cli/src/commands/agents/sessions/shared.test.ts
  • packages/cli/src/commands/agents/sessions/shared.ts
  • packages/cli/src/commands/agents/sessions/wait/command.ts
  • packages/cli/src/commands/workspaces/create/agent-results.test.ts
  • packages/cli/src/commands/workspaces/create/agent-results.ts
  • packages/cli/src/commands/workspaces/create/command.ts
  • packages/cli/src/lib/host-agent-sessions.ts
  • packages/cli/src/lib/host-target/index.ts
  • packages/cli/src/lib/host-target/queryHostTargets.test.ts
  • packages/cli/src/lib/host-target/queryHostTargets.ts
  • packages/cli/src/lib/host-workspaces/listHostWorkspaces.ts
  • packages/cli/test/e2e/agent-sessions.e2e.ts
  • packages/cli/test/e2e/harness.ts
  • packages/cli/test/fixtures/fake-terminal-agent.mjs
  • packages/cli/tsconfig.json
  • packages/host-service/src/daemon/DaemonSupervisor.test.ts
  • packages/host-service/src/daemon/DaemonSupervisor.ts
  • packages/host-service/src/terminal-agents/index.ts
  • packages/host-service/src/terminal-agents/status.test.ts
  • packages/host-service/src/terminal-agents/status.ts
  • packages/host-service/src/terminal/DaemonClient/DaemonClient.node-test.ts
  • packages/host-service/src/terminal/DaemonClient/DaemonClient.ts
  • packages/host-service/src/terminal/DaemonClient/index.ts
  • packages/host-service/src/terminal/terminal-snapshot.test.ts
  • packages/host-service/src/terminal/terminal-snapshot.ts
  • packages/host-service/src/terminal/terminal.adoption.node-test.ts
  • packages/host-service/src/terminal/terminal.ts
  • packages/host-service/src/trpc/router/agents/agent-launch.test.ts
  • packages/host-service/src/trpc/router/agents/agent-launch.ts
  • packages/host-service/src/trpc/router/agents/agents.test.ts
  • packages/host-service/src/trpc/router/agents/agents.ts
  • packages/host-service/src/trpc/router/agents/attachment-prompt.ts
  • packages/host-service/src/trpc/router/terminal-agents/terminal-agents.test.ts
  • packages/host-service/src/trpc/router/terminal-agents/terminal-agents.ts
  • packages/host-service/test/fixtures/agent-sessions-cli-host.ts
  • packages/pty-daemon/package.json
  • packages/pty-daemon/src/Server/Server.ts
  • packages/pty-daemon/src/SessionStore/SessionStore.test.ts
  • packages/pty-daemon/src/SessionStore/SessionStore.ts
  • packages/pty-daemon/src/SessionStore/snapshot.test.ts
  • packages/pty-daemon/src/SessionStore/snapshot.ts
  • packages/pty-daemon/src/handlers/handlers.test.ts
  • packages/pty-daemon/src/handlers/handlers.ts
  • packages/pty-daemon/src/handlers/index.ts
  • packages/pty-daemon/src/protocol/index.ts
  • packages/pty-daemon/src/protocol/messages.ts
  • packages/pty-daemon/src/protocol/version.ts
  • packages/pty-daemon/src/protocol/wire-shape.test.ts
  • packages/pty-daemon/test/control-plane.test.ts
  • packages/pty-daemon/test/helpers/client.ts
  • packages/pty-daemon/test/integration.test.ts
  • skills/superset/SKILL.md
💤 Files with no reviewable changes (44)
  • packages/host-service/src/trpc/router/agents/attachment-prompt.ts
  • packages/cli/src/commands/agents/sessions/meta.ts
  • packages/host-service/src/terminal-agents/status.ts
  • packages/host-service/src/terminal-agents/status.test.ts
  • packages/pty-daemon/src/handlers/index.ts
  • apps/desktop/docs/CLI_CDP_E2E.md
  • packages/cli/src/commands/agents/sessions/wait/command.ts
  • packages/cli/src/commands/agents/sessions/read/command.ts
  • packages/cli/src/commands/workspaces/create/agent-results.ts
  • packages/cli/src/commands/agents/sessions/send/command.test.ts
  • packages/host-service/src/trpc/router/terminal-agents/terminal-agents.test.ts
  • packages/cli/test/fixtures/fake-terminal-agent.mjs
  • packages/cli/src/commands/workspaces/create/agent-results.test.ts
  • packages/host-service/src/trpc/router/agents/agent-launch.test.ts
  • packages/cli/src/commands/agents/sessions/shared.test.ts
  • packages/host-service/src/terminal/DaemonClient/index.ts
  • packages/pty-daemon/src/SessionStore/snapshot.test.ts
  • packages/cli/src/lib/host-target/queryHostTargets.ts
  • packages/host-service/src/trpc/router/agents/agent-launch.ts
  • packages/host-service/src/terminal/terminal-snapshot.test.ts
  • packages/host-service/test/fixtures/agent-sessions-cli-host.ts
  • packages/cli/src/lib/host-agent-sessions.ts
  • packages/cli/test/e2e/agent-sessions.e2e.ts
  • packages/host-service/src/terminal/terminal-snapshot.ts
  • packages/cli-framework/src/parser.test.ts
  • packages/cli/src/commands/agents/sessions/send/command.ts
  • packages/cli/src/commands/agents/sessions/shared.ts
  • packages/pty-daemon/src/protocol/messages.ts
  • packages/cli/src/lib/host-target/queryHostTargets.test.ts
  • packages/cli/package.json
  • packages/cli/src/commands/agents/sessions/list/command.ts
  • package.json
  • packages/cli/src/commands/workspaces/create/command.ts
  • packages/pty-daemon/src/SessionStore/SessionStore.test.ts
  • packages/pty-daemon/src/handlers/handlers.ts
  • packages/host-service/src/terminal-agents/index.ts
  • AGENTS.md
  • packages/pty-daemon/src/handlers/handlers.test.ts
  • packages/cli/src/lib/host-target/index.ts
  • packages/pty-daemon/src/SessionStore/snapshot.ts
  • packages/pty-daemon/src/Server/Server.ts
  • packages/pty-daemon/src/protocol/index.ts
  • packages/host-service/src/terminal/terminal.adoption.node-test.ts
  • packages/cli/test/e2e/harness.ts

Comment on lines +63 to +84
let targetHostIds: string[];
if (options.hostId) {
targetHostIds = [options.hostId];
} else if (hosts.length > 0) {
const ids = new Set(
hosts.filter((host) => host.online).map((host) => host.id),
);
// Cloud presence can lag: always include this machine's host when its
// host-service manifest points at a live process.
const manifest = readManifest(options.organizationId);
if (manifest && isProcessAlive(manifest.pid)) {
ids.add(localHostId);
}
targetHostIds = [...ids];
} else {
if (discoveryError !== undefined) {
warnings.push(
`Cloud host discovery failed (${describeError(discoveryError)}); listing this machine's host only`,
);
}
targetHostIds = [localHostId];
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Silent empty result when discovered hosts exist but none are online/reachable.

If options.api.host.list.query succeeds and returns hosts, but none are online and the local manifest is missing/stale, ids (and thus targetHostIds) ends up empty. Promise.allSettled([]) then produces no results, so the function returns { workspaces: [], warnings: [] } with no explanation — the caller can't tell "no workspaces exist" apart from "no hosts are reachable." The sibling else branch (cloud discovery failure) already handles this correctly by warning and falling back to localHostId; this branch should do the same.

🛠️ Proposed fix
 		const manifest = readManifest(options.organizationId);
 		if (manifest && isProcessAlive(manifest.pid)) {
 			ids.add(localHostId);
 		}
 		targetHostIds = [...ids];
+		if (targetHostIds.length === 0) {
+			warnings.push(
+				"No hosts are currently online; listing this machine's host only",
+			);
+			targetHostIds = [localHostId];
+		}
 	} else {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let targetHostIds: string[];
if (options.hostId) {
targetHostIds = [options.hostId];
} else if (hosts.length > 0) {
const ids = new Set(
hosts.filter((host) => host.online).map((host) => host.id),
);
// Cloud presence can lag: always include this machine's host when its
// host-service manifest points at a live process.
const manifest = readManifest(options.organizationId);
if (manifest && isProcessAlive(manifest.pid)) {
ids.add(localHostId);
}
targetHostIds = [...ids];
} else {
if (discoveryError !== undefined) {
warnings.push(
`Cloud host discovery failed (${describeError(discoveryError)}); listing this machine's host only`,
);
}
targetHostIds = [localHostId];
}
let targetHostIds: string[];
if (options.hostId) {
targetHostIds = [options.hostId];
} else if (hosts.length > 0) {
const ids = new Set(
hosts.filter((host) => host.online).map((host) => host.id),
);
// Cloud presence can lag: always include this machine's host when its
// host-service manifest points at a live process.
const manifest = readManifest(options.organizationId);
if (manifest && isProcessAlive(manifest.pid)) {
ids.add(localHostId);
}
targetHostIds = [...ids];
if (targetHostIds.length === 0) {
warnings.push(
"No hosts are currently online; listing this machine's host only",
);
targetHostIds = [localHostId];
}
} else {
if (discoveryError !== undefined) {
warnings.push(
`Cloud host discovery failed (${describeError(discoveryError)}); listing this machine's host only`,
);
}
targetHostIds = [localHostId];
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/lib/host-workspaces/listHostWorkspaces.ts` around lines 63 -
84, Update the host-selection logic in listHostWorkspaces so that when discovery
returns hosts but the online-host Set is empty after the local manifest check,
it adds a warning explaining that no discovered hosts are reachable and falls
back to localHostId. Preserve the existing targetHostIds behavior when reachable
hosts are present and retain the discovery-error fallback in the sibling branch.

@Kitenite
Kitenite merged commit cdf55f9 into main Jul 21, 2026
18 checks passed
saddlepaddle added a commit that referenced this pull request Jul 24, 2026
Adds a public API to message an already-running terminal agent (claude/codex)
instead of re-spawning a session per message via agents.create — which spiked
terminal-session counts and started a fresh CLI each time rather than
continuing the conversation.

Host (host-service):
- ModeTracker.isBracketedPasteActive() + snapshot() off the existing
  per-session headless xterm; scrollback 1 -> 1000 so snapshot serves
  line-mode history.
- writeFramedInputToSession (bracketed-paste framing + Enter) and
  snapshotSession. Both adopt daemon-owned sessions on an in-memory miss
  (same adoptOnly path pane auto-adoption uses), so background agents stay
  reachable across host-service restarts.
- terminal.send mutation + terminal.snapshot query.

Public surfaces — the terminals resource gains list/send/read/close alongside
create, following the explicit-host-targeting convention (#5885):
- MCP v2: terminals_list/_send/_read/_close with tool annotations
- SDK: client.terminals.list/send/read/close
- CLI: superset terminals list/send/read/close (--host defaults to this
  machine)

close reuses the existing terminal.killSession; list reuses
terminal.listSessions (daemon+DB truth, #5823). No pty-daemon or protocol
changes — this is the surgical subset of the capability #5784 attempted
before its revert (#5837).

Recommended flow: agents.create once to start, then terminals.send for
follow-ups (0 new sessions) and terminals.read to observe the reply.

Claude-Session: https://claude.ai/code/session_01C4cXgxgH3A7k3qHSLEyFNJ
saddlepaddle added a commit that referenced this pull request Jul 24, 2026
#5256)

* feat(terminals): send/read/close follow-ups to running terminal agents

Adds a public API to message an already-running terminal agent (claude/codex)
instead of re-spawning a session per message via agents.create — which spiked
terminal-session counts and started a fresh CLI each time rather than
continuing the conversation.

Host (host-service):
- ModeTracker.isBracketedPasteActive() + snapshot() off the existing
  per-session headless xterm; scrollback 1 -> 1000 so snapshot serves
  line-mode history.
- writeFramedInputToSession (bracketed-paste framing + Enter) and
  snapshotSession. Both adopt daemon-owned sessions on an in-memory miss
  (same adoptOnly path pane auto-adoption uses), so background agents stay
  reachable across host-service restarts.
- terminal.send mutation + terminal.snapshot query.

Public surfaces — the terminals resource gains list/send/read/close alongside
create, following the explicit-host-targeting convention (#5885):
- MCP v2: terminals_list/_send/_read/_close with tool annotations
- SDK: client.terminals.list/send/read/close
- CLI: superset terminals list/send/read/close (--host defaults to this
  machine)

close reuses the existing terminal.killSession; list reuses
terminal.listSessions (daemon+DB truth, #5823). No pty-daemon or protocol
changes — this is the surgical subset of the capability #5784 attempted
before its revert (#5837).

Recommended flow: agents.create once to start, then terminals.send for
follow-ups (0 new sessions) and terminals.read to observe the reply.

Claude-Session: https://claude.ai/code/session_01C4cXgxgH3A7k3qHSLEyFNJ

* test(host-service): e2e coverage for terminal send/snapshot; deterministic adoption replay wait

Real-daemon node-test suite (same harness as terminal.adoption.node-test)
covering the headless follow-up surface: send delivers text + Enter,
submit: false stages without executing, snapshot serves normal and
alt-screen buffers plus maxLines, bracketed-paste framing verified
byte-for-byte via `cat > f`, restart-adoption for both verbs, and the
not-found / exited / cross-workspace error paths. 10 consecutive runs green.

Replaces the fixed 300ms post-adoption sleep with a wait for the replayed
ring-buffer bytes to quiesce (they accumulate in session.buffer because no
renderer is attached right after adoption), capped at 500ms. Typical
adoption now settles in ~50ms instead of a blind 300ms, and slow replays
no longer race the tracker rebuild. eventBus is optional on the new
functions, matching createTerminalSessionInternal.

Claude-Session: https://claude.ai/code/session_01C4cXgxgH3A7k3qHSLEyFNJ

* test(host-service): exercise terminal.send/snapshot through the tRPC wire layer

Same real-daemon harness, now also through appRouter.createCaller — the
layer the public MCP/SDK/CLI verbs actually hit. Verifies the zod schemas,
the submit-defaults-to-true behavior, and the error mapping: NOT_FOUND for
missing terminals, FORBIDDEN for cross-workspace targeting, BAD_REQUEST for
empty text, UNAUTHORIZED for unauthenticated callers.

The suite now runs with the tsx loader (the router tree uses extensionless
imports that --experimental-strip-types cannot resolve).

Claude-Session: https://claude.ai/code/session_01C4cXgxgH3A7k3qHSLEyFNJ

This branch was previously deployed

1 inactive deployment
preview — efa6d3c8 Deployed Jul 21, 2026 by Kitenite via Deploy Web #6737
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant