news 2026/9/10 14:04:53

iTerm2 会话输入输出完全指南:cli-anything-iterm2 的 send / inject / screen / scrollback 实战解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
iTerm2 会话输入输出完全指南:cli-anything-iterm2 的 send / inject / screen / scrollback 实战解析

iTerm2 会话输入输出完全指南:cli-anything-iterm2 的 send / inject / screen / scrollback 实战解析

【免费下载链接】CLI-Anything"CLI-Anything: Making ALL Software Agent-Native" -- CLI-Hub: https://clianything.cc/项目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything

cli-anything-iterm2是 CLI-Anything 仓库中围绕 iTerm2 打造的会话控制命令行工具(源码入口见 iterm2_ctl_cli.py,通过 setup.py 注册为cli-anything-iterm2命令)。本文聚焦于该工具的Session I/O能力——向某个终端会话(Session,即一个 pane)发送文本、注入原始字节、读取可视屏幕与完整回滚历史、获取选区文本——这些是所有"通过命令行驱动真实终端"场景(让 Agent 操作 shell、观察输出、核对构建结果)的基础设施。读完本文,你将掌握session命令组下六个 I/O 子命令的完整用法、参数语义、JSON 返回结构与底层 iTerm2 Python API 调用链。

前置环境:工具如何连接到 iTerm2

Session I/O 的一切操作都建立在与运行中的 iTerm2 实例建立连接的基础上。其底层通过iterm2.run_until_complete在同步 Click CLI 与异步 iTerm2 Python API 之间搭桥(见 iterm2_backend.py)。使用前需要满足:

  1. macOS 上已运行 iTerm2(建议brew install --cask iterm2);
  2. 在 iTerm2 → Preferences → General → Magic 中勾选Enable Python API
  3. 安装命令行工具:pip install cli-anything-iterm2(或从iterm2/agent-harness目录pip install -e .)。

命令整体语法为cli-anything-iterm2 [--json] <group> <command> [OPTIONS] [ARGS]。在后续所有涉及"读取内容"的场景中,必须带上--json--json是根级开关(在 CLI 根函数中注册,见 iterm2_ctl_cli.py),开启后所有输出经json.dumps序列化,是 Agent 可稳定解析的唯一形态。技能文档(SKILL.md)将本主题的参考索引指向 references/session-io.md,正是本文展开的主体。

向会话发送文本:session send

session send把一段文本作为键盘输入写入目标会话,是"替用户在终端里敲命令"的最基本操作:

# 发送文本 + 回车(默认行为) cli-anything-iterm2 session send "echo hello" # 指定会话发送 cli-anything-iterm2 session send "text" --session-id <id> # 仅发送文本,不追加换行 cli-anything-iterm2 session send "text" --no-newline

参数语义在 CLI 层已经说明(见 iterm2_ctl_cli.py):

  • 默认追加换行:若不指定--no-newline,CLI 会把text + "\n"作为实际载荷(payload = text if no_newline else (text + "\n")),即按下回车执行;
  • --session-id:显式指定目标会话;省略时使用上下文保存的 session id(可由app current/app set-context设定),未设置则报错提示;
  • --suppress-broadcast:关闭向广播域同步转发,避免在一次send中影响其它被广播的 pane。

底层实现位于 core/session.py:先通过async_find_session在全窗口/全 tab 范围内定位会话(找不到即抛出Session '...' not found),再调用 iTerm2 Python API 的session.async_send_text(text, suppress_broadcast=...),返回{"session_id": ..., "text_length": ..., "sent": true}。文本长度信息可用于确认写入量。对应单元测试在 test_core.py 中验证了"默认追加换行"与"--no-newline不追加换行"两种载荷构造路径。

注入原始字节:session inject

普通send处理的是文本;而有些场景需要直接注入"仿佛由运行中程序发出的"终端控制字节(转义序列、OSC 码、响铃等),此时使用session inject

# 注入转义序列(清除屏幕 ESC[2J) cli-anything-iterm2 session inject $'\x1b[2J' # 同一操作,用十六进制字符串表达 cli-anything-iterm2 session inject "1b5b324a" --hex

两个细节值得注意(见 iterm2_ctl_cli.py):

  • --hex模式下数据按 UTF-8 编码(errors="surrogateescape")直接编码为字节;
  • --hex模式用bytes.fromhex1b5b324a这类十六进制串还原为原始字节(ESC [ 2 J),非法十六进制串会以 Click 错误形式被拒绝——test_core.py 中专门覆盖了session inject "ZZZZ" --hex的非法输入用例。

底层调用session.async_inject(data)(见 core/session.py),返回{"session_id": ..., "injected_bytes": 4}之类的字节数确认。实际可应用的注入包括清屏、光标控制、OSC 标题变更等原本只会来自前台进程的控制码,适合驱动交互式 TUI 程序。

读取可视屏幕:session screen(务必 --json)

session screen读取会话当前可见区域(visible screen)的文本内容,相当于"拍一张当前画面":

# 读取可视区域(文档特别警告:必须使用 --json,否则输出对解析而言是静默无效的) cli-anything-iterm2 --json session screen # 最多返回 20 行 cli-anything-iterm2 --json session screen --lines 20

为什么必须--json:根据 references/session-io.md 的明确说明,读屏时若不使用--json,输出是静默无效的(human-readable 分支打印的是嵌套字段与分隔线装饰,Agent 无法稳定消费)。参考技能约定"Always use--jsonfor machine-readable output"(见 SKILL.md),凡是需要把屏幕内容交给程序解析的调用一律带--json

--lines/-n限制最多返回的行数。JSON 返回结构如下(schema 见 references/json-session.md):

{"session_id": "...", "total_lines": 40, "returned_lines": 40, "lines": ["$ echo hello", "hello"]}

其中total_lines是可视区域总行数,returned_lines是实际返回行数(受--lines约束),lines数组自上而下排列。实现上(见 core/session.py)通过session.async_get_screen_contents()取回整个可视缓冲,再按需切片contents.line(i).string

读取完整回滚历史:session scrollback

session scrollback读取的是自会话开始以来(受回滚上限约束)的整段历史,包括可见屏幕之外的旧输出,且返回顺序固定为最旧 → 最新:

# 全部历史 cli-anything-iterm2 --json session scrollback # 只取最近 100 行 cli-anything-iterm2 --json session scrollback --tail 100 # 取最近 500 行,并剥离控制字符(避免空字节污染输出) cli-anything-iterm2 --json session scrollback --tail 500 --strip # 从最旧开始取前 200 行 cli-anything-iterm2 --json session scrollback --lines 200

参数与返回的完整定义(见 references/session-io.md,CLI 侧见 iterm2_ctl_cli.py):

参数作用优先级
--tail N/-t N只返回最近 N 行覆盖--lines
--lines N/-n N从最旧开始最多返回 N 行默认返回全部
--strip剥离空字节及不可打印控制字符仅清洗返回文本

JSON 返回包含丰富元数据:

{ "session_id": "...", "total_available": 4922, "scrollback_lines": 4862, "screen_lines": 60, "overflow": 0, "returned_lines": 100, "lines": ["...", "..."] }

关键字段语义(结合 core/session.py 的get_scrollback实现解读):

  • total_available=scrollback_buffer_height + mutable_area_height,即"历史缓冲行数 + 当前可见区域行数";
  • scrollback_lines:回滚历史缓冲中的行数;screen_lines:可见 mutable 区域行数;
  • overflow:缓冲写满时因溢出丢失的行数。若配置的回滚上限很小而输出量巨大,overflow > 0意味着历史出现空洞,最早的部分输出已被丢弃;要彻底避免,应在 iTerm2 Profile 中将回滚行数限制设为unlimited(文档原话:set profile limit to "unlimited" to avoid);
  • 读取在iterm2.Transaction事务内完成:先async_get_line_info()获取缓冲区几何信息,再async_get_contents(first_line, count)取回内容,保证"行数与内容来自同一瞬间"的一致性快照,避免读取过程中缓冲区滚动导致错位。--tail模式下first_line = overflow + (total_available - want),从逻辑上的最新窗口起点读取。

--strip的实现则是在 CLI 层对返回行做正则清洗:剔除[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f]范围内的控制字符,防止空字节/ESC 干扰下游解析(见 iterm2_ctl_cli.py)。

读取选区文本:session selection

当用户在终端里用鼠标/键盘选中了文本(例如复制了一段日志),可以用session selection取回选区内容:

cli-anything-iterm2 session selection

返回结构形如{"session_id": "...", "selected_text": "...", "has_selection": true};无选区时has_selectionfalseselected_text为空串(CLI 层见 iterm2_ctl_cli.py)。实现上先取当前 Selection 对象,再调用session.async_get_selection_text(...)转换文本(见 core/session.py)。

screen 与 scrollback 的边界与选择

文档给出一条简单而关键的判定规则:

session screen=仅可视区域session scrollback=完整历史,一次性原子读取,顺序最旧 → 最新。

选择建议:

  • 需要"当前运行到哪了""最后一条输出是什么" →screen(轻量、快),或直接用app snapshot(一次性汇总所有 pane 的名称/路径/进程/角色/最后一行,见 SKILL.md 与 app snapshot 文档);
  • 需要追溯长任务历史、回看已被顶出屏幕的输出、核对完整构建日志 →scrollback,且务必关注overflow字段以判断历史是否完整;
  • 行数截取方向不同:scrollback --tail N取最近 N 行(调试、核对最新结果最常用),scrollback --lines N从最旧取 N 行(读取任务起点),而screen --lines N只是可视区域内的头部截断。

与 Shell Integration 组合:send → wait → read 可靠执行模式

严格说,把 I/O 与执行同步结合才能构成完整的自动化闭环。session-io.md与 references/session-shell-integration.md 相互配合,后者在目标会话安装 Shell Integration 后提供get-promptwait-promptwait-command-end三个同步原语。推荐的可靠执行模式为:

# 1) 发送命令 cli-anything-iterm2 session send "make build" # 2) 阻塞等待命令结束,返回 exit_status cli-anything-iterm2 session wait-command-end --timeout 120 # 3) 读取最近输出(剥离控制字符) cli-anything-iterm2 --json session scrollback --tail 50 --strip

wait-command-end通过iterm2.PromptMonitor监听COMMAND_END事件(其值为命令退出码),返回{"session_id": "...", "exit_status": 0, "timed_out": false}(实现见 core/prompt.py)。也就是说:写入用send/inject,等待用 Shell Integration 原语,读取用scrollback/screen——三者在 e2e 测试中已有验证路径(test_full_e2e.py 的test_send_text_and_read_screen覆盖"发送命令 → 读屏 → 断言输出包含命令或结果"的完整链路)。

错误处理约定

当 iTerm2 未运行、Python API 未开启或会话不存在时,命令会给出明确错误。连接失败时(底层在 iterm2_backend.py 中检测connect/refused/websocket等关键字后抛出带修复步骤的RuntimeError),非 JSON 模式输出Error: Cannot connect to iTerm2...,JSON 模式输出结构化错误:

{"error": "Session 'abc123' not found."}

错误统一由handle_iterm2_error装饰器捕获并格式化(见 iterm2_ctl_cli.py),因此 Agent 可以用error键判断失败原因并决定重试或提示用户。

小结:一条命令在底层发生了什么

以最常用的session send为例,梳理 Session I/O 的完整调用链,便于在阅读或二次开发时快速定位代码(相关文件均在本仓库的iterm2/agent-harness/cli_anything/iterm2_ctl/目录下):

  1. Click 解析session send "echo hello"(入口 iterm2_ctl_cli.py),未指定--session-id时取会话上下文;
  2. run_iterm2将同步调用桥接为异步(utils/iterm2_backend.py);
  3. async_find_session在全部 window/tab 中定位目标 Session;
  4. session.async_send_text(payload)真正把echo hello\n写入 iTerm2 会话(core/session.py);
  5. 结果经output()--json开关输出为{"session_id", "text_length", "sent"}或人类可读文本。

同理,读屏/读历史分别落在async_get_screen_contents()与事务化async_get_line_info()+async_get_contents()两条底层路径。掌握 send / inject / screen / scrollback / selection 五类 I/O 原语及其 JSON 结构,再叠加--tail--stripoverflow--lines这些"读取几何"参数与 Shell Integration 的等待原语,即可在 Agent 工作流中稳定地"写进去、等到完成、读回来",实现真正可控的终端自动化。

【免费下载链接】CLI-Anything"CLI-Anything: Making ALL Software Agent-Native" -- CLI-Hub: https://clianything.cc/项目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 14:03:08

COMSOL相场法模拟锂枝晶生长与电池优化

1. 项目概述&#xff1a;树枝晶生长模拟的工程价值树枝晶生长现象在金属凝固、电池失效等工业场景中普遍存在。以锂电池为例&#xff0c;充放电过程中锂枝晶的不可控生长会刺穿隔膜导致短路&#xff0c;这是制约高能量密度电池发展的关键瓶颈。传统实验观测手段存在成本高、周期…

作者头像 李华
网站建设 2026/9/10 13:57:11

JVM内存模型解析与实战调优指南

1. JVM内存模型深度解析作为Java开发者面试必考知识点&#xff0c;JVM内存模型的理解程度直接决定了你解决实际生产问题的能力。我在处理线上OOM问题时发现&#xff0c;90%的故障根源都能追溯到对内存模型的误解。不同于教科书上的理论图解&#xff0c;这里我会结合15次真实故障…

作者头像 李华