命令行
文档编写中
部分内容可能尚不完整。
thinkterm 是你在 shell 里日常使用的那个命令。
thinkterm --help它不是唯一装上的可执行文件。桌面端和服务器安装都会带上 thinkterm-mux-server —— 真正为远程客户端和浏览器提供服务的是它,见 远程、网页访问 和下文的 mux 服务端。同时还会装一个兼容用的 wezterm 名字,补全脚本两个名字都覆盖。桌面端和服务器安装还都带有 thinkterm-plugin-server,插件都在它之下运行,内置的「片段」插件也在其中;它在第一次有需要时被启动,从不需要手动运行 —— 见 插件。
子命令
| 命令 | 作用 |
|---|---|
start | 启动 GUI,可选择运行另一个程序。别名 -e |
tui [DOMAIN…] | 在当前终端里打开 ThinkTerm 界面 |
connect <name> | 连接到一个 ThinkTerm 多路复用器 |
ssh | 建立 SSH 会话 |
serial | 打开串口 |
cli <subcommand> | 通过运行中的多路复用服务端查看和控制 pane、标签与窗口,并查看编码 agent 的情况 |
update | 检查新版本并安装。见 更新 |
plugin | 列出插件、开关插件、重新加载插件,以及向某个插件发送调用。见 插件 |
skill setup|status|remove|show | 把 ThinkTerm 的 skill 和会话启动 hook 装进编码 agent。见 让编码 agent 使用 ThinkTerm |
config check [FILE] | 像应用那样加载一份配置文件,报告其中的错误和警告,但不应用它;运行中的应用不受影响。不给文件时检查应用会加载的那一份。文件加载失败时以状态 1 退出 |
imgcat <file> | 把图片输出到终端 |
ls-fonts | 显示当前使用的字体信息 |
show-keys | 显示当前的按键绑定 |
set-working-directory | 告知终端当前工作目录,用于 shell 集成 |
record | 把终端会话录制为 asciicast |
replay | 回放 asciicast |
shell-completion | 输出 bash、zsh、fish、elvish、PowerShell 或 Fig 的补全脚本 |
还有一个子命令不出现在 --help 里。list-files 输出一个 Project 的文件列表,桌面端在远程主机上搜索文件时运行的就是它 —— 见 文件与笔记。它不是给人手动运行的,但必须存在:ThinkTerm 版本早于它的主机无法被搜索。
与运行中的多路复用器通信
thinkterm cli 面向的是一个已经在运行的服务端 —— 你 GUI 窗口背后的那个,或者一个后台 mux 服务端。由于多路复用器能寻址任意窗口、Thread 和已连接客户端中的任意 pane,这些命令可以够到你当前并没有在看的会话。
到底由哪个服务端应答是隐含的,而这通常就是「命令看上去什么也没做」的原因:默认优先找运行中的 GUI,找不到就自己起一个。--prefer-mux 改为发给后台 mux 服务端,--no-auto-start 则让命令直接失败,而不是为了应答它而拉起一个服务端。
--class <NAME> 用来找以自己的窗口类启动的 GUI,也就是 thinkterm start 带了 --class 的那种。不加它时,命令找的是你正常启动的那个 GUI;只有你用自定义窗口类另外启动过 GUI,才需要用 --class 去找它。thinkterm tui 也接受同样的参数,用法一样。
作用于 pane 的命令,用 --pane-id 接收 pane 的编号,不给时就作用于命令所在的那个 pane,也就是 WEZTERM_PANE 指的那个。--pane 则按你给它起的 label 来指定 pane —— 见 给 pane 起名。
查询
| 命令 | 作用 |
|---|---|
list | 列出窗口、标签和 pane,有 label 的一并显示 |
list-clients | 列出已连接的客户端 |
get-pane-direction | 报告某个方向上的 pane |
创建与销毁
| 命令 | 作用 |
|---|---|
spawn | 新建标签或窗口。打印新 pane 的 id。--label 给这个 pane 起名;--wait 等它的程序结束,并以其状态退出 |
split-pane | 分割已有的 pane。打印新 pane 的 id,和 spawn 一样接受 --label 与 --wait |
move-pane-to-new-tab | 把一个 pane 移出为独立标签 |
kill-pane | 关闭一个 pane |
移动与调整大小
| 命令 | 作用 |
|---|---|
activate-pane | 聚焦某个 pane |
activate-pane-direction | 聚焦某个方向上的 pane |
activate-tab | 聚焦某个标签 |
adjust-pane-size | 调整 pane 大小 |
zoom-pane | 把 pane 放大到填满其标签 |
文本进出
| 命令 | 作用 |
|---|---|
send-text | 以粘贴的方式向某个 pane 写入文本;如果其中的程序要求,就用括号粘贴。不会补 Enter:--enter 会在文本之后稍等片刻按一下 Enter,--no-paste 则把文本作为普通输入发送 |
send-key | 按名字依次按下按键,按 pane 里的程序要求的方式编码,就像真的敲下去一样。--wait 会接着等它们启动的命令结束。见 按键 |
get-text | 读取某个 pane 屏幕上的文本。--pane-id 或 --pane 指定 pane,默认是命令所在的那个 pane。--start-line 和 --end-line 指定行范围:0 是屏幕顶端,负数向回延伸到回滚区。--format 可以是 text(默认)、像 --escapes 那样保留颜色和样式序列的 vt,或带颜色的 html。--trim 去掉行尾空格和末尾的空行,--unwrap 把终端折行的内容接回原来的一行 |
等待与观察
| 命令 | 作用 |
|---|---|
wait | 等某个 pane 里的程序结束,加 --command 则等它 shell 里正在运行的命令结束,并以其状态退出。见 等待程序或命令 |
events | 事情一发生就打印出来,直到被中断。见 观察发生了什么 |
命名与基础设施
| 命令 | 作用 |
|---|---|
set-tab-title | 重命名标签 |
set-pane-label | 给 pane 起个 label,之后 --pane 就能找到它。空 label 表示去掉 |
set-window-title | 重命名窗口 |
rename-workspace | 重命名工作区 |
agent list | 列出检测到正在运行编码 agent 的 pane,以及各自的状态。只读 |
agent context | 为在其中启动的编码 agent,打印它所在的 pane 在哪里、同一标签里还有什么。见 让编码 agent 使用 ThinkTerm |
tlscreds | 获取 TLS 凭据 |
proxy | 启动 RPC 代理管道 |
color-schemes | 列出内置配色方案。由可执行文件直接应答,不需要服务端;--json 会连同颜色一起输出 |
stop-server | 停止后台会话服务器。里面的每个终端都会结束,因此在终端里运行时会先询问;--force 不询问 |
网页访问
| 命令 | 作用 |
|---|---|
web-server status|on|off | 是否在接受浏览器连接、在哪里接受。on 可带 --bind-address |
web-token mint|list|revoke | 发放、列出和吊销浏览器用来进入的链接 |
这两个命令面向的都是 mux 服务端,而不是 GUI 自带的多路复用器;而发放出去的链接等同于在那台机器上以你的身份登录。如果开启了连接其他机器,它还是通往那个账户用 SSH 进得去的每一台机器的入口。网页访问说明了这意味着什么。
list、list-clients、agent list 和 web-token list 默认输出表格,加 --format json 则输出 JSON。前三个和 events 还可以简写为 --json。
会打印列表或文本的命令 —— 上面这四个,以及 get-text、color-schemes 等 —— 在管道另一端不再读取时,会悄悄结束并返回成功状态,比如 thinkterm cli list | head。
停止会话服务器
thinkterm cli stop-server 停止默认 socket 上的后台会话服务器,里面的每个终端都随之结束。它从不启动服务器:没有服务器在运行时,它会说明这一点,什么也不改。
在终端里运行时,它会报出服务器的进程和 socket 并先询问,回答 y 或 yes 以外的任何内容都会让服务器继续运行。只有标准输入是终端时它才询问,所以脚本或管道会不经询问直接停掉服务器;--force 在终端里也跳过询问。随后它最多等十秒让服务器退出,过后若服务器仍在关闭中,会如实说明。
下一次需要服务器的启动、connect 或 cli 命令会起一个全新的。其他停止它的方式见 远程。
给 pane 起名
pane 的编号每次运行都会变,label 不会。thinkterm cli set-pane-label --pane-id 12 build 给 12 号 pane 起名;spawn 和 split-pane 用 --label build 给它们创建的 pane 起名;此后 --pane build 就能找到它。
thinkterm cli set-pane-label build
thinkterm cli spawn --label tests -- npm test
thinkterm cli get-text --pane tests --trimlabel 就是窗口里 pane 标签上的那个名字,所以在那里重命名标签,设置的是同一个 label。它由服务端保存,因此每个窗口、CLI、浏览器和恢复出来的 Thread 都看得到。label 里不能有控制字符,最多 128 个字符,两端的空白会被去掉。只由数字构成的 label 会被拒绝,因为 --pane 把数字当作 pane 编号。空 label 表示去掉 label。list 和 agent list 把 label 显示在 LABEL 列和 label 字段里,events 会报告 pane 被起了名。
--pane 接受:
- pane 编号。 只有数字。如果另一个 pane 的 label 恰好是这串数字,命令会停下并把两个都列出来,而不是去猜。
- label,不区分大小写。
- Thread 的名字,单独写,或者像侧边栏那样接在 Project 名后面(
my-project · fix login);仅当这个 Thread 只有一个 pane 时。 thread/label,用于多个 Thread 都在用的 label。
当一个 label 被好几个 pane 用着,而其中只有一个在运行命令的那个 pane 所在的 Thread 里,指的就是它。否则命令会停下,说明这个名字可能指几个 pane,并列出每个的编号、label、标题和 Thread;请按编号指定。--pane 不能和 --pane-id 一起用。每个接收 pane 的命令都接受 --pane,spawn、split-pane 和 activate-tab 也不例外。
按键
send-key 接受一个或多个按键,每个写成修饰键和按键用 + 连起来,不区分大小写:
thinkterm cli send-key --pane build ctrl+c
thinkterm cli send-key escape up up enter修饰键有 ctrl、alt(或 opt)、shift 和 cmd(或 super)。按键可以是单个字符,或 enter、tab、escape、backspace、delete、space、up、down、left、right、home、end、pageup、pagedown、insert,以及 f1 到 f24。每个键都按 pane 里的程序要求的方式编码,就像真的敲下去一样。遇到不认识的键,命令会在发送任何东西之前停下。
等待程序或命令
wait 一直等到 pane 里的某件事结束,并以它的结束方式作为退出状态:
thinkterm cli spawn --label tests --wait -- npm test
thinkterm cli wait --pane tests --for 10m
thinkterm cli send-key --pane build --wait enterwait等 pane 启动的那个程序结束,并以它的状态退出。wait --command等 pane 的 shell 里正在运行的命令结束,并以该命令的状态退出。刚敲下去的命令有一秒钟时间开始;没有开始的话,就以最近一条结束的命令的状态退出,一条也没结束过则为 0。send-key --wait KEY…按下按键,然后等它们启动的命令结束。它会先数一下 shell 已结束的命令数,所以一下就结束的命令不会漏掉。要敲入一条命令并等它,先send-text,再send-key --wait enter,比事后再wait --command更稳妥。spawn --wait和split-pane --wait先打印新 pane 的编号,再等它的程序结束。
--timeout(简写 --for)在若干秒、或数字加 s、m、h 之后放弃:90、30s、10m、1.5h。放弃的等待会打印 timed out,以状态 124 退出。程序或命令结束了但没有已知状态时,会如实说明并以 125 退出:shell 结束一条命令却没给退出状态,或者 --takeover 之后被新服务端接管的 pane,它里面的程序已经说不出自己是怎么结束的。两者都不会被当作成功。pane 关闭时程序的状态还没送到,则以 1 退出;被信号结束的程序,会在标准错误里写出信号的名字。
wait --command 和 send-key --wait 需要一个会报告命令从哪里开始、到哪里结束的 shell,也就是 ThinkTerm 的 shell 集成,见 安装。没有它们会报错停下并说明这一点;spawn --wait 不需要。
观察发生了什么
thinkterm cli events 为服务端上发生的每件事打印一行,直到被中断:
14:02:11 command_finished pane 12 status 0
14:02:11 agent_status pane 12 claude idle--pane 或 --pane-id 只保留发生在某一个 pane 上的事;标签、窗口和客户端的事件会被略去。--format json,或简写 --json,改为每行打印一个对象,带 type 和该事件自己的字段。这些会保持稳定:事件和字段可能增加,但不会被删除或改变类型。如果有几千条事件来不及打印而堆积,多出的会被丢弃。服务端连接被替换时,命令会自行重连;连接丢失时报错停下。
type | 何时 | type 之外的字段 |
|---|---|---|
pane_added, pane_removed | pane 打开或关闭 | pane_id |
program_exited | pane 启动的程序结束了 | pane_id、exit_code(未知时为 null)、signal |
command_finished | pane 的 shell 报告一条命令结束了 | pane_id、exit_code(没给时为 null) |
bell | pane 响了铃 | pane_id |
notification | 程序发出了桌面通知 | pane_id、title、body |
title_changed | pane 的标题变了 | pane_id、title |
cwd_changed | pane 的工作目录变了 | pane_id |
progress | 一条进度报告 | pane_id、state(none、percentage、error 或 indeterminate)、percent |
user_var | 程序设置了用户变量 | pane_id、name、value |
clipboard_written | 程序写了剪贴板。写的内容不会重复 | pane_id |
agent_status | pane 里发现了编码 agent、状态变了,或它走了 | pane_id、agent、state |
foreground_program | pane 的前台程序变了 | pane_id、executable、runs |
pane_focused | 某个 pane 获得焦点 | pane_id |
pane_label_changed | pane 被起了 label,或 label 被去掉 | pane_id、label(被去掉时为 null) |
tab_added | 窗口里新增了标签 | tab_id、window_id |
tab_title_changed | 标签被重命名 | tab_id、title |
window_title_changed | 窗口被重命名 | window_id、title |
workspace_changed | 窗口换到了另一个工作区 | window_id、workspace |
workspace_renamed | 工作区被重命名 | old_workspace、new_workspace |
client_joined, client_left | 一个窗口、浏览器或手机开始、或不再显示 pane | hostname、username、pid、epoch、id |
退出状态
失败的 cli 命令以 1 退出,下面这些除外:
| 状态 | 含义 |
|---|---|
| 2 | 命令行要求的事不可能成立:参数解析不了、不认识的键、只由数字构成的 label 等 |
| 3 | 没有这个 pane,或者 --pane 的名字一个都对不上、或对上了好几个 |
| 4 | 连不上服务端,或者服务端不肯和这个版本的程序通信 |
会等待的命令,则像上面那样,以所等待之物的结果退出。
在脚本里读 agent 状态
thinkterm cli agent list 为 ThinkTerm 发现了编码 agent 的每个 pane 打印一行:
| 列 | 内容 |
|---|---|
PANEID | 这个 pane,用的是其他 cli 命令接受的那个 id |
AGENT | agent 的 id,比如 claude |
STATE | working、blocked、idle、error 或 unknown |
EVIDENCE | 状态由什么决定:report 表示程序发送了自己的状态上报,contract 表示程序通过 THINKTERM_AGENT 自己报告,screen 表示某条屏幕规则匹配,fallback 表示什么都没匹配上,于是把已知的 agent 视为空闲 |
AGE | 状态上次变化到现在多久 |
WORKSPACE | 这个 pane 所在的多路复用器工作区。Thread 里的 pane 这里是一个内部名字,不是 Thread 的名字 |
TITLE | pane 的标题 |
LABEL | pane 的 label,没有时为空 |
--format json 改为输出一个对象数组,字段为 pane_id、label(没有时为 null)、agent、state、evidence、session_id(没有时为 null)、since_unix(状态上次变化的时间,Unix 秒,按检测它的那台机器的时钟)、workspace 和 title。这些字段是给脚本用的,会保持稳定。状态从哪里来,见 Agent 状态。
让编码 agent 使用 ThinkTerm
在 ThinkTerm 的 pane 里运行的编码 agent,可以用 thinkterm cli 查看其他 pane、读取它们、向它们输入,以及新开 pane。thinkterm skill setup 会教 Claude Code 和 Codex 这么做,并在它们启动时告诉它们自己在哪里。它和识别 agent是两回事,后者什么也不安装;而它在你运行之前什么也不会改。
thinkterm skill setup --dry-run
thinkterm skill setup| 命令 | 作用 |
|---|---|
skill setup | 在这台机器上找到的 agent 里安装或更新 skill 和 hook。可以放心重复运行。--dry-run 只说明会改什么,不真的改 |
skill status | 对每个 agent,显示 skill 和 hook 是 current、outdated、missing、someone else's 还是 unreadable |
skill remove | 把 skill 和 hook 再取出来 |
skill show | 打印 skill,给 setup 不认识的 agent 用。npx skills add RoversX/ThinkTerm --skill thinkterm -g 会把同一个 skill 从仓库装给其他 agent,比如 Cursor |
setup、status 和 remove 都接受 --agent claude 或 --agent codex,指定一个 agent,不管有没有找到它。不加时,它们处理自己的文件夹在这里存在的那些 agent;一个也没有就如实说明。
setup 写入的内容
| Agent | skill | hook |
|---|---|---|
| Claude Code | ~/.claude/skills/thinkterm/SKILL.md | ~/.claude/settings.json 里的一条 SessionStart |
| Codex | ~/.agents/skills/thinkterm/SKILL.md | ~/.codex/hooks.json 里的一条 SessionStart |
CLAUDE_CONFIG_DIR 和 CODEX_HOME 会挪动 agent 自己的文件夹,Claude Code 的 skill 和两个设置文件跟着挪。skill 是一份简短的说明:agent 身在 ThinkTerm 里,thinkterm cli --help 列出了所有命令,thinkterm 不在 PATH 里时它在哪,以及向不是自己开的 pane 输入、关闭 pane、停掉服务端之前,也许该先问问你。pane 里设有 THINKTERM=1,skill 的描述就以它为触发条件。
hook 在 agent 启动时运行。在 ThinkTerm 的 pane 里,它会打印这个 pane 的编号、label 和标题,以及所在标签的标题;然后是同一标签里的其他 pane(最多十二个,其余只给个数)、其他标签里有多少个 pane,以及怎么读一个 pane。这就是 thinkterm cli agent context。在 ThinkTerm 的 pane 之外,或者 ThinkTerm 不应答时,它什么也不打印并返回成功,也从不启动服务端,所以 agent 的启动和没有它时一样。等待它最多十秒。hook 暂时还不会装到 Windows 上;skill 会。
setup 只编辑设置文件里的 hooks 一项,文件其余部分的文本保持原样。不是 JSON 对象的设置文件,以及不是 ThinkTerm 的、也叫 thinkterm 的 skill 文件,它都不碰,并会说明。Claude Code 只在你信任的文件夹里运行 hook,Codex 则在你用 /hooks 批准新 hook 之后才运行。更新之后再运行一次 setup,就能把 outdated 的 skill 或 hook 更新到最新。
撤销。 thinkterm skill remove 删掉 skill 文件(里面没有别的东西时连文件夹一起删),并把 hook 从设置文件里取出,同时清掉因此变空的 SessionStart 列表或 hooks 对象。别的 hook 和 skill 原样保留。手动的话,删掉文件,再删掉那一项。
作为数据的配色方案
thinkterm cli color-schemes 逐行打印内置配色方案的名字。--json 改为输出一个 JSON 数组,每个方案一个对象:name、foreground、background、cursor_bg、cursor_fg、cursor_border、selection_bg 和 selection_fg 是 #rrggbb 字符串,ansi 和 brights 各是八个颜色的列表。没有给出光标或选区颜色的方案,会用默认值补上。
这份列表是编译进可执行文件的那一份,所以不需要服务端,也不读配置。你在配置里定义的、或放在配色目录里的方案都不在其中。
mux 服务端
thinkterm-mux-server 是单独的多路复用器,没有窗口。桌面端把终端放在会话服务器里时,那个服务器就是它,由桌面端替你启动;在没有桌面的主机上,你自己启动它,通常带上 --daemonize。
| 参数 | 作用 |
|---|---|
--daemonize | 脱离终端,在后台运行 |
--takeover | 接管同一 socket 上已经在运行的 mux 服务端:它的 pane、窗口和客户端在新的可执行文件下继续,旧服务端退出。正在运行的那个必须支持接管。Windows 上不可用 |
--no-initial-pane | 启动时不带任何 pane,而不是带一个运行默认程序的 pane。桌面端的会话服务器就是这样启动的,因为其中每个 pane 都是桌面端要求开的 |
--cwd <DIR> | 第一个 pane 里程序的工作目录 |
-- <PROG>… | 在第一个 pane 里运行这个程序,而不是你的 shell |
-n、--config-file、--config name=value | 跳过配置、指定配置文件,或覆盖单个选项 —— 与 thinkterm 的全局参数相同 |
两个 pane 里的程序可以互相通信
send-text 和 get-text 就足以让一个程序驱动另一个,两边都不需要任何改动:
程序 A ──send-text──► 程序 B 的终端输入
B 完成工作并打印回应
程序 A ◄──get-text─── 读回结果任何交互式程序都能参与 —— 编码助手、shell 脚本、REPL。接口就是 pane 本身,所以不需要为此专门实现什么。
目前这个交换是靠注入终端输入完成的,这意味着没有消息身份、没有结构化回应。输入由 send-text --enter 和 send-key 完成,屏幕用 get-text --trim 读回。完成与否不必轮询:B 是一条 shell 命令时,send-key --wait enter 会在它结束时带着它的状态返回,程序则由 wait 做同样的事;B 是编码 agent 时,events --pane 会报告它的 agent_status 回到了空闲。更结构化的协议正在设计中。
