You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
…and each adapter lowers that into its own CLI's env vars and flags. Today the
core speaks Claude Code's dialect directly, so there is no seam to swap.
The hard part — capability mismatch
This is what makes it a real design problem rather than a rename:
Model tiers are Claude Code's model. opencode may have no
opus/sonnet/haiku/fable concept at all. What does a 4-tier profile mean
against a CLI with one model slot?
Permission models differ.--dangerously-skip-permissions has no
guaranteed analogue.
The catalog is shared — OpenRouter's model list is useful to any CLI, so CatalogPort stays in the core, correctly.
The likely answer is that AgentCliPort declares capabilities, and the core
refuses or warns on profiles that ask for something the target CLI can't
express — rather than silently dropping it, which is the failure mode this
whole project exists to avoid.
This is a design change; Migrate to TypeScript #18 is a mechanical one. Reviewing a language
migration and a boundary change together means reviewing neither.
Ports are far better expressed as real TS interfaces, and capabilities
with per-CLI variance is exactly where a union type earns its keep.
Migrate to TypeScript #18 should not deepen the coupling while it passes through. Types that
encode Claude Code specifics belong near the eventual adapter boundary, not
baked into core domain types.
Acceptance criteria
AgentCliPort defined; claude-code as the reference adapter
Core speaks neutral intent — no ANTHROPIC_* or CLAUDE_CODE_* literals
outside the Claude Code adapter
Binary resolution is per-adapter, and the self-resolution guard survives
Capability declaration, with a defined behaviour when a profile asks for
something unsupported (warn or refuse — never silently drop)
[1m], the 200K clamp and compat flags all move into the Claude Code
adapter
execve stays the launch mechanism regardless of adapter
A second adapter — even a stub — proves the abstraction, the same way
ModelScope proved the catalog port
Existing profiles keep working with no user-visible change
Problem
The refactor made providers pluggable but left the agent CLI hardcoded.
Claude Code is assumed everywhere:
resolvelooks for a binary literally namedclaudeANTHROPIC_BASE_URL,ANTHROPIC_AUTH_TOKEN,ANTHROPIC_DEFAULT_*_MODEL— Claude Code's vocabulary, not a neutral one--dangerously-skip-permissionsis a Claude Code flag, modelled in the coreas
skipPermissionsCLAUDE_CODE_*) are Claude-Code-specific by definitionThese are two orthogonal axes that are currently fused:
Running opencode or another CLI against the
same profiles should be a matter of writing one adapter.
Proposed port
The domain core should speak a neutral intent:
…and each adapter lowers that into its own CLI's env vars and flags. Today the
core speaks Claude Code's dialect directly, so there is no seam to swap.
The hard part — capability mismatch
This is what makes it a real design problem rather than a rename:
opus/sonnet/haiku/fable concept at all. What does a 4-tier profile mean
against a CLI with one model slot?
[1m]is a Claude Code mechanism, and so is the 200K first-party clamp(CLAUDE_CODE_MAX_CONTEXT_TOKENS is real but conditionally honored #15, Investigate _CLAUDE_CODE_ASSUME_FIRST_PARTY_BASE_URL (do not ship by default) #16). Those belong to the Claude Code adapter, not the core.
--dangerously-skip-permissionshas noguaranteed analogue.
CatalogPortstays in the core, correctly.The likely answer is that
AgentCliPortdeclares capabilities, and the corerefuses or warns on profiles that ask for something the target CLI can't
express — rather than silently dropping it, which is the failure mode this
whole project exists to avoid.
Sequencing
Do this after #18 (TypeScript). Rationale:
migration and a boundary change together means reviewing neither.
capabilitieswith per-CLI variance is exactly where a union type earns its keep.
encode Claude Code specifics belong near the eventual adapter boundary, not
baked into core domain types.
Acceptance criteria
AgentCliPortdefined;claude-codeas the reference adapterANTHROPIC_*orCLAUDE_CODE_*literalsoutside the Claude Code adapter
something unsupported (warn or refuse — never silently drop)
[1m], the 200K clamp and compat flags all move into the Claude Codeadapter
execvestays the launch mechanism regardless of adapterModelScope proved the catalog port