close
Skip to content

feat: bundle CLIProxyAPI as optional service with auto-wire for OpenCode + Hermes#4

Open
btg94 wants to merge 2 commits intoCoderLuii:mainfrom
btg94:feat/cli-proxy-api-integration
Open

feat: bundle CLIProxyAPI as optional service with auto-wire for OpenCode + Hermes#4
btg94 wants to merge 2 commits intoCoderLuii:mainfrom
btg94:feat/cli-proxy-api-integration

Conversation

@btg94
Copy link
Copy Markdown

@btg94 btg94 commented May 2, 2026

Summary

  • Adds CLI Proxy API (eceasy/cli-proxy-api v6.10.1, port 8317) as a fourth optional bundled service alongside Hermes and Paperclip — supervised by s6-overlay, toggled with ENABLE_CLI_PROXY=true.
  • Lets HolyCode users sign into Claude / Codex / Gemini / Antigravity with their subscription accounts via OAuth and route OpenCode (and Paperclip workers) and Hermes through those credentials — no API keys required.
  • Auto-wire mutates ~/.config/opencode/opencode.json (provider.<name>.options.baseURL + apiKey) and ~/.hermes/config.yaml (model.* + auxiliary.*) and is reverted cleanly when toggled off via a managed-state sentinel. Disabling the proxy forces revert even if CLI_PROXY_AUTOWIRE is left set.
  • New /cli-proxy-api-setup skill guides the user through provider selection, OAuth port publishing, the right login command, verification, and auto-wire.

Why

OpenCode users on Claude Max / ChatGPT Plus / Gemini Advanced have no first-class way to use those subscriptions inside HolyCode without putting raw API keys (or session tokens) in env vars. CLIProxyAPI solves that by speaking the Anthropic, OpenAI, and Gemini protocols against OAuth tokens it manages itself. Bundling it as a toggleable service mirrors how Hermes and Paperclip are integrated, so users only learn one pattern.

Configuration surface

Var Default Purpose
ENABLE_CLI_PROXY (unset) Start the proxy on 8317
CLI_PROXY_API_KEY holycode-local Shared client key (Anthropic x-api-key, OpenAI Authorization: Bearer, Google X-Goog-Api-Key)
CLI_PROXY_AUTOWIRE (unset) all or comma-list of opencode-anthropic, opencode-openai, opencode-google, hermes. false/none reverts.
CLI_PROXY_HERMES_PROVIDER anthropic Protocol Hermes uses to talk to the proxy (anthropic/openai/google)

Compose adds five new commented ports: 8317 (API) plus 54545 / 1455 / 8085 / 51121 for Claude / Codex / Gemini / Antigravity OAuth callbacks. Codex device-flow login (-codex-device-login) needs no callback port.

Architecture

  • Multi-stage Docker COPY of the binary from eceasy/cli-proxy-api:v6.10.1 (~50 MB)
  • s6-overlay supervised service (/etc/s6-overlay/s6-rc.d/cli-proxy-api/)
  • Conditional dependencies.d/cli-proxy-api on the opencode service when proxy is enabled — guarantees opencode waits for proxy startup
  • Config seeded into ~/.cli-proxy-api/config.yaml on first boot (hot-reloads on save)
  • OAuth tokens persist via the existing ./data/opencode bind mount

Test plan

End-to-end verified locally on Apple Silicon:

  • docker build succeeds (image size +~50 MB)
  • Proxy disabled (default): cli-proxy-api absent from s6-rc.d/user/contents.d/, web UI on 4096 healthy, port 8317 not listening
  • Proxy enabled, no auto-wire: /v1/models returns 200, dependencies marker present, bootstrap seeded config.yaml
  • Auto-wire all + Hermes anthropic: opencode.json shows the three provider blocks with correct baseURLs and {env:CLI_PROXY_API_KEY} substitution; ~/.hermes/config.yaml shows model.* + auxiliary.* with sentinel
  • Hermes provider switch (anthropic → openai → google): config picks up new base URLs cleanly
  • CLI_PROXY_AUTOWIRE=false: opencode.json + hermes config reverted, sentinels removed
  • ENABLE_CLI_PROXY=false with CLI_PROXY_AUTOWIRE=all left set: forces revert (proxy not running, no broken pointers left)
  • API key enforcement: 401 on wrong key, 200 on x-api-key, 200 on Authorization: Bearer
  • with-contenv propagates CLI_PROXY_API_KEY and friends to s6 services
  • config.yaml hot-reload (host edit → reload log line within 1s)
  • OAuth binary smoke test (-h works, login flags listed)

Not tested in this branch (requires live OAuth):

  • End-to-end Claude / Codex / Gemini OAuth login completion
  • Real chat traffic through /v1/messages with valid subscription tokens

Out of scope

  • TLS termination (use tls.enable: true in config.yaml if needed)
  • Sidecar deployment (documented as one-line note — the upstream image works standalone if a user prefers)

🤖 Generated with Claude Code

btg94 and others added 2 commits May 2, 2026 14:30
Adds CLI Proxy API (eceasy/cli-proxy-api v6.10.1, port 8317) as an optional
bundled service supervised by s6-overlay alongside OpenCode, Hermes and
Paperclip. The proxy lets HolyCode users sign into Claude / Codex / Gemini /
Antigravity with their subscription accounts via OAuth and route OpenCode
(plus Paperclip workers) and Hermes through those credentials -- no API keys.

Toggle: ENABLE_CLI_PROXY=true. Auto-wire: CLI_PROXY_AUTOWIRE=all (or comma-list
of opencode-anthropic, opencode-openai, opencode-google, hermes). Auto-wire
mutates ~/.config/opencode/opencode.json (provider.<name>.options.baseURL +
apiKey) and ~/.hermes/config.yaml (model.* + auxiliary.*) and is reverted
cleanly when toggled off via a managed-state sentinel. Disabling the proxy
forces revert even if CLI_PROXY_AUTOWIRE is left set.

Verified end-to-end: clean default state, proxy serves /v1/models with auth
enforcement, OpenCode + Hermes auto-wire correctly with sentinel, revert is
clean, with-contenv propagates CLI_PROXY_API_KEY to s6 services, and
config.yaml hot-reloads on host edits.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Four critical fixes and three concerns from code review:

C1 (entrypoint died on malformed user config): wrap both auto-wire heredocs
with `|| echo "WARNING..."` so a malformed opencode.json or hermes config.yaml
logs a warning instead of aborting entrypoint under `set -e`.

C2 (custom CLI_PROXY_API_KEY EPERM'd bootstrap): drop the runuser indirection
in bootstrap.sh -- root writes config.yaml as part of the seed and the chown
at the end normalises ownership. Adds a non-fatal guard around the python
mutation too.

C3 + C4 (silent overwrite of hand-edited configs): both auto-wire paths now
detect user-managed values (existing baseURL/apiKey or model.{provider,
base_url,api_key} that don't match what we'd write, with no managed sentinel
present) and skip those providers/Hermes wiring with a clear warning. The
template-seed case is excluded via a `file_existed` guard so newly-created
Hermes configs still wire correctly.

W1 (`all,hermes` mixed-list silently wired only Hermes): token parser now
treats "all" within a comma-list as expansion of every target plus hermes,
matching user expectation.

W6 (marker file `.json` extension): renamed to `.holycode-cli-proxy-managed`
(no extension) for consistency with the existing `.holycode-bootstrapped`
marker and to avoid any future glob-based config discovery picking it up.

W3 + W4 (security): proxy `host: ""` retained (needed for port publishing
and OAuth callbacks to work) but the seed config and .env.example now warn
prominently that the default `holycode-local` API key is in the public repo
and must be changed before publishing port 8317. SKILL.md updated to surface
this and to drop Kimi (W7 -- callback port not verified).

Verified each fix end-to-end:
- C1: malformed JSON in opencode.json -> WARNING logged, entrypoint continues,
  proxy still serves
- C2: CLI_PROXY_API_KEY=secretkey99 -> bootstrap injects it, proxy accepts
  the new key, rejects the default
- C3: user-edited anthropic baseURL preserved, openai+google still wired,
  warning logged
- C4: user-edited Hermes config left untouched, warning logged
- W1: CLI_PROXY_AUTOWIRE=all,hermes -> all 3 OC providers + Hermes wired
- W6: marker file is `.holycode-cli-proxy-managed` (no `.json`)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant