Explorar el Código

test(cli): help-text snapshots for every CLI command (#28267)

Kit Langton hace 3 meses
padre
commit
18b9cec50d

+ 623 - 0
packages/opencode/test/cli/help/__snapshots__/help-snapshots.test.ts.snap

@@ -0,0 +1,623 @@
+// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode acp --help 1`] = `
+"opencode acp
+
+start ACP (Agent Client Protocol) server
+
+Options:
+  -h, --help         show help                                                             [boolean]
+  -v, --version      show version number                                                   [boolean]
+      --print-logs   print logs to stderr                                                  [boolean]
+      --log-level    log level                  [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure         run without external plugins                                          [boolean]
+      --port         port to listen on                                         [number] [default: 0]
+      --hostname     hostname to listen on                           [string] [default: "127.0.0.1"]
+      --mdns         enable mDNS service discovery (defaults hostname to 0.0.0.0)
+                                                                          [boolean] [default: false]
+      --mdns-domain  custom domain name for mDNS service (default: opencode.local)
+                                                                [string] [default: "opencode.local"]
+      --cors         additional domains to allow for CORS                      [array] [default: []]
+      --cwd          working directory [string] [default: "<HOME>"]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode mcp --help 1`] = `
+"opencode mcp
+
+manage MCP (Model Context Protocol) servers
+
+Commands:
+  opencode mcp add            add an MCP server
+  opencode mcp list           list MCP servers and their status                        [aliases: ls]
+  opencode mcp auth [name]    authenticate with an OAuth-enabled MCP server
+  opencode mcp logout [name]  remove OAuth credentials for an MCP server
+  opencode mcp debug <name>   debug OAuth connection for an MCP server
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode attach --help 1`] = `
+"opencode attach <url>
+
+attach to a running opencode server
+
+Positionals:
+  url  http://localhost:4096                                                     [string] [required]
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]
+      --dir         directory to run in                                                     [string]
+  -c, --continue    continue the last session                                              [boolean]
+  -s, --session     session id to continue                                                  [string]
+      --fork        fork the session when continuing (use with --continue or --session)    [boolean]
+  -p, --password    basic auth password (defaults to OPENCODE_SERVER_PASSWORD)              [string]
+  -u, --username    basic auth username (defaults to OPENCODE_SERVER_USERNAME or 'opencode')[string]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode run --help 1`] = `
+"opencode run [message..]
+
+run opencode with a message
+
+Positionals:
+  message  message to send                                                     [array] [default: []]
+
+Options:
+  -h, --help                          show help                                            [boolean]
+  -v, --version                       show version number                                  [boolean]
+      --print-logs                    print logs to stderr                                 [boolean]
+      --log-level                     log level [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure                          run without external plugins                         [boolean]
+      --command                       the command to run, use message for args              [string]
+  -c, --continue                      continue the last session                            [boolean]
+  -s, --session                       session id to continue                                [string]
+      --fork                          fork the session before continuing (requires --continue or
+                                      --session)                                           [boolean]
+      --share                         share the session                                    [boolean]
+  -m, --model                         model to use in the format of provider/model          [string]
+      --agent                         agent to use                                          [string]
+      --format                        format: default (formatted) or json (raw JSON events)
+                                          [string] [choices: "default", "json"] [default: "default"]
+  -f, --file                          file(s) to attach to message                           [array]
+      --title                         title for the session (uses truncated prompt if no value
+                                      provided)                                             [string]
+      --attach                        attach to a running opencode server (e.g.,
+                                      http://localhost:4096)                                [string]
+  -p, --password                      basic auth password (defaults to OPENCODE_SERVER_PASSWORD)
+                                                                                            [string]
+  -u, --username                      basic auth username (defaults to OPENCODE_SERVER_USERNAME or
+                                      'opencode')                                           [string]
+      --dir                           directory to run in, path on remote server if attaching
+                                                                                            [string]
+      --port                          port for the local server (defaults to random port if no value
+                                      provided)                                             [number]
+      --variant                       model variant (provider-specific reasoning effort, e.g., high,
+                                      max, minimal)                                         [string]
+      --thinking                      show thinking blocks                                 [boolean]
+      --replay                        replay visible session history on interactive resume
+                                                                          [boolean] [default: false]
+      --replay-limit                  cap visible interactive replay to the newest N messages
+                                                                                            [number]
+  -i, --interactive                   run in direct interactive split-footer mode
+                                                                          [boolean] [default: false]
+      --dangerously-skip-permissions  auto-approve permissions that are not explicitly denied
+                                      (dangerous!)                        [boolean] [default: false]
+      --demo                          enable direct interactive demo slash commands; pass one as the
+                                      message to run it immediately       [boolean] [default: false]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode debug --help 1`] = `
+"opencode debug
+
+debugging and troubleshooting tools
+
+Commands:
+  opencode debug config        show resolved configuration
+  opencode debug lsp           LSP debugging utilities
+  opencode debug rg            ripgrep debugging utilities
+  opencode debug file          file system debugging utilities
+  opencode debug scrap         list all known projects
+  opencode debug skill         list all available skills
+  opencode debug snapshot      snapshot debugging utilities
+  opencode debug startup       print startup timing
+  opencode debug agent <name>  show agent configuration details
+  opencode debug v2            debug v2 catalog and built-in plugins
+  opencode debug info          show debug information
+  opencode debug paths         show global paths (data, config, cache, state)
+  opencode debug wait          wait indefinitely (for debugging)
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode providers --help 1`] = `
+"opencode providers
+
+manage AI providers and credentials
+
+Commands:
+  opencode providers list         list providers and credentials                       [aliases: ls]
+  opencode providers login [url]  log in to a provider
+  opencode providers logout       log out from a configured provider
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode agent --help 1`] = `
+"opencode agent
+
+manage agents
+
+Commands:
+  opencode agent create  create a new agent
+  opencode agent list    list all available agents
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode upgrade --help 1`] = `
+"opencode upgrade [target]
+
+upgrade opencode to the latest or a specific version
+
+Positionals:
+  target  version to upgrade to, for ex '0.1.48' or 'v0.1.48'                               [string]
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]
+  -m, --method      installation method to use
+                          [string] [choices: "curl", "npm", "pnpm", "bun", "brew", "choco", "scoop"]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode uninstall --help 1`] = `
+"opencode uninstall
+
+uninstall opencode and remove all related files
+
+Options:
+  -h, --help         show help                                                             [boolean]
+  -v, --version      show version number                                                   [boolean]
+      --print-logs   print logs to stderr                                                  [boolean]
+      --log-level    log level                  [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure         run without external plugins                                          [boolean]
+  -c, --keep-config  keep configuration files                             [boolean] [default: false]
+  -d, --keep-data    keep session data and snapshots                      [boolean] [default: false]
+      --dry-run      show what would be removed without removing          [boolean] [default: false]
+  -f, --force        skip confirmation prompts                            [boolean] [default: false]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode serve --help 1`] = `
+"opencode serve
+
+starts a headless opencode server
+
+Options:
+  -h, --help         show help                                                             [boolean]
+  -v, --version      show version number                                                   [boolean]
+      --print-logs   print logs to stderr                                                  [boolean]
+      --log-level    log level                  [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure         run without external plugins                                          [boolean]
+      --port         port to listen on                                         [number] [default: 0]
+      --hostname     hostname to listen on                           [string] [default: "127.0.0.1"]
+      --mdns         enable mDNS service discovery (defaults hostname to 0.0.0.0)
+                                                                          [boolean] [default: false]
+      --mdns-domain  custom domain name for mDNS service (default: opencode.local)
+                                                                [string] [default: "opencode.local"]
+      --cors         additional domains to allow for CORS                      [array] [default: []]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode web --help 1`] = `
+"opencode web
+
+start opencode server and open web interface
+
+Options:
+  -h, --help         show help                                                             [boolean]
+  -v, --version      show version number                                                   [boolean]
+      --print-logs   print logs to stderr                                                  [boolean]
+      --log-level    log level                  [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure         run without external plugins                                          [boolean]
+      --port         port to listen on                                         [number] [default: 0]
+      --hostname     hostname to listen on                           [string] [default: "127.0.0.1"]
+      --mdns         enable mDNS service discovery (defaults hostname to 0.0.0.0)
+                                                                          [boolean] [default: false]
+      --mdns-domain  custom domain name for mDNS service (default: opencode.local)
+                                                                [string] [default: "opencode.local"]
+      --cors         additional domains to allow for CORS                      [array] [default: []]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode models --help 1`] = `
+"opencode models [provider]
+
+list all available models
+
+Positionals:
+  provider  provider ID to filter models by                                                 [string]
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]
+      --verbose     use more verbose model output (includes metadata like costs)           [boolean]
+      --refresh     refresh the models cache from models.dev                               [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode stats --help 1`] = `
+"opencode stats
+
+show token usage and cost statistics
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]
+      --days        show stats for the last N days (default: all time)                      [number]
+      --tools       number of tools to show (default: all)                                  [number]
+      --models      show model statistics (default: hidden). Pass a number to show top N, otherwise
+                    shows all
+      --project     filter by project (default: all projects, empty string: current project)[string]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode export --help 1`] = `
+"opencode export [sessionID]
+
+export session data as JSON
+
+Positionals:
+  sessionID  session id to export                                                           [string]
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]
+      --sanitize    redact sensitive transcript and file data                              [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode import --help 1`] = `
+"opencode import <file>
+
+import session data from JSON file or URL
+
+Positionals:
+  file  path to JSON file or share URL                                           [string] [required]
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode github --help 1`] = `
+"opencode github
+
+manage GitHub agent
+
+Commands:
+  opencode github install  install the GitHub agent
+  opencode github run      run the GitHub agent
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode pr --help 1`] = `
+"opencode pr <number>
+
+fetch and checkout a GitHub PR branch, then run opencode
+
+Positionals:
+  number  PR number to checkout                                                  [number] [required]
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode session --help 1`] = `
+"opencode session
+
+manage sessions
+
+Commands:
+  opencode session list                list sessions
+  opencode session delete <sessionID>  delete a session
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode plugin --help 1`] = `
+"opencode plugin <module>
+
+install plugin and update config
+
+Positionals:
+  module  npm module name                                                        [string] [required]
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]
+  -g, --global      install in global config                              [boolean] [default: false]
+  -f, --force       replace existing plugin version                       [boolean] [default: false]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode db --help 1`] = `
+"opencode db
+
+database tools
+
+Commands:
+  opencode db [query]     open an interactive sqlite3 shell or run a query                 [default]
+  opencode db path        print the database path
+  opencode db migrate     migrate JSON data to SQLite (merges with existing data)
+
+Positionals:
+  query  SQL query to execute                                                               [string]
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]
+      --format      Output format                 [string] [choices: "json", "tsv"] [default: "tsv"]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode mcp list --help 1`] = `
+"opencode mcp list
+
+list MCP servers and their status
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode mcp add --help 1`] = `
+"opencode mcp add
+
+add an MCP server
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode mcp auth --help 1`] = `
+"opencode mcp auth [name]
+
+authenticate with an OAuth-enabled MCP server
+
+Commands:
+  opencode mcp auth list  list OAuth-capable MCP servers and their auth status         [aliases: ls]
+
+Positionals:
+  name  name of the MCP server                                                              [string]
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode mcp logout --help 1`] = `
+"opencode mcp logout [name]
+
+remove OAuth credentials for an MCP server
+
+Positionals:
+  name  name of the MCP server                                                              [string]
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode providers list --help 1`] = `
+"opencode providers list
+
+list providers and credentials
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode providers login --help 1`] = `
+"opencode providers login [url]
+
+log in to a provider
+
+Positionals:
+  url  opencode auth provider                                                               [string]
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]
+  -p, --provider    provider id or name to log in to (skips provider selection)             [string]
+  -m, --method      login method label (skips method selection)                             [string]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode providers logout --help 1`] = `
+"opencode providers logout
+
+log out from a configured provider
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode agent create --help 1`] = `
+"opencode agent create
+
+create a new agent
+
+Options:
+  -h, --help                  show help                                                    [boolean]
+  -v, --version               show version number                                          [boolean]
+      --print-logs            print logs to stderr                                         [boolean]
+      --log-level             log level         [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure                  run without external plugins                                 [boolean]
+      --path                  directory path to generate the agent file                     [string]
+      --description           what the agent should do                                      [string]
+      --mode                  agent mode            [string] [choices: "all", "primary", "subagent"]
+      --permissions, --tools  comma-separated list of permissions to allow (default: all).
+                              Available: "bash, read, edit, glob, grep, webfetch, task, todowrite,
+                              websearch, lsp, skill"                                        [string]
+  -m, --model                 model to use in the format of provider/model                  [string]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode agent list --help 1`] = `
+"opencode agent list
+
+list all available agents
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode session list --help 1`] = `
+"opencode session list
+
+list sessions
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]
+  -n, --max-count   limit to N most recent sessions                                         [number]
+      --format      output format             [string] [choices: "table", "json"] [default: "table"]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode session delete --help 1`] = `
+"opencode session delete <sessionID>
+
+delete a session
+
+Positionals:
+  sessionID  session ID to delete                                                [string] [required]
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode github install --help 1`] = `
+"opencode github install
+
+install the GitHub agent
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode github run --help 1`] = `
+"opencode github run
+
+run the GitHub agent
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]
+      --event       GitHub mock event to run the agent for                                  [string]
+      --token       GitHub personal access token (github_pat_********)                      [string]"
+`;
+
+exports[`opencode CLI help-text snapshots every documented command emits stable help text: opencode db path --help 1`] = `
+"opencode db path
+
+print the database path
+
+Options:
+  -h, --help        show help                                                              [boolean]
+  -v, --version     show version number                                                    [boolean]
+      --print-logs  print logs to stderr                                                   [boolean]
+      --log-level   log level                   [string] [choices: "DEBUG", "INFO", "WARN", "ERROR"]
+      --pure        run without external plugins                                           [boolean]"
+`;

+ 139 - 0
packages/opencode/test/cli/help/help-snapshots.test.ts

@@ -0,0 +1,139 @@
+// Help-text snapshots for every CLI command + key subcommand. Catches
+// accidental flag removals, renames, and reordering in a single sweep —
+// any change to the user-visible CLI surface shows up here as a diff.
+//
+// This is the broad coverage layer that makes the future Effect CLI
+// migration (yargs → effect-smol/cli) safe to attempt: if a refactor
+// preserves the surface, the snapshots stay green; if it doesn't, the
+// diff tells you exactly which command(s) changed.
+//
+// Snapshots are taken at COLUMNS=120 so wrapping is stable across
+// terminal sizes. The default opencode tui command is excluded —
+// `opencode --help` includes an ASCII banner that pulls in the install
+// version (changes per release), so we'd snapshot a moving target.
+import { describe, expect } from "bun:test"
+import { Effect } from "effect"
+import fs from "node:fs"
+import os from "node:os"
+import { cliIt } from "../../lib/cli-process"
+
+// Strips dynamic content that varies per run so snapshots are stable.
+// Currently only the tmpdir prefix bleeds in (via `--cwd` defaults that
+// resolve to `process.cwd()`). Add new patterns here as they surface.
+//
+// On macOS `os.tmpdir()` returns `/var/folders/...` but `process.cwd()`
+// inside the child returns the realpath `/private/var/folders/...` — so
+// we strip both forms.
+const TMP = os.tmpdir()
+const REAL_TMP = fs.realpathSync(TMP)
+function normalize(text: string): string {
+  return (
+    text
+      // Windows emits CRLF on stderr; collapse first so the rest of the
+      // pipeline doesn't need separate Windows-vs-POSIX branches.
+      .replaceAll("\r\n", "\n")
+      .replaceAll(REAL_TMP, "<TMPDIR>")
+      .replaceAll(TMP, "<TMPDIR>")
+      // The harness writes the random home dir at `<TMPDIR>/oc-cli-XXX` on
+      // POSIX, `<TMPDIR>\oc-cli-XXX` on Windows. Strip either form.
+      .replace(/<TMPDIR>[/\\]oc-cli-[a-z0-9]+/g, "<HOME>")
+      // yargs wraps the `[string] [default: "..."]` clause based on the
+      // pre-normalized default's character length, so different random home
+      // path widths produce different leading-whitespace counts (or even
+      // line-wraps onto a fresh line on Windows). `\s+` matches both forms.
+      .replace(/\s+\[string\] \[default: "<HOME>"\]/g, ' [string] [default: "<HOME>"]')
+  )
+}
+
+// Top-level commands. Order matches what `opencode --help` prints today;
+// keep it in that order so the snapshot file reads as a table of contents.
+// `completion` is intentionally excluded — it's a yargs built-in that emits
+// top-level help on `--help` and exits 1; not a real opencode command.
+const TOP_LEVEL = [
+  "acp",
+  "mcp",
+  "attach",
+  "run",
+  "debug",
+  "providers", // aliased to `auth`
+  "agent",
+  "upgrade",
+  "uninstall",
+  "serve",
+  "web",
+  "models",
+  "stats",
+  "export",
+  "import",
+  "github",
+  "pr",
+  "session",
+  "plugin",
+  "db",
+] as const
+
+// Subcommands worth pinning. Not exhaustive — the goal is one snapshot per
+// distinct argv shape, not every leaf. Add new entries when a subcommand
+// gains user-visible flags that we want to lock in.
+const SUBCOMMANDS = [
+  ["mcp", "list"],
+  ["mcp", "add"],
+  ["mcp", "auth"],
+  ["mcp", "logout"],
+  ["providers", "list"],
+  ["providers", "login"],
+  ["providers", "logout"],
+  ["agent", "create"],
+  ["agent", "list"],
+  ["session", "list"],
+  ["session", "delete"],
+  ["github", "install"],
+  ["github", "run"],
+  ["db", "path"],
+] as const
+
+// Fixed wrap width so a developer's terminal doesn't affect snapshots.
+// yargs honors COLUMNS; CI runners typically default to 80 which produces
+// different wraps from a 200-col local terminal.
+const SNAPSHOT_ENV = { COLUMNS: "120" }
+
+describe("opencode CLI help-text snapshots", () => {
+  // Single test, parallel spawns. Each command's help fires under
+  // `concurrency: 8` — wall-clock stays under ~10s even for ~35 commands,
+  // versus ~1 minute if we serialized.
+  cliIt.live(
+    "every documented command emits stable help text",
+    ({ opencode }) =>
+      Effect.gen(function* () {
+        const argvs: Array<readonly string[]> = [...TOP_LEVEL.map((c) => [c] as const), ...SUBCOMMANDS]
+
+        // Spawn in parallel, then assert in argv order so snapshot output is
+        // deterministic and per-command failures don't abort the rest of
+        // the sweep. `Effect.partition` is the canonical "run all, separate
+        // failures from successes" primitive — no mutable accumulator needed.
+        const [failures, results] = yield* Effect.partition(
+          argvs,
+          (argv) =>
+            Effect.gen(function* () {
+              const result = yield* opencode.spawn([...argv, "--help"], { env: SNAPSHOT_ENV })
+              if (result.exitCode !== 0) {
+                return yield* Effect.fail(`opencode ${argv.join(" ")}: exit ${result.exitCode}`)
+              }
+              return { argv, result }
+            }),
+          { concurrency: 8 },
+        )
+
+        for (const { argv, result } of results) {
+          // yargs writes --help to stderr, not stdout. Snapshotting stderr
+          // means our test catches the help body; stdout for these commands
+          // is expected to be empty.
+          expect(normalize(result.stderr)).toMatchSnapshot(`opencode ${argv.join(" ")} --help`)
+        }
+        if (failures.length > 0) {
+          throw new Error(`Help text failed for:\n  ${failures.join("\n  ")}`)
+        }
+      }),
+    180_000,
+  )
+})

+ 41 - 42
packages/opencode/test/lib/cli-process.ts

@@ -33,6 +33,30 @@ const cliEntry = path.join(opencodeRoot, "src/index.ts")
 
 export const testModelID = "test/test-model"
 
+// Wrap a Bun subprocess pipe (or any ReadableStream<Uint8Array>) as a Stream.
+// Centralizes the `evaluate` + `onError` boilerplate and tags errors with the
+// stream name so a stderr/stdout failure is greppable in logs.
+function fromBunStream(name: string, get: () => ReadableStream<Uint8Array>) {
+  return Stream.fromReadableStream({
+    evaluate: get,
+    onError: (cause) => new Error(`${name} stream error: ${String(cause)}`),
+  })
+}
+
+// Long-lived processes (serve, acp) all want the same stderr drain: read every
+// chunk, push to a tail buffer, swallow stream errors (the child closing the
+// pipe is normal). `log: true` surfaces a real protocol error to logs so a
+// regression doesn't silently disappear.
+function forkStderrDrain(stream: ReadableStream<Uint8Array>, into: string[]) {
+  return Effect.forkScoped(
+    fromBunStream("stderr", () => stream).pipe(
+      Stream.decodeText(),
+      Stream.runForEach((chunk) => Effect.sync(() => into.push(chunk))),
+      Effect.ignore({ log: true }),
+    ),
+  )
+}
+
 function isolatedEnv(home: string, configJson: string): Record<string, string> {
   return {
     OPENCODE_TEST_HOME: home,
@@ -225,20 +249,10 @@ export function withCliFixture<A, E>(
           }).pipe(Effect.ignore),
       )
 
-      // Drain stderr in a scope-bound fork. Without this the OS pipe buffer
-      // eventually fills and the child blocks on its next log call. Kept as a
-      // tail buffer so timeout failures can include context.
+      // Tail buffer so timeout failures can include stderr context. The fork
+      // also keeps the OS pipe buffer from filling and wedging the child.
       const stderrChunks: string[] = []
-      yield* Effect.forkScoped(
-        Stream.fromReadableStream({
-          evaluate: () => proc.stderr,
-          onError: () => new Error("stderr stream error"),
-        }).pipe(
-          Stream.decodeText(),
-          Stream.runForEach((chunk) => Effect.sync(() => stderrChunks.push(chunk))),
-          Effect.ignore,
-        ),
-      )
+      yield* forkStderrDrain(proc.stderr, stderrChunks)
 
       // Watch stdout line-by-line for the listening sentinel. Format
       // (see src/cli/cmd/serve.ts):
@@ -246,17 +260,14 @@ export function withCliFixture<A, E>(
       const readyRe = /listening on (http:\/\/([^\s:]+):(\d+))/
       const readyDeferred = yield* Deferred.make<{ url: string; hostname: string; port: number }>()
       yield* Effect.forkScoped(
-        Stream.fromReadableStream({
-          evaluate: () => proc.stdout,
-          onError: () => new Error("stdout stream error"),
-        }).pipe(
+        fromBunStream("stdout", () => proc.stdout).pipe(
           Stream.decodeText(),
           Stream.splitLines,
           Stream.runForEach((line) => {
             const m = line.match(readyRe)
             return m ? Deferred.succeed(readyDeferred, { url: m[1], hostname: m[2], port: Number(m[3]) }) : Effect.void
           }),
-          Effect.ignore,
+          Effect.ignore({ log: true }),
         ),
       )
 
@@ -323,26 +334,14 @@ export function withCliFixture<A, E>(
       )
 
       const stderrChunks: string[] = []
-      yield* Effect.forkScoped(
-        Stream.fromReadableStream({
-          evaluate: () => proc.stderr,
-          onError: () => new Error("stderr stream error"),
-        }).pipe(
-          Stream.decodeText(),
-          Stream.runForEach((chunk) => Effect.sync(() => stderrChunks.push(chunk))),
-          Effect.ignore,
-        ),
-      )
+      yield* forkStderrDrain(proc.stderr, stderrChunks)
 
       // Each ndjson line becomes one queue entry. JSON.parse failures are
       // surfaced as the raw string so a malformed protocol message doesn't
       // silently wedge the test in `receive`.
       const responses = yield* Queue.unbounded<unknown>()
       yield* Effect.forkScoped(
-        Stream.fromReadableStream({
-          evaluate: () => proc.stdout,
-          onError: () => new Error("stdout stream error"),
-        }).pipe(
+        fromBunStream("stdout", () => proc.stdout).pipe(
           Stream.decodeText(),
           Stream.splitLines,
           Stream.runForEach((line) => {
@@ -355,23 +354,23 @@ export function withCliFixture<A, E>(
             }
             return Queue.offer(responses, parsed)
           }),
-          Effect.ignore,
+          Effect.ignore({ log: true }),
         ),
       )
 
       return {
+        // `proc.stdin.write` returns `number | Promise<number>`. The promise
+        // form is the backpressure signal — if we don't await it, rapid
+        // successive sends can interleave under pipe-buffer-full conditions
+        // and corrupt the ndjson framing.
         send: (msg: object) =>
-          Effect.sync(() => {
-            proc.stdin.write(JSON.stringify(msg) + "\n")
+          Effect.promise(async () => {
+            const ret = proc.stdin.write(JSON.stringify(msg) + "\n")
+            if (typeof ret !== "number") await ret
           }),
         receive: Queue.take(responses),
-        close: () => {
-          try {
-            proc.stdin.end()
-          } catch {
-            // already closed
-          }
-        },
+        // proc.stdin.end() is idempotent in Bun; no try/catch needed.
+        close: () => proc.stdin.end(),
         exited: proc.exited as Promise<number>,
       } satisfies AcpHandle
     })