跳转到内容

CLI 伴侣工具

oxt CLI 是一个独立的命令行二进制程序,通过 IPC(进程间通信)与正在运行的 OxideTerm GUI 进行通信。用户可以在终端或 shell 脚本中:

  • 查询 OxideTerm 状态与健康信息
  • 列出连接、会话、本地终端与端口转发
  • 执行连接、断开、聚焦、附着(mirror)等会话操作
  • 创建/删除端口转发规则
  • 读取配置(分组、连接详情)
  • 使用 AI(ask / exec),支持流式输出、会话续聊与终端 Markdown 渲染

主要设计决策:

  • 独立二进制oxt 是一个独立的 Rust crate(cli/),不编译进 Tauri 后端,保持 CLI 轻量(约 1 MB)且与 GUI 生命周期解耦。
  • 内置不自动安装:CLI 二进制文件作为 Tauri 资源分发在应用包内。用户通过 设置 → 通用 → CLI 伴侣工具 选择安装,安装后会在 Unix 上创建符号链接,在 Windows 上复制二进制到 ~/.local/bin/oxt
  • IPC 而非 HTTP:通信使用 Unix Domain Socket(macOS/Linux)或命名管道(Windows)——无网络暴露、无端口冲突、无 TLS 开销。
┌─────────────┐ JSON-RPC 2.0 ┌─────────────────┐
│ oxt CLI │◄──── (换行符分隔) ──────────►│ OxideTerm GUI │
│ (Rust bin) │ │ cli_server │
└──────┬──────┘ └────────┬────────┘
│ │
Unix Socket Tokio 异步
~/.oxideterm/oxt.sock accept 循环
│ │
Named Pipe(Windows) methods.rs
\\.\pipe\OxideTerm-CLI-{user} ├─ 状态/列表/健康类方法
├─ 会话与标签操作方法
├─ 转发与配置方法
└─ ask(流式 AI)

服务端src-tauri/src/cli_server/):

模块职责
mod.rsCliServer — 生命周期管理(启动、接受连接循环、关闭)
transport.rsIpcListener / IpcStream — Unix Socket 与命名管道的抽象层
handler.rs单连接请求循环,含读取上限与空闲超时
protocol.rsJSON-RPC 2.0 的 RequestResponseRpcErrorNotification 类型
methods.rsRPC 方法分发与具体实现

客户端cli/src/):

模块职责
main.rsClap CLI 入口,命令定义
connect.rsIpcConnection — 同步 IPC 客户端(Unix Socket / 命名管道)
protocol.rs客户端 JSON-RPC 请求/响应类型
output.rsOutputMode — 人类可读或 JSON 输出格式化

GUI 集成src-tauri/src/commands/cli.rs):

命令职责
cli_get_status返回打包/安装状态供设置界面使用
cli_install在 Unix 上创建符号链接,在 Windows 上复制二进制到安装路径
cli_uninstall删除已安装的 CLI 二进制文件
  • 传输层:Unix Domain Socket 或命名管道
  • 帧格式:换行符分隔 JSON(每行一个 JSON 对象,以 \n 结尾)
  • 编码:UTF-8

请求示例:

{"id": 1, "method": "status", "params": {}}

成功响应:

{"id": 1, "result": {"version": "0.21.0", "sessions": 5, "connections": {"ssh": 3, "local": 2}, "pid": 12345}}

错误响应:

{"id": 1, "error": {"code": -32601, "message": "Method not found: foo"}}
错误码常量含义
-32600ERR_INVALID_REQUESTJSON-RPC 请求格式错误
-32601ERR_METHOD_NOT_FOUND未知方法名
-32602ERR_INVALID_PARAMS方法参数无效
-32603ERR_INTERNAL内部服务器错误
1001ERR_NOT_CONNECTED无活跃连接(保留)
1003ERR_TIMEOUT操作超时(保留)

说明:ask 被归类为流式方法(服务端通过 stream_chunk 通知推送增量文本),其余为普通 JSON-RPC 请求/响应。

分类方法名
状态/探活statusping
列表/查询list_saved_connectionslist_sessionslist_active_connectionslist_forwardslist_local_terminalshealth
会话/标签操作disconnectconnectopen_tabfocus_tabattach
转发管理create_forwarddelete_forward
配置读取config_listconfig_get
AI(流式)ask

返回 OxideTerm 实例的状态摘要。

参数{}

响应

{
"version": "0.21.0",
"sessions": 5,
"connections": {
"ssh": 3,
"local": 2
},
"pid": 12345
}

返回所有已保存的连接配置(来自 connections.json)。

参数{}

响应

[
{
"name": "prod-server",
"host": "10.0.1.5",
"port": 22,
"username": "deploy",
"auth_type": "key"
}
]

注意:响应中永远不包含密码和私钥内容。

返回 SessionRegistry 中所有活跃会话。

参数{}

响应

[
{
"id": "abc123...",
"name": "prod-server",
"host": "10.0.1.5",
"state": "active",
"uptime_secs": 3600
}
]

返回 SshConnectionRegistry 中所有活跃 SSH 连接。

参数{}

响应

[
{
"id": "conn-456...",
"host": "10.0.1.5",
"port": 22,
"username": "deploy",
"state": "active",
"ref_count": 2
}
]

列出端口转发规则,可按会话过滤。

参数{ "session_id": "abc123" }{}(列出所有会话的转发)

响应

[
{
"session_id": "abc123...",
"id": "fwd-456...",
"forward_type": "local",
"bind_address": "127.0.0.1",
"bind_port": 8080,
"target_host": "localhost",
"target_port": 80,
"status": "active",
"description": "Web server"
}
]

获取连接健康状态。

参数{ "session_id": "abc123" }(单个会话)或 {}(所有会话)

单个会话响应

{
"session_id": "abc123...",
"status": "healthy",
"latency_ms": 42,
"message": "Connected • 42ms"
}

所有会话响应

{
"abc123...": {
"session_id": "abc123...",
"status": "healthy",
"latency_ms": 42,
"message": "Connected • 42ms"
},
"def456...": {
"session_id": "def456...",
"status": "degraded",
"latency_ms": 350,
"message": "High latency: 350ms"
}
}

健康状态枚举值:healthydegradedunresponsivedisconnectedunknown

断开指定会话。支持按会话 ID 或名称匹配。

参数{ "target": "abc123" }{ "target": "prod-server" }

响应

{
"success": true,
"session_id": "abc123..."
}

断开操作会依次执行:持久化终端缓冲区 → 停止端口转发 → 关闭 SSH 会话 → 清理 WebSocket 桥接 → 清理 SFTP 缓存 → 清理健康检查器 → 释放连接池。

连通性检查,立即返回。

参数{}

响应

{"pong": true}

返回本地终端会话列表(local-terminal 特性开启时可用)。

参数{}

响应示例

[
{
"id": "local-123...",
"shell_name": "zsh",
"cwd": "/Users/name/project"
}
]

根据保存的连接名称/ID/主机匹配并发起连接(在 GUI 中打开会话)。

参数{ "target": "prod-server" }

打开一个新的本地终端标签页。

参数{ "path": "/path/to/workdir" }

聚焦一个已存在标签页(SSH 会话或本地终端)。

参数{ "target": "session-id-or-name" }

附着到一个正在运行的会话(SSH/本地),进行终端镜像。

参数{ "session_id": "abc123" }

响应示例

{
"ws_url": "ws://127.0.0.1:55321",
"ws_token": "single-use-token",
"terminal_type": "ssh",
"cols": 160,
"rows": 48
}

为会话创建端口转发规则(local / remote / dynamic)。

删除指定端口转发规则。

列出连接分组及统计信息。

查询单个连接详情(不返回密码或私钥内容)。

AI 提问接口。支持:

  • context(stdin 管道上下文)
  • session_id(附带终端缓冲区上下文)
  • modelprovider 覆盖
  • stream 流式输出
  • conversation_id 续聊

流式过程中服务端会发送:

{"method":"stream_chunk","params":{"text":"..."}}

最终响应示例:

{
"text": "...",
"model": "moonshot-v1-8k",
"done": true,
"conversation_id": "b1d0..."
}

CLI 工具已捆绑在 OxideTerm 应用包内,安装步骤:

  1. 打开 OxideTerm → 设置 → 通用
  2. 找到 CLI 伴侣工具 区块
  3. 点击 安装

这将在 macOS/Linux 上创建符号链接,在 Windows 上复制二进制文件到安装路径。

安装路径:

  • macOS/Linux:~/.local/bin/oxt
  • Windows:%LOCALAPPDATA%\OxideTerm\bin\oxt.exe

请确保安装目录已添加到 $PATH

Terminal window
# 查看 OxideTerm 状态
oxt status
# 列出已保存的连接
oxt list connections
# 列出活跃会话
oxt list sessions
# 列出所有端口转发
oxt list forwards
# 列出指定会话的端口转发
oxt list forwards <session-id>
# 查看所有会话健康状态
oxt health
# 查看指定会话健康状态
oxt health <session-id>
# 断开会话(按 ID 或名称)
oxt disconnect <session-id-or-name>
# 连通性检查
oxt ping
# AI 提问(默认流式)
oxt ask "explain this log"
# 从 stdin 管道上下文
echo "$(cat app.log)" | oxt ask "find root cause"
# 强制原始文本输出(不做 Markdown 渲染)
oxt ask --raw "show me command"
# 续聊
oxt ask --continue <conversation-id> "give me safer variant"
# 代码/命令生成模式(代码优先输出)
oxt exec "write a bash script to rotate logs"
# 按名称连接并在 GUI 打开
oxt connect prod-server
# 打开本地终端标签(可指定路径)
oxt open ~/work
# 聚焦标签
oxt focus <session-id-or-name>
# 附着镜像会话
oxt attach <session-id-or-name>
# 创建/删除端口转发
oxt forward add 8080:localhost:80 --session <session-id>
oxt forward remove <forward-id> --session <session-id>
# 配置查询
oxt config list
oxt config get <connection-name-or-id>
# 显示版本
oxt version
# 生成 Shell 补全脚本
oxt completions bash
oxt completions zsh
oxt completions fish
oxt completions powershell
参数默认值说明
--json自动检测强制 JSON 输出(默认:管道时输出 JSON,终端时输出人类可读格式)
--timeout <ms>30000IPC 超时时间(毫秒)
--socket <path>平台默认值自定义 socket/管道路径(用于调试)

CLI 会自动检测 stdout 是否为终端:

  • 终端 → 人类可读的格式化表格
  • 管道/重定向 → 紧凑 JSON(单行)

对于 AI 输出(oxt ask):

  • TTY 且未指定 --raw:输出完成后按 Markdown 渲染(ANSI)
  • 管道/重定向 或 --raw:原始文本输出

使用 --json 可强制始终输出 JSON。

Terminal window
# 人类可读格式的状态信息
$ oxt status
OxideTerm v0.21.0
Sessions: 5 active
Connections: 3 SSH, 2 local
# JSON 格式输出(适合脚本使用)
$ oxt status --json
{"version":"0.21.0","sessions":5,"connections":{"ssh":3,"local":2},"pid":12345}
# 在脚本中列出连接
$ oxt list connections --json | jq '.[].host'
"10.0.1.5"
"192.168.1.100"
# 查看所有会话健康状态
$ oxt health
SESSION STATUS LATENCY MESSAGE
abc123de... healthy 42ms Connected • 42ms
def456gh... degraded 350ms High latency: 350ms
# 在监控脚本中检查是否有不健康的会话
$ oxt health --json | jq 'to_entries[] | select(.value.status != "healthy")'
# 列出端口转发
$ oxt list forwards
SESSION TYPE BIND TARGET STATUS DESC
abc123de local 127.0.0.1:8080 localhost:80 active Web server
abc123de dynamic 127.0.0.1:1080 SOCKS5 active SOCKS5 Proxy
# 断开会话(按名称)
$ oxt disconnect prod-server
Disconnected session: abc123...
# 检查 OxideTerm 是否正在运行
$ oxt ping && echo "正在运行" || echo "未运行"
# 生成 zsh 补全并安装
$ oxt completions zsh > ~/.zfunc/_oxt
# 自定义超时时间
$ oxt status --timeout 5000
# AI:流式 + Markdown 终端渲染
$ oxt ask "explain pwd command"
# AI:用于脚本/管道时建议 raw
$ oxt ask --raw "generate curl command" | pbcopy
# AI:多轮续聊
$ oxt ask "summarize this" --provider openai
...
Conversation: b1d0...
$ oxt ask --continue b1d0... "give me concise version"
# Attach:会话镜像,`~.` 退出
$ oxt attach prod-server
变量平台说明
OXIDETERM_SOCKmacOS/Linux覆盖默认 socket 路径
OXIDETERM_PIPEWindows覆盖默认命名管道路径
  • Unix Socket:创建于 ~/.oxideterm/oxt.sock,权限为 0o600(仅所有者可读写)
  • 命名管道\\.\pipe\OxideTerm-CLI-{username}——作用域限定于当前用户
  • 过期 socket 检测:启动时服务端会探测已存在的 socket。若不可达则删除过期 socket;若可达则启动失败并提示「另一个 OxideTerm 实例正在运行」。
限制项数值目的
最大并发连接数16防止资源耗尽(Semaphore 信号量)
最大请求大小1 MB有界行读取,防止内存滥用
最大响应大小4 MB客户端 .take() 限制
空闲超时60 秒断开不活跃的客户端

AI 相关补充限制:

限制项数值说明
MAX_PROMPT_SIZE50 KB单次 prompt 上限
MAX_CONTEXT_SIZE500 KBstdin 上下文上限
MAX_TERMINAL_BUFFER_LINES2000 行会话缓冲区注入上限
流式读取超时180 秒oxt ask 客户端读取超时
  • 任何 RPC 方法均不返回密码
  • list_saved_connections 只暴露私钥文件路径,不包含私钥内容
  • IPC 服务端仅绑定到本地 IPC,不开放任何网络可访问端口
Terminal window
# 编译检查
cd cli && cargo check
# 正式构建(体积优化)
cd cli && cargo build --release

Release 配置使用 lto = truestrip = trueopt-level = "z",最终二进制约 1 MB。

CLI 在 GitHub Actions 中自动为全部 6 个平台目标构建并打包:

  1. 构建步骤:在 cli/ 目录执行 cargo build --release --target ${{ matrix.target }}
  2. 复制:二进制放入 src-tauri/cli-bin/
  3. 打包tauri.conf.jsonbundle.resources 包含 "cli-bin/*" glob,Tauri 自动将匹配到的 CLI 二进制打包为资源
  4. 分发:Tauri 将 CLI 二进制包含在最终的 .app / .deb / .exe 安装包中

本地 pnpm tauri devcli-bin/ 目录不存在,glob 匹配零个文件,不会报错。

平台构建目标二进制名
macOS(ARM)aarch64-apple-darwinoxt
macOS(Intel)x86_64-apple-darwinoxt
Linux(x64)x86_64-unknown-linux-gnuoxt
Linux(ARM)aarch64-unknown-linux-gnuoxt
Windows(x64)x86_64-pc-windows-msvcoxt.exe
Windows(ARM)aarch64-pc-windows-msvcoxt.exe

CLI 版本通过 pnpm version:bump 与 OxideTerm 保持同步,该脚本会同步更新 cli/Cargo.tomlpackage.jsonsrc-tauri/Cargo.tomlsrc-tauri/tauri.conf.json

CLI 伴侣工具区块位于 设置 → 通用:

  • 状态徽章:显示「已安装」、「未安装」或「未打包」
  • 安装按钮:将内置 CLI 符号链接/复制到 ~/.local/bin/oxt
  • 卸载按钮:删除已安装的 CLI 二进制文件
  • 自动检测:打开「通用」选项卡时自动刷新状态
IPC 命令说明
cli_get_status返回 { bundled: bool, installed: bool, install_path: string }
cli_install将内置资源中的 CLI 安装到安装路径
cli_uninstall删除已安装的 CLI 二进制文件

find_bundled_cli() 按以下顺序查找 CLI 二进制:

  1. Tauri 资源路径:cli-bin/{binary_name}(来自 tauri.conf.json 静态配置)
  2. 直接资源路径:{binary_name}(备用)
  3. 主程序同目录:{exe_dir}/{binary_name}(开发环境备用)

CLI 服务端在 OxideTerm 的 Tauri setup 回调中自动启动:

应用启动 → setup() → CliServer::start(app_handle) → 生成 accept 循环

启动失败不影响主程序:若 IPC 服务端绑定失败(例如另一个实例正在运行),GUI 照常运行,错误仅记录日志。

应用退出时,CLI 服务端优雅关闭:

应用退出 → server.shutdown() → oneshot 信号 → accept 循环退出 → socket 清理

关闭采用 Mutex<Option<oneshot::Sender>> 模式,确保单次信号的可靠传递。

每个 CLI 连接在独立的 Tokio 任务中运行:

接受连接 → Semaphore 许可 → 生成任务 → 读取/分发/响应循环 → 释放许可

Semaphore 将并发连接数限制为 16,超出的连接会被立即拒绝。

oxt 通过 clap_complete 内置了 Shell 补全脚本生成功能,支持 bash、zsh、fish 和 PowerShell。

Bash

Terminal window
oxt completions bash > ~/.local/share/bash-completion/completions/oxt

Zsh

Terminal window
# 确保 ~/.zfunc 在 fpath 中(在 .zshrc 中添加 fpath=(~/.zfunc $fpath))
oxt completions zsh > ~/.zfunc/_oxt

Fish

Terminal window
oxt completions fish > ~/.config/fish/completions/oxt.fish

PowerShell

Terminal window
oxt completions powershell >> $PROFILE

安装后重新加载 Shell 即可使用 Tab 补全。

后续版本可能新增的功能:

  • oxt transfer <name> <local> <remote> — SFTP 文件传输
  • oxt config set — 命令行修改连接配置
  • oxt chat — 交互式多轮 REPL(当前为 ask --continue
  • 服务端主动推送通知(事件流)
  • 动态 Shell 补全(实时查询连接名、会话 ID)

可将二进制文件位置添加到你的 PATH 以便在任何终端中便捷使用。

#!/bin/bash
# 在尝试操作前检查 OxideTerm 是否在运行
if oxt status --json | jq -e '.status == "running"' > /dev/null 2>&1; then
echo "OxideTerm 正在运行"
oxt list --json | jq '.sessions[] | .host'
fi
Terminal window
# 持续监控活跃会话(每 5 秒刷新)
watch -n 5 oxt list