diff --git a/agent/display.py b/agent/display.py index bd1367a37..b87e272d2 100644 --- a/agent/display.py +++ b/agent/display.py @@ -535,3 +535,46 @@ def get_cute_tool_message( preview = build_tool_preview(tool_name, args) or "" return _wrap(f"┊ ⚡ {tool_name[:9]:9} {_trunc(preview, 35)} {dur}") + + +# ========================================================================= +# Honcho session line (one-liner with clickable OSC 8 hyperlink) +# ========================================================================= + +_DIM = "\033[2m" +_SKY_BLUE = "\033[38;5;117m" +_ANSI_RESET = "\033[0m" + + +def honcho_session_url(workspace: str, session_name: str) -> str: + """Build a Honcho app URL for a session.""" + from urllib.parse import quote + return ( + f"https://app.honcho.dev/explore" + f"?workspace={quote(workspace, safe='')}" + f"&view=sessions" + f"&session={quote(session_name, safe='')}" + ) + + +def _osc8_link(url: str, text: str) -> str: + """OSC 8 terminal hyperlink (clickable in iTerm2, Ghostty, WezTerm, etc.).""" + return f"\033]8;;{url}\033\\{text}\033]8;;\033\\" + + +def honcho_session_line(workspace: str, session_name: str) -> str: + """One-line session indicator: `Honcho session: `.""" + url = honcho_session_url(workspace, session_name) + linked_name = _osc8_link(url, f"{_SKY_BLUE}{session_name}{_ANSI_RESET}") + return f"{_DIM}Honcho session:{_ANSI_RESET} {linked_name}" + + +def write_tty(text: str) -> None: + """Write directly to /dev/tty, bypassing stdout capture.""" + try: + fd = os.open("/dev/tty", os.O_WRONLY) + os.write(fd, text.encode("utf-8")) + os.close(fd) + except OSError: + sys.stdout.write(text) + sys.stdout.flush() diff --git a/cli.py b/cli.py index d8c3e64db..eab52af4f 100755 --- a/cli.py +++ b/cli.py @@ -2681,6 +2681,8 @@ class HermesCLI: self.agent._honcho_session_key = new_key from tools.honcho_tools import set_session_context set_session_context(self.agent._honcho, new_key) + from agent.display import honcho_session_line, write_tty + write_tty(honcho_session_line(hcfg.workspace_id, new_key) + "\n") _cprint(f" Honcho session: {old_key} → {new_key}") except Exception: pass @@ -3743,6 +3745,18 @@ class HermesCLI: """Run the interactive CLI loop with persistent input at bottom.""" self.show_banner() + # One-line Honcho session indicator (TTY-only, not captured by agent) + try: + from honcho_integration.client import HonchoClientConfig + from agent.display import honcho_session_line, write_tty + hcfg = HonchoClientConfig.from_global_config() + if hcfg.enabled: + sname = hcfg.resolve_session_name(session_id=self.session_id) + if sname: + write_tty(honcho_session_line(hcfg.workspace_id, sname) + "\n") + except Exception: + pass + # If resuming a session, load history and display it immediately # so the user has context before typing their first message. if self._resumed: