Skip to content

命令行 ​

文档编写中

部分内容可能尚不完整。

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 --trim

label 就是窗口里 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 enter
  • wait 等 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_removedpane 打开或关闭pane_id
program_exitedpane 启动的程序结束了pane_id、exit_code(未知时为 null)、signal
command_finishedpane 的 shell 报告一条命令结束了pane_id、exit_code(没给时为 null)
bellpane 响了铃pane_id
notification程序发出了桌面通知pane_id、title、body
title_changedpane 的标题变了pane_id、title
cwd_changedpane 的工作目录变了pane_id
progress一条进度报告pane_id、state(none、percentage、error 或 indeterminate)、percent
user_var程序设置了用户变量pane_id、name、value
clipboard_written程序写了剪贴板。写的内容不会重复pane_id
agent_statuspane 里发现了编码 agent、状态变了,或它走了pane_id、agent、state
foreground_programpane 的前台程序变了pane_id、executable、runs
pane_focused某个 pane 获得焦点pane_id
pane_label_changedpane 被起了 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一个窗口、浏览器或手机开始、或不再显示 panehostname、username、pid、epoch、id

退出状态 ​

失败的 cli 命令以 1 退出,下面这些除外:

状态含义
2命令行要求的事不可能成立:参数解析不了、不认识的键、只由数字构成的 label 等
3没有这个 pane,或者 --pane 的名字一个都对不上、或对上了好几个
4连不上服务端,或者服务端不肯和这个版本的程序通信

会等待的命令,则像上面那样,以所等待之物的结果退出。

在脚本里读 agent 状态 ​

thinkterm cli agent list 为 ThinkTerm 发现了编码 agent 的每个 pane 打印一行:

列内容
PANEID这个 pane,用的是其他 cli 命令接受的那个 id
AGENTagent 的 id,比如 claude
STATEworking、blocked、idle、error 或 unknown
EVIDENCE状态由什么决定:report 表示程序发送了自己的状态上报,contract 表示程序通过 THINKTERM_AGENT 自己报告,screen 表示某条屏幕规则匹配,fallback 表示什么都没匹配上,于是把已知的 agent 视为空闲
AGE状态上次变化到现在多久
WORKSPACE这个 pane 所在的多路复用器工作区。Thread 里的 pane 这里是一个内部名字,不是 Thread 的名字
TITLEpane 的标题
LABELpane 的 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 写入的内容

Agentskillhook
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 回到了空闲。更结构化的协议正在设计中。

相关 ​

  • Agent 状态 —— cli agent 和 cli events 报告的内容
  • 网页访问 —— web-server 和 web-token 打开的是什么
  • TUI —— 纯终端里的工作区
  • 插件 —— thinkterm plugin 管理的对象
  • 快捷键与命令 —— show-keys 打印的键位表