Headroom 持久化安装实战:用 headroom install 把 8787 端口常驻代理变成可管理的本地运行时
2026/9/5 15:39:55 网站建设 项目流程

Headroom 持久化安装实战:用 headroom install 把 8787 端口常驻代理变成可管理的本地运行时

【免费下载链接】headroomCompress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.项目地址: https://gitcode.com/GitHub_Trending/head/headroom

本篇指南基于 Headroom 仓库的 persistent-installs 文档展开,讲清楚headroom install子系统的三大持久化预设(persistent-service / persistent-task / persistent-docker)、--scope--providers的完整参数语义、部署清单(manifest)的存储位置与结构,以及headroom wrap如何自动复用或恢复常驻部署。读完并对照仓库源码后,你将掌握三种常驻运行时的选型依据、每个 CLI 命令的底层行为,以及 manifest 原子写入与损坏恢复等工程细节。

从临时代理到常驻运行时:persistent install 要解决什么问题

此前运行 Headroom 只有两种方式:临时起一个headroom proxy(进程退出即消失),或headroom wrap ...包一层工具会话(代理生命周期与会话绑定)。这两种方式都要求代理在需要时"恰好活着"。

Persistent Installs 让 Headroom 以持久本地运行时的形式安装到机器上:受支持的编码工具(Claude Code、Codex、Copilot 等)持续访问http://127.0.0.1:8787上一直开着的代理,而headroom wrap ...复用或恢复这个部署,而不是再启一个第二套临时代理。文档明确建议:当你希望工具长期对接一个 always-on 代理时,使用 Python 原生的headroom installCLI。

整个子系统位于 headroom/install/ 包内,从源码结构看,各模块职责划分如下:

模块职责
models.py预设、运行时、supervisor、作用域等枚举与DeploymentManifest数据类
planner.py目标探测、参数解析、生成规范化 manifest
state.pymanifest 的原子写入、加载与删除
paths.py部署状态目录、runner 脚本路径、各工具的配置文件路径
supervisors.pysystemd / launchd / 计划任务等 supervisor 的渲染与启停
providers.py对工具配置的可逆修改(mutation)与应用/回滚
runtime.py前台/后台运行、端口探测、健康等待、Docker 启动
health.pyreadyz/health端点探测

对应的回归测试位于 tests/test_install/,覆盖 planner、state、supervisors、runtime、health、providers、native installers 等每个模块(如 test_planner.py、test_supervisors.py)。

运行时矩阵:先选对模式,再执行命令

原文档给出的运行时矩阵是选型的核心依据,完整继承如下:

ModeWhat stays runningPrimary entrypoint
Persistent ServiceNative background serviceheadroom install apply --preset persistent-service
Persistent TaskScheduled watchdog + on-demand runnerheadroom install apply --preset persistent-task
Persistent DockerRestartable Docker containerheadroom install apply --preset persistent-docker
On-Demand CLI (Python)Nothing after command exitsheadroom proxy
On-Demand CLI (Docker)Nothing after container exitsDocker-native wrapper / compose CLI
Wrapped (Python)Proxy lasts for wrapped sessionheadroom wrap ...
Wrapped (Docker)Containerized proxy + host tool sessionDocker-native wrapper

三种持久化预设的区别本质在于"谁来保证代理活着":

  • persistent-service交给操作系统原生服务管理器(Linux 上是 systemd unit,macOS 上是 launchd LaunchAgent);
  • persistent-task用定时任务(cron / 计划任务)跑一个 watchdog,周期性探测并按需拉起,适合不允许注册系统服务的场景;
  • persistent-docker则把存活责任完全交给 Docker 的 restart policy,不引入额外 OS 层监督。

快速上手:三种预设的最短命令

本机持久服务

headroom install apply --preset persistent-service --providers auto headroom install status

这条命令在当前机器上安装一个后台服务,应用"持久化工具接线"(即把代理端点写进各工具配置),并保证8787端口上的代理持续健康。

从源码看,apply的完整链路是:cli/install.py 中的install命令组接收参数 → planner.py 的build_manifest()生成DeploymentManifest→ state.py 的save_manifest()落盘 → supervisors.py 的install_supervisor()注册 supervisor → runtime.py 的wait_ready()等待readyz通过。

一个值得注意的平台细节:在 Windows 上,build_manifest()会把persistent-service静默降级为persistent-task(见 planner.py 的注释)——因为 Python runner 是普通控制台进程,无法实现 Windows SCM 协议协议,sc.exe create注册的服务永远无法启动(SCM error 1053),而任务计划程序既能开机自启又能周期健康恢复,因此成为 Windows 上的有效预设(对应 issue #2552)。

持久看门狗任务

headroom install apply --preset persistent-task --providers manual --target claude --target codex

这条命令安装的是"定时恢复路径"而非传统常驻服务。从 supervisors.py 看,apply会为每个 profile 渲染两个脚本:

  • run-headroom.sh:前台 runner,执行headroom install agent run --profile <profile>
  • ensure-headroom.sh:watchdog 脚本,执行headroom install agent ensure --profile <profile>,由 cron/计划任务周期性调用,发现代理挂了就拉起。

Windows 上对应的是run-headroom.ps1/run-headroom.cmdensure-headroom.ps1/ensure-headroom.cmd(见 paths.py)。

持久 Docker

headroom install apply --preset persistent-docker --scope user --providers auto

这条命令让 Docker 的 restart policy 取代 OS supervisor。源码中有个针对该预设的实现细节:开启--memory时,Python 运行时会显式传--memory-db-path <宿主路径>,但Docker 运行时会被刻意省略该参数(见 planner.py 注释)——因为容器内 HOME 是/tmp/headroom-home,宿主的~/.headroom只是挂载进来,直接传宿主绝对路径会导致 SQLite 打不开、/readyz恒 503、部署超时回滚(issue #2803);省略后代理在容器工作目录下解析 DB,恰好落在同一个绑定挂载文件上。

另外,如果你使用的是Docker 原生宿主 wrapper(而非 Python 安装),也可以直接从已安装的 wrapper 上对persistent-docker预设执行headroom install apply|status|start|stop|restart|remove。但注意边界:service/task 安装以及 provider/user/system 的变更流程仍属于 Python 原生 CLI 的职责

命令面:六个生命周期子命令

headroom install apply headroom install status headroom install start headroom install stop headroom install restart headroom install remove

文档说明:apply创建或更新一个具名部署档案(profile),把清单存到~/.headroom/deploy/<profile>/manifest.json,应用可逆的配置变更,然后启动所选运行时。

源码对这条命令的补充细节:

  • profile 命名有校验:paths.py 中validate_profile_name()要求 profile 只含[A-Za-z0-9._-],且不允许./..,防止路径穿越;
  • 目录布局:每个 profile 一个目录,除manifest.json外还放runner.log(运行日志)、runner.pid(前台进程 pid)、各平台 runner/watchdog 脚本(见 paths.py);
  • 显式--profile不容错:cli/install.py 中,如果命令行显式传了--profile但该 profile 不存在,命令会原样报错而不是悄悄转向其他已安装 profile——stop/restart/remove这类破坏性命令绝不允许误伤别的部署。只有--profile缺省时才走恢复回退(读HEADROOM_DEPLOYMENT_PROFILE环境变量或唯一的已安装 profile);
  • remove的行为:先revert_mutations()回滚对工具配置的修改,再remove_supervisor()注销 supervisor,最后delete_manifest()删除整个 profile 目录(见 state.py 的shutil.rmtree)。

Presets 与 Runtime kinds

Presets

  • persistent-service-> 原生服务监督器
  • persistent-task-> 定时看门狗 / 恢复监督器
  • persistent-docker-> Docker restart policy,无额外 OS 监督器

这与 models.py 中的枚举一一对应:InstallPresetSupervisorKindservice/task/none)。预设到 supervisor 的映射逻辑在build_manifest()里:service 预设产生SupervisorKind.SERVICE,task 预设产生TASK,Docker 预设产生NONE(由容器引擎负责重启)。

supervisor 的实际产物(从 supervisors.py 可见):

  • Linuxpersistent-service渲染 systemd unit,scope=user时放在~/.config/systemd/user/headroom-<profile>.servicescope=system时放在/etc/systemd/system/;unit 内容为Restart=on-failureRestartSec=5ExecStart指向渲染出的run-headroom.sh
  • macOS:渲染 launchd plist 并通过launchctl bootstrap加载。源码还处理了一个真实的竞态:launchctl bootout之后立刻bootstrap同一 label 可能在数秒内返回 EIO,因此_bootstrap_with_retry()会重试最多 30 次(每次 0.5 秒,约 15 秒)以扛过 launchd 的释放窗口(见 supervisors.py)。

Runtime kinds

  • --runtime python:直接运行headroom proxy
  • --runtime docker:在 Docker 内运行 Headroom,但部署本身仍由本机管理

persistent-docker预设,runtime 永远是 Docker。DeploymentManifest中 Docker 相关默认值可在 models.py 看到:镜像ghcr.io/headroomlabs-ai/headroom:latest、容器名headroom-<profile>、健康检查 URLhttp://127.0.0.1:8787/readyz

配置作用域(Scope):改到哪里、改多少

ScopeWhat changes
providerTool-specific config surfaces where Headroom can make a precise reversible edit
userUser-level shell or environment surfaces
systemMachine-wide shell or environment surfaces

从 paths.py 可以看到各 scope 实际落笔的文件:

  • user~/.bashrc~/.zshrc~/.profile(可写入持久环境块的文件列表);
  • system:Linux 上是/etc/profile.d/headroom.sh;macOS 上是/etc/profile/etc/zprofile/etc/bashrc
  • provider:直接编辑各工具自己的配置文件。

当前 Provider scope 支持的直接适配器

文档强调 provider scope 是有意保守的,当前的直接适配器为:

  • Claude Code ->~/.claude/settings.jsonenv
  • Codex ->~/.codex/config.toml中的托管块(managed block)
  • OpenClaw -> 复用既有的wrap openclaw/unwrap openclaw流程

对于 Copilot、Aider、Cursor 以及更宽泛的 env 驱动配置,建议用--scope user--scope system

与文档的一个差异值得注意:源码里PROVIDER_SCOPE_TARGETS实际包含claude、codex、openclaw、opencode四个目标(见 planner.py),且 paths.py 为 OpenCode 提供了配置路径解析(优先OPENCODE_CONFIG环境变量,其次~/.config/opencode/opencode.jsoncopencode.json)。也就是说 OpenCode 已具备 provider 级直接适配能力,只是 Wiki 文档尚未同步更新这一条。apply对 provider scope 下不支持的 target 会明确报错列出,例如Provider scope supports only claude, codex, openclaw, and opencode(见 planner.py)。

Provider 选择:auto / all / manual

OptionMeaning
--providers autoDetect supported tools on the host and configure the best available defaults
--providers allConfigure all known targets
--providers manual --target ...Configure only the named tools
headroom install apply --providers auto headroom install apply --providers all --scope user headroom install apply --providers manual --target claude --target copilot

从 models.py 的ToolTarget枚举看,当前支持的全部 target 为:claude、copilot、codex、aider、cursor、grok_build、grok、openclaw、opencode

auto模式的探测机制在 planner.py 的detect_targets():对每个 target 用shutil.which()查可执行文件是否在 PATH 上;若一个都没探测到,resolve_targets()会回退到默认集合claude + codex(provider scope 下再额外去掉 copilot,见 planner.py)。

生成 manifest 时,每个 target 会得到一份专属环境变量(build_install_target_envs()),代理自身的基础环境则固定写入HEADROOM_PORTHEADROOM_HOST=127.0.0.1HEADROOM_MODEHEADROOM_BACKEND、显式的HEADROOM_TELEMETRY=on|off(见 planner.py)。另有两条自动派生规则:

  1. 若目标只含 Grok / Grok Build 且没有共享该代理的 OpenAI 系工具,自动设置OPENAI_TARGET_API_URL指向 xAI 端点(从 providers/grok/runtime.py 引入DEFAULT_API_URL);
  2. --env显式传入的变量最后应用,可覆盖上述所有自动派生默认值。

健康端点与 wrap 的复用/恢复行为

持久化部署发布与临时代理运行完全相同readyzhealth端点。当代理经由 install 子系统启动时,/health额外暴露部署元数据:

{ "deployment": { "profile": "default", "preset": "persistent-service", "runtime": "python", "supervisor": "service", "scope": "user" } }

这些字段恰好对应DeploymentManifest的同名属性(profile/preset/runtime_kind/supervisor_kind/scope),说明/health是把 manifest 中相应字段原样透出,方便运维端判断"这个 8787 端口是谁在管"。

Python 原生的headroom wrap ...流程会先检查请求端口上是否存在匹配的持久化部署,再决定是否新起临时代理;如果已安装的部署存在但处于停止或不健康状态,它会先尝试恢复它。探测逻辑基于 health.py 的probe_ready()/probe_json(),等待逻辑在 runtime.py 的wait_ready(),对/readyz轮询直到 200。

需要明确的边界:Docker 原生宿主 wrapper 尚不会自动复用或恢复持久化 profile——除非显式--no-proxy,否则它总是启动一个全新的代理容器。

Docker 原生路径的关系与 compose 管理

Docker 原生宿主 wrapper 与 Python install CLI 解决的是运行时故事的不同层

  • Docker-Native Install -> 容器化的按需 CLI、宿主工具的 wrap 流程,以及 Docker 原生的persistent-docker生命周期命令;
  • headroom install ...-> 完整的持久 service / task / Docker 生命周期管理,包含 provider/user/system 变更。

对于不依赖 Python的持久 Docker 工作流,使用 docker/docker-compose.native.yml 中 compose 管理的代理路径:

export HEADROOM_HOST_HOME="$HOME" export HEADROOM_WORKSPACE="$PWD" docker compose -f docker/docker-compose.native.yml up -d proxy

这样可以保持localhost:8787稳定,并在容器退出时自动重启代理。

注意HEADROOM_WORKSPACE(compose 文件使用的宿主侧 bind-mount 源目录)与HEADROOM_WORKSPACE_DIR(容器内 Headroom 状态根的规范变量)不是同一个变量。两者都保留;compose 文件会自动设置后者。完整的 bucket 模型见 Filesystem Contract。

清单持久化的可靠性细节

manifest.json是整套安装系统的"事实来源",state.py 对它做了三层保护:

  1. 原子写入save_manifest()经由_atomic_write_text()先把 payload 写入同目录临时文件(mkstemp),flush+fsync后再os.replace()原子改名。即使写入中途被 SIGKILL、OOM 或断电打断,磁盘上也只会留下旧文件或完整新文件,绝不出现被截断的 manifest;只读文件系统则降级为告警而非崩溃。
  2. 损坏清单的优雅失败load_manifest()对解析失败(部分写入、手改、schema 漂移)抛出类型化的ManifestError,而不是裸 traceback——因为所有 install 生命周期命令以及自动执行的init hook ensure路由都要经过这里;CLI 层会把它转成可读的报错(见 cli/install.py)。
  3. 旧镜像仓库自动迁移:旧 manifest 若仍钉在已停止更新的ghcr.io/chopratejas/headroom镜像上,加载时会被自动重写到组织仓库ghcr.io/headroomlabs-ai/headroom并保留 tag(issue #2426,见 state.py)。

与文档配套的其他资源

  • CLI Reference:headroom全部命令参考
  • Docker-Native Install:Docker 原生安装与 wrapper 详解
  • Proxy Server:代理服务端点、readyz/health行为
  • macOS LaunchAgent:macOS 上 launchd 部署的细节
  • Filesystem Contract:容器内外状态目录(bucket)的完整模型
  • docker/docker-compose.native.yml:无 Python 持久 Docker 的 compose 定义
  • tests/test_install/:install 子系统的完整回归测试集

【免费下载链接】headroomCompress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.项目地址: https://gitcode.com/GitHub_Trending/head/headroom

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询