
cli-anything-iterm2 窗口与标签页管理实战Windows Tabs 命令完整指南【免费下载链接】CLI-AnythingCLI-Anything: Making ALL Software Agent-Native -- CLI-Hub: https://clianything.cc/项目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything导读本文以 layout-window-tab.md 为核心系统讲解cli-anything-iterm2CLI-Anything 项目为 iTerm2 打造的 Agent 原生命令行 harness中window窗口与tab标签页两层容器对象的全部操作命令创建、列举、关闭、激活、改标题、移动/调整尺寸、全屏切换以及在分裂窗格split pane间按方向跳转焦点。读完本文你既能照抄命令完成 iTerm2 布局自动化也能理解每条命令在 window.py 与 tab.py 中的底层实现、JSON 输出结构以及与之配套的有状态 Context 机制从而真正把“打开多少个窗口、每个窗口放几个标签页”这种手工操作交给脚本或 Agent 完成。一、使用前提与基础语法所有 window / tab 操作都通过 iTerm2 官方 Python API 驱动一个正在运行的 iTerm2 实例因此在执行前需要满足三个前置条件同样记录于 SKILL.mdmacOS 上安装并运行 iTerm2例如brew install --cask iterm2开启 Python APIiTerm2 → Preferences → General → Magic →Enable Python API安装 CLIpip install cli-anything-iterm2或在本仓库源码目录执行pip install -e .。基础调用语法为cli-anything-iterm2 [--json] group command [OPTIONS] [ARGS]其中window与tab是并列的两大命令组面向 Agent 与脚本使用时建议始终追加--json让输出成为可被程序直接消费的结构化数据。命令的连接与错误提示逻辑在 iterm2_ctl_cli.py 中实现与 iTerm2 实例之间的 async 桥接则统一收敛在 iterm2_backend.py 的run_iterm2()中。版本前提本文命令与输出格式以当前仓库 iterm2/agent-harness 中的实际实现为准仅适用于已开启 Python API 的 iTerm2 环境。二、命令全景总览下表覆盖 layout-window-tab.md 的全部命令并补齐了在 CLI 定义中实际存在的可选参数详见 iterm2_ctl_cli.py类别命令核心作用关键参数Windowwindow list列出所有打开的窗口及元数据—Windowwindow create新建窗口--profile/-p、--command/-c、--use-as-contextWindowwindow close [WINDOW_ID]关闭窗口位置参数缺省用 Context 窗口--forceWindowwindow activate [WINDOW_ID]将窗口带到前台聚焦—Windowwindow set-title TITLE设置窗口标题--window-idWindowwindow frame读取窗口位置与尺寸--window-idWindowwindow set-frame设置窗口位置与尺寸--x--y--width--height必填、--window-idWindowwindow fullscreen on\|off\|toggle\|status全屏控制/查询--window-idTabtab list [--window-id]列出标签页可按窗口过滤--window-idTabtab create在窗口内新建标签页--window-id、--profile/-p、--command/-c、--use-as-contextTabtab close [TAB_ID]关闭标签页位置参数--forceTabtab activate [TAB_ID]聚焦标签页—Tabtab info [TAB_ID]查看标签页内会话明细—Tabtab select-pane left\|right\|above\|below向相邻分裂窗格移动焦点--tab-id两条约定值得特别留意close系列使用位置参数而非--window-id命令注释与实现中都明确写着# positional arg, NOT --window-id。省略 ID 时自动回落到 Context 中保存的窗口/标签页见下文第四节因此cli-anything-iterm2 window close等价于“关闭当前上下文指向的窗口”。select-pane的合法方向只有四个left、right、above、belowCLI 层用click.Choice限制取值tab.py 内部再映射为 iTerm2 的NavigationDirection枚举。三、Window窗口生命周期与几何控制3.1 列出窗口window listcli-anything-iterm2 window list cli-anything-iterm2 --json window list人读模式下每个窗口输出window_id、tabs、sessions当前聚焦窗口会附带*标记。JSON 模式下结构为{windows: [...]}其中每个元素包含四个字段——这是 window.py 中list_windows()逐窗口统计的结果字段含义window_idiTerm2 窗口唯一标识形如w0、w1…tab_count该窗口内标签页数量session_count该窗口内全部会话含各标签页分裂出的 pane数量之和is_current是否为当前处于前台聚焦的终端窗口session_count是tab_count的“加权值”代码对每个窗口先tabs window.tabs统计标签页数再sum(len(t.sessions) for t in tabs)把每个标签页内部的会话全部累加因此它能直接反映窗口的真实密度一个标签页含 4 个分裂 pane 时会计为 4 个会话。3.2 新建窗口window createcli-anything-iterm2 window create cli-anything-iterm2 window create --profile Default cli-anything-iterm2 window create --profile Dev --command tmux -CC attach cli-anything-iterm2 window create --use-as-context对应实现是 window.py 的create_window()它调用iterm2.Window.async_create(connection, profileprofile, commandcommand)并返回新窗口里第一个标签页、第一个会话的 ID{window_id: w2, tab_id: w2t0, session_id: w2t0p0}参数语义--profile NAME指定使用哪个 iTerm2 Profile缺省为默认 Profile。Profile 名必须是 profile list 里实际存在的名称--command CMD窗口打开后立即执行的命令缺省进入登录 shell。注意若提供的是tmux -CC ...这类命令将创建 tmux 集成会话后续可用 tmux 命令组接管--use-as-context创建成功后把返回的window_id/tab_id/session_id一并写入 Context 状态文件后续省略 ID 的命令会默认作用于这个新窗口。如果创建失败如 iTerm2 拒绝创建create_window会抛出RuntimeError(Failed to create window)并由 CLI 层的错误装饰器统一格式化输出。3.3 关闭与激活window close/window activatecli-anything-iterm2 window close w1 # 显式指定 cli-anything-iterm2 window close # 关闭 Context 窗口 cli-anything-iterm2 window close w1 --force # 跳过确认直接关闭 cli-anything-iterm2 window activate w0 # 把 w0 带到前台close先通过 iterm2_backend.py 的async_find_window()全量扫描app.windows按window_id定位找不到会抛出ValueError并列出当前可用窗口 ID随后调用window.async_close(forceforce)。activate则调用window.async_activate()。e2e 测试 test_full_e2e.py 对“创建 → 出现在列表 → 关闭 → 从列表消失”的完整闭环做了端到端断言验证的正是这条生命周期。3.4 窗口标题window set-titlecli-anything-iterm2 window set-title My Window cli-anything-iterm2 window set-title Deploy Monitor --window-id w0标题是窗口级而非会话级的显示文本底层即window.async_set_title(title)见 window.py。在 Agent 编排多窗口时用它把窗口语义化如API Server、Log Tail再配合app snapshot即可一眼还原整个工作区结构。3.5 窗口几何window frame/window set-frame# 查询当前 Context 窗口的位置与尺寸 cli-anything-iterm2 window frame # 显式把窗口钉到屏幕坐标 (0,0)尺寸 1200x800 cli-anything-iterm2 window set-frame --x 0 --y 0 --width 1200 --height 800 cli-anything-iterm2 window set-frame --x 200 --y 100 --width 800 --height 600 --window-id w1frame的返回由get_window_frame()构造包含window_id/x/y/width/height五个字段其中x/y为窗口左上角在屏幕坐标系中的位置单位是点pointset-frame的四个参数在 CLI 中均标为requiredTrue的 float缺一不可。底层 window.py 会把它们组装成iterm2.util.Frame(originiterm2.util.Point(xx, yy), sizeiterm2.util.Size(widthwidth, heightheight))再调用window.async_set_frame()——这正是“把窗口精确摆放到屏幕某处”的坐标模型来源。测试 test_full_e2e.py 用「创建窗口 → 读取 frame → 断言 width/height 大于 0 → 关闭」验证了读写两个方向都可用。3.6 全屏控制window fullscreencli-anything-iterm2 window fullscreen status # 查询当前窗口是否全屏 cli-anything-iterm2 window fullscreen on # 进入全屏 cli-anything-iterm2 window fullscreen off # 退出全屏 cli-anything-iterm2 window fullscreen toggle # 翻转状态mode参数是click.Choice([on, off, toggle, status])。toggle的实现很有意思——它不是盲目切换而是先查再设fullscreen命令处理逻辑中当 mode 为toggle时会先调用get_window_fullscreen()拿到当前布尔状态再取反见 iterm2_ctl_cli.py从而避免“状态与预期相反”的竞态底层读写在 window.py 分别对应async_get_fullscreen()/async_set_fullscreen(bool)。四、Tab标签页管理与分裂窗格导航4.1 列出标签页tab listcli-anything-iterm2 tab list # 列出全部窗口下的所有标签页 cli-anything-iterm2 tab list --window-id w0 # 只查 w0 窗口内的标签页对应 tab.py 的list_tabs()遍历所有窗口若指定window_id则跳过不匹配的窗口对每个标签页输出tab_id / window_id / session_count / is_current四项。其中is_current依据window.current_tab判定即“该标签页是否为所在窗口当前显示的标签页”。人读输出中当前标签同样以*标注。注意--window-id缺省时会使用 Context 中的window_id而不是无条件返回全部CLI 层wid window_id or get_state().window_id这点与直觉略有差异跨窗口清点时建议显式传参或先app clear-context。4.2 新建标签页tab createcli-anything-iterm2 tab create # 在 Context 窗口新建标签页 cli-anything-iterm2 tab create --window-id w0 cli-anything-iterm2 tab create --profile Dev --command htop cli-anything-iterm2 tab create --use-as-context实现见 tab.py。关键行为未指定window_id时取app.current_terminal_window如果当前一个窗口都没有会抛出RuntimeError(No open windows. Create a window first with: window create)——这是一条非常实用的 Agent 自纠错提示底层调用window.async_create_tab(profileprofile, commandcommand, indexindex)index参数在 CLI 中虽未暴露但核心函数已预留“指定插入位置”的能力返回值同样是三件套tab_id / window_id / session_id。4.3 关闭与激活tab close/tab activatecli-anything-iterm2 tab close w0t1 # 关闭指定标签页 cli-anything-iterm2 tab close # 关闭 Context 标签页 cli-anything-iterm2 tab close w0t1 --force cli-anything-iterm2 tab activate w0t2 # 切换到 w0t2close_tab()的实现策略与窗口不同见 tab.pyiTerm2 的标签页没有“直接关闭自身”的 API因此实现是遍历标签页内全部会话并逐个session.async_close(forceforce)——这也解释了为什么带分裂 pane 的标签页需要--force才能安静关闭。activate_tab()则取该标签页的current_session调用session.async_activate()把前台焦点带过去。4.4 标签页详情tab infocli-anything-iterm2 tab info w0t0对应 tab.py 的get_tab_info()返回{ tab_id: w0t0, session_count: 2, sessions: [ {session_id: w0t0p0, name: api-server}, {session_id: w0t0p1, name: log-tail} ] }即把标签页内每个分裂窗格session的 ID 与显示名一起列出是“先 info 看清内部结构、再对具体 session 发命令”的典型前奏。4.5 在分裂窗格间导航tab select-panecli-anything-iterm2 tab select-pane right cli-anything-iterm2 tab select-pane left cli-anything-iterm2 tab select-pane above --tab-id w0t0 cli-anything-iterm2 tab select-pane below --tab-id w0t0这是 Tab 组中最“智能”的一条命令。核心函数 tab.pyselect_pane_in_direction()用一张方向映射表把四个方向词转成 iTerm2 枚举{left: iterm2.NavigationDirection.LEFT, right: iterm2.NavigationDirection.RIGHT, above: iterm2.NavigationDirection.ABOVE, below: iterm2.NavigationDirection.BELOW}然后调用tab.async_select_pane_in_direction(nav_dir)。注意它返回的new_session_id可能为None——当目标方向上没有相邻 pane 时焦点不动返回moved: falseCLI 会据此输出No pane right of current selection.。返回结构同时记录于 json-session.md{tab_id: w0t0, direction: right, new_session_id: w0t0p1, moved: true} {tab_id: w0t0, direction: left, new_session_id: null, moved: false}单元测试 test_core.py 覆盖了两个关键分支传入非法方向如diagonal会抛出ValueError而合法方向命中 pane 时把新会话 ID 原样带回。方向跳转的前提是 tab 内存在分裂窗格——若标签页只有一个会话四个方向都会返回moved: false此时应先用session split切分 pane。五、支撑机制一有状态 Context为什么可以省略 ID前文大量命令“省略 ID 自动生效”背后是有状态的 Context 机制定义在 session_state.py。它把window_id / tab_id / session_id三元组持久化到~/.cli-anything-iterm2/session.json跨 CLI 调用保留因此多次命令可以像“在一个终端会话里”那样连贯操作。维护 Context 的方式有四种cli-anything-iterm2 app current # 把当前聚焦的 窗口/标签/会话 存为 Context cli-anything-iterm2 app set-context --window-id w0 --tab-id w0t0 --session-id w0t0p0 cli-anything-iterm2 app context # 查看当前 Context cli-anything-iterm2 app clear-context # 清空 Context新建命令的--use-as-context则是创建窗口/标签页后直接“切换语境”的快捷方式。省略 ID 却未设置 Context 时CLI 会抛出UsageError如No window ID specified and no context window set. Use app current or app set-context first.引导用户先建立上下文。写状态时save_state()使用fcntl.flock加排他锁保证多进程并发写不会互相破坏 JSON 文件。六、支撑机制二JSON 输出与错误契约面向 Agent 时统一加--json顶层cli会把全局标志传入每个命令输出经json.dumps(data, indent2, defaultstr)序列化见 iterm2_ctl_cli.py。窗口/标签命令的 JSON 契约汇总如下命令JSON 结构window list{windows: [{window_id, tab_count, session_count, is_current}]}window create{window_id, tab_id, session_id}window frame{window_id, x, y, width, height}window fullscreen status{window_id, fullscreen: true/false}tab list{tabs: [{tab_id, window_id, session_count, is_current}]}tab create{tab_id, window_id, session_id}tab info{tab_id, session_count, sessions: [...]}tab select-pane{tab_id, direction, new_session_id, moved}错误时同样走 JSON{error: Session abc123 not found.}。所有命令函数都包裹了handle_iterm2_error装饰器将RuntimeError连接失败、创建失败等与ValueErrorID 不存在、非法方向等统一捕获连接类错误会附带三段排障指引——确认 iTerm2 正在运行、确认已开启 Python APIPreferences → General → Magic、必要时重启 iTerm2。七、把窗口与标签页编排成工作流将上面的命令串起来可以拼出典型的多窗口 Agent 工作流——例如“一个窗口做服务另一个窗口做监控”# 1. 建立第一个窗口并运行服务 cli-anything-iterm2 window create --use-as-context cli-anything-iterm2 window set-title API Server cli-anything-iterm2 session send python3 -m http.server 8000 cli-anything-iterm2 session set-var user.role api-server # 2. 同窗口内新开一个标签页向右分裂出两个 pane cli-anything-iterm2 tab create --use-as-context cli-anything-iterm2 session split --vertical --use-as-context cli-anything-iterm2 session send tail -f /var/log/app.log cli-anything-iterm2 session set-var user.role log-tail # 3. 在分裂 pane 间切换焦点先回到 Context 标签页再选方向 cli-anything-iterm2 tab select-pane left cli-anything-iterm2 tab select-pane above # 4. 第二个独立窗口窗口几何 全屏彻底铺满副屏 cli-anything-iterm2 window create --profile Default --command htop cli-anything-iterm2 window set-frame --x 1920 --y 0 --width 1920 --height 1080 cli-anything-iterm2 window fullscreen status # 5. 收尾查一次全局布局再按需清理 cli-anything-iterm2 --json window list cli-anything-iterm2 --json tab list cli-anything-iterm2 window close # 关闭 Context 窗口整个过程仅依赖 CLI 语法与 SKILL.md 中推荐的「snapshot 定位 → 建立 context → 交互 → 复用 pane」Agent 工作流完全一致先用app snapshot观察现状再用 window/tab 命令搭建目标布局最后用session set-var user.role打标签方便日后定位。完整端到端验证参考 TEST.md其中列出的test_window_create_and_close、test_window_create_with_profile、test_tab_create_and_close等用例与 test_full_e2e.py 中的真实 iTerm2 回环测试。八、常见问题速查现象原因与处理Error: Cannot connect to iTerm2...iTerm2 未运行或 Python API 未开启按提示检查 Preferences → General → Magic必要时重启 iTerm2Error: Window w9 not found. Available: [...]window_id已失效窗口被手动关闭先用window list刷新 IDNo window ID specified and no context window set省略 ID 前未建立 Context先执行app current或app set-contextNo open windows. Create a window first with: window create当前一个窗口都没有时试图tab create先创建窗口No pane left of current selection.该方向不存在相邻分裂窗格用session split先切分或用tab info确认内部会话数UsageError: Invalid value for mode: onwindow fullscreen的合法取值仅为on/off/toggle/status窗口与标签页是 iTerm2 布局的“骨架”session组命令发送文本、读取 scrollback、分裂 pane、设置角色变量是填充骨架的“血肉”。当你需要把整套终端工作区——含多个窗口、标签页、分裂窗格及方向导航——交给脚本或 Agent 编排时本文的 window/tab 命令即可作为最底层、最可靠的原子操作库使用。【免费下载链接】CLI-AnythingCLI-Anything: Making ALL Software Agent-Native -- CLI-Hub: https://clianything.cc/项目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考