Issue #376 asked for `omp`. Oh My Pi is a fork of Pi (can1357/oh-my-pi, descended from badlogic/pi-mono), but the fork is where the similarity stops for our purposes: it ships one binary of its own — `omp`, the only `bin` in `@oh-my-pi/pi-coding-agent`, and it never installs a `pi` — and it keeps its config under `~/.omp`. A pane running it was therefore not detected at all, and aliasing `omp` onto `CLIAgent::Pi` would have been worse than nothing: the status bridge would land in `~/.pi`, and Resume Session would offer `pi --session <id>` to a binary that spells that flag `--resume`. So it gets its own variant, wired the whole way through: | | | |---|---| | Detection | argv stem `omp`, distinct from `pi` in both directions | | Avatar | its own mark, normalized from the project's `assets/icon.svg` | | Resume | `omp --resume <id>`, opting out on `--no-session` | | Fork | `omp --fork <id>` — a verified fork command, so the menu item appears | | Hooks | Settings → Agents, at `~/.omp/agent/extensions/tty7/index.ts` | The status bridge is the one piece the fork did not change. Oh My Pi inherited Pi's extension contract intact — same default-exported factory, same `session_start` / `agent_start` / `agent_end` / `session_shutdown`, same `ctx.sessionManager.getSessionId()` — so `pi_extension_ts` now takes the agent and substitutes two things, the package it imports the type from and the slug it calls the emitter with. Pi's generated file is byte-identical to before, so no installed bridge goes stale. `--resume`, `-r` and `--session` are three spellings of one flag in Oh My Pi; all three shed when a session command is rebuilt, while `--session-dir` is a different flag and rides along. `fork_command` now honors the same `--no-session` opt-out `resume_command` already did — Oh My Pi rejects `--fork` outright under it, and no existing agent declares an opt-out.
13 KiB
功能
English · 简体中文
输入
- 影子建议 —— 边打字边用你的历史补全整条命令,→ 接受
- 带说明的 Tab 补全 —— 每个 flag、每个子命令都带说明,覆盖约 100 个常用命令;tty7 没有候选时 Tab 自动交给 shell 自己的补全,整个功能也可关闭(设置 → 终端 → 键盘,或
config.json里的tab_completion) - 语法高亮 —— 边打边亮,什么都不用装
- 模糊历史搜索 —— ⌃ R 看到每条命令在哪跑的、什么时候、有没有失败;关掉它(设置 → 终端 → 键盘,或
config.json里的history_search)后 ⌃ R 直接交给 shell,你绑的 fzf / percol 照常可用 - 历史开箱即用 —— 你已有的 shell 历史直接生效,并跨会话延续
- 行编辑 —— 点击定位光标、鼠标选区、词级移动、撤销
- 多行编辑 —— 折行和多行命令原地编辑;网格自动上移,光标始终可见。⇧ ⏎ · ⌥ ⏎ 插入换行而不提交(可改绑,动作名
InsertNewline),单独按 ⏎ 提交整个缓冲区
窗口
- 标签页与分屏 —— 永远开在当前目录
- 侧栏按仓库分组 —— 左侧标签栏按 git 仓库分组、每组一个标题行,不在仓库里的标签归入末尾的 Scratch 组;切分支、仓库内
cd都不会挪动行(config.json的sidebar_grouping:默认repo,none恢复扁平列表) - 命令面板 ⌘ P · scrollback 搜索 ⌘ F
- ⌘ 点击打开链接 · 桌面通知 · 划选即复制(可选,设置 → 终端 → 剪贴板)
- 智能双击选中 —— 双击直接选中整条 URL、文件路径、括号/引号对,中文按词典分词出词;Shift 点击扩展选区(设置 → 终端 → 鼠标可开关;分隔符用
config.json的word_separators配置) - 9 套主题,也能自定义 — YAML 种子主题,背景支持纯色、渐变或图片;可导入 iTerm2
.itermcolors;应用内颜色编辑器带背景图选择 - 跟随系统外观 — 设置 → Appearance;分别选好浅色和深色主题,tty7 随系统深浅模式实时切换(
config.json中的theme_follow_system、theme_preset_light/theme_preset_dark) - 窗口透明与模糊 — 设置 → Appearance → Window;对所有主题生效,Follow theme 恢复主题自带的
opacity/blur - CJK / 输入法输入
- Windows 资源管理器右键菜单 —— 安装程序提供 Add “Open in tty7” to the folder context menu 这个安装任务,默认不勾选,卸载时一律移除。写 shell verb 是安装期的决定,所以没有运行时开关;用 portable zip 的话可以自己执行
tty7-app.exe --register-explorer-menu(或--unregister-explorer-menu)。两种方式写入的键都在HKCU下,只影响你自己的 Windows 账户
字体
- 内置 Hack —— 打包进二进制,默认配置在各平台渲染完全一致,不依赖系统安装
- 主字体 + 有序 fallback ——
config.json里的font_family和font_fallbacks;可选font_family_bold/font_family_italic指定独立字面,font_features透传 OpenType 特性(上下文连字默认关闭) - 默认列表按平台分支 —— fallback 只写宿主系统真正自带的字体(macOS 用 PingFang SC / Apple Color Emoji,Windows 用 Microsoft YaHei / Segoe UI Emoji,Linux 用 Noto)。这些名字也会追加到你手写的列表后面,所以在别的平台写出来的
config.json一样能落地
中文与两列网格
一个格子等于主字体的一个 advance,宽字符(CJK)被钉死在正好两格上。所以中文 fallback 只有在汉字 advance 等于主字体西文 advance 的两倍时,才能严丝合缝地 填满自己的槽。
内置 Hack 的 advance 是 0.60205em,两格就是 1.2041em —— 而系统自带的中文字体 (Microsoft YaHei、PingFang SC、Noto Sans CJK)全都是 1.0em。这些字形在槽里左 对齐,多出来的约 0.2em 就变成每个字右边的一道空隙。
Maple Mono NF CN 在所有平台都排在 第一位正是因为这个 —— 西文 0.6em、中文 1.2em,对上 Hack 正好两格。它只按名字引 用,不打包(每字重约 20MB):装上即生效,不用改配置。
想让中文排得紧而不只是均匀,要换的是主字体:选一个 advance 为 0.5em 的 (比如 Sarasa Mono SC 更纱黑体等宽),两格就正好 1.0em。
Coding agent
tty7 能识别 pane 里跑着的第三方 coding agent(Claude Code、Codex、Gemini CLI、 Aider、Amp、OpenCode 等约 18 个)并在其外围加功能 —— 绝不包裹或替代 agent 本身。
- 品牌头像 —— 标签 chip / 侧栏行显示每个 pane 跑的是哪个 agent;自定义包装命令可通过
config.json的agent_commands映射 - 状态点 —— 工作中(蓝)/ 等你输入(琥珀)/ 完成(绿),由 agent 自己上报的 OSC 事件驱动;在 设置 → Agents 一键装好对应 hooks(Claude Code、Codex、Copilot CLI、OpenCode、Pi、Grok Build、Oh My Pi)
- 通知 —— agent 卡在等你批准的那一刻弹 "needs your permission…",每轮结束弹 "finished after Ns",遵循你的通知策略
- 一眼看分支 —— 侧栏每行显示该 pane 的 git 分支和工作区改动(
+N −M),cd或命令跑完时自动刷新;点改动数字会打开 diff 浮层,关掉它(设置 → 窗口与标签,或config.json的sidebar_diff_preview: false)分支和数字照常显示,只是不再可点 - 会话恢复 —— 重启后无法重连的 pane 会自动续上 agent 对话,并带上原始启动 flags(
claude --dangerously-skip-permissions --resume …;restore_agent_sessions,默认开启) - Fork 会话 —— 直接调 agent 自己的 fork 命令(
codex fork <id>、claude --resume <id> --fork-session,OpenCode、Grok Build 和 Oh My Pi 同样支持),把当前对话分叉成一个独立会话;原会话原封不动,两边各自往下走。在 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,默认开启) tty7 wait—— CLI 的编排原语:阻塞到某个 pane 的 agent 等待输入或完成一轮(tty7 wait %3 --until waiting,done --changed --timeout 600,超时退出码 124),让一个 agent 睡到同伴卡在权限确认的那一刻,而不是抓屏猜——然后tty7 capture %3 --plain收结果。agent 状态是电平不是边沿,所以--changed会忽略 wait 开始时 pane 本来就处在的那个状态;不加它的话,JSON 里的stale标记会告诉你这个答案是不是上一轮留下的- Orchestration skill —— 一个开关(设置 → Agents),安装一个 Claude Code skill(
~/.claude/skills/tty7-orchestration),教 primary agent 完整的委派循环——开 worker pane、发一个边界清晰的任务、wait等待、收结果。特意做成 skill 而非全局指令:平时只有一行描述占上下文,显式调用才加载全文,worker agent 也不会继承编排权限 tty7上 PATH —— CLI 随每个安装包一起发布,启动时自动放到 PATH 上,脚本和 coding agent 在任何终端里都能驱动 tty7。tty7 自己的 pane 里则一定可用,因为 pane 继承 app 的环境。Unix 上是往/opt/homebrew/bin、/usr/local/bin、~/.local/bin、~/bin、~/.cargo/bin中你 PATH 已经覆盖的那个目录里放一个软链;Windows 上是把安装目录追加到用户 PATH,卸载时再摘掉。你自己装的tty7一律保持原样,不会被覆盖。关掉:设置 → Agents,或config.json里install_cli_on_path: false
SSH
唯一路径就是原生 Rust SSH 栈(russh)—— profile、凭据、SFTP 全部内置,
不 shell 出 ssh,也没有系统 ssh 兼容模式。
- QuickConnect —— 面板里打
user@host[:port]回车即连;支持 IPv6[::1]:port - 保存 profile —— 完整连接配置,密码 / passphrase 进 OS keychain,不落盘
~/.ssh/configalias —— 直接输入 alias 即连(原生解析常用字段,尽力而为,走 russh),也可在设置页一键导入为 profile- GUI 认证 —— pane 内 sheet 输入密码、私钥 passphrase、2FA,并确认主机密钥(新主机 vs 已变更)
- 内置 SFTP —— 滑入式文件面板:浏览、上传 / 下载、重命名 / 删除 / chmod,可拖进 Finder
- 端口转发 —— Local / Remote / Dynamic,预配置或运行时增删,外加 ⌘ 点击
localhost:PORT一键转发 - 跳板与代理 —— 经 profile 引用或
ProxyJump多跳、ProxyCommand、SOCKS5 / HTTP
| 入口 | 连接方式 |
|---|---|
保存 profile · QuickConnect · 输入 user@host[:port] |
原生 russh —— SFTP · keychain · GUI 认证 · L/R/D 转发 |
~/.ssh/config alias |
原生解析后走 russh(Match/canonicalize/GSSAPI 不支持,且无回退) |
快捷键
下表按 macOS 记法书写 —— 在 Windows 和 Linux 上,把 ⌘ 读作 Ctrl。最常用的几个:
| ⌘ T · ⌘ W · ⌘ ⇧ T | 新建标签页 · 关闭标签页 · 恢复关闭的标签页 |
| ⌘ 1…⌘ 9 · ⌃ ⇥ · ⌃ ⇧ ⇥ | 跳到第 1–9 个标签页 · 下一个 · 上一个标签页 |
| ⌘ D · ⌘ ⇧ D | 向右分屏 · 向下分屏 |
| ⌘ ] · ⌘ [ | 下一个窗格 · 上一个窗格 |
| ⌘ ⌥ ←→↑↓ | 按方向切换焦点窗格 |
| ⌘ ⏎ · ⌘ ⇧ ⏎ | 切换全屏 · 最大化 / 还原窗格 |
| ⌘ K | 清屏并清空 scrollback |
| ⌘ P | 命令面板 |
| ⌘ F | 搜索 scrollback |
| ⌃ R | 模糊搜索 shell 历史 |
| ⌘ + · ⌘ − · ⌘ 0 | 字号增大 · 减小 · 重置 |
Settings → Keybindings(⌘ ,)列出全部快捷键。点一行、按下新键即可 (Esc 取消,Backspace 恢复默认),改完立即生效。窗格缩放与 交换默认不绑定键 —— 在这里绑定,或从命令面板执行。
tmux 预设 —— 把窗格/标签页操作映射到前缀键(默认 ⌃ B):
⌃ B C 新建标签页,⌃ B % 分屏,
⌃ B 接方向键切换焦点。单独按前缀键会在短暂延迟后送达 shell,
前缀 + 未绑定的键原样透传给终端。
性能说明
- 以设备速度读取 PTY,在渲染路径之外成批解析
- 热路径全程无锁 —— 再大的
cat也不会阻塞在渲染上 - 触发背压前,守护进程最多可领先窗口缓冲 16 MiB
macOS 隐私
窗格是从 app bundle 里的可执行文件 fork 出来的,所以程序申请受保护资源时, macOS 会把这次请求算到 tty7.app 头上。tty7 声明了对应的 TCC usage strings (摄像头、麦克风、通讯录、日历、提醒、照片、定位、本地网络、蓝牙、语音识别、 Apple Events、系统管理),这样程序才能正常弹出一次性授权窗口,而不是连弹窗都 没有就被直接拒绝。
不受 usage strings 覆盖的:
- 完全磁盘访问 —— 苹果没有为它定义 usage-string 键。要读写
~/Library/Mail、~/Library/Messages、~/Library/Safari或~/Library/Containers,需要在「系统设置」中手动授权。
声明 usage string 不等于持有权限:tty7.app 自己一项都没有拿到。你看到的每个 授权弹窗都属于你在窗格里运行的那个程序,也可以在「隐私与安全性」中撤销。
本地化
GUI 目前提供英文、简体中文和日文三套文案。在「设置 → 外观 → 语言」中选择,或直接改
config.json:
{ "gui_language": "zh-CN" }
只接受 en、zh-CN 和 ja-JP 三个值,其它值一律回落到 en。语言必须显式指定,不会
去猜系统语言。CLI 输出保持英文,保证 agent、脚本和开发者工作流的输出稳定可预测。