---
title: "TUI"
description: "在纯终端里运行 ThinkTerm 工作区，作为同一个多路复用服务端的平级客户端 —— 它的按键、鼠标、设置和手机布局。"
url: "https://docs.closex.org/zh/thinkterm/tui.html"
markdown_url: "https://docs.closex.org/zh/thinkterm/tui.md"
site: "CloseX Docs"
product: "ThinkTerm"
language: "zh-Hans"
last_updated: "2026-11-08T12:04:16.000Z"
alternates:
  en: "https://docs.closex.org/thinkterm/tui.md"
  zh-Hans: "https://docs.closex.org/zh/thinkterm/tui.md"
  ja: "https://docs.closex.org/ja/thinkterm/tui.md"
---

# TUI

> **文档编写中**
> 部分内容可能尚不完整。

同一个工作区，不带 GUI：

```bash
thinkterm tui [DOMAIN ...]
```

它是 `thinkterm` 可执行文件的一个子命令，而不是第二个程序，所以不运行的时候不占用任何成本。

## 它是平级客户端，不是镜像

TUI 不是 GUI 的只读视图。它是同一个权威服务端的另一个客户端，并且遵守同样的规则：

- Space、Project 和 Thread 数据只接受来自服务端的快照
- 每一次改动都要等服务端确认之后，显示才会更新

因此同时开着 GUI 和 TUI，不可能出现两边对"存在什么"各执一词的情况。离线的服务端在 TUI 里根本无法修改：不会有任何改动被排队等着以后再发。

### 它能做什么

终端里的日常工作它都覆盖：新建标签、分屏、调整大小、放大、关闭 pane 和标签、带回滚搜索的复制模式，并且完整支持鼠标。

在侧边栏上，它可以新建和改名 Space、Project 与 Thread，置顶和取消置顶 Thread，并在每一层执行删除 —— 每次都会确认，因为删除可能结束里面的会话。拖动可以在 Project 内部重排 Thread、在 Space 内部重排 Project；Space 本身的顺序不变。它还能从下文介绍的连接面板接入和重试服务端，以及跳到下一个需要你关注的 Thread。

### 它没有什么

TUI 比桌面应用窄。它没有归档、没有 Thread 引用、没有文件、笔记、片段或状态面板、没有插件、没有实时总览，也没有标签图标。它新建的 Project 不绑定你挑选的文件夹：名字由你定，起点是你的主目录。用 TUI 不会让这些东西丢失 —— 它们保持桌面端留下的样子 —— 只是要用桌面应用才能碰到它们。

### 终端由谁驱动

数据是共享的，但一个终端同一时刻只有一个驱动者。默认是交接模式 —— 客户端在你与之交互时把终端拿过来 —— 而 TUI 可以把服务端切换成类似 tmux 的共享模式，让所有接入的客户端看到同一张网格。这个模式属于服务端，并且在它重启后依然保留，所以它是对那个服务端做的决定，而不是对当前这个客户端。在共享模式下，最后一个与某个标签交互的客户端决定它的尺寸。交接的那一面见 [远程](https://docs.closex.org/zh/thinkterm/remote.md)。

切换开关在标签栏的 `⋮` 菜单里，即 `A · Shared (tmux-like)` 和 `B · Handoff (exclusive)`，当前模式旁边带勾。底部状态栏打开时会写明状态：`A SHARED`；这个 TUI 握着终端时是 `B ACTIVE`；另一台设备握着时是 `B VIEW · example-host`。在共享模式下，尺寸由另一个客户端决定的标签会改显示 `A SHARED · VIEW 120×30`，带上这个标签被保持的尺寸。

被另一台设备握着的终端，上面会盖一条提示，说明它正在哪里使用，以及 `Click or scroll to continue`。在 TUI 里只有点击或滚动能接管它，键盘永远不会：没法分辨一次按键是想接管，还是要打给下面那个终端的，所以提示还在时敲的键不会去任何地方。

## 退出不会结束任何东西

退出 TUI 只是从服务端脱离。里面的每个会话都继续运行，与 GUI 客户端断开时完全一样。

这正是那个显而易见的用法成立的原因：SSH 到一台机器，跑 `thinkterm tui`，做点事，然后断开。或者在一台你本来就不想要 GUI 的机器上彻底跳过它。

用 `Ctrl-b d` 或 `Ctrl-b q`、`⋮` 菜单里的 `Detach`，或状态栏上的 `Detach` 按钮脱离。

## 它不会在自己的服务端里打开

如果 TUI 运行在它要接入的那个服务端的某个 pane 里，它就是在那个服务端的一个终端里画那个服务端自己的终端。ThinkTerm 会拒绝：它脱离所有已接入的服务端，带着错误退出，你的终端保持原样。错误信息会提示你从另一个终端应用里运行 `thinkterm tui`，或者换一个域。

是不是同一个，看的是服务端的身份，而不是域的名字：每个 ThinkTerm pane 都记录着承载它的服务端，报告同一身份的目标会被拒绝。旧到没有这项记录的 pane 也会被拒绝，因为从它无法证明目标是另一个服务端。

## 界面

**侧边栏**是一棵树：每个已接入的服务端、它的 Space、Space 里的 Project，以及其中的 Thread。`▾` 和 `▸` 用来折叠一层。每一行都带一个 `⋯` 按钮打开它的菜单，Space 行和 Project 行还带一个 `+`，分别用来添加 Project 和 Thread。树的上方是 `⊕ New Thread`，在你所在的 Project 里添加一个 Thread；还有一个 `WORKSPACES` 标题，它的 `+` 在你所在的 Space 里添加 Project。`⚙ Settings` 位于底部。顶部的 `≡` 用来显示和隐藏侧边栏。

Thread 行以一个标记开头：

| 标记 | 含义 |
|---|---|
| `*` | 里面有东西在运行 |
| `!` | 它需要关注，或者被标记为未读 |
| `+` | 它的工作在你没看的时候完成了 |
| `★` | 它已置顶 |

打开一个 Thread 会在服务端清除它的未读标记，对所有客户端生效。`Ctrl-b o` 按树的顺序跳到下一个带 `!` 或 `+` 的 Thread，到底后从头再来。TUI 启动时如果没有记住的 Thread，就打开最需要关注的那一个。

**标签栏**放着所选 Thread 的标签，每个标签上有一个 `✕` 用来关闭，`+` 新建标签，`⋮` 是主菜单。标签放不下时，两端的 `<` 和 `>` 会标出藏起来了几个。在标签栏上滚动滚轮可以切换标签。

**pane 导航栏**是每个 pane 顶部的一条。左边是堆叠在这个 pane 位置上的各个 pane —— 几个终端共用同一块矩形，各自以标签的形式切换 —— 每个都带一个 `✕`。右边是四个按钮：`⤢` 放大（放大后变成 `⤡`）、`◫` 向右分屏、`⊟` 向下分屏，以及 `+` 在同一位置上堆叠一个新终端。pane 窄到放不下四个按钮时，先去掉分屏按钮，保留放大。

**状态栏**在底部，默认关闭。它显示当前模式的按键、消息、访问状态、需要关注的 Thread 数 `! N` —— 点一下跳到下一个 —— 以及 `Detach`。关闭时，消息和模式提示以浮层显示，永远不会从终端那里占走一行。

## 按键

除了前缀 `Ctrl-b` 之后的按键，其余一切都交给终端。按下 `Ctrl-b`，松开，再按命令键。`Ctrl-b Ctrl-b` 会把一个字面的 `Ctrl-b` 发给 pane 里的程序。`Ctrl-b ?` 显示按键汇总，`Esc` 或 `?` 关闭它。

### 前缀之后

| 按键 | 作用 |
|---|---|
| `?` | 帮助 |
| `d` 或 `q` | 脱离 |
| `b` 或 `s` | 显示或隐藏侧边栏 |
| `g` 或 `w` | 导航模式 |
| `C` | 连接面板 |
| `,` | 设置 |
| `c` | 在所选 Thread 里新建标签 |
| `n` / `p` | 下一个 / 上一个标签 |
| `1` … `9` | 第 1 到第 9 个标签 |
| `↑` / `↓` | 上一个 / 下一个 Thread |
| `o` | 下一个需要关注的 Thread |
| `Tab` | 下一个 pane |
| `h` `j` `k` `l`、`←` `→` | 聚焦左、下、上、右侧的 pane |
| `v` | 向右分屏 |
| `-` | 向下分屏 |
| `x` | 确认后关闭 pane |
| `X` | 确认后关闭标签 |
| `z` | 放大 pane，或取消放大 |
| `r` | 调整大小模式 |
| `[` | 复制模式 |

前缀之后按其他键，除了提示一句什么也不做。

### 导航模式

打开侧边栏并把键盘留在那里，这样不用前缀就能在树上走动。

| 按键 | 作用 |
|---|---|
| `j` / `k`、`↓` / `↑` | 下一个 / 上一个 Thread |
| `h` / `l`、`←` / `→` | 聚焦左 / 右侧的 pane |
| `n` / `p` | 下一个 / 上一个标签 |
| `?` | 帮助 |
| `Enter` 或 `Esc` | 离开导航模式 |

### 调整大小模式

| 按键 | 作用 |
|---|---|
| `h` `j` `k` `l` 或方向键 | 把当前 pane 的边朝那个方向移动一格 |
| `Enter` 或 `Esc` | 结束 |

### 复制模式

复制模式在当前 pane 里放一个光标，它在回滚内容中移动，与 pane 里运行的程序无关。

| 按键 | 作用 |
|---|---|
| `h` `j` `k` `l` 或方向键 | 移动光标 |
| `PgUp` / `PgDn` | 滚动十行 |
| `End` | 回到底部 |
| `Space` | 开始选择；再按一次结束 |
| `y`、`Y` 或 `Enter` | 复制所选内容 |
| `/` | 向前搜索 |
| `?` | 向后搜索 |
| `n` / `N` | 下一个 / 上一个匹配 |
| `Esc` | 离开复制模式 |

搜索覆盖整个回滚内容，不区分大小写。向前搜索跳到第一个匹配，向后搜索跳到最后一个，并把光标移过去；没有匹配时显示 `No matches`。

### 菜单、输入框和确认

| 场合 | 按键 |
|---|---|
| 菜单 | `j` / `k` 或方向键移动，`Enter` 选择，`Esc` 关闭 |
| 名称输入框 | 直接输入，`Backspace` 删除，`Enter` 确定，`Esc` 取消 |
| 确认对话框 | `Enter` 或 `y` 确认，`Esc` 或 `n` 取消 |

输入框留空时什么也不做。

## 鼠标

`Application mouse` 打开时（默认如此），鼠标能做按键能做的大部分事：

- **点击** Thread 打开它，点击标签显示它，点击 pane 聚焦它。在终端上点击或滚动滚轮，也会把它从另一台设备那里接管过来。
- 在 pane 里**拖动**选择文本。靠近上下边缘时，选择会带着 pane 滚动。沿同一行拖动要超过三格才算数，所以手指滑开一两格的轻点仍然是点击。
- **右键**任何东西打开它的菜单。侧边栏行上的 `⋯` 打开的是同一个菜单。
- **拖动**分隔线调整两侧 pane 的大小，拖动侧边栏右边缘调整侧边栏宽度，拖动 pane 的滚动条在回滚内容中移动。侧边栏宽度会被保存。
- 把一个 Thread **拖到**同一 Project 的另一个 Thread 上，或把一个 Project 拖到同一 Space 的另一个 Project 上，就把它移到对方前面。

pane 里的程序要求接管鼠标时 —— `vim`、`htop`、开了鼠标支持的 `less` —— 点击和拖动会交给那个程序。按住 `Shift` 可以自己选择文本。`Shift` 加右键，以及中键，总是交给程序。

在 pane 上滚动滚轮有三种结果。程序要求了鼠标，滚轮交给它。pane 处于备用屏幕 —— 一个没有要求鼠标的全屏程序 —— 时，每一格都变成方向键，正因如此 `less` 和 `git log` 在触摸屏上也能滚动。其余情况滚动回滚内容。按住 `Shift`，或者已经往回滚过，总是滚动回滚内容。滚轮每一格是 `scroll_lines` 行。

### 右键菜单

| 对象 | 提供 |
|---|---|
| 服务端 | `New Space`、`Retry connection`、`Disconnect` |
| Space | `New Project`、`Rename Space`、`Delete from server`、`End sessions and delete` |
| Project | `New Thread`、`Rename Project`、`End sessions and remove` |
| Thread | `Open`、`New Thread`、`Rename Thread`、`Pin` 或 `Unpin`、`End session and delete` |
| 标签 | `Open`、`New Tab`、`Rename Tab`、`Close Tab` |
| pane | `Copy`、`Paste`、`Split Right`、`Split Down`、`Zoom`、`Close Pane` |
| 标签栏上的 `⋮` | `New Tab`、`Split Right`、`Split Down`、`Copy Mode`、`Paste`、`Connections`、`A · Shared (tmux-like)`、`B · Handoff (exclusive)`、`TUI Settings`、`Toggle Sidebar`、`Help`、`Detach` |

只有当那个 pane 里有一段已完成的选择时，`Copy` 才可用。

### 新建和删除做了什么

`New Space` 询问名称，然后建立这个 Space，里面带一个位于主目录的 Project `Home` 和一个 Thread `main`。`New Project` 询问名称，在主目录建立这个 Project，并带一个 `main` Thread。`New Thread` 询问名称。每一项都会打开它刚建好的东西。

删除之前一定会询问；会结束 pane 的，对话框会写明结束几个：

- **`Delete from server`** 为所有客户端从服务端移除一个 Space，里面的会话继续运行。
- **`End sessions and delete`** 移除这个 Space，并结束其中每一个 pane。
- **`End sessions and remove`** 移除一个 Project，并结束它的 pane。
- **`End session and delete`** 移除一个 Thread，并结束它的 pane。
- **`Close Pane`** 和 **`Close Tab`** 在服务端结束那些 pane，对所有客户端生效。

服务端上的 `Disconnect` 不是删除：TUI 只是放开它，它的会话继续运行。

## 复制与粘贴

`Copy on select` 打开时（默认如此），拖动结束即复制，复制模式里用 `y` 复制。关掉它，完成的选择会留在屏幕上；这时 `Ctrl-C` 会复制它，而不是中断程序。复制之后选择就被丢弃，所以下一次 `Ctrl-C` 又会送到程序那里。

TUI 通过系统自己的工具写入剪贴板：

| 系统 | 使用 |
|---|---|
| macOS | `pbcopy` 和 `pbpaste` |
| Linux | Wayland 下用 `wl-copy` 和 `wl-paste`，其次 `xclip`，再次 `xsel` |
| Windows | Windows 剪贴板 |

这些都写不进去时 —— 典型情况是 SSH 到一台没有显示器的 Linux 机器 —— TUI 改为把文本以 OSC 52 序列发给它所运行的那个终端，支持 OSC 52 的终端会把它放进你面前那台机器的剪贴板。行不行取决于那个终端，而不是 ThinkTerm。

菜单里的 `Paste` 通过同样的工具读取剪贴板，所以在 SSH 上它读的是远程机器的剪贴板，或者干脆失败。你所用终端自己的粘贴快捷键总是有效的：TUI 会把收到的内容交给当前 pane。

复制和粘贴每次最多 8 MiB。

## 窄屏与手机

TUI 会随着所在终端的宽度改变形态。

- **宽屏** —— 侧边栏以你设定的宽度待在终端旁边。
- **紧凑** —— 比 `narrow_width` 宽不到 24 列时，侧边栏固定为 18 列。
- **窄屏** —— 在 `narrow_width` 列（默认 64）或更窄时，树不再与终端共享屏幕。打开时它盖住终端，你选中一个 Thread 后它就让开；`≡` 再把它叫回来。窄屏下的 TUI 总是从终端开始，在那里打开或关闭树也不会被保存，所以共用同一个 `tui.toml` 的手机和电脑不会互相覆盖对方的选择。

手机报告的列数差别很大，所以 `narrow_width` 是唯一值得手动调整的数字。

`Touch targets` 按指尖来设定按钮大小：按钮更宽，顶部是两行高的栏。保持 `Auto` 时它跟随窄屏布局，多数时候是对的，但手机横过来报告的列数多到像一台电脑时就不对了 —— 所以才有这个设置。

在手机上，pane 导航栏是手指唯一能碰到放大、分屏和新终端的地方，因为软键盘上几乎没有像样的 `Ctrl-b`。即使是很矮的 pane，也会保留它的导航栏。

## 设置

`Ctrl-b ,`、侧边栏底部的 `⚙ Settings`，或 `⋮` 菜单里的 `TUI Settings` 都能打开设置界面。`↑` `↓` 或 `j` `k` 在行间移动；`←` `→`、`h` `l`、`Enter` 或 `Space` 改变取值；`Esc` 关闭。点击某一行也会改变它。每次改动立即生效并保存。

界面上有十行。另有两个设置只存在于文件中：`sidebar_width`（拖动侧边栏边缘也会设置它）和 `narrow_width`。

| `tui.toml` 中的键 | 界面上 | 默认值 | 取值 |
|---|---|---|---|
| `theme` | Theme | `monochrome-dark` | 下面十个主题之一 |
| `sidebar_visible` | Sidebar | `true` | `true`、`false` |
| `pane_nav_bar` | Pane nav bar | `true` | `true`、`false` |
| `pane_borders` | Pane borders | `true` | `true`、`false` |
| `pane_scrollbars` | Pane scrollbars | `false` | `true`、`false` |
| `show_status_bar` | Bottom status bar | `false` | `true`、`false` |
| `mouse` | Application mouse | `true` | `true`、`false` |
| `copy_on_select` | Copy on select | `true` | `true`、`false` |
| `touch_targets` | Touch targets | 不设置（`Auto`） | 不设置、`true`、`false` |
| `scroll_lines` | Scroll lines | `3` | 1 到 20 |
| `sidebar_width` | — | `26` | 18 到 36 列 |
| `narrow_width` | — | `64` | 20 到 200 列 |

超出范围的值会被拉回范围内。边框需要富余的空间，滚动条要占一列，所以两者只在足够大的 pane 上画出来；滚动条默认关闭，因为它占用的那一列是服务端不知道的。

关掉 `Application mouse`，普通的点击、拖动和滚轮就不再以鼠标事件的形式送到程序：点击和拖动始终用来选择，滚轮用来滚动，在备用屏幕上则发送方向键。

一个最小的 `tui.toml`：

```toml
theme = "tokyo-night"
narrow_width = 80
touch_targets = true
```

### 主题

| `theme` | 界面上 |
|---|---|
| `monochrome-dark` | Monochrome Dark |
| `monochrome-light` | Monochrome Light |
| `terminal` | Terminal Default |
| `catppuccin` | Catppuccin |
| `tokyo-night` | Tokyo Night |
| `dracula` | Dracula |
| `nord` | Nord |
| `gruvbox` | Gruvbox |
| `solarized-dark` | Solarized Dark |
| `solarized-light` | Solarized Light |

主题给 TUI 自己的界面上色，不给终端上色：终端保持服务端给它们的颜色。深色主题画在你的终端原有的背景上，所以侧边栏和 pane 在背景色上永远不会不一致。两个浅色主题自带背景色，因为深色文字放在深色终端上没法看。`Terminal Default` 连文字也用终端自己的颜色。

`NO_COLOR` 不会把这些有名字的主题变成灰色。想要不带颜色，请选两个 Monochrome 主题之一。

## 连接面板

`Ctrl-b C`，或 `⋮` 菜单里的 `Connections`，列出 TUI 能接入的每个服务端：

- 本机，显示为 `Local` —— 有正在运行的 ThinkTerm 桌面应用就是它，否则是本地会话 server
- 你配置里的多路复用域
- `远程主机` 里使用 ThinkTerm Connect 的主机，以它们的标签显示

无法接入的主机也会列出，但呈灰色并附上原因：普通 SSH 主机提示 `Enable ThinkTerm Connect in Remote Hosts`，Mosh 主机则说明它的会话不是 mux 服务端。

| 标记 | 状态 |
|---|---|
| `●` | 已接入 |
| `…` | 正在连接 |
| `!` | 失败 |
| `○` | 未接入 |
| `-` | 无法接入 |

| 按键 | 作用 |
|---|---|
| `j` / `k`、`↓` / `↑` | 移动 |
| `Enter` 或 `r` | 接入，或重试 |
| `d` | 断开 —— 服务端保留它的会话 |
| `q` | 脱离并退出 TUI |
| `Esc` | 关闭面板 |

点击某一行也会接入它。重试 `Local` 时会重新寻找桌面应用，所以桌面应用退出之后，它连到的就是会话 server。

## 选项

| 选项 | 效果 |
|---|---|
| `[DOMAIN ...]` | 要接入哪些服务端，按域名指定。不指定时，TUI 只接入本机；其他服务端可以之后从连接面板接入 |
| `--prefer-mux` | 连接到后台 mux 服务端，而不是正在运行的 ThinkTerm GUI。默认优先连 GUI |
| `--class <NAME>` | 用于发现运行中 ThinkTerm GUI 套接字的窗口类名 |
| `--tui-config <PATH>` | 使用另一个 TUI 设置文件。TUI 的设置独立于 GUI |

### 它的设置文件在哪里

默认文件是 `~/.config/thinkterm/tui.toml`，TOML 格式，遵循 `$XDG_CONFIG_HOME`；不想用命令行标志时，`$THINKTERM_TUI_CONFIG` 也能指定另一个。这个文件可以在 TUI 内部编辑，并且只有与默认值不同的项才会被写回 —— 默认值仍然是默认值，不会被固定成今天的取值。

另外，`~/.local/state/thinkterm/tui.json`（遵循 `$XDG_STATE_HOME`）记住你上次停在哪个域、哪个 Thread 和哪个标签。

## 相关

- [远程](https://docs.closex.org/zh/thinkterm/remote.md) —— TUI 接入的那些服务端
- [Space、Project 与 Thread](https://docs.closex.org/zh/thinkterm/spaces.md) —— 以及桌面应用为它们添加的东西
- [快捷键与命令](https://docs.closex.org/zh/thinkterm/keyboard.md) —— 桌面应用的快捷键
- [命令行](https://docs.closex.org/zh/thinkterm/cli.md) —— `thinkterm` 可执行文件的其余部分
