Files
herdr-session-switch/README.md
T

212 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# herdr-hub
`herdr-hub` 是一个 Linux 下的 Herdr session 切换器。它让 tmux 做最外层路由,
把每个本地或 `herdr --remote` attach 放进独立 tmux window,并在 Herdr 画面顶部
显示可点击的 Sessions 条。
它不是 Herdr 插件,也不会修改 Herdr core。Herdr 0.8.2 的插件 API 不能向原生
sidebar 插入 UI,也不能让 thin client 从一个 server 原地改连另一个 server;
所以顶部状态栏横跨整个终端,而不是只嵌在 Spaces 上方。
## 功能
- 自动读取 `herdr session list --json`,导入本机正在运行的 sessions。
- 记住使用过的远端,并通过 SSH 实时读取运行中及已停止的 Herdr sessions。
- 在 Linux `/proc/*/cmdline` 中查找仍在运行的 `herdr --remote …` clients,并自动记住目标。
- 首次接管已有 remote client 时安全地再 attach,不结束原进程。
- 一个 endpoint 对应一个 tmux window,隐藏 window 中的连接继续在线。
- 顶部 Sessions 条在窄屏下也为每个 Tab 显示 Session 优先的短名称,并支持鼠标点击、数字切换和无需 fzf 的动态 popup 选择。
- 可隐藏不再需要的 Tab,而不停止底层本地或远端 Herdr Session。
- dead window 留在顶栏,可原地重连。
- 不修改 `~/.tmux.conf`,不保存 SSH 凭据或远端 Session 缓存。
## 依赖
- Linux
- Python 3.11+
- tmux 3.4+
- Herdr 0.8.2+
- OpenSSH client
检查当前环境:
```bash
./bin/herdr-hub doctor
```
## 安装
直接从仓库运行:
```bash
./bin/herdr-hub
```
或把启动器链接到 `~/.local/bin`:
```bash
make install
herdr-hub doctor
```
安装脚本只创建一个指向本仓库的符号链接。移动或删除仓库后需重新安装。
## 第一次接管
如果本地和 remote Herdr clients 已经分别开在其他终端中:
1. 保持这些 clients 运行。
2. 从一个新的、未嵌套在 tmux 中的终端执行 `herdr-hub`。
3. Hub 扫描现有 clients,并为每个 endpoint 创建一个新的 attach window。
4. 确认 Hub 中可以正常操作后,手动退出原来的 clients。
tmux 不能把另一个终端里已经运行的进程搬进 window,所以首次接管会短暂存在两个
clients;它们连接的是同一个 Herdr server,不会复制 server 或 panes。
只有一个终端时,本地 Herdr 可以先 detach,因为 `herdr session list` 仍能发现后台
server。remote target 在 client 退出后没有本地记录,因此直接使用:
```bash
herdr-hub open --remote orangepi
herdr-hub open --remote orangepi --session work
herdr-hub open --remote ssh://me@server:2222 --remote-keybindings server
```
打开本地 named session:
```bash
herdr-hub open --session work
```
`open` 会把 endpoint 保存在当前 tmux hub 的 window metadata 中。远端 target 还会
同时加入 `~/.config/herdr-hub/remotes.json`,以后可直接从 Sessions
弹窗浏览这台机器上的其他 Session。
## 日常操作
Hub 使用独立 tmux socket `herdr-hub`,不会接管普通 tmux server。外层前缀固定为
`Ctrl+A`,Herdr 原来的 `Ctrl+B` 可以直接使用。
| 操作 | 快捷键 / 命令 |
| --- | --- |
| 点击切换 | 鼠标点击顶部 session |
| 打开 Session 弹窗 | 点击左上角 `Sessions` 或 `Ctrl+A g` |
| 上一个/下一个 window | `Ctrl+A p` / `Ctrl+A n` |
| 按编号切换 | `Ctrl+A 0..9` |
| 扫描新增 sessions | `Ctrl+A r` 或 `herdr-hub refresh` |
| 强制重连当前 window | `Ctrl+A R` |
| 关闭/隐藏当前 Tab | `Ctrl+A &`,确认 `y`;也可在 Sessions 弹窗中选择 |
| detach Hub | `Ctrl+A d` |
| 重新进入 Hub | `herdr-hub` |
| 停止 Hub clients | `herdr-hub stop` |
## 远端 Session 弹窗
弹窗由 tmux `display-popup` 和 Hub 内置选择器组成,不依赖 fzf。它会立即显示已打开的
window,同时在后台并行查询所有已登记远端;每台机器的结果就绪后原地更新。
状态与选择行为:
| 状态 | 选择后的行为 |
| --- | --- |
| `▶` 当前 / `●` 已打开 | 跳转到已有 window |
| `×` 已断线 | 自动重连并跳转 |
| `○` 远端运行 | 新建 attach window 并跳转 |
| `■` 远端已停止 | 启动该 Session、attach 并跳转 |
弹窗靠前位置提供“关闭当前 Tab”;它只结束该 Tab 中的 Hub client,底层 Herdr
Session 和工作现场继续运行。每个远端下方都有“新建 Session”入口。弹窗底部还可添加或管理远端;移除远端只删除
记忆记录,不关闭已有 window,也不停止远端 Herdr server。手机端单击条目即可执行,
键盘支持上下键、Enter、输入搜索、Backspace、`Ctrl+R` 刷新和 Esc 返回/关闭。
也可通过 CLI 管理远端:
```bash
herdr-hub remote list
herdr-hub remote add orangepi
herdr-hub remote add ssh://me@server:2222 --remote-keybindings server
herdr-hub remote remove orangepi
```
注册表默认位于 `~/.config/herdr-hub/remotes.json`(遵循 `$XDG_CONFIG_HOME`),权限为
`0600`。它只保存 SSH target 和 remote keybinding 模式。
## 复制与剪贴板
Hub 启用 tmux 的 OSC 52 剪贴板透传。Herdr 触发的自动复制,以及 tmux 接管后的
鼠标拖选,都会尝试写入当前 Hub 访问端的本地剪贴板。远程 session 中复制的
文本也回到访问端,不是远程机器的剪贴板。
访问端的终端需要支持并允许 OSC 52。如果终端或 Web terminal 禁止了这项能力,
可按住 `Shift` 再拖选,绕过 tmux 并使用终端原生复制。
当访问端宽度小于 80 列时,Hub 会自动进入窄屏模式:隐藏右侧快捷键说明,
所有 Tab 都显示状态和最多 12 列的短名称,并优先显示主机:默认 Session 的本地与
远端分别显示 `local`、`host`,非默认 Session 才显示 `local/work`、`host/work`。
宽度小于 50 列时左上角标题会缩成 `S`,继续给 Tab 留空间。点击 `Sessions`/`S`
可打开占 90% 屏幕的完整选择器。
`refresh` 是 add-only:它添加新发现的 endpoint,不自动删除已有 window,也不会改变
当前焦点。通过 `Ctrl+A &` 或弹窗关闭的 endpoint 会在当前 Hub 生命周期内记为已隐藏,
刷新和断开终端后重新进入都不会让它自动回来。要恢复它,打开 Sessions 弹窗并重新选择;
也可以执行对应的 `herdr-hub open` 命令。远端通过 SSH 目录重新选择,本地隐藏的运行中
Session 会列在“本机”下。Hub 至少保留一个 Tab;要全部退出请使用 `herdr-hub stop`。
当 endpoint 连接进程退出时,window 会保留:顶栏将它标记为 `× [断开]`,
当前 pane 底部会显示退出状态和 `Ctrl+A R` 重连提示。这与正常 detach Hub
不同;仅关闭外层终端后,直接再次执行 `herdr-hub` 即可。
`herdr-hub stop` 只结束 tmux 中的 client processes。本地及远端 Herdr servers 和
它们的 panes 会继续运行。
## CLI
```text
herdr-hub
herdr-hub start
herdr-hub refresh
herdr-hub open [--session NAME]
herdr-hub open --remote TARGET [--session NAME]
[--remote-keybindings local|server]
herdr-hub choose
herdr-hub remote list
herdr-hub remote add TARGET [--remote-keybindings local|server]
herdr-hub remote remove TARGET
herdr-hub reconnect [--window ID]
herdr-hub close [--window ID]
herdr-hub doctor
herdr-hub stop
```
## 自动发现与远端查询的边界
零配置的首次发现只覆盖:
- 当前用户正在运行的本地 Herdr servers;
- 当前用户、同一 PID namespace 中仍然存活的 `herdr --remote` processes。
发现或手动添加一次后,remote target 会被记住,不再要求本地 client 持续存活。弹窗使用
非交互 SSH 查询 `$HOME/.local/bin/herdr session list --json`;SSH key/passphrase 应已由
ssh-agent 处理。未知 host key、需要密码或远端不可达时会显示可重试的错误,不会卡住
整个弹窗。首次安装或 host-key 确认仍可在实际新建的 Herdr window 中交互完成。
首次使用且尚未登记时,以下情况仍无法自动找回 remote target:
- remote client 已经退出,但远端 server 仍在后台运行;
- client 位于另一个 container/PID namespace;
- `/proc` 使用了阻止读取同用户 argv 的安全配置;
- 可执行文件不叫 `herdr`。
这些场景可在弹窗中选择“添加远端”,或使用 `herdr-hub open --remote …`。为了避免嵌套 tmux 与前缀冲突,
`herdr-hub` 应从普通终端启动;若当前已经在另一个 tmux server 中,它会拒绝再次
attach。
## 开发与测试
```bash
make test
```
测试使用伪造的 `/proc` 和 Herdr executable;tmux 集成测试使用唯一 socket 和
`/dev/null` 配置,不接触真实 Herdr sessions 或现有 tmux server。