feat: bundle CLIProxyAPI as optional service with auto-wire for OpenCode + Hermes#4
Open
btg94 wants to merge 2 commits intoCoderLuii:mainfrom
Open
feat: bundle CLIProxyAPI as optional service with auto-wire for OpenCode + Hermes#4btg94 wants to merge 2 commits intoCoderLuii:mainfrom
btg94 wants to merge 2 commits intoCoderLuii:mainfrom
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
v6.10.1, port8317) as a fourth optional bundled service alongside Hermes and Paperclip — supervised by s6-overlay, toggled withENABLE_CLI_PROXY=true.~/.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 ifCLI_PROXY_AUTOWIREis left set./cli-proxy-api-setupskill 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
ENABLE_CLI_PROXY8317CLI_PROXY_API_KEYholycode-localx-api-key, OpenAIAuthorization: Bearer, GoogleX-Goog-Api-Key)CLI_PROXY_AUTOWIREallor comma-list ofopencode-anthropic,opencode-openai,opencode-google,hermes.false/nonereverts.CLI_PROXY_HERMES_PROVIDERanthropicanthropic/openai/google)Compose adds five new commented ports:
8317(API) plus54545/1455/8085/51121for Claude / Codex / Gemini / Antigravity OAuth callbacks. Codex device-flow login (-codex-device-login) needs no callback port.Architecture
eceasy/cli-proxy-api:v6.10.1(~50 MB)/etc/s6-overlay/s6-rc.d/cli-proxy-api/)dependencies.d/cli-proxy-apion the opencode service when proxy is enabled — guarantees opencode waits for proxy startup~/.cli-proxy-api/config.yamlon first boot (hot-reloads on save)./data/opencodebind mountTest plan
End-to-end verified locally on Apple Silicon:
docker buildsucceeds (image size +~50 MB)s6-rc.d/user/contents.d/, web UI on 4096 healthy, port 8317 not listening/v1/modelsreturns 200, dependencies marker present, bootstrap seededconfig.yamlall+ Hermes anthropic:opencode.jsonshows the three provider blocks with correct baseURLs and{env:CLI_PROXY_API_KEY}substitution;~/.hermes/config.yamlshowsmodel.*+auxiliary.*with sentinelCLI_PROXY_AUTOWIRE=false: opencode.json + hermes config reverted, sentinels removedENABLE_CLI_PROXY=falsewithCLI_PROXY_AUTOWIRE=allleft set: forces revert (proxy not running, no broken pointers left)x-api-key, 200 onAuthorization: Bearerwith-contenvpropagatesCLI_PROXY_API_KEYand friends to s6 servicesconfig.yamlhot-reload (host edit → reload log line within 1s)-hworks, login flags listed)Not tested in this branch (requires live OAuth):
/v1/messageswith valid subscription tokensOut of scope
tls.enable: trueinconfig.yamlif needed)🤖 Generated with Claude Code