FWS – 可通过 pip 安装的嵌入式进程监护器,支持 PTY/管道/dtach 后端
2 分•作者: mrsurge•大约 19 小时前
我发布了 *Framework Shells* (`fws`):一个独立的 Python 包,用于编排长时间运行的后台进程(“shell”),支持 *PTY*、*管道* 和 *dtach* 后端。<p>这适用于那些不想搭建完整 supervisor 堆栈(或没有堆栈)的环境:快速的多服务原型、开发环境、受限的用户空间等。<p>### 它的作用<p>* 使用以下方式生成/管理 shell:<p><pre><code> * **PTY**: 交互式终端会话(调整大小、输入、流)
* **管道**: stdin/stdout/stderr 流(适用于守护进程/LSP)
* **dtach**: 可附着/分离的持久会话(在管理器重启后仍然存在)</code></pre>
* *运行时隔离*(主要功能):shell 通过
`~/.cache/framework_shells/runtimes/<repo_fingerprint>/<runtime_id>/...`
进行命名空间管理,因此同一仓库的两个克隆可以并发运行,而不会出现交叉采用或交叉控制的情况。
* *控制界面*:CLI + 可选的 FastAPI/WS UI,用于列出、查看日志和生命周期操作。
* 可选的 *钩子*,用于主机集成(外部注册表/遥测)。<p>### CLI 快速入门<p>```bash
# 列出 shell
fws list<p># 运行一次性 shell(无规范)
fws run --backend pty --label demo -- bash -l -i<p># 应用 YAML shellspec(推荐)
fws up shells.yaml<p># 终止 shell
fws down<p># 附着到 dtach 后端 shell
fws attach <shell_id><p># 显示已管理的 shell + procfs 后代
fws tree --depth 4
```<p>### Shellspec 示例<p>```yaml
version: "1"
shells:
worker:
backend: proc
cwd: ${ctx:PROJECT_ROOT}
subgroups: ["worker", "project:${ctx:APP_ID}"]
command: ["python", "-m", "your_module.worker", "--port", "${free_port}"]
```<p>### 隔离 + 安全模型(默认简单)<p>* `FRAMEWORK_SHELLS_SECRET` 派生 `runtime_id`(命名空间)和 API 令牌。
* 如果设置了 secret,则修改 API 端点需要:<p><pre><code> * `Authorization: Bearer <token>` (或 `X-Framework-Key`)。</code></pre>
* 如果未设置 secret,则禁用身份验证(开发模式)。<p>硬限制:如果两个运行时共享相同的 OS 用户/UID,OS 仍然可能允许相互发出信号。保证是:*通过库的控制平面*,不会出现交叉计数/采用/控制。<p>### 实际应用<p>我将其用作完整开发环境的基础,其中“应用程序是 shell”(终端、IDE + LSP、代理/MCP、aria2 RPC、文件浏览器、llama.cpp 运行器等)。仓库:<p>```text
https://github.com/mrsurge/termux-extensions-2
```<p>### 我想要的反馈<p>* secret/fingerprint/运行时隔离的契约感觉对吗?
* 默认 API/CLI 中是否有明显的陷阱?
* 与 systemd/supervisord/tmux/dtach 相比:您会在哪里使用它?<p>github.com/mrsurge/framework-shells<p>pip install "framework-shells @ git+https://github.com/mrsurge/framework-shells@main"<p>```bash
fws --help
```
查看原文
I’m releasing *Framework Shells* (`fws`): a standalone Python package for orchestrating long-running background processes (“shells”) with *PTY*, *pipes*, and *dtach* backends.<p>This is meant for environments where you don’t want to stand up a full supervisor stack (or don’t have one): quick multi-service prototypes, dev environments, constrained userlands, etc.<p>### What it does<p>* Spawn/manage shells with:<p><pre><code> * **PTY**: interactive terminal sessions (resize, input, stream)
* **Pipes**: stdin/stdout/stderr streams (good for daemons/LSPs)
* **dtach**: persistent sessions you can attach/detach to (survives manager restarts)</code></pre>
* *Runtime isolation* (the big feature): shells are namespaced by
`~/.cache/framework_shells/runtimes/<repo_fingerprint>/<runtime_id>/...`
so two clones of the same repo can run concurrently without cross-adoption or cross-control.
* *Control surfaces*: CLI + optional FastAPI/WS UI for listing, logs, and lifecycle actions.
* Optional *hooks* for host integration (external registries/telemetry).<p>### CLI quickstart<p>```bash
# list shells
fws list<p># run a one-off shell (no spec)
fws run --backend pty --label demo -- bash -l -i<p># apply a YAML shellspec (recommended)
fws up shells.yaml<p># terminate shells
fws down<p># attach to a dtach-backed shell
fws attach <shell_id><p># show managed shells + procfs descendants
fws tree --depth 4
```<p>### Shellspec example<p>```yaml
version: "1"
shells:
worker:
backend: proc
cwd: ${ctx:PROJECT_ROOT}
subgroups: ["worker", "project:${ctx:APP_ID}"]
command: ["python", "-m", "your_module.worker", "--port", "${free_port}"]
```<p>### Isolation + security model (simple by default)<p>* `FRAMEWORK_SHELLS_SECRET` derives the `runtime_id` (namespace) and API tokens.
* If the secret is set, mutating API endpoints require:<p><pre><code> * `Authorization: Bearer <token>` (or `X-Framework-Key`).</code></pre>
* If the secret is unset, auth is disabled (dev mode).<p>Hard limit: if two runtimes share the same OS user/UID, the OS may still allow signaling each other’s processes. The guarantee is: no cross-count/adopt/control *through the library’s control plane*.<p>### Real-world usage<p>I use this as the substrate of a full dev environment where “apps are shells” (terminals, IDE + LSP, agent/MCP, aria2 RPC, file explorer, llama.cpp runner, etc.). Repo:<p>```text
https://github.com/mrsurge/termux-extensions-2
```<p>### Feedback I want<p>* Does the secret/fingerprint/runtime isolation contract feel right?
* Any obvious foot-guns in the default API/CLI?
* Expectations vs systemd/supervisord/tmux/dtach: where would you use this?<p>github.com/mrsurge/framework-shells<p>pip install "framework-shells @ git+https://github.com/mrsurge/framework-shells@main"<p>```bash
fws --help
```