FWS - 可通过pip安装的嵌入式进程监控器,支持PTY/管道/dtach后端
我发布了 *Framework Shells* (`fws`): 这是一个独立的 Python 包,用于协调长时间运行的后台进程(“shells”),支持 *PTY*、*pipes* 和 *dtach* 后端。
这款工具适用于不想搭建完整监控栈(或没有监控栈)的环境:快速的多服务原型、开发环境、受限的用户空间等。
### 功能介绍
* 生成/管理 shell,支持:
```
* **PTY**: 交互式终端会话(调整大小、输入、流)
* **Pipes**: stdin/stdout/stderr 流(适合守护进程/LSP)
* **dtach**: 可以附加/分离的持久会话(在管理器重启后仍然有效)
```
* *运行时隔离*(主要特性):shell 通过
`~/.cache/framework_shells/runtimes/<repo_fingerprint>/<runtime_id>/...`
进行命名空间隔离,因此同一仓库的两个克隆可以并发运行,而不会相互干扰或控制。
* *控制界面*:CLI + 可选的 FastAPI/WS UI,用于列出、查看日志和生命周期操作。
* 可选的 *hooks* 用于主机集成(外部注册表/遥测)。
### CLI 快速入门
```bash
# 列出 shell
fws list
# 运行一次性 shell(无规范)
fws run --backend pty --label demo -- bash -l -i
# 应用 YAML shellspec(推荐)
fws up shells.yaml
# 终止 shell
fws down
# 附加到一个 dtach 支持的 shell
fws attach <shell_id>
# 显示管理的 shell 及其 procfs 子进程
fws tree --depth 4
```
### Shellspec 示例
```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}"]
```
### 隔离 + 安全模型(默认简单)
* `FRAMEWORK_SHELLS_SECRET` 用于派生 `runtime_id`(命名空间)和 API 令牌。
* 如果设置了密钥,变更 API 端点需要:
```
* `Authorization: Bearer <token>`(或 `X-Framework-Key`)。
```
* 如果未设置密钥,则禁用身份验证(开发模式)。
硬性限制:如果两个运行时共享相同的操作系统用户/UID,操作系统仍可能允许彼此的进程进行信号传递。保证是:通过库的控制平面,不会有交叉计数/采用/控制。
### 真实世界的使用
我将其用作完整开发环境的基础,其中“应用就是 shell”(终端、IDE + LSP、代理/MCP、aria2 RPC、文件浏览器、llama.cpp 运行器等)。仓库链接:
```text
https://github.com/mrsurge/termux-extensions-2
```
### 我希望得到的反馈
* 密钥/指纹/运行时隔离契约是否合理?
* 默认 API/CLI 中是否存在明显的陷阱?
* 与 systemd/supervisord/tmux/dtach 的期望对比:你会在哪里使用这个?
github.com/mrsurge/framework-shells
pip install "framework-shells @ git+https://github.com/mrsurge/framework-shells@main"
```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
```