opencode-provider-switch/.trellis/tasks/archive/2026-04/04-17-04-17-agent-first-cli-help-prd/prd.md
apale7 cf3dcec399 refactor(cli): rename tool to ocswitch
Avoid collision with the existing Opswitch product while keeping the repository name as opencode-provider-switch.

This aligns the CLI, provider key, config paths, examples, and Trellis history under one public-facing name.
2026-04-17 21:43:21 +08:00

608 lines
18 KiB
Markdown

# OCSWITCH Agent-First CLI Help System
## Summary
`ocswitch` already has a working CLI and a reasonably complete README, but its help
surface is still optimized for a human reading source-adjacent docs, not for an
AI agent trying to configure the tool end-to-end with high reliability.
This PRD defines a narrow product change:
- every user-facing `ocswitch` command must provide `Long` help
- every user-facing `ocswitch` command must provide `Example` help
- help content must be written for **AI agent execution reliability first**
- manual CLI ergonomics remain important, but are secondary to agent clarity
The intended result is that an AI agent can use `ocswitch --help` and nested
`--help` output as a trustworthy local interface contract for discovery,
planning, execution, and recovery during configuration.
## Product Goal
Make `ocswitch` self-describing enough that a capable AI agent can complete normal
configuration workflows without relying on hidden tribal knowledge, source code
inspection, or README-only instructions.
## Core User Need
User wants to say, in effect:
"Configure `ocswitch` for my providers and aliases, then sync OpenCode and tell me
how to run it."
The agent should be able to do that safely by reading CLI help output and
executing commands in order.
## Why This Matters
Current repository state already supports the core workflow:
- add or import upstream providers
- create aliases and bind ordered targets
- validate config via `ocswitch doctor`
- sync aliases into OpenCode via `ocswitch opencode sync`
- run proxy via `ocswitch serve`
But the command tree does not yet expose the full operational contract through
help text. In practice this means:
- some commands only have `Short`
- side effects are not always explained in help output
- default target paths and scope boundaries are not always repeated where used
- the "what to do next" step is often only in README, not in command help
- an agent may need to infer workflow rules from source code instead of help
This is acceptable for an engineering MVP, but not good enough if `ocswitch` wants
to recommend agent-driven configuration as a first-class path.
## Design Principle
Treat CLI help as a **machine-consumable operational interface**, not as a
minimal hint for humans.
That means help text should answer these questions explicitly for each command:
1. What job does this command do?
2. When should an agent call it?
3. What must already exist before calling it?
4. What state does it read or write?
5. What does it intentionally not do?
6. What command usually comes next?
7. What concrete examples should be copied for common workflows?
## Priority Order
When there is a tradeoff, the implementation should optimize for:
1. AI agent understanding and execution reliability
2. Deterministic and explicit side-effect descriptions
3. Copy-paste-safe examples
4. Human readability
5. Brevity
This means slightly longer help is acceptable if it reduces agent mistakes.
## Non-Goals
1. No GUI or local web setup flow in this task.
2. No new interactive wizard in this task.
3. No major command model redesign unless required to support help clarity.
4. No attempt to encode every README detail into root help output.
5. No hidden behavior added only for agents; behavior must stay consistent with
the real command implementation.
## Scope
### In Scope
All user-facing commands in the current Cobra tree:
- `ocswitch`
- `ocswitch serve`
- `ocswitch doctor`
- `ocswitch provider`
- `ocswitch provider add`
- `ocswitch provider list`
- `ocswitch provider remove`
- `ocswitch provider import-opencode`
- `ocswitch alias`
- `ocswitch alias add`
- `ocswitch alias list`
- `ocswitch alias bind`
- `ocswitch alias unbind`
- `ocswitch alias remove`
- `ocswitch opencode`
- `ocswitch opencode sync`
### Also In Scope
- defining a consistent writing contract for `Long` and `Example`
- deciding which workflow facts must be repeated in help instead of delegated to
README only
- optional README adjustments if needed to point agents toward `--help` as the
authoritative interface contract
### Out of Scope
- adding brand-new command groups just for documentation cosmetics
- changing proxy/runtime semantics unrelated to help clarity
- solving remote connectivity testing beyond what already exists
## Agent-First Help Requirements
Every command help page must be written to support agent execution. The text
does not need to be machine-parseable JSON, but it must be operationally
unambiguous.
### Requirement 1: Each command must define `Long`
`Long` must not repeat `Short` mechanically. It must explain behavior,
preconditions, scope, and next-step guidance.
Minimum `Long` contents per command:
1. command purpose
2. state read/write behavior
3. prerequisites or expected prior commands
4. important defaults and path resolution rules
5. behavior boundaries or non-effects
6. recommended next step
### Requirement 2: Each command must define `Example`
`Example` must contain realistic command lines that an agent can copy with minor
substitutions.
Examples must prefer:
- real flag names
- complete command lines
- stable placeholder values
- workflow-oriented ordering
- one example per important usage pattern
Examples must avoid:
- vague ellipses when a concrete placeholder is better
- examples that omit required flags without explanation
- examples that imply unsupported behavior
### Requirement 3: Root and group commands must explain workflow position
Commands like `ocswitch`, `ocswitch provider`, `ocswitch alias`, and `ocswitch opencode` are not
action commands themselves, but they are decision points for an agent.
Their help must answer:
- what subcommands exist
- in what order agents usually use them
- which subcommand to inspect next for each workflow
### Requirement 4: Help must surface side effects explicitly
Whenever a command writes local config or OpenCode config, help must say so.
Examples:
- provider commands write `ocswitch` config
- alias commands write `ocswitch` config
- `opencode sync` writes the target OpenCode config unless `--dry-run`
- `doctor` validates statically and does not call upstream providers
- `serve` starts a long-running local proxy and does not mutate config
### Requirement 5: Help must surface defaults locally
Agents should not need to jump to README or source to know command-local
defaults.
Examples of defaults that must appear where relevant:
- default `ocswitch` config path via `--config`
- default OpenCode sync target resolution order
- default proxy bind address and API key when describing `serve` or workflows
### Requirement 6: Help must be safe for secrets
Help examples may use placeholder keys like `sk-example`, but must never suggest
printing or leaking real secrets. Examples should not instruct agents to copy
config files to chat or expose API keys in logs.
## Content Contract By Command Type
### Root Command: `ocswitch`
`Long` should define the full happy-path workflow:
1. add/import providers
2. create alias and bind targets
3. run `doctor`
4. run `opencode sync`
5. run `serve`
`Example` should include:
- inspect root help
- scratch setup flow
- import-first flow
### Group Command: `provider`
`Long` should explain that providers are upstream OpenAI-compatible endpoints
used by alias targets. It should state that provider definitions live in local
`ocswitch` config and are separate from alias routing.
`Example` should include:
- add provider
- import from OpenCode
- list providers
### Action Command: `provider add`
`Long` should explain:
- creates or updates a provider entry
- `--base-url` must include `/v1`
- omitted mutable fields may preserve existing values on update
- repeated `--header` appends explicit extra headers
- command does not validate upstream reachability
`Example` should include:
- minimal add
- add with API key
- add with repeated headers
- update only base URL of existing provider
### Action Command: `provider list`
`Long` should explain that output is for inspection, redacts keys, and is often
used by agents to confirm imported or saved provider IDs before binding aliases.
`Example` should include:
- plain listing
- listing with explicit `--config`
### Action Command: `provider remove`
`Long` should explain:
- removes provider from `ocswitch` config
- does not automatically clean alias references
- follow-up `doctor` may fail if aliases still reference removed provider
`Example` should include:
- remove provider
- inspect aliases afterward
### Action Command: `provider import-opencode`
`Long` should explain:
- source defaults to global OpenCode config resolution
- only supported import shape is config-defined `@ai-sdk/openai` custom
providers with `baseURL` and `apiKey`
- unsupported providers are skipped by design
- `--overwrite` changes update semantics
`Example` should include:
- default import
- import from explicit file
- overwrite existing providers
### Group Command: `alias`
`Long` should explain aliases as the primary user-facing abstraction exposed to
OpenCode as `ocswitch/<alias>`, and that target order defines failover priority.
`Example` should include:
- create alias
- bind primary and fallback targets
- list aliases
### Action Command: `alias add`
`Long` should explain:
- creates or updates alias metadata only
- does not add targets
- disabled aliases are not meant for OpenCode exposure until enabled and valid
`Example` should include:
- create enabled alias
- create disabled alias
- update display name
### Action Command: `alias list`
`Long` should explain output semantics:
- alias enabled/disabled state
- target ordering
- target enabled markers
- common use before `doctor` and `opencode sync`
`Example` should include:
- plain listing
- listing under explicit config path
### Action Command: `alias bind`
`Long` should explain:
- appends target in failover order
- provider must already exist
- alias auto-creates if missing
- binding does not test upstream health
- order matters operationally
`Example` should include:
- first target bind
- second fallback bind
- bind disabled target
### Action Command: `alias unbind`
`Long` should explain:
- removes one concrete target tuple from alias
- does not delete the alias itself
- may leave alias invalid if no enabled targets remain
`Example` should include:
- remove one fallback target
- run `doctor` afterward
### Action Command: `alias remove`
`Long` should explain:
- removes entire alias from local config
- future `opencode sync` will stop exposing it in `provider.ocswitch.models`
- does not directly remove model selection already set elsewhere in OpenCode
`Example` should include:
- remove alias
- sync afterward
### Action Command: `doctor`
`Long` should explain:
- performs static validation only
- validates local config structure and OpenCode sync preview assumptions
- does not issue real upstream requests
- should be called before `opencode sync` or `serve`
`Example` should include:
- plain validation
- validation with alternate config path
### Group Command: `opencode`
`Long` should explain that these commands manage the narrow integration boundary
between `ocswitch` and OpenCode, and do not attempt full OpenCode config takeover.
`Example` should include:
- inspect sync help
- run sync dry-run
### Action Command: `opencode sync`
Existing `Long` is a strong starting point but must be aligned to the new help
contract.
`Long` should explain:
- exact write target rules
- what fields are mutated and not mutated
- that aliases become `provider.ocswitch.models`
- meaning of `--dry-run`
- recommended call order around `doctor`
`Example` should include:
- basic sync
- dry-run preview
- sync and set top-level model
- sync and set model plus small model
- sync to explicit target file
### Action Command: `serve`
`Long` should explain:
- starts long-running proxy
- reads validated local config
- requires a valid alias/provider setup first
- handles OpenCode traffic at the configured local base URL
- should generally be called after `doctor` and `opencode sync`
`Example` should include:
- start with defaults
- start with explicit config path
## Writing Rules For `Long`
All `Long` help should follow a shared style so agents can scan it quickly.
Recommended structure:
1. one-sentence job statement
2. short paragraph describing read/write effects
3. short paragraph describing prerequisites and defaults
4. short paragraph describing boundaries or important caveats
5. one-line next step recommendation when useful
Writing rules:
- use direct, operational language
- prefer exact nouns from the product: provider, alias, target, OpenCode config
- say "does" and "does not" explicitly
- repeat important defaults instead of assuming root help was read
- avoid marketing language
- avoid implementation trivia that does not affect execution
## Writing Rules For `Example`
Examples should be optimized for agent reuse.
Rules:
- use fenced multi-line examples where grouping improves clarity
- order examples from safest/common to more advanced
- keep placeholders stable across commands when possible
- use provider IDs and alias names that match repository terminology
- reflect real workflow order
Preferred placeholder vocabulary:
- provider ids: `su8`, `codex`, `relay`
- alias names: `gpt-5.4`, `gpt-5.4-mini`
- api keys: `sk-example`
- local paths: `/path/to/opencode.jsonc`
## Workflow Scenarios The Help Must Support
Help output across the command tree must enable an agent to execute these common
scenarios without README-only dependency.
### Scenario 1: Configure from scratch
1. inspect `ocswitch --help`
2. add one or more providers
3. add alias
4. bind targets in order
5. run `doctor`
6. run `opencode sync`
7. run `serve`
### Scenario 2: Import existing OpenCode provider definitions first
1. inspect `ocswitch provider import-opencode --help`
2. import supported providers
3. list providers
4. create aliases and bindings
5. validate, sync, serve
### Scenario 3: Change only one provider endpoint
1. inspect `provider add --help`
2. update existing provider base URL or key
3. run `doctor`
4. restart `serve` if already running
### Scenario 4: Remove or replace a fallback target safely
1. inspect `alias list`
2. `alias unbind`
3. optionally `provider remove`
4. run `doctor`
5. run `opencode sync` if alias exposure changed
## README Relationship
README remains useful, but after this task its role changes:
- README explains the product and quick-start narrative
- CLI help becomes the authoritative local execution contract
- README may include one short section telling users and agents to prefer
command-local `--help` for exact behavior and flag usage
README should not be the only place where critical command semantics live.
## Acceptance Criteria
### Functional Acceptance
1. Every user-facing Cobra command in the current `ocswitch` tree defines non-empty
`Long` and non-empty `Example` help.
2. `ocswitch --help` and all nested `--help` pages expose enough information for an
agent to discover the intended configuration workflow without reading source.
3. Help text for mutating commands explicitly states what files/config are
written.
4. Help text for non-mutating commands explicitly states that they do not write
config or contact upstreams when that distinction matters.
5. `opencode sync --help` explicitly documents default target resolution and the
non-default behavior of `--set-model` and `--set-small-model`.
6. `provider add --help` explicitly documents `/v1` requirement and update
semantics for omitted fields.
7. `alias bind --help` explicitly documents auto-create behavior and ordering
semantics.
### Quality Acceptance
1. Help examples are copy-paste-ready after simple placeholder substitution.
2. Help text does not contain contradictions with actual runtime behavior.
3. Terminology is consistent across all help pages.
4. No command relies only on README for a behavior that materially affects safe
execution.
### Agent Success Acceptance
This task is successful if a fresh agent can reasonably do the following with
CLI help as its primary reference:
1. determine the canonical happy-path setup order
2. configure providers and aliases
3. understand what `doctor` validates and what it does not
4. sync aliases into OpenCode safely
5. understand when to start `serve`
## Implementation Notes
This PRD does not require a new documentation subsystem. Current Cobra support
is enough:
- `Short`
- `Long`
- `Example`
Implementation should prefer a small, consistent helper style only if needed to
avoid repeated wording mistakes. Do not over-abstract help generation unless the
duplication becomes genuinely harmful.
## Risks
1. Help text may drift from behavior if future command semantics change without
updating examples.
2. Longer help output may become noisy if not structured carefully.
3. Over-optimizing for agents could make help feel less natural for humans.
## Risk Mitigation
1. Keep help operational and specific, not verbose by default.
2. Prefer one shared writing contract across all commands.
3. Add tests that assert key phrases exist for high-risk commands.
4. Treat help text as behavior-adjacent surface that must change with command
semantics.
## Future Extensions
These are explicitly out of this task, but compatible with it later:
- `ocswitch setup` guided workflow command
- shell completion tuned for provider/alias names
- structured `--help-format json` for agent-native consumption
- README agent prompt template that mirrors the help contract
## Final Product Decision
`ocswitch` should recommend an **agent-first, CLI-native** configuration workflow.
The CLI itself must become the most reliable place to learn how to configure the
tool. `Long` and `Example` are therefore not documentation polish; they are part
of the product interface.