diff --git a/packages/cli/src/commands/handlers/auth/list.ts b/packages/cli/src/commands/handlers/auth/list.ts index cf93491295e4..03ab4e4e1c35 100644 --- a/packages/cli/src/commands/handlers/auth/list.ts +++ b/packages/cli/src/commands/handlers/auth/list.ts @@ -38,6 +38,7 @@ const list = Effect.fn("cli.auth.list")(function* (input) { integration: integration.name, source: connection.type === "credential" ? connection.label : connection.name, type: connection.type === "credential" ? "stored" : "environment", + id: connection.type === "credential" ? connection.id : "-", })), ) if (rows.length === 0) { @@ -46,6 +47,7 @@ const list = Effect.fn("cli.auth.list")(function* (input) { } const width = Math.max(...rows.map((row) => row.integration.length)) + 2 process.stdout.write( - rows.map((row) => row.integration.padEnd(width) + row.source.padEnd(28) + row.type).join(EOL) + EOL, + rows.map((row) => row.integration.padEnd(width) + row.source.padEnd(28) + row.type.padEnd(13) + row.id).join(EOL) + + EOL, ) }) diff --git a/packages/cli/test/auth.test.ts b/packages/cli/test/auth.test.ts index 5e82a2fc639f..367afbc89ea7 100644 --- a/packages/cli/test/auth.test.ts +++ b/packages/cli/test/auth.test.ts @@ -38,7 +38,7 @@ describe("auth command", () => { expect(logout.stdout).toContain("opencode auth logout [flags] [] []") }) - test("lists stored and environment connections", async () => { + test("lists distinct stored credential IDs without changing JSON connections", async () => { const requests: string[] = [] using server = authServer((request, url) => { if (url.pathname === "/api/integration") { @@ -50,6 +50,7 @@ describe("auth command", () => { methods: [], connections: [ { type: "credential", method: "key", id: "cred_test", label: "default" }, + { type: "credential", method: "key", id: "cred_other", label: "default" }, { type: "env", name: "ANTHROPIC_API_KEY" }, ], }, @@ -61,18 +62,32 @@ describe("auth command", () => { }, requests) const result = await cli(["auth", "list", "--format", "json", "--server", server.url.toString()]) + expect(requests).toContain("/api/model/default") + expect(requests.indexOf("/api/model/default")).toBeLessThan(requests.indexOf("/api/integration")) + const table = await cli(["auth", "list", "--server", server.url.toString()]) expect({ exitCode: result.exitCode, stderr: result.stderr }).toEqual({ exitCode: 0, stderr: "" }) + expect({ exitCode: table.exitCode, stderr: table.stderr }).toEqual({ exitCode: 0, stderr: "" }) + expect( + table.stdout + .trim() + .split("\n") + .map((line) => line.split(/\s{2,}/)), + ).toEqual([ + ["Anthropic", "default", "stored", "cred_test"], + ["Anthropic", "default", "stored", "cred_other"], + ["Anthropic", "ANTHROPIC_API_KEY", "environment", "-"], + ]) expect(JSON.parse(result.stdout)).toEqual([ { id: "anthropic", name: "Anthropic", connections: [ { type: "credential", method: "key", id: "cred_test", label: "default" }, + { type: "credential", method: "key", id: "cred_other", label: "default" }, { type: "env", name: "ANTHROPIC_API_KEY" }, ], }, ]) - expect(requests.indexOf("/api/model/default")).toBeLessThan(requests.indexOf("/api/integration")) }) test("lists OpenCode Go before Zen and preserves the remaining integration order", async () => { diff --git a/services/www/src/docs/content/cli/commands.mdx b/services/www/src/docs/content/cli/commands.mdx index db38dbd6dceb..fea4af6984f2 100644 --- a/services/www/src/docs/content/cli/commands.mdx +++ b/services/www/src/docs/content/cli/commands.mdx @@ -164,10 +164,14 @@ $ opencode session --help ## auth -Manages AI providers and credentials. +Manages AI providers and credentials. The default table shows the integration name, account label or environment variable, +connection type, and credential ID. Environment connections show `-` instead of an ID. ```bash $ opencode auth list +Anthropic work stored cred_work +Anthropic work stored cred_other +Anthropic ANTHROPIC_API_KEY environment - ``` List them as JSON. @@ -188,16 +192,18 @@ Log in with a specific authentication method. $ opencode auth login anthropic --method key ``` -Log out of a saved account. +Log out of a saved account by label or credential ID. Use the ID from `auth list` when labels are identical. ```bash $ opencode auth logout anthropic work +$ opencode auth logout anthropic cred_other ``` -Switch the active account for an integration. +Switch the active account for an integration by label or credential ID. ```bash $ opencode auth switch anthropic work +$ opencode auth switch anthropic cred_work ``` Export saved credentials and import them on another machine. The file contains secrets.