besh 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
besh-0.1.0/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .pytest_cache/
2
+ .workbuddy/
3
+ __pycache__/
4
+ dist/
besh-0.1.0/LICENSE.txt ADDED
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026-present cqian-cs <cqian.cs@qq.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
besh-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,244 @@
1
+ Metadata-Version: 2.4
2
+ Name: besh
3
+ Version: 0.1.0
4
+ Summary: Beacon Shell:让 Agent 把计算任务交给闲置算力(手机 Termux / 云 IDE / 云 Notebook)
5
+ Project-URL: Documentation, https://github.com/cqian-cs/besh#readme
6
+ Project-URL: Issues, https://github.com/cqian-cs/besh/issues
7
+ Project-URL: Source, https://github.com/cqian-cs/besh
8
+ Author-email: cqian-cs <cqian.cs@qq.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE.txt
11
+ Keywords: agent,beacon,rclone,remote,tmux,worker
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Programming Language :: Python
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: Implementation :: CPython
18
+ Requires-Python: >=3.10
19
+ Requires-Dist: aiofiles>=22.1
20
+ Requires-Dist: aiohttp>=3.8
21
+ Requires-Dist: orjson>=3.6
22
+ Requires-Dist: sqless>=5.0.1
23
+ Provides-Extra: test
24
+ Requires-Dist: pytest-asyncio>=0.21; extra == 'test'
25
+ Requires-Dist: pytest>=7.0; extra == 'test'
26
+ Description-Content-Type: text/markdown
27
+
28
+ # Beacon Shell (besh)
29
+
30
+ **把闲置算力变成 AI Agent 可远程操作的工人。**
31
+
32
+ 闲置算力随处可见:手机 Termux、免费的云 IDE、云 Notebook……但它们大多没有公网 IP,没法通过 SSH 远程操作。
33
+
34
+ besh 用一个"信标 + 工人"的架构解决这个问题:只要闲置终端能访问外网,就能反向连接信标、领取命令、回传结果——你(或你的 AI Agent)则可以像操作 tmux 一样操作散落在各处的机器。
35
+
36
+ ```mermaid
37
+ flowchart TB
38
+ UR["人类"]
39
+ AG["AI Agent"]
40
+ RC["本地电脑<br>besh run -t 工人ID:窗口名 命令"]
41
+ BE["公网服务器<br>besh serve"]
42
+
43
+ UR -- CLI --> RC
44
+ UR -- Web --> BE
45
+ AG -- CLI --> RC -- API --> BE
46
+ AG -- MCP --> BE
47
+
48
+ BE <-- "轮询取命令 <br> 回传屏幕 / 结果" --> W1["闲置算力<br>besh worker 工人ID"]
49
+ BE <-- "轮询取命令 <br> 回传屏幕 / 结果" --> W2["闲置算力<br>besh worker 工人ID"]
50
+
51
+ W1 -.->|"rclone 定时备份"| R2[("对象存储<br>Cloudflare R2")]
52
+ W2 -.->|"rclone 定时备份"| R2
53
+
54
+ classDef purple fill:#ede9fe,stroke:#7c3aed,color:#1e293b
55
+ classDef blue fill:#dbeafe,stroke:#2563eb,color:#1e293b
56
+ classDef green fill:#d1fae5,stroke:#059669,color:#1e293b
57
+ classDef amber fill:#fef3c7,stroke:#d97706,color:#1e293b
58
+
59
+ class RC,AG,UR purple
60
+ class BE blue
61
+ class W1,W2 green
62
+ class R2 amber
63
+ ```
64
+
65
+ ## 四个角色
66
+
67
+ | 角色 | 运行位置 | 职责 |
68
+ |------|----------|------|
69
+ | 信标 | 有公网 IP 的服务器 | 中转命令、记录状态、提供 Web 界面与 MCP 接口 |
70
+ | 工人 | 任意闲置终端(无公网 IP) | 轮询信标领命令,在 tmux 窗口里执行,定时备份工作目录 |
71
+ | 遥控器 | 本地电脑 | 类似 tmux 的命令行,把 session 换成工人 ID,可同时操作多台 |
72
+ | 对象存储 | Cloudflare R2 | 备份工人工作目录(工人是临时的,随时会释放) |
73
+
74
+ ## 安装
75
+
76
+ ```bash
77
+ pip install besh
78
+ ```
79
+
80
+ 要求 Python ≥ 3.10。工人机器上还需要安装 [tmux](https://github.com/tmux/tmux)。
81
+
82
+ ## 快速开始
83
+
84
+ ### 1. 启动信标(云服务器)
85
+
86
+ ```bash
87
+ export besh_secret=CHANGE_TO_YOUR_PASSWORD
88
+ besh serve
89
+ ```
90
+
91
+ 启动时会生成自包含的 `besh_beacon.py`(主程序)和 `www/index.html`(Web 界面),数据存放在 `./db/`。默认监听 `12242` 端口,输出类似:
92
+
93
+ ```
94
+ 工人连接 : export besh_url=http://<HOST>:12242?secret=xxx
95
+ 浏览器 : http://<HOST>:12242/?secret=xxx
96
+ MCP : http://<HOST>:12242/mcp (Authorization: Bearer xxx)
97
+ ```
98
+
99
+ ### 2. 接入工人(闲置终端)
100
+
101
+ ```bash
102
+ export besh_url=http://BEACON-HOST:12242?secret=CHANGE_TO_YOUR_PASSWORD
103
+ besh worker WORKER_ID
104
+ ```
105
+
106
+ - 会创建 `./WORKER_ID` 作为工作目录,后续所有命令都在这个目录里执行
107
+ - 通过 tmux 启动 `besh_worker` 会话(创建窗口、执行命令)和 `besh_sync` 会话(定时把工作目录同步到对象存储)
108
+
109
+ ### 3. 远程操作(本地电脑)
110
+
111
+ ```bash
112
+ export besh_url=http://BEACON-HOST:12242?secret=CHANGE_TO_YOUR_PASSWORD
113
+
114
+ # 列出所有工人(ls / list-sessions / list-workers 等价)
115
+ besh ls
116
+
117
+ # 列出某工人的所有窗口
118
+ besh list-windows -t WORKER_ID
119
+
120
+ # 查看窗口内容(同 tmux capture-pane)
121
+ besh capture-pane -t WORKER_ID:WINDOW_NAME -p -S -50
122
+
123
+ # 发送按键(窗口不存在会自动创建)
124
+ besh send-keys -t WORKER_ID:WINDOW_NAME "ls -l" Enter
125
+
126
+ # 发送按键,-l 按字面处理(不展开变量)
127
+ besh send-keys -t WORKER_ID:WINDOW_NAME -l 'echo "Hello $USER"'
128
+
129
+ # 执行一条命令并打印输出(体验类似 ssh host cmd)
130
+ besh run -t WORKER_ID "uname -a"
131
+
132
+ # 跑长任务:先输入不等待,稍后等它执行完(窗口回到提示符)
133
+ besh type -t WORKER_ID:WINDOW_NAME "python train.py"
134
+ besh wait -t WORKER_ID:WINDOW_NAME
135
+ ```
136
+
137
+ ## 对象存储(Cloudflare R2)
138
+
139
+ 信标带宽贵、网速慢,不适合备份工作目录;[Cloudflare R2](https://developers.cloudflare.com/r2/) 免费 10GB 且网速快,所以用它。工人工作目录备份在 `cf:besh/YYYY-MM-DD/WORKER_ID/*`。
140
+
141
+ 1. 开通 Cloudflare R2,创建存储桶 `besh`
142
+ 2. 在信标与工人机器上安装 [rclone](https://rclone.org/install/):
143
+
144
+ ```bash
145
+ sudo -v ; curl https://rclone.org/install.sh | sudo bash
146
+ ```
147
+
148
+ 3. 配置 rclone 环境变量访问 R2:
149
+
150
+ ```bash
151
+ export RCLONE_CONFIG_CF_TYPE=s3
152
+ export RCLONE_CONFIG_CF_PROVIDER=Cloudflare
153
+ export RCLONE_CONFIG_CF_ACCESS_KEY_ID=
154
+ export RCLONE_CONFIG_CF_SECRET_ACCESS_KEY=
155
+ export RCLONE_CONFIG_CF_ENDPOINT=
156
+ export RCLONE_CONFIG_CF_REGION=auto
157
+ ```
158
+
159
+ 配置好后,遥控器即可管理备份:
160
+
161
+ ```bash
162
+ besh backup -t WORKER_ID # 立刻备份(不等定时任务)
163
+ besh restore -t WORKER_ID # 从最新备份恢复工作目录
164
+ besh files -t WORKER_ID # 列出对象存储里的备份文件
165
+ besh download / besh upload / besh rm # 下载 / 上传 / 删除文件
166
+ ```
167
+
168
+ ## Web 操作界面
169
+
170
+ 浏览器打开 `http://BEACON-HOST:12242?secret=xxx`:
171
+
172
+ - 每个工人的实时状态(主机名、工作目录、窗口列表、在线状态)
173
+ - 完善的 WebShell:实时屏幕、输入框、`^C` / `^D` / `Tab` / `↑` / `↓` / `Esc` 按键助手
174
+ - 基于对象存储的文件上传 / 下载 / 直链分享
175
+
176
+ ## AI Agent 接入
177
+
178
+ besh 为 AI Agent 提供两条通道,任选其一:
179
+
180
+ **MCP**(信标内置):
181
+
182
+ ```bash
183
+ besh mcp # 打印 MCP 客户端配置
184
+ besh mcp --write ~/.workbuddy/mcp.json # 直接写入客户端配置
185
+ ```
186
+
187
+ **CLI 技能**(把 besh 命令教给 Agent):
188
+
189
+ ```bash
190
+ besh skill # 打印 SKILL.md
191
+ besh skill --install ~/.workbuddy/skills/ # 安装为 Agent 技能
192
+ ```
193
+
194
+ ## 命令一览
195
+
196
+ | 命令 | 说明 |
197
+ |------|------|
198
+ | `besh serve` | 在当前目录启动信标 |
199
+ | `besh worker ID` | 以工人身份接入信标 |
200
+ | `besh ls` | 列出所有工人 |
201
+ | `besh list-windows -t ID` | 列出工人的窗口 |
202
+ | `besh capture-pane -t ID:WIN` | 查看窗口内容 |
203
+ | `besh send-keys -t ID:WIN …` | 向窗口发送按键 |
204
+ | `besh type -t ID:WIN TEXT` | 输入文本(可选回车),Agent 友好 |
205
+ | `besh run -t ID:WIN CMD` | 执行命令并打印输出 |
206
+ | `besh new-window` / `kill-window` | 新建 / 关闭窗口 |
207
+ | `besh kill-worker -t ID` | 让工人退出(tmux 会话一并关闭) |
208
+ | `besh wait -t ID:WIN` | 等待窗口回到提示符(命令执行完毕) |
209
+ | `besh wait CMD_ID` | 等待某条异步命令的回执 |
210
+ | `besh history` / `besh info` | 命令历史 / 工人详情 |
211
+ | `besh files` / `download` / `upload` / `rm` | 管理对象存储里的文件 |
212
+ | `besh backup` / `restore` | 备份 / 恢复工作目录 |
213
+ | `besh mcp` / `besh skill` | 生成 MCP / Agent 技能配置 |
214
+
215
+ 环境变量:`besh_url`(信标地址)、`besh_secret`(密钥)。也可以用 `-u` / `--secret` 参数临时指定,或 `--json` 输出 JSON。
216
+
217
+ ## 可靠性设计
218
+
219
+ - **命令不丢**:命令入队即落盘(sqlite)。信标重启后,pending 和已投递未回执的命令都会重新排队;工人侧用执行记录去重,最坏情况重复执行一次(at-least-once)。
220
+ - **屏幕秒回**:工人定期把各窗口屏幕快照推给信标缓存,`capture-pane` 无需等待。
221
+ - **投递超时重排**:命令投递后 120 秒无回执,自动重新排队(工人可能已重启)。
222
+ - **安全模型**:单一密钥认证(信标侧);工人本身处在容器 / 虚拟机内,不提供额外的安全隔离。
223
+
224
+ ## 实现细节
225
+
226
+ 1. 信标基于 [sqless](https://github.com/cqian-cs/sqless) 框架(简易单用户认证 + sqlite 数据库 + 函数转 API + 函数转 MCP)。`besh serve` 会在当前路径通过 `sqless --app besh_beacon.py` 生成服务端代码。
227
+ 2. 工人内部跑两个 tmux 会话:`besh_worker`(窗口与命令执行)和 `besh_sync`(定时 rclone 备份)。
228
+ 3. 遥控器客户端只依赖 Python 标准库。
229
+
230
+ ## 开发
231
+
232
+ ```bash
233
+ git clone https://github.com/cqian-cs/besh
234
+ cd besh
235
+ pip install -e . --no-build-isolation
236
+ pip install -e ".[test]"
237
+ pytest
238
+ ```
239
+
240
+ 测试包含 55 个单元/集成测试;`tests/fake_worker.py` 提供不依赖 tmux 的假工人,可用于本地联调。
241
+
242
+ ## License
243
+
244
+ MIT © [cqian-cs](https://github.com/cqian-cs)
besh-0.1.0/README.md ADDED
@@ -0,0 +1,217 @@
1
+ # Beacon Shell (besh)
2
+
3
+ **把闲置算力变成 AI Agent 可远程操作的工人。**
4
+
5
+ 闲置算力随处可见:手机 Termux、免费的云 IDE、云 Notebook……但它们大多没有公网 IP,没法通过 SSH 远程操作。
6
+
7
+ besh 用一个"信标 + 工人"的架构解决这个问题:只要闲置终端能访问外网,就能反向连接信标、领取命令、回传结果——你(或你的 AI Agent)则可以像操作 tmux 一样操作散落在各处的机器。
8
+
9
+ ```mermaid
10
+ flowchart TB
11
+ UR["人类"]
12
+ AG["AI Agent"]
13
+ RC["本地电脑<br>besh run -t 工人ID:窗口名 命令"]
14
+ BE["公网服务器<br>besh serve"]
15
+
16
+ UR -- CLI --> RC
17
+ UR -- Web --> BE
18
+ AG -- CLI --> RC -- API --> BE
19
+ AG -- MCP --> BE
20
+
21
+ BE <-- "轮询取命令 <br> 回传屏幕 / 结果" --> W1["闲置算力<br>besh worker 工人ID"]
22
+ BE <-- "轮询取命令 <br> 回传屏幕 / 结果" --> W2["闲置算力<br>besh worker 工人ID"]
23
+
24
+ W1 -.->|"rclone 定时备份"| R2[("对象存储<br>Cloudflare R2")]
25
+ W2 -.->|"rclone 定时备份"| R2
26
+
27
+ classDef purple fill:#ede9fe,stroke:#7c3aed,color:#1e293b
28
+ classDef blue fill:#dbeafe,stroke:#2563eb,color:#1e293b
29
+ classDef green fill:#d1fae5,stroke:#059669,color:#1e293b
30
+ classDef amber fill:#fef3c7,stroke:#d97706,color:#1e293b
31
+
32
+ class RC,AG,UR purple
33
+ class BE blue
34
+ class W1,W2 green
35
+ class R2 amber
36
+ ```
37
+
38
+ ## 四个角色
39
+
40
+ | 角色 | 运行位置 | 职责 |
41
+ |------|----------|------|
42
+ | 信标 | 有公网 IP 的服务器 | 中转命令、记录状态、提供 Web 界面与 MCP 接口 |
43
+ | 工人 | 任意闲置终端(无公网 IP) | 轮询信标领命令,在 tmux 窗口里执行,定时备份工作目录 |
44
+ | 遥控器 | 本地电脑 | 类似 tmux 的命令行,把 session 换成工人 ID,可同时操作多台 |
45
+ | 对象存储 | Cloudflare R2 | 备份工人工作目录(工人是临时的,随时会释放) |
46
+
47
+ ## 安装
48
+
49
+ ```bash
50
+ pip install besh
51
+ ```
52
+
53
+ 要求 Python ≥ 3.10。工人机器上还需要安装 [tmux](https://github.com/tmux/tmux)。
54
+
55
+ ## 快速开始
56
+
57
+ ### 1. 启动信标(云服务器)
58
+
59
+ ```bash
60
+ export besh_secret=CHANGE_TO_YOUR_PASSWORD
61
+ besh serve
62
+ ```
63
+
64
+ 启动时会生成自包含的 `besh_beacon.py`(主程序)和 `www/index.html`(Web 界面),数据存放在 `./db/`。默认监听 `12242` 端口,输出类似:
65
+
66
+ ```
67
+ 工人连接 : export besh_url=http://<HOST>:12242?secret=xxx
68
+ 浏览器 : http://<HOST>:12242/?secret=xxx
69
+ MCP : http://<HOST>:12242/mcp (Authorization: Bearer xxx)
70
+ ```
71
+
72
+ ### 2. 接入工人(闲置终端)
73
+
74
+ ```bash
75
+ export besh_url=http://BEACON-HOST:12242?secret=CHANGE_TO_YOUR_PASSWORD
76
+ besh worker WORKER_ID
77
+ ```
78
+
79
+ - 会创建 `./WORKER_ID` 作为工作目录,后续所有命令都在这个目录里执行
80
+ - 通过 tmux 启动 `besh_worker` 会话(创建窗口、执行命令)和 `besh_sync` 会话(定时把工作目录同步到对象存储)
81
+
82
+ ### 3. 远程操作(本地电脑)
83
+
84
+ ```bash
85
+ export besh_url=http://BEACON-HOST:12242?secret=CHANGE_TO_YOUR_PASSWORD
86
+
87
+ # 列出所有工人(ls / list-sessions / list-workers 等价)
88
+ besh ls
89
+
90
+ # 列出某工人的所有窗口
91
+ besh list-windows -t WORKER_ID
92
+
93
+ # 查看窗口内容(同 tmux capture-pane)
94
+ besh capture-pane -t WORKER_ID:WINDOW_NAME -p -S -50
95
+
96
+ # 发送按键(窗口不存在会自动创建)
97
+ besh send-keys -t WORKER_ID:WINDOW_NAME "ls -l" Enter
98
+
99
+ # 发送按键,-l 按字面处理(不展开变量)
100
+ besh send-keys -t WORKER_ID:WINDOW_NAME -l 'echo "Hello $USER"'
101
+
102
+ # 执行一条命令并打印输出(体验类似 ssh host cmd)
103
+ besh run -t WORKER_ID "uname -a"
104
+
105
+ # 跑长任务:先输入不等待,稍后等它执行完(窗口回到提示符)
106
+ besh type -t WORKER_ID:WINDOW_NAME "python train.py"
107
+ besh wait -t WORKER_ID:WINDOW_NAME
108
+ ```
109
+
110
+ ## 对象存储(Cloudflare R2)
111
+
112
+ 信标带宽贵、网速慢,不适合备份工作目录;[Cloudflare R2](https://developers.cloudflare.com/r2/) 免费 10GB 且网速快,所以用它。工人工作目录备份在 `cf:besh/YYYY-MM-DD/WORKER_ID/*`。
113
+
114
+ 1. 开通 Cloudflare R2,创建存储桶 `besh`
115
+ 2. 在信标与工人机器上安装 [rclone](https://rclone.org/install/):
116
+
117
+ ```bash
118
+ sudo -v ; curl https://rclone.org/install.sh | sudo bash
119
+ ```
120
+
121
+ 3. 配置 rclone 环境变量访问 R2:
122
+
123
+ ```bash
124
+ export RCLONE_CONFIG_CF_TYPE=s3
125
+ export RCLONE_CONFIG_CF_PROVIDER=Cloudflare
126
+ export RCLONE_CONFIG_CF_ACCESS_KEY_ID=
127
+ export RCLONE_CONFIG_CF_SECRET_ACCESS_KEY=
128
+ export RCLONE_CONFIG_CF_ENDPOINT=
129
+ export RCLONE_CONFIG_CF_REGION=auto
130
+ ```
131
+
132
+ 配置好后,遥控器即可管理备份:
133
+
134
+ ```bash
135
+ besh backup -t WORKER_ID # 立刻备份(不等定时任务)
136
+ besh restore -t WORKER_ID # 从最新备份恢复工作目录
137
+ besh files -t WORKER_ID # 列出对象存储里的备份文件
138
+ besh download / besh upload / besh rm # 下载 / 上传 / 删除文件
139
+ ```
140
+
141
+ ## Web 操作界面
142
+
143
+ 浏览器打开 `http://BEACON-HOST:12242?secret=xxx`:
144
+
145
+ - 每个工人的实时状态(主机名、工作目录、窗口列表、在线状态)
146
+ - 完善的 WebShell:实时屏幕、输入框、`^C` / `^D` / `Tab` / `↑` / `↓` / `Esc` 按键助手
147
+ - 基于对象存储的文件上传 / 下载 / 直链分享
148
+
149
+ ## AI Agent 接入
150
+
151
+ besh 为 AI Agent 提供两条通道,任选其一:
152
+
153
+ **MCP**(信标内置):
154
+
155
+ ```bash
156
+ besh mcp # 打印 MCP 客户端配置
157
+ besh mcp --write ~/.workbuddy/mcp.json # 直接写入客户端配置
158
+ ```
159
+
160
+ **CLI 技能**(把 besh 命令教给 Agent):
161
+
162
+ ```bash
163
+ besh skill # 打印 SKILL.md
164
+ besh skill --install ~/.workbuddy/skills/ # 安装为 Agent 技能
165
+ ```
166
+
167
+ ## 命令一览
168
+
169
+ | 命令 | 说明 |
170
+ |------|------|
171
+ | `besh serve` | 在当前目录启动信标 |
172
+ | `besh worker ID` | 以工人身份接入信标 |
173
+ | `besh ls` | 列出所有工人 |
174
+ | `besh list-windows -t ID` | 列出工人的窗口 |
175
+ | `besh capture-pane -t ID:WIN` | 查看窗口内容 |
176
+ | `besh send-keys -t ID:WIN …` | 向窗口发送按键 |
177
+ | `besh type -t ID:WIN TEXT` | 输入文本(可选回车),Agent 友好 |
178
+ | `besh run -t ID:WIN CMD` | 执行命令并打印输出 |
179
+ | `besh new-window` / `kill-window` | 新建 / 关闭窗口 |
180
+ | `besh kill-worker -t ID` | 让工人退出(tmux 会话一并关闭) |
181
+ | `besh wait -t ID:WIN` | 等待窗口回到提示符(命令执行完毕) |
182
+ | `besh wait CMD_ID` | 等待某条异步命令的回执 |
183
+ | `besh history` / `besh info` | 命令历史 / 工人详情 |
184
+ | `besh files` / `download` / `upload` / `rm` | 管理对象存储里的文件 |
185
+ | `besh backup` / `restore` | 备份 / 恢复工作目录 |
186
+ | `besh mcp` / `besh skill` | 生成 MCP / Agent 技能配置 |
187
+
188
+ 环境变量:`besh_url`(信标地址)、`besh_secret`(密钥)。也可以用 `-u` / `--secret` 参数临时指定,或 `--json` 输出 JSON。
189
+
190
+ ## 可靠性设计
191
+
192
+ - **命令不丢**:命令入队即落盘(sqlite)。信标重启后,pending 和已投递未回执的命令都会重新排队;工人侧用执行记录去重,最坏情况重复执行一次(at-least-once)。
193
+ - **屏幕秒回**:工人定期把各窗口屏幕快照推给信标缓存,`capture-pane` 无需等待。
194
+ - **投递超时重排**:命令投递后 120 秒无回执,自动重新排队(工人可能已重启)。
195
+ - **安全模型**:单一密钥认证(信标侧);工人本身处在容器 / 虚拟机内,不提供额外的安全隔离。
196
+
197
+ ## 实现细节
198
+
199
+ 1. 信标基于 [sqless](https://github.com/cqian-cs/sqless) 框架(简易单用户认证 + sqlite 数据库 + 函数转 API + 函数转 MCP)。`besh serve` 会在当前路径通过 `sqless --app besh_beacon.py` 生成服务端代码。
200
+ 2. 工人内部跑两个 tmux 会话:`besh_worker`(窗口与命令执行)和 `besh_sync`(定时 rclone 备份)。
201
+ 3. 遥控器客户端只依赖 Python 标准库。
202
+
203
+ ## 开发
204
+
205
+ ```bash
206
+ git clone https://github.com/cqian-cs/besh
207
+ cd besh
208
+ pip install -e . --no-build-isolation
209
+ pip install -e ".[test]"
210
+ pytest
211
+ ```
212
+
213
+ 测试包含 55 个单元/集成测试;`tests/fake_worker.py` 提供不依赖 tmux 的假工人,可用于本地联调。
214
+
215
+ ## License
216
+
217
+ MIT © [cqian-cs](https://github.com/cqian-cs)
@@ -0,0 +1,82 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "besh"
7
+ dynamic = ["version"]
8
+ description = "Beacon Shell:让 Agent 把计算任务交给闲置算力(手机 Termux / 云 IDE / 云 Notebook)"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ keywords = ["tmux", "remote", "agent", "beacon", "worker", "rclone"]
13
+ authors = [
14
+ { name = "cqian-cs", email = "cqian.cs@qq.com" },
15
+ ]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Programming Language :: Python",
19
+ "Programming Language :: Python :: 3.10",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: Implementation :: CPython",
23
+ ]
24
+ dependencies = [
25
+ "sqless>=5.0.1",
26
+ "aiohttp>=3.8",
27
+ "aiofiles>=22.1",
28
+ "orjson>=3.6",
29
+ ]
30
+
31
+ [project.scripts]
32
+ besh = "besh.cli:main"
33
+
34
+ [project.urls]
35
+ Documentation = "https://github.com/cqian-cs/besh#readme"
36
+ Issues = "https://github.com/cqian-cs/besh/issues"
37
+ Source = "https://github.com/cqian-cs/besh"
38
+
39
+ [project.optional-dependencies]
40
+ test = ["pytest>=7.0", "pytest-asyncio>=0.21"]
41
+
42
+ [tool.hatch.version]
43
+ path = "src/besh/__about__.py"
44
+
45
+ [tool.hatch.build.targets.wheel]
46
+ packages = ["src/besh"]
47
+ core-metadata-version = "2.4"
48
+
49
+ [tool.hatch.build.targets.sdist]
50
+ include = ["src/besh", "tests", "README.md"]
51
+ core-metadata-version = "2.4"
52
+
53
+ [tool.hatch.envs.types]
54
+ extra-dependencies = [
55
+ "mypy>=1.0.0",
56
+ ]
57
+
58
+ [tool.hatch.envs.types.scripts]
59
+ check = "mypy --install-types --non-interactive {args:src/besh tests}"
60
+
61
+ [tool.pytest.ini_options]
62
+ testpaths = ["tests"]
63
+ filterwarnings = ["ignore::DeprecationWarning"]
64
+
65
+ [tool.coverage.run]
66
+ source_pkgs = ["besh", "tests"]
67
+ branch = true
68
+ parallel = true
69
+ omit = [
70
+ "src/besh/__about__.py",
71
+ ]
72
+
73
+ [tool.coverage.paths]
74
+ besh = ["src/besh", "*/besh/src/besh"]
75
+ tests = ["tests", "*/besh/tests"]
76
+
77
+ [tool.coverage.report]
78
+ exclude_lines = [
79
+ "no cov",
80
+ "if __name__ == .__main__.:",
81
+ "if TYPE_CHECKING:",
82
+ ]
@@ -0,0 +1,4 @@
1
+ # SPDX-FileCopyrightText: 2026-present cqian-cs <cqian.cs@qq.com>
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ __version__ = "0.1.0"
@@ -0,0 +1,18 @@
1
+ # SPDX-FileCopyrightText: 2026-present cqian-cs <cqian.cs@qq.com>
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ """besh - Beacon Shell.
5
+
6
+ 把闲置算力(手机 Termux、免费云 IDE、云 NoteBook)变成可远程操作的工人。
7
+
8
+ 四个角色:
9
+
10
+ * 信标(beacon)—— 有公网 IP 的服务器,中转命令、记录状态、提供 Web 界面与 MCP。
11
+ * 工人(worker)—— 任意终端,向信标轮询命令并交给 tmux 执行。
12
+ * 遥控器(controller)—— 本地电脑,用 tmux 风格的命令行操作多个工人。
13
+ * 对象存储(R2)—— 备份工人的工作目录。
14
+ """
15
+
16
+ from .__about__ import __version__
17
+
18
+ __all__ = ["__version__"]
@@ -0,0 +1,9 @@
1
+ # SPDX-FileCopyrightText: 2026-present cqian-cs <cqian.cs@qq.com>
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ import sys
5
+
6
+ from .cli import main
7
+
8
+ if __name__ == "__main__":
9
+ sys.exit(main())