CliSubprocessCore.ProviderFeatures is the public, canonical metadata layer for
the built-in provider profiles.
It exists so higher-level adapter layers can discover provider-native terminology and partial common-surface support without reimplementing profile knowledge in separate lookup tables.
What It Owns
- provider-native permission mode metadata
- rendered CLI args for those permission modes
- partial feature manifests for built-in providers
The partial-feature manifest covers Ollama-backed model routing, structured output, and completion-only invocation. Permission metadata covers each first-party provider's native permission terminology.
Permission Metadata
Use permission_mode!/2 or permission_args/2 when a caller needs to present
or render the provider-native form of a normalized approval choice.
iex> CliSubprocessCore.ProviderFeatures.permission_mode!(:codex, :yolo)
%{
native_mode: :yolo,
cli_args: ["--dangerously-bypass-approvals-and-sandbox"],
cli_excerpt: "--dangerously-bypass-approvals-and-sandbox",
label: "yolo"
}
iex> CliSubprocessCore.ProviderFeatures.permission_args(:amp, :dangerously_allow_all)
["--dangerously-allow-all"]
iex> CliSubprocessCore.ProviderFeatures.permission_args(:cursor, :bypass)
["--force"]
iex> CliSubprocessCore.ProviderFeatures.permission_args(:cursor, :plan)
["--mode", "plan"]
iex> CliSubprocessCore.ProviderFeatures.permission_args(:antigravity, :bypass)
["--dangerously-skip-permissions"]This keeps provider profiles authoritative for the real CLI contract while still giving adapter layers a stable public lookup surface.
Important boundary:
- this metadata is about provider-native permission terminology and rendered CLI args
- it is not a general sandbox, approval-policy, or thread-options catalog
- if a provider has extra knobs outside the shared permission concept, those remain in the provider profile or the provider SDK layer
Examples:
- Codex
--dangerously-bypass-approvals-and-sandboxappears here because it is the provider-native rendering of a permission choice - Cursor
:askis not a permission mode. It is an operational Cursormoderendered by the Cursor profile or SDK as--mode ask. - Antigravity
--sandboxis provider-native runtime behavior, while--dangerously-skip-permissionsis the permission-mode rendering.
Partial Features
Use partial_feature!/2 when you need to know whether a built-in provider
supports a feature that is shared by some, but not all, providers.
iex> CliSubprocessCore.ProviderFeatures.partial_feature!(:claude, :ollama)
%{
supported?: true,
activation: %{provider_backend: :ollama},
model_strategy: :canonical_or_direct_external,
notes: [...]
}Codex's manifest also carries compatibility metadata for the shared Ollama route:
iex> CliSubprocessCore.ProviderFeatures.partial_feature!(:codex, :ollama)
%{
supported?: true,
activation: %{provider_backend: :oss, oss_provider: "ollama"},
model_strategy: :direct_external,
compatibility: %{
acceptance: :runtime_validated_external_model,
default_model: "gpt-oss:20b",
validated_models: ["gpt-oss:20b"]
},
notes: [...]
}Current built-in :ollama support:
- Claude: supported through
provider_backend: :ollama - Codex: supported through
provider_backend: :oss, oss_provider: "ollama" - Cursor: unsupported on the common CLI surface
- Amp: unsupported on the common CLI surface
- Antigravity: unsupported on the common CLI surface
For Codex, the compatibility manifest describes the validated default and the acceptance rule separately:
- acceptance: any Ollama model that passes runtime validation
- validated default:
gpt-oss:20b - non-default models: allowed, but may run with upstream fallback metadata
Structured output and completion-only
Every built-in provider has an explicit manifest entry for
:structured_output and :completion_only; absence is never interpreted as
support.
| Provider | Structured output | Completion-only |
|---|---|---|
| Claude | supported, inline JSON schema | supported |
| Codex | supported, owner-tracked schema file | supported |
| Cursor | unsupported | unsupported |
| Amp | unsupported | unsupported |
| Antigravity | unsupported | unsupported |
Amp and Antigravity remain ordinary coding-agent providers. Their
completion-only entries are unsupported because no verified provider posture
proves the absence of tools, MCP, prompt extensions, and writes. Antigravity
--sandbox or strict permissions alone do not establish that stronger
contract.
Provider profiles call require_option/4 before command resolution when one
of these common options is requested:
{:error,
%CliSubprocessCore.ProviderFeatures.Error{
provider: :amp,
feature: :structured_output,
option: :output_schema,
support_state: :unsupported
}} =
CliSubprocessCore.ProviderProfiles.Amp.build_invocation(
prompt: "return JSON",
output_schema: %{"type" => "object"}
)This failure is typed and occurs before a provider process is started.
Design Rule
CliSubprocessCore.ProviderFeatures should only describe built-in provider
profile behavior that the core itself owns.
It should not become a generic SDK catalog or an adapter-specific policy layer. Higher-level packages such as ASM may wrap this metadata to describe their own common surfaces, but the source of truth for built-in CLI behavior stays here.
Session-Control Capability Vocabulary
Provider manifests may now advertise the following session-control capabilities when the runtime really supports them:
:session_history:session_resume:session_pause:session_intervene
These names are intentionally shared with the upper orchestration layers. A profile should only publish them when the runtime can surface a truthful provider-native history/resume/pause path; the manifest is not the place for speculative claims.