opencode icon indicating copy to clipboard operation
opencode copied to clipboard

feat: If an `apiKey` is provided, skip Oauth handling.

Open toastdriven opened this issue 1 month ago • 5 comments

Context

My situation is this:

  • I have a personal Claude Code Pro subscription, which is Oauth-ed (just like Claude Code the agent does).
  • My work uses Anthropic Claude Enterprise, with multiple API keys (one key for each client). Those are usually set in the config via provider.anthropic.options.apiKey.

Using fake "profiles" (individually managed custom config files), I'd like to be able to use opencode with either type.

Expected

When configured to use the Anthropic Claude provider, if an (enterprise) apiKey is provided, it should take precedence over the stored Oauth (Claude Code Pro) credentials. If not provided, opencode should use the Oauth credentials.

Actual

Because of the way the configurations merging happens, the Oauth credentials (from ~/.local/share/opencode/auth.json) always "win", and the manually set apiKey is ignored.

This means all usage, even when I provide an enterprise API key, always ends up pointed at my personal Claude Pro subscription.

Solution

If an apiKey is configured & present, assume the user knows better & skip the loading of the Oauth credentials.


Deeper Explanation of Setup/Situation

  • I'm simulating having different "profiles" (one-per-client + a personal) by creating a bunch of custom config files within ~/.config/opencode/my_profiles/<profile-name>.jsonc.
  • In the work-based config files, under the provider.anthropic.options.apiKey path, I supply {file:~/.secrets/<profile-name>.apikey}, with different key paths for each work config.
  • I then launch opencode with: OPENCODE_CONFIG=~/.config/opencode/my_profiles/<profile-name>.jsonc opencode.
  • (Assuming I've renamed/moved the ~/.local/share/opencode/auth.json away) This works great for all the different clients/keys... but because that file is gone, I can no longer use my personal subscription (e.g. OPENCODE_CONFIG=~/.config/opencode/my_profiles/personal.jsonc opencode).
  • (Assuming I move the ~/.local/share/opencode/auth.json back) My personal Claude Pro subscription is back, but now takes over everything, & the client API keys are never used.

This adds a small skip (non-specific to Anthropic/Claude) to the provider code, only if an apiKey is set/present. It includes a new passing test that demonstrates the behavior.

toastdriven avatar Dec 18 '25 00:12 toastdriven

Also, this may help with (or completely) resolve #4291.

toastdriven avatar Dec 18 '25 00:12 toastdriven

/review

rekram1-node avatar Dec 18 '25 01:12 rekram1-node

lgtm

github-actions[bot] avatar Dec 18 '25 01:12 github-actions[bot]

hm im not sure this is proper fix, ik it prolly works but doesnt this skip all plugins that have auth in them? ik some people pass custom fetch implementations to their providers and this skips loading the plugin altogether i think

rekram1-node avatar Dec 18 '25 06:12 rekram1-node

Ah, that's a good point. So from there, while still trying to solve this, I'd propose two options:

  1. Reorder the loading so that the plugins come first, before the apiKey. Not sure that this will work, but I will give it a try.
  2. Introduce a new configuration option. In looking through the schema, there only seems to be the top-level plugins, with nothing under the provider. So maybe: a. An explicit plugins list under provider or provider.options (might be painful to keep in-sync long-term?) b. A disabled_plugins list under provider or provider.options (just disabling the specific Oauth plugin opencode-anthropic-auth for this instance, while not blocking other plugins) c. An ignore_oauth setting covering this specific case.

Maybe there's a different approach I'm not seeing.

toastdriven avatar Dec 18 '25 18:12 toastdriven