feat(cli): add ocx opencode launcher - #568
Merged
Merged
Conversation
opencode reads providers from a JSON config rather than env slots, so the
`ocx claude` env-injection pattern does not transfer. This adds a launcher that
generates a provider block from the proxy's visible catalog and points
OPENCODE_CONFIG at it.
The user's own opencode.json is never written to. Their effective config is read
(explicit OPENCODE_CONFIG first, then the XDG global path), merged forward into
a generated copy under the opencodex config dir, and only the `opencodex`
provider key is overwritten. Carrying the base config forward keeps the command
correct whether opencode merges the OPENCODE_CONFIG layer or replaces it, and
leaves plain `opencode` completely unchanged.
Credential handling: the generated file is written to disk and outlives the
child, so it carries opencode's documented `{env:VAR}` reference instead of the
admission key, and the real value is passed only through the child environment.
The key resolves OPENCODEX_API_AUTH_TOKEN before config.apiKeys, matching
fetchClaudeContextWindows — a non-loopback bind requires the env token and may
have no apiKeys at all, where a placeholder would 401 every request.
Model limits: limit.context is emitted only from an authoritative context
window, including native slugs via nativeOpenAiContextWindow. opencode's schema
rejects a limit block carrying context without output and CatalogModel has no
authoritative output field, so a documented budget rides along, clamped to the
context window so a small-context model is never emitted with output > context.
Robustness: opencode.json is parsed as JSONC (strict JSON first, tolerant only
on failure) because opencode documents that syntax and a commented config would
otherwise be rejected as malformed; the generated file is written atomically so
a concurrent launch cannot read a torn file; the detached proxy-start child gets
an error listener so a failed spawn reports through the health poll instead of
throwing; and a project-level opencode.json defining provider.opencodex is
detected and warned about, since opencode loads that layer last and it outranks
the generated block.
Verified against a live proxy: 76 models registered, 47 carrying authoritative
limits with no output > context violations, `opencode models opencodex` lists
all of them, and an end-to-end run through opencodex/kiro/claude-haiku-4.5
returns a completion.
3 tasks
This comment was marked as outdated.
This comment was marked as outdated.
Merge inherited OPENCODE_CONFIG_CONTENT instead of replacing it, probe the live proxy hostname for baseURL, resolve admission from env/service token/ config keys, add x-opencodex-api-key on non-loopback binds, omit native slugs in Codex Direct mode, and widen global override detection. Stabilize the Windows storage-policy concurrency test timing.
When ocx opencode spawns a detached ocx start and OPENCODEX_API_AUTH_TOKEN is absent, propagate OCX_API_TOKEN_FILE (or the default hardened path) so handleStart can load the service token before a non-loopback bind.
Use a deterministic loopback default config in provider-block helpers instead of loadConfig(), send proxy admission via apiKey on loopback and only x-opencodex-api-key on non-loopback binds, and split the docs/help examples accordingly.
Fetch the live model list from the running proxy instead of calling fetchAllModels in the CLI process, so env-backed provider keys resolve in the proxy environment and namespaced selectors carry display metadata.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/cli/opencode.ts`:
- Around line 353-361: Bound both the fetch and response body read in the
`/api/models` request flow around `fetchImpl` and `response.text()` so a stalled
management API cannot hang indefinitely. Use the existing request-timeout
mechanism or introduce a shared deadline that covers connection, response, and
body-reading phases, and preserve the current unreachable-error handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 4a0f0db8-ad00-4774-a59c-75bf3fcc7eac
📒 Files selected for processing (4)
docs-site/src/content/docs/guides/opencode.mdsrc/cli/help.tssrc/cli/opencode.tstests/opencode-cli.test.ts
Abort stalled proxy catalog requests after 8s so ocx opencode fails fast instead of hanging before OpenCode launches.
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
Maintainer takeover of #461 — lands @mihneaptu's
ocx opencodelauncher with review fixes from the maintainer pass on #461.ocx opencode [args…]: ensure proxy, buildprovider.opencodexfrom the visible catalog, launchopencodewith stdio inherited.OPENCODE_CONFIG_CONTENT); never copies or rewrites the user's global/project config, so API keys, MCP credentials, and relative{file:…}paths stay on their original files.opencode.json/opencode.jsoncto the nearest Git root and prints an informational message whenprovider.opencodexis also defined locally (runtime layer wins for this launch).guides/opencode.mdplus sidebar entry.Supersedes #461 (contributor fork could not be updated;
maintainerCanModify=false).Test plan
bun test tests/opencode-cli.test.ts— 30 passbun run typecheckbun run privacy:scanSummary by CodeRabbit
ocx opencodeto launch OpenCode via the local proxy with a generated runtime provider configuration.opencodeconfig generation/merging and routing/limits; adjusted concurrency timing assertions for policy updates.