bug: Inconsistent Provider/Plugin Selection Between CLI and TUI (.find() vs fromEntries()) #7775

Open
opened 2026-02-16 18:08:12 -05:00 by yindo · 1 comment
Owner

Originally created by @iam-brain on GitHub (Jan 27, 2026).

Originally assigned to: @thdxr on GitHub.

Description

There is a discrepancy in how opencode selects which plugin to use when multiple plugins register the same providerId (e.g., openai).
Because internal/built-in plugins like CodexAuthPlugin are loaded first when using opencode auth login, the CLI's selection logic causes it to "lock" to the internal version, while the TUI menus correctly displays the metadata of the external/configured plugin. This creates a state where a user can see their custom plugin in the opencode auth list but cannot actually use it via opencode auth login.

Technical Details:

  1. Plugin Load Order: In packages/opencode/src/plugin/index.ts, plugins are loaded in this order:
    • Internal plugins
    • Configuration-based plugins
    • Built-in plugins
  2. CLI Behavior (First-Wins): In packages/opencode/src/cli/cmd/auth.ts, the CLI looks up the plugin using .find():
    const plugin = Plugin.list().find(p => p.id === providerId);
    This causes the CLI to always select the internal plugin if it exists, ignoring any custom plugin with the same ID.
  3. TUI/Provider Behavior (Last-Wins): In packages/opencode/src/provider/auth.ts, the list is converted to an object:
    const providers = Object.fromEntries(Plugin.list().map(p => [p.id, p]));
    In an object literal/fromEntries, the last key wins. This causes the TUI to select the custom/external plugin, leading to the metadata (label/description) being shown in the opencode auth list, while opencode auth login uses the internal one.

Expected Behavior:

The CLI and TUI should use a consistent selection strategy. Generally, user-defined or external plugins should be allowed to override internal ones to support custom authentication backends or specialized model configurations.
Proposed Fix:
Align the CLI to match the TUI's "last-wins" behavior (or vice versa, provided external plugins take precedence). Using findLast() or reversing the list before calling find() in the CLI would resolve the immediate inconsistency.

Plugins

"opencode-antigravity-auth@latest", "opencode-openai-codex-multi-auth@latest", https://github.com/obra/superpowers

OpenCode version

1.1.36

Steps to reproduce

  1. Install a custom plugin that overrides a built-in provider ID (e.g., openai from https://github.com/iam-brain/opencode-openai-codex-multi-auth).
  2. In the TUI, use the command palette or keybinds to add a provider and observe that the custom plugin's label and description are displayed correctly (plugin overrides the native plugin).
  3. In your terminal/CLI, run opencode auth login, select OpenAI. Observe that the built-in authentication flow via the native plugin (CodexAuthPlugin) is triggered instead of the custom plugin's authorize() method.

Screenshot and/or share link

No response

Operating System

macOS 26.3

Terminal

Ghostty

Originally created by @iam-brain on GitHub (Jan 27, 2026). Originally assigned to: @thdxr on GitHub. ### Description There is a discrepancy in how opencode selects which plugin to use when multiple plugins register the same providerId (e.g., **openai**). Because internal/built-in plugins like CodexAuthPlugin are loaded first when using opencode auth login, the CLI's selection logic causes it to "lock" to the internal version, while the TUI menus correctly displays the metadata of the external/configured plugin. This creates a state where a user can see their custom plugin in the opencode auth list but cannot actually use it via opencode auth login. **Technical Details**: 1. Plugin Load Order: In packages/opencode/src/plugin/index.ts, plugins are loaded in this order: * Internal plugins * Configuration-based plugins * Built-in plugins 2. CLI Behavior (First-Wins): In packages/opencode/src/cli/cmd/auth.ts, the CLI looks up the plugin using .find(): const plugin = Plugin.list().find(p => p.id === providerId); This causes the CLI to always select the internal plugin if it exists, ignoring any custom plugin with the same ID. 3. TUI/Provider Behavior (Last-Wins): In packages/opencode/src/provider/auth.ts, the list is converted to an object: const providers = Object.fromEntries(Plugin.list().map(p => [p.id, p])); In an object literal/fromEntries, the last key wins. This causes the TUI to select the custom/external plugin, leading to the metadata (label/description) being shown in the opencode auth list, while opencode auth login <id> uses the internal one. **Expected Behavior**: The CLI and TUI should use a consistent selection strategy. Generally, user-defined or external plugins should be allowed to override internal ones to support custom authentication backends or specialized model configurations. Proposed Fix: Align the CLI to match the TUI's "last-wins" behavior (or vice versa, provided external plugins take precedence). Using findLast() or reversing the list before calling find() in the CLI would resolve the immediate inconsistency. ### Plugins "opencode-antigravity-auth@latest", "opencode-openai-codex-multi-auth@latest", https://github.com/obra/superpowers ### OpenCode version 1.1.36 ### Steps to reproduce 1. Install a custom plugin that overrides a built-in provider ID (e.g., openai from https://github.com/iam-brain/opencode-openai-codex-multi-auth). 2. In the TUI, use the command palette or keybinds to add a provider and observe that the custom plugin's label and description are displayed correctly (plugin overrides the native plugin). 4. In your terminal/CLI, run opencode auth login, select OpenAI. Observe that the built-in authentication flow via the native plugin (CodexAuthPlugin) is triggered instead of the custom plugin's authorize() method. ### Screenshot and/or share link _No response_ ### Operating System macOS 26.3 ### Terminal Ghostty
yindo added the bug label 2026-02-16 18:08:12 -05:00
Author
Owner

@github-actions[bot] commented on GitHub (Jan 27, 2026):

This issue might be a duplicate of existing issues. Please check:

  • #6261: bug: multiple plugins registering auth for the same provider silently overwrite each other - This is closely related as it addresses the same root cause (inconsistent plugin selection between .find() and fromEntries()) and impacts the same auth flow.

Feel free to ignore if this doesn't address your specific case.

@github-actions[bot] commented on GitHub (Jan 27, 2026): This issue might be a duplicate of existing issues. Please check: - #6261: bug: multiple plugins registering auth for the same provider silently overwrite each other - This is closely related as it addresses the same root cause (inconsistent plugin selection between .find() and fromEntries()) and impacts the same auth flow. Feel free to ignore if this doesn't address your specific case.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#7775