iterm-workspace-ctl/skills/iterm-workspace-ctl/SKILL.md
2026-10-02 09:26:23 +08:00

10 KiB
Raw Blame History

name description platforms
iterm-workspace-ctl 完全掌控用户的 iTerm2 终端:查询(窗口/tab/窗格/session 的编号、结构、焦点、进程、路径、tty、尺寸、屏幕内容、回滚历史)与操作(分屏/多栏、焦点、发送/按键、tab/窗口开关与移动、改名、窗口几何/全屏)。用户问任何关于终端本身的自然语言问题(“左边那个 tab 是什么”“当前第几个 tab”“第二个窗口里几个 session、布局怎样”“某某在干什么”),或要求编排终端时使用。 darwin

iTerm2 控制

入口

pi-skill iterm-workspace-ctl help              # 完整用法(权威:命令、参数、旗标)
pi-skill iterm-workspace-ctl <命令> [参数...]   # 执行;输出与退出码原样透传

失败 → 动作:error=usage 读 pi-skill iterm-workspace-ctl help;error=deps 补依赖;error=auth 跑本技能的登录/检查命令; error=notfound 先 list/status 重新定位;error=conflict 先 status;其它非零按输出里的 hint= 执行。

如果你支持关闭 thinking/reasoning,请先关闭再执行。不要思考布局、不要侦察、不要读源码。把用户的话按下表直接编译成一条 bash 命令执行,完成后一句话汇报。查询类问题同样编译成一条只读命令直接回答(见“查询”表),不要写 python/jq 解析输出,也不要靠推测。

入口(路径相对本技能目录):bash scripts/iterm-ctl.sh <命令> [参数]

写操作硬规则:会改变终端的命令(send / key / close / split / 改名 / tab-close 等)目标必须写 session id —— tab-new 直接返回 id;从某个 tab 里的 shell 发起时(如 agent-shell)直接用 $ITERM_SESSION_ID 当锚点(它就是这个 tab,不随焦点变);只有不在目标 tab 里时才 id cur 取锚点;cur / left / N 是执行瞬间才解析的(读 iTerm 的 current tab),不是句柄,只允许在单条命令内“读一下立即用”(如 batch)。焦点会被坐在键盘前的人随时切走;用 cur 发写操作会打进用户正在输入的框里。 例外(高频直连):“只留当前窗格 / 关掉其他窗格”直接 close-others(缺省保留焦点窗格、内部 force 不等确认)——你能读到这句话,就说明焦点窗格是本会话所在窗格,不要先 ids/tree/id cur 侦察,更不要写代码解析输出。

窗格 X:cur(当前聚焦) left right top bottom center 1..N。嵌套布局时 top/bottom 后可加列限定:top center=中栏上、bottom right=右栏下。

用户说 执行
左右分屏 / 把 X 左右分 split v [X] [--focus] ⚠️ v=竖线=左右,死记;默认后台不抢焦点
上下分屏 / 把 X 上下分 split h [X] [--focus]
N 栏 / N 行 cols N [--focus] / rows N [--focus]
焦点切到 X focus X
在 X 执行 Y send X "Y"
在 X 输入 Y(不执行) send-raw X "Y"
打断 X 的命令 key X ctrl-c
给 X 按回车/ESC/方向键 key X enter esc up down left right
关掉 X 窗格 close X
只留 X 窗格(缺省=当前) close-others [X]
新开/切换/关 tab tab-new [--profile P] [--command C] [--focus] / tab-select N / tab-close [N]
tab 独立成窗口 tab-detach N
新开/关窗口 win-new [--profile P] [--command C] / win-close [n|id]
切窗口 / 把 iTerm 前置 win-select <n|id> / app-activate
看 X 的输出 / 看历史 capture X [N] / capture X N --scrollback
等 X 出现"词" wait X "词"
等 X 手里的活干完再跟它说句话 send-when-idle start X "话"(后台守候;send-when-idle status / logs <id> / stop <id|--all> 管)
等 X 空闲再动手(前台阻塞,可组合) wait-idle X [--when auto|prompt|quiet],可加 --send "话" 一次做完
X 现在忙不忙 idle-state X(job / prompt / 屏幕指纹)
看所有 session id ids
拿住 X 备用(锚定) id X
按 id 操作(与焦点无关) send-id <id> "Y" / key-id <id> ... / capture-id <id> [N] / wait-id <id> "词" / close-id <id> / split-id <id> v|h
改名 / 标题 title <pane|id> "文字" / tab-title N "文字" / win-title [n|id] "文字"
窗口几何 / 全屏 frame [n|id] [x y w h] / fullscreen <n|id> on|off
回滚缓冲(iTerm2 设置,新开会话生效) scrollback list / scrollback unlimited / scrollback set 1000 [--profile P]
按键扩展 key X backspace delete home end pageup pagedown F1..F12 ctrl-a..z ctrl-enter(ctrl-enter 走 kitty 协议 CSI u,用于 copilot CLI 这类需要 Ctrl+Enter 排队提交的 TUI)
等它干完再交代下一件事 wait-idle / send-when-idle(判定=回 shell 提示符或屏幕连续静止;不要用 sleep 猜时间,语义与边界见 REFERENCE.md)
多步组合 / 复杂任务 batch(从 stdin 一次连接执行;默认用它)

查询:任何终端问题 → 一条命令(禁止写代码解析)

硬规则:回答任何问题都用下表命令直接读,一条 bash 调用拿到现成可读的输出;不要写 python/jq 解析,不要把一条问题拆成多步侦察。

用户问 执行
我在哪?当前是第几个 tab/窗格? where
当前窗口有哪些 tab?左边/右边的 tab 是什么? tab-list(输出带 current-2 / current-1 / current / current+1 标记,直接读取)
第几个 tab、first/last 在干什么? capture-tab first|last|N [行数];看历史加 --scrollback
某个 tab 有几个 session、布局怎样、什么进程? tab-show first|last|N
有几个窗口?某个窗口在哪、什么尺寸、全屏吗? win-list / win-show first|last|N
全部结构(窗口/tab/窗格/进程/路径/尺寸) tree(机器处理才用 tree --json)
某 session 的 cwd/进程/tty/任意变量 tab-show/tree 已含 job/path/tty;或 var <pane|id> <名字>
有哪些 profile profiles
窗口位置/大小/是否全屏 frame [n|id] / fullscreen <n|id> on|off(不传 on/off 只读)
给某个 tab 发命令/按键(不用先查 id) send-tab first|last|N "命令" / key-tab first|last|N ctrl-c
  • 编号(window/tab/pane)会随增删变化:回答时以本次输出为准。
  • “在干什么”看 tab-show 的 job/path,“细节/最新输出”用 capture-tab;不要臆测。
  • 用户说“窗口”= iTerm 顶层 window;一个 window 里有多个 tab。

锚定规则(跨调用必遵守):left/right/cur 是相对当前聚焦 tab 实时解析的,用户切 tab/窗口后同一条命令会落到别的窗格。凡是要跨多次 bash 调用或多轮对话连续操作的窗格,先 id <pane>(或 ids)拿到 session id,之后一律用 *-id 命令,与前台焦点完全无关。同一时刻连续动作(如 split v && send right "pi")可以直接用方位。

焦点规则(默认不抢):split / split-id / cols / rows / tab-new 一律在后台创建,保持用户当前焦点不动;只有用户明确说"切过去 / 打开给我看 / 我要看着它"时才加 --focus。发送、按键、读屏、关闭等 *-id 操作全程不动焦点。绝不主动 focus/focus-id,除非用户明确要求。

批量规则(默认合并执行):多步任务默认写成 batch heredoc,一次连接全部执行完;只有用户明确说"一步步来 / 我要看着它执行 / 每步分开做"时才拆成单条命令逐步执行。batch 内遇错即停,行首 # 为注释。支持纯赋值 A=$ITERM_SESSION_ID;$VAR 没在 batch 里捕获过时退回环境变量($ITERM_SESSION_ID 可直接用,w0t1p0: 前缀各 *-id 命令都认)。

组合:多个动作按语序用 && 串成一条 bash 调用。"等它跑起来" = sleep 2。分屏后新窗格在下/右:split h center && send top "htop" && send bottom "x" = 中栏上跑 htop、中栏下跑 x。

例:

  • 左右分屏右边开 pi → split v && send right "pi"
  • 三栏各开 pi → cols 3 && send left "pi" && send center "pi" && send right "pi"
  • 打断右边再关掉 → key right ctrl-c && close right

配方(多步组合,一律 id 锚定、不抢焦点;默认用 batch):

  • 新 tab + 左右分屏 + 左 pi / 右 proxy→codex:
    pi-skill iterm-workspace-ctl batch <<'EOF'
    T=$(tab-new)            # 后台新 tab;输出左窗格 id,焦点不变
    R=$(split-id "$T" v)    # 原 session 在左、新窗格在右;输出右窗格 id
    send-id "$T" "pi"
    send-id "$R" "proxy"
    sleep 2
    send-id "$R" "codex"
    EOF
    
  • 新 tab + 多栏各自起工具:batch 里 T=$(tab-new) → 逐个 R=$(split-id "$T" v) 收集 id → 对每个 id send-id <id> "命令"。
  • 等启动完成:用 wait-id <id> "词" [秒] 代替盲目 sleep;读结果 capture-id <id> [行数];结束清理 close-id <id>。
  • 在已有后台 tab 里增减窗格:直接 batch 里 split-id <该 tab 内任一 session id> v|h,不会切用户焦点。

⚠️ close/close-others 会杀窗格里的进程,别关到用户自己正在用的窗格。

复杂流程(>3 步)机械处理:先在配方表里找相同组合,命中就直接照抄;没命中就切小段查映射表,每段单独编译,用 && 串成一条。跨调用的每一步必须带 *-id。不要规划状态转移,不要推演“执行后窗格变成什么样”。

生成命令后、执行前,机械核对(不要思考,只对照): □ 查询类问题是否用了“查询”表的直接命令(tab-list/tab-show/win-show/capture-tab/where)且没写代码解析? □ 命令里每个词都在映射表里出现过? □ 没有 info/capture/grep/ls 等侦察命令? □ 是一条 bash 调用(多步用 && 串)? □ 跨调用操作是否已用 id/ids 锚定,并改用 *-id? □ 创建类是否默认不抢焦点(没自作主张加 --focus)? 全部打勾 → 立即执行。任何一项没打勾 → 重查映射表,不要自己想。

只有命令报错或缺库时,才读 REFERENCE.md(安装、排查、AppleScript 退回方案)。