From ee165819449da7b3b8c92b3436513de1e6a96dd3 Mon Sep 17 00:00:00 2001 From: shenghui kevin Date: Sat, 21 Feb 2026 05:02:55 -0800 Subject: [PATCH 1/3] feat(cli): add --format json option to models command The session list command supports --format json for machine-readable output, but the models command only supported plain text. This adds a --format option with choices "text" (default) and "json" to bring consistency across CLI commands and enable scripting use cases. Closes #14550 Co-Authored-By: Claude Opus 4.6 --- packages/opencode/src/cli/cmd/models.ts | 45 ++++++++++++++++++------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/packages/opencode/src/cli/cmd/models.ts b/packages/opencode/src/cli/cmd/models.ts index 156dae91c676..44dcd4d227b3 100644 --- a/packages/opencode/src/cli/cmd/models.ts +++ b/packages/opencode/src/cli/cmd/models.ts @@ -24,6 +24,12 @@ export const ModelsCommand = cmd({ describe: "refresh the models cache from models.dev", type: "boolean", }) + .option("format", { + describe: "output format", + type: "string", + choices: ["text", "json"] as const, + default: "text", + }) }, handler: async (args) => { if (args.refresh) { @@ -36,6 +42,18 @@ export const ModelsCommand = cmd({ async fn() { const providers = await Provider.list() + function collectModels(providerID: string) { + const provider = providers[providerID] + return Object.entries(provider.models) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([modelID, model]) => ({ + id: `${providerID}/${modelID}`, + provider: providerID, + model: modelID, + ...model, + })) + } + function printModels(providerID: string, verbose?: boolean) { const provider = providers[providerID] const sortedModels = Object.entries(provider.models).sort(([a], [b]) => a.localeCompare(b)) @@ -49,18 +67,7 @@ export const ModelsCommand = cmd({ } } - if (args.provider) { - const provider = providers[args.provider] - if (!provider) { - UI.error(`Provider not found: ${args.provider}`) - return - } - - printModels(args.provider, args.verbose) - return - } - - const providerIDs = Object.keys(providers).sort((a, b) => { + const targetProviderIDs = args.provider ? [args.provider] : Object.keys(providers).sort((a, b) => { const aIsOpencode = a.startsWith("opencode") const bIsOpencode = b.startsWith("opencode") if (aIsOpencode && !bIsOpencode) return -1 @@ -68,7 +75,19 @@ export const ModelsCommand = cmd({ return a.localeCompare(b) }) - for (const providerID of providerIDs) { + if (args.provider && !providers[args.provider]) { + UI.error(`Provider not found: ${args.provider}`) + return + } + + if (args.format === "json") { + const models = targetProviderIDs.flatMap(collectModels) + process.stdout.write(JSON.stringify(models, null, 2)) + process.stdout.write(EOL) + return + } + + for (const providerID of targetProviderIDs) { printModels(providerID, args.verbose) } }, From 5de731434dd76787bcf7877cadf63be0975f1506 Mon Sep 17 00:00:00 2001 From: shenghui kevin Date: Sat, 21 Feb 2026 05:20:47 -0800 Subject: [PATCH 2/3] fix: resolve TS2783 duplicate 'id' property in models command Spread model properties before explicit id/provider/model fields so the explicit values take precedence and TypeScript no longer warns about 'id' being specified more than once. Co-Authored-By: Claude Opus 4.6 --- packages/opencode/src/cli/cmd/models.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/cli/cmd/models.ts b/packages/opencode/src/cli/cmd/models.ts index 44dcd4d227b3..99d80b67ed8f 100644 --- a/packages/opencode/src/cli/cmd/models.ts +++ b/packages/opencode/src/cli/cmd/models.ts @@ -47,10 +47,10 @@ export const ModelsCommand = cmd({ return Object.entries(provider.models) .sort(([a], [b]) => a.localeCompare(b)) .map(([modelID, model]) => ({ + ...model, id: `${providerID}/${modelID}`, provider: providerID, model: modelID, - ...model, })) } From 1fc46b5c4a7ccd4e29c5d158ef19cc99f76b9531 Mon Sep 17 00:00:00 2001 From: shenghui kevin Date: Sat, 21 Feb 2026 18:11:29 -0800 Subject: [PATCH 3/3] ci: retrigger checks