hermes - 💡(How to fix) Fix [Feature]: /split slash command — branch session AND open the branch in a new terminal window

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Root Cause

  1. Add a --new-window flag to /branch instead of a new command. Rejected because it conflates two distinct intents (/branch = "I'm going down a new path", /split = "I want a parallel sandbox while staying here") and would make the /branch codepath more conditional than it needs to be.

Code Example

/split                # spawn new window with auto-titled branch, stay in current session
/split <name>         # same, but with explicit branch name
/split --inplace      # fall back to /branch behaviour (switch current window) — useful when no GUI terminal is available

---

Split session "branch-name" (12 user messages)
  Parent session:   20260523_184227_a4f1c8   (this window)
  Branch session:   20260524_011503_b9d2e7   (opened in new window)
New terminal window spawned with: hermes --resume 20260524_011503_b9d2e7
RAW_BUFFERClick to expand / collapse

Problem or Use Case

/branch (alias /fork) already forks the current session and copies the transcript, but it switches the current window to the new branch. That's the wrong default for one specific (and common) workflow:

"I'm mid-conversation, working on something real, and I want to ask a quick side question or try a risky tangent — without losing my place or polluting this thread."

Today the user has to either:

  1. Run /branch, accept that the current window is now in the fork, then manually open another terminal and run hermes --resume <parent_id> to keep working in the parent
  2. Or script the whole thing themselves (open new terminal via AppleScript / wt.exe / gnome-terminal, copy session ID, run hermes --resume <new_branch_id> in it)

Both work but both put friction on a workflow that genuinely happens multiple times a day for power users with long-running sessions. The proposed /split keeps the common case to a single command: stay where you are, get a parallel window with the branched conversation, carry on.


Proposed Solution

Add a /split slash command. UX:

/split                # spawn new window with auto-titled branch, stay in current session
/split <name>         # same, but with explicit branch name
/split --inplace      # fall back to /branch behaviour (switch current window) — useful when no GUI terminal is available

After /split, the user's current window shows:

  ⑂ Split session "branch-name" (12 user messages)
  Parent session:   20260523_184227_a4f1c8   (this window)
  Branch session:   20260524_011503_b9d2e7   (opened in new window)
  ✓ New terminal window spawned with: hermes --resume 20260524_011503_b9d2e7

The current window's session is unchanged — same prompt, same context, ready for the next message. A second terminal opens running hermes --resume <new_session_id>.

Behaviour spec

  1. Reuse existing branch logic. Extract the body of _handle_branch_command (cli.py:6349) into a shared _create_branch_session(branch_name) -> (new_session_id, branch_title, msg_count) helper. Both /branch and /split call it. This guarantees the two commands stay in sync on session-creation semantics (history copy, parent linking, memory-provider notification via on_session_switch with reason="branch", title generation via get_next_title_in_lineage).

  2. /branch keeps current behaviour — switch current window to the new branch. Fully backwards compatible, no migration concern.

  3. /split differs only in two ways:

    • Does NOT mutate self.session_id / self.agent.session_id — the current window stays on the parent
    • Spawns a new OS terminal window running hermes --resume <new_session_id> after creating the branch
  4. Cross-platform window spawn (graceful fallback chain):

    • macOS: osascripttell application "Terminal" to do script "hermes --resume <id>"; detect iTerm2 via $TERM_PROGRAM == iTerm.app and use its dictionary instead
    • Linux: try in order — $TERMINAL, then x-terminal-emulator, gnome-terminal, konsole, xfce4-terminal, alacritty, kitty; pick the first one on PATH
    • Windows / WSL2: wt.exe new-tab for Windows Terminal; fall back to cmd.exe /c start hermes ...
    • If spawn fails or no GUI terminal detected (SSH, headless container, launchd / cron): print the hermes --resume <id> command + session ID for the user to run manually. Exit cleanly. The branch already exists in the SQLite session DB, user picks up from there. Do not silently switch the current window to the branch — that would surprise the user who explicitly asked for /split not /branch.
  5. --inplace flag for users who want /branch semantics on-demand without remembering which command does what.

  6. CommandDef registration: cli_only=True. Gateway platforms (Telegram, Discord, Slack) have no concept of "open a new window" — /split should be gated out of those platforms to avoid surprise. Documented in the gateway help.


Alternatives Considered

  1. Add a --new-window flag to /branch instead of a new command. Rejected because it conflates two distinct intents (/branch = "I'm going down a new path", /split = "I want a parallel sandbox while staying here") and would make the /branch codepath more conditional than it needs to be.

  2. Script the workflow client-side with a shell wrapper (hermes-split binary that wraps /branch + window spawn). Considered and even prototyped locally. Works, but it's:

    • Not discoverable (no /help entry)
    • Has to scrape session IDs from the running Hermes process
    • Has to be installed/maintained per machine
    • Doesn't benefit from the same memory-provider hook flow that the in-process /branch does (on_session_switch notification with the correct lineage metadata — see agent/memory_provider.py:173)
    • Pure cosmetic asymmetry: /branch is in-engine and ergonomic; hermes-split is a half-tier-down shell escape
  3. Add a tmux integration that auto-splits the current pane. Rejected — too tightly coupled to one terminal multiplexer. The proposed solution works in raw Terminal.app / iTerm2 / gnome-terminal / Windows Terminal without requiring tmux/zellij/wezterm.

  4. Leave /branch switching behaviour as-is and document the manual workflow ("after /branch, open a new terminal and hermes --resume <parent_id>"). Rejected — that's friction added to a workflow that's clearly common enough to deserve a first-class command.

Duplicate check: Searched open + closed issues on 2026-05-23 for split session window, branch new window, and fork session terminal. No existing request for this. The closest related item is #11347 (/detach — Run Hermes Agent in Background After Exiting CLI), but that's a different concept — background detachment of the current session vs. parallel window-spawn of a forked session. /split and /detach could coexist cleanly.


Implementation notes (for whoever picks this up)

Files that would change:

  • cli.py — extract _create_branch_session() helper from _handle_branch_command, add _handle_split_command() + _spawn_session_in_new_window(session_id) helper
  • hermes_cli/commands.py — add CommandDef("split", "Branch session and open the branch in a new terminal window", "Session", args_hint="[name] [--inplace]", cli_only=True) next to the existing branch entry on line 84
  • gateway/run.py — if cli_only=True gating works, no change needed; otherwise add parallel handler that degrades gracefully on non-CLI platforms
  • ui-tui/src/app/slash/commands/session.ts — add TUI parity entry next to the existing branch entry on line 201
  • website/docs/reference/slash-commands.md — add docs entry next to /branch on line 60
  • tests/cli/test_split_command.py (new) — mirror tests/cli/test_branch_command.py. Cover:
    • Current session state is unchanged after /split
    • Branch session exists in SQLite with correct parent link and copied history
    • Window spawn is mocked and called with the right hermes --resume <id> command
    • Fallback path triggers when spawn fails / no GUI terminal
    • --inplace flag falls through to existing /branch behaviour
  • tests/gateway/test_split_command.py (new) — verify gateway degrades cleanly (no spawn attempt for non-CLI sources)

Estimated size: ~80-150 LOC + ~150 LOC of tests. Most logic already exists in _handle_branch_command and just needs a clean refactor + the spawn helper + cross-platform fallback.

Out of scope (deliberately):

  • Window placement / tiling. /split opens a new window — it does NOT tile, position, or otherwise manage window geometry. Users who want tmux-style splits can wrap /split in their own workflow on top of tmux/zellij/wezterm.
  • Sharing live conversation between parent and branch. The branch is a fork at creation time. Subsequent messages in either session do NOT sync. Matches /branch semantics — what users expect from a fork.
  • Closing the current window automatically after /split. Could be added later behind a --close-parent flag if requested.

Edge cases handled in spec:

  • No conversation history → mirror /branch's existing guard
  • Session DB unavailable → mirror existing guard via format_session_db_unavailable()
  • Headless / SSH / Docker / launchd / cron contexts → detect via $DISPLAY (Linux), $TERM_PROGRAM (macOS), absence of tty; fall back to printing the resume command
  • iTerm2 vs Terminal.app on macOS → check $TERM_PROGRAM first
  • Window opens but hermes not on PATH → use sys.argv[0] to get the absolute path of the running hermes binary
  • Branch name collision → lineage-aware title generation already handled inside reused _create_branch_session() helper

Open questions for maintainers:

  • Preferred name (/split vs /branch --new-window vs something else)
  • Whether cli_only=True is the right gating for the CommandDef (my read: yes, since gateway platforms have no concept of "open a new window")
  • Preferred fallback when GUI terminal spawn fails — print-only vs auto-fall-through to /branch semantics

Prior art

  • /branch (alias /fork) in this codebase — already credited to Claude Code's /branch in the docstring at cli.py:6354
  • tmux split-window, zellij pane new — well-understood window-spawn UX
  • VS Code "Split Editor" — same workflow, different tool

Reproducibility context

This came up from a real workflow today: long-running session, mid-task, wanted to ask a side question without losing context. /branch did the fork correctly but left me with one window in the fork and the parent backgrounded — I had to manually hermes --resume <parent_id> in a new terminal window to keep the original work going. Doing that two or three times a session adds up.

The proposed /split keeps the common case ("I want to try a tangent without losing where I am") to a single command.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - 💡(How to fix) Fix [Feature]: /split slash command — branch session AND open the branch in a new terminal window