From a7240f394dd70158db87e369ad4a663e7df9255e Mon Sep 17 00:00:00 2001 From: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Date: Tue, 28 Jul 2026 19:42:12 +0800 Subject: [PATCH] fix(agents): label forking the same for every agent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fork row said "Branch Session" on Claude Code and "Fork Session" everywhere else, on the strength of a source comment claiming "Claude Code calls it branching". It does not. `claude --help` documents the flag as `--fork-session`, described as "When resuming, create a new session ID instead of reusing the original"; the only occurrences of "branch" in its help are an unrelated git-branch review option. The claim came from otty's own UI wording, which I mistook for Claude's vocabulary and then wrote into the source as fact — so the comment goes with the special case rather than being left behind as a false statement about someone else's tool. The split was also inconsistent with itself: Grok takes the identical `--fork-session` flag and was already labelled "Fork Session". Every agent that has the capability calls it forking — `codex fork`, `--fork-session` on Claude Code and Grok, `--fork` on OpenCode — so one wording covers all four. `fork_label` keeps returning `Option<&'static str>`: it is still the UI's single capability gate (`None` = no verified fork command, no row offered), and per-agent wording stays expressible should one ever genuinely diverge. Generated commands are untouched — the existing table test still pins `claude --resume --fork-session` and the other three verbatim. Also drops the two doc sentences that promised the per-agent label, and the stale "Branch Session" mentions left in comments; no occurrence survives anywhere in the tree. --- crates/tty7-core/src/core/cli_agent.rs | 16 +++++++++------- docs/features.md | 2 +- docs/features.zh-CN.md | 2 +- src/terminal/view.rs | 3 +-- src/ui/app.rs | 8 ++++---- src/ui/tab_strip.rs | 15 +++++++-------- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/crates/tty7-core/src/core/cli_agent.rs b/crates/tty7-core/src/core/cli_agent.rs index b645a1e1..f83ee2b9 100644 --- a/crates/tty7-core/src/core/cli_agent.rs +++ b/crates/tty7-core/src/core/cli_agent.rs @@ -265,15 +265,17 @@ impl CLIAgent { } } - /// The agent's own word for forking, for menu labels — otty's convention, - /// and the word a user hunting the menu will be looking for. `Some` exactly - /// when [`fork_command`](Self::fork_command) can build a command, so the UI - /// can use it as the single capability gate. + /// The menu label for forking this agent's session — one wording for every + /// agent, because every agent that has the capability calls it forking + /// (`codex fork`; `--fork-session` on Claude Code and Grok; `--fork` on + /// OpenCode). `Some` exactly when [`fork_command`](Self::fork_command) can + /// build a command, so the UI can use it as the single capability gate; + /// per-agent wording stays expressible here should one ever diverge. pub fn fork_label(self) -> Option<&'static str> { match self { - // Claude Code calls it branching. - CLIAgent::Claude => Some("Branch Session"), - CLIAgent::Codex | CLIAgent::Grok | CLIAgent::OpenCode => Some("Fork Session"), + CLIAgent::Claude | CLIAgent::Codex | CLIAgent::Grok | CLIAgent::OpenCode => { + Some("Fork Session") + } _ => None, } } diff --git a/docs/features.md b/docs/features.md index e41cdace..1b0efa79 100644 --- a/docs/features.md +++ b/docs/features.md @@ -60,7 +60,7 @@ it never wraps or replaces the agent. - **Notifications** — "needs your permission…" the moment an agent blocks on you, and "finished after Ns" per turn, honoring your notification policy - **Branch at a glance** — each sidebar row shows its pane's git branch and working-tree diff (`+N −M`), refreshed on `cd` and when a command finishes - **Session resume** — panes lost to a reboot re-launch their agent conversation on restore, carrying the original launch flags (`claude --dangerously-skip-permissions --resume …`) (`restore_agent_sessions`, on by default) -- **Fork session** — branch a live agent conversation into a second, independent one by shelling the agent's own fork command (`codex fork `, `claude --resume --fork-session`, also OpenCode and Grok Build); the original is untouched and both continue separately. Right-click a pane to pick a split placement, or right-click the tab / sidebar row to open the fork in a new tab. The row is labelled with the agent's own word for it, so a Claude Code pane says *Branch Session*. Needs the agent's hooks installed, since the fork targets the session id they report; a remote pane can't fork, because the command would run against the local agent — and note a fork copies the whole transcript, so repeated forking costs real disk in the agent's own session store +- **Fork session** — branch a live agent conversation into a second, independent one by shelling the agent's own fork command (`codex fork `, `claude --resume --fork-session`, also OpenCode and Grok Build); the original is untouched and both continue separately. Right-click a pane to pick a split placement, or right-click the tab / sidebar row to open the fork in a new tab. Needs the agent's hooks installed, since the fork targets the session id they report; a remote pane can't fork, because the command would run against the local agent — and note a fork copies the whole transcript, so repeated forking costs real disk in the agent's own session store - **Copy Session ID** — put the agent's native session id on the clipboard, beside *Copy Working Directory*, for pasting into `codex resume`, a bug report, or another tool - **Context feed** — palette commands send the current selection or the repo's `git diff` to the running agent as a ready-made prompt - **Tray icon** — a system tray / menu bar item that flips to an attention state the moment any agent needs your input; its menu lists every agent pane (brand avatar + status dot, click to reveal), switches the notification policy, and offers *Quit and Stop Daemon* alongside the plain session-keeping quit (`show_tray_icon`, on by default) diff --git a/docs/features.zh-CN.md b/docs/features.zh-CN.md index 918bfb66..94730bb6 100644 --- a/docs/features.zh-CN.md +++ b/docs/features.zh-CN.md @@ -57,7 +57,7 @@ Aider、Amp、OpenCode 等约 17 个)并在其外围加功能 —— 绝不包 - **通知** —— agent 卡在等你批准的那一刻弹 "needs your permission…",每轮结束弹 "finished after Ns",遵循你的通知策略 - **一眼看分支** —— 侧栏每行显示该 pane 的 git 分支和工作区改动(`+N −M`),`cd` 或命令跑完时自动刷新 - **会话恢复** —— 重启后无法重连的 pane 会自动续上 agent 对话,并带上原始启动 flags(`claude --dangerously-skip-permissions --resume …`;`restore_agent_sessions`,默认开启) -- **Fork 会话** —— 直接调 agent 自己的 fork 命令(`codex fork `、`claude --resume --fork-session`,OpenCode 和 Grok Build 同样支持),把当前对话分叉成一个独立会话;原会话原封不动,两边各自往下走。在 pane 上右键可选择分屏位置,在标签 / 侧栏行上右键则直接开新标签。菜单项用的是各 agent 自己的说法,所以 Claude Code 的 pane 里显示的是 *Branch Session*。需要先装好该 agent 的 hooks(fork 认的是 hooks 上报的 session id);远程 pane 不能 fork,因为命令会跑在本机的 agent 上;另外 fork 会整份复制对话历史,反复 fork 会在 agent 自己的会话目录里占掉不少磁盘 +- **Fork 会话** —— 直接调 agent 自己的 fork 命令(`codex fork `、`claude --resume --fork-session`,OpenCode 和 Grok Build 同样支持),把当前对话分叉成一个独立会话;原会话原封不动,两边各自往下走。在 pane 上右键可选择分屏位置,在标签 / 侧栏行上右键则直接开新标签。需要先装好该 agent 的 hooks(fork 认的是 hooks 上报的 session id);远程 pane 不能 fork,因为命令会跑在本机的 agent 上;另外 fork 会整份复制对话历史,反复 fork 会在 agent 自己的会话目录里占掉不少磁盘 - **复制 Session ID** —— 把 agent 的原生 session id 复制到剪贴板,就在 *Copy Working Directory* 旁边,方便粘进 `codex resume`、bug 报告或别的工具 - **上下文回填** —— 面板命令把当前选区或仓库 `git diff` 打包成 prompt 直接喂给正在跑的 agent - **托盘图标** —— 系统托盘 / 菜单栏常驻图标,任何 agent 等你输入时立即切换为提醒态;菜单列出所有 agent pane(品牌头像 + 状态点,点击直达)、可切换通知策略,并在保留会话的普通退出之外提供 *Quit and Stop Daemon*(`show_tray_icon`,默认开启) diff --git a/src/terminal/view.rs b/src/terminal/view.rs index 1d23670c..bc7b5100 100644 --- a/src/terminal/view.rs +++ b/src/terminal/view.rs @@ -6337,8 +6337,7 @@ impl Render for TerminalView { // inherit it. // // Offered only for agents tty7 has a verified fork command - // for, labelled with that agent's own word for it ("Fork - // Session" / "Branch Session"). A *pane*-level ask is a spatial + // for. A *pane*-level ask is a spatial // one, so this menu asks where the fork goes; the tab menu, // which has no pane in hand, just opens a new tab (issue #211). // Disabled — not hidden — until the session id is known, so the diff --git a/src/ui/app.rs b/src/ui/app.rs index 90b09c16..547ecbd3 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -730,8 +730,8 @@ pub(crate) enum ForkPlacement { /// menu-open time (like `tab_cwd`) so enablement can't go stale between render /// and click. pub(crate) struct TabAgentSession { - /// The agent's own word for forking, or `None` when tty7 has no verified - /// fork command for it — then no fork row is offered at all, rather than a + /// The fork row's label, or `None` when tty7 has no verified fork command + /// for this agent — then no fork row is offered at all, rather than a /// disabled one promising a capability that doesn't exist. pub(crate) fork_label: Option<&'static str>, /// The agent's native session id, absent until its hooks report one. @@ -3728,8 +3728,8 @@ impl Tty7App { } } - /// What the tab's agent-session menu rows ("Fork Session" / "Branch - /// Session" and "Copy Session ID") need, or `None` when the tab's + /// What the tab's agent-session menu rows ("Fork Session" and "Copy Session + /// ID") need, or `None` when the tab's /// label-driving pane runs no coding agent — then neither row is offered. /// Reads the same leaf `tab_cwd` does, so all three rows agree on which /// pane a tab-level action means. diff --git a/src/ui/tab_strip.rs b/src/ui/tab_strip.rs index 980a2034..042c4fed 100644 --- a/src/ui/tab_strip.rs +++ b/src/ui/tab_strip.rs @@ -1010,14 +1010,13 @@ impl Tty7App { })); } - // Fork / Branch Session — the same kind of operation as New Worktree - // Tab (spin a parallel line of work off this one), so it sits in the - // same block. A *tab*-level ask carries no placement question, so it - // lands in a new tab; the pane right-click menu is where the split - // directions live (issue #211). Offered only for agents tty7 has a - // verified fork command for, labelled with that agent's own word for - // it; disabled — not hidden — while the session id is still unknown, - // so the capability stays discoverable when the hooks aren't installed. + // Fork Session — the same kind of operation as New Worktree Tab (spin a + // parallel line of work off this one), so it sits in the same block. A + // *tab*-level ask carries no placement question, so it lands in a new + // tab; the pane right-click menu is where the split directions live + // (issue #211). Offered only for agents tty7 has a verified fork command + // for; disabled — not hidden — while the session id is still unknown, so + // the capability stays discoverable when the hooks aren't installed. let agent_session = this.tab_agent_session(index, window, cx); if let Some(session) = &agent_session && let Some(label) = session.fork_label