SIwithin 发布:在沙箱与预算限制下无人值守运行 Claude Code
开源工具 SIwithin 允许用户在严格的文件系统隔离和美元预算上限下,无人值守地运行 Claude Code 或 OpenAI Codex。它通过本地代理拦截 API 请求以强制实施成本控制,并确保每次运行仅留下单一审计记录,解决了 Agent 自主执行时的安全与成本失控痛点。
报道正文
本文目录4 个章节
SIwithin
SIwithin 以无人值守模式运行 Agent CLI,在指定的文件夹范围内设置隔离围栏,并施加美元预算限制。每次运行结束后,它会留下一条记录。它通过工具机制而非仅凭期望来坚守以下三项承诺:
- 运行仅触及被授权的文件夹。 拒绝访问你的主目录(禁止读写),仅允许访问本次运行指定的文件夹。
- 运行花费不得超过分配的美元预算。 设有单次运行预算、所有运行的总上限以及每次运行的计时器;对于 Claude 适配器,还包含一个回环代理作为通往 API 的唯一入口:运行持有的是单次运行令牌而非你的密钥,无论其如何发起请求,均在此处计量,超出预算即被拒绝。若某 CLI 无法在运行中途停止,除非你明确接受该风险,否则工具将拒绝执行(参见“账本”和“Codex 适配器”章节)。
- 每次运行留下一行记录,说明其成本及是否完成。
支持 Claude Code 和 OpenAI Codex 命令行工具。SIwithin 是一个独立项目,并非由 Anthropic 或 OpenAI 制作、背书或赞助。Claude、Claude Code、OpenAI 和 Codex 均为其各自所有者的名称,此处使用仅为说明 SIwithin 可驱动哪些程序。当你通过 SIwithin 使用这些厂商的 CLI 时,你仍受各厂商服务条款和使用政策的约束;SIwithin 不会改变任何此类条款。
SIwithin 仅支持 macOS。在 Linux 和 Windows 上,它会直接拒绝运行并输出一行提示,而不是在没有隔离围栏的情况下运行。
安装
SIwithin 是单个文件,需要 Python 3.10 或更高版本,仅依赖标准库。它自身不发起任何网络调用,也不发送遥测数据;它为运行启动的代理监听回环端口,且仅与你配置的 API 主机通信。
git clone <this repository> && cd siwithin
python3 siwithin.py --version
# optional: put it on your PATH
install -m 755 siwithin.py ~/.local/bin/siwithin你还需要安装想要驱动的 CLI 并将其加入 PATH,同时为其配置 API 密钥(参见“认证”章节)。
冒烟测试 (python3 tests/smoke.py) 在其编写所用的 Python 3.9.6 上通过。3.10 是支持的最低版本,代码避免了较新的语法特性,但尚未在 3.10 或更高版本上运行过。
快速开始:Claude Code
mkdir -p ~/.config/siwithin && echo 20 > ~/.config/siwithin/cap # all runs together may spend $20
export ANTHROPIC_API_KEY=... # see "Auth"; the tool reads it once, outside the fence, and the run gets a per-run token in its placepython3 siwithin.py --dir ~/work/proj --model sonnet --dry-run < brief.md # 打印所有内容,不执行任何操作
python3 siwithin.py --dir ~/work/proj --model sonnet --budget 2 \
--done "ALL TESTS PASS" --out notes.md < brief.md--dir 指定运行目录:CLI 在该目录中工作并可能向其写入内容(使用 --readonly 可将其设为只读)。--read <folder> 添加允许该运行读取的文件夹。--model 接受模型 ID 或别名(如 haiku、sonnet、opus)。
快速开始:Codex
mkdir -p ~/.config/siwithin && echo 20 > ~/.config/siwithin/cap
export CODEX_API_KEY=...
python3 siwithin.py --adapter codex --model gpt-5.3-codex --soft-budget --network open --dir ~/work/proj --dry-run < brief.md
python3 siwithin.py --adapter codex --model gpt-5.3-codex --soft-budget --network open --budget 2 --dir ~/work/proj < brief.md此适配器需要两个标志,原因详见“Codex 适配器”一节:--model(因为 CLI 仅报告 token 数量而不报告成本,因此需根据模型 ID 计算运行费用)和 --soft-budget(因为 CLI 仅在回合结束时报告使用情况)。该适配器基于文档构建,尚未针对实际运行的 CLI 进行测试。它使用 auth = "env" 模式:密钥位于运行环境的环境中(参见“认证”部分),且由于没有代理服务器,网络防火墙无需开放特定端口,因此必须设置 --network open,或在 config.toml 的 [fence] 部分配置 network = "open";若使用默认设置,运行将被拒绝而非在无网络状态下执行(参见“围栏机制”)。
认证
SIwithin 从不解析、存储、打印或记录密钥,也不会将密钥写入任何文件、日志行或错误消息中。密钥如何传递至 API 取决于适配器的 auth 字段。
Claude 适配器,auth = "proxy"(自 0.3.0 版本起为默认配置)。 在启动前、沙箱隔离区之外,runner 会读取一次密钥:来源可以是其自身环境中的 ANTHROPIC_API_KEY,也可以是 config.toml 中 [auth] key_command 命令输出的第一行内容(该命令由用户定义,用于打印密钥,例如通过钥匙串查询获取)。Runner 保留该密钥,并仅使用标准库在其自身的回环端口上启动一个小型 HTTP 服务器。运行时的环境变量包含 ANTHROPIC_API_KEY=siwithin-<32 个字符>,这是一个每次运行都新生成的令牌,在其他地方毫无价值;以及 ANTHROPIC_BASE_URL=http://127.0.0.1:<port>。运行时发出的每一个请求——无论是通过 CLI、手动发起还是由其启动的第二个 CLI 发出——都会经过这个“门”:代理只接受该运行时的令牌(其他任何令牌均返回 401 且不被处理),仅转发 [auth] paths 中列出的路径(默认为 /v1/messages 和 /v1/messages/count_tokens;其他任何路径均返回 403 且不会附加真实密钥),添加真实密钥,以流式方式中继响应,并根据 [prices] 费率基于用量对每个 /v1/messages 响应进行计价。一旦总费用达到预算上限,后续所有 /v1/messages 请求均返回 402,首次拒绝会像流式停止信号一样终止运行时的进程,且代理将持续拒绝请求直到 runner 退出。当运行时结束时,代理被密封,其日志关闭,服务器停止,因此该令牌变得毫无价值。每个请求会在运行时文件夹中的 proxy.jsonl 里记录一行信息(包括路径、模型、状态码、用量、成本、累计总额、客户端端口、拒绝原因;绝不记录请求体、密钥或令牌)。如果运行时的配置目录中存在一个指定了 apiKeyHelper 的 settings.json,则在启动前会被拒绝,因为 CLI 会在沙箱隔离区内执行该 helper,从而让运行时能够读取它:请将 helper 的命令放入 [auth] key_command 中,这样 runner 会在沙箱隔离区外执行它。--dry-run 会打印 auth: proxy 127.0.0.1:<port> 且不启动任何服务。
auth = "env" 按名称将密钥变量复制到运行时环境中,行为与 0.2.1 版本相同。这是 Codex 适配器的唯一模式,也是 Claude 适配器的可选模式(检查工具会发出警告)。在此模式下,密钥存在于运行时环境中,并被运行时启动的所有命令继承,且无法建立网络防火墙,因为没有可供允许的代理端口:在默认的 [fence] network = "proxy" 设置下,该运行将被拒绝,并且
(注:更多技术实现细节与完整 API 文档请查阅原项目 README)