DEV Community

day
day

Posted on

Claude Code can't use your Max plan's free API credit. OpenCode can.

TL;DR

  • Claude's Max and Team plans include a monthly API credit at no extra cost. Claude Code can't spend it, but OpenCode can, once you register an API key. The official pages don't mention third-party clients, but on my machine the credit went down when I used OpenCode.
  • The credit is $100 a month on Max 5x and $200 on Max 20x. Team gets a per-seat pool, capped at $500. It resets every month and doesn't roll over. Pro isn't eligible.
  • It isn't added automatically. You get it by linking a Console organization in claude.ai.
  • In OpenCode you register a Console API key. Anthropic doesn't allow signing in to OpenCode with a Pro/Max account.
  • The second half is a paste-ready prompt, plus the pitfalls, for moving your Claude Code setup (CLAUDE.md, subagents, skills, MCP, hooks) to OpenCode.

The whole thing in three steps:

# 1. In claude.ai, link a Console organization under Settings > Billing, then create an API key in the Console
# 2. Register the key in OpenCode (you paste it at the prompt)
opencode auth login anthropic --method key
# 3. Check that it works
opencode run --model anthropic/claude-haiku-5-5 "Reply with exactly one word: pong"
Enter fullscreen mode Exit fullscreen mode

Tested on macOS 27.0.1, OpenCode v2.0.27 and Claude Code 2.1.296. The quotes from official pages and my own runs are both as of Oct 12, 2026.

Why I moved to OpenCode

On the night of Oct 11, 2026, in the last push on a hackathon project, Claude Code hit its weekly limit. I logged in again with a Console account, and this time it said Credit balance is too low. Since the next day, Oct 12, I've been on OpenCode v2.0.27 with an API key.

Monthly API credits for Max and Team plans are rolling out from Oct 7, 2026 (Platform release notes). Interactive Claude Code can't use them; the API can. This post covers how to connect OpenCode, and the pitfalls I hit moving my Claude Code setup to V2.

Connect OpenCode to the credit

What the credit covers

The table below is what the Help Center and the Platform docs say.

How you use it Credit
Interactive Claude Code (terminal, IDE, desktop, web) Not eligible
claude -p or the Agent SDK, run by you with an API key from the linked organization Eligible
Claude API, Console Playground Eligible
Bedrock, Vertex AI, Foundry Not eligible
Third-party clients such as OpenCode (with a Console API key) Not mentioned (it went down on my machine)

The monthly amount is $100 on Max 5x and $200 on Max 20x; Team gets a per-seat pool (capped at $500). It renews every month with no carry-over. A plan can link only one Console organization, and you can't change it yourself later (it goes through support).

Logging in to Claude Code with a Console account doesn't get you this credit either. The docs say that if an organization holds only this credit, you get Credit balance too low · Add funds: ….

1. Link a Console organization

  1. Open Settings > Billing in claude.ai (Team owners: Organization settings > Billing).
  2. Under API credits, click "Link organization" and pick an organization or create a new one.
  3. Read the Supplemental Credit Terms and link.

On the plan side you need to be the subscriber (Max) or an Owner or Primary Owner (Team). On the Console side you need one of the Owner, Admin or Billing roles. A new subscription can link only after 7 days. If you're eligible but "API credits" doesn't show up, the rollout may not have reached you yet (the Help Center says it's rolling out over several days). Once linked, the Console's Settings > Billing shows the amount and expiry under Promotional credits. Pick the organization you actually work in.

2. Create an API key

In the Console's Settings → API keys, press Create key, choose a name and an expiry, and set Linked account to yourself. The key starts with sk-ant- and is shown only once, when you create it. Keys in the linked organization draw from the same balance, even across different workspaces.

3. Register it in OpenCode

curl -fsSL https://opencode.ai/v2/install | bash   # if you're on V1: opencode upgrade --major
opencode auth login anthropic --method key
Enter fullscreen mode Exit fullscreen mode

Paste the key at the prompt (this needs an interactive terminal). In the TUI, use /connect and pick Anthropic. Each time you register a key, another saved account is added, and the newest one becomes active. If you already had a different key registered, check with opencode auth list and switch to the linked organization's key with opencode auth switch anthropic <label> (Providers).

Warning: Don't sign in to OpenCode with a Pro/Max subscription. Anthropic's legal page doesn't allow third-party developers to route users' requests through Free, Pro or Max plan credentials. OpenCode's own V1 docs say of using Pro/Max models in OpenCode: "Anthropic explicitly prohibits this". They also say the plugin for it was removed in 1.3.0. An old step that says to pick "Claude Pro/Max" is still on the same page, but it doesn't work.

Using a Console API key that you set up in your own development environment, on the other hand, is not restricted, according to the legal page. I couldn't find a sentence saying it works with any client, though.

Warning: Don't put ANTHROPIC_API_KEY in ~/.zshrc either. If you approve a key found in the environment, Claude Code runs on that key instead of your subscription. Interactive mode isn't eligible for this credit, so you can end up with Credit balance is too low. With claude -p, a key in the environment is always used, with no approval step (Authentication, error reference).

If you'd rather pass the key as an environment variable, you can set it for OpenCode's background server only (opencode service set env ANTHROPIC_API_KEY sk-ant-...). I don't use this.

4. Check that it works

$ opencode auth list
Anthropic  Anthropic                   stored

$ opencode run --model anthropic/claude-haiku-5-5 "Reply with exactly one word: pong"
> build · claude-haiku-5-5
pong
Enter fullscreen mode Exit fullscreen mode

With opencode auth list --format json, you'll see "method": "key".

To see whether the credit is being used, look at Promotional credits under Settings > Billing in the Console and at the Cost page, before and after a request. On my machine, Promotional credits went down after I used OpenCode. Consumption through third-party clients isn't described officially, so it's worth confirming once on your own account. If it doesn't go down, first suspect that the key isn't from the linked organization. When the balance runs out, requests draw on any purchased credits or auto-reload you have; if there are none, API requests stop (your Claude plan isn't billed).

Move your Claude Code setup to OpenCode V2

Start with a prompt

I put the pitfalls from this section into a prompt for OpenCode. Start OpenCode and paste it as is.

Migrate my Claude Code setup to OpenCode V2.

- The source of truth is the OpenCode V2 docs (https://opencode.ai/v2/docs/). Don't use V1 syntax (`permission`, `bash`, `task`, `mcp.<name>`)
- Read: `~/.claude/CLAUDE.md`, `~/.claude/settings.json`, `~/.claude/agents/`, `~/.claude/skills/`, the enabled plugins (`enabledPlugins` in `settings.json`; their contents are under `~/.claude/plugins/cache/`), and the output of `claude mcp list`
- Treat `~/.claude` as read-only and don't change it. If `~/.config/opencode` already has files, back them up first
- Create:
  1. `~/.config/opencode/AGENTS.md`: the contents of `CLAUDE.md`, plus one sentence saying "if a repository has a `CLAUDE.md`, read it before working"
  2. `~/.config/opencode/agents/*.md`: give each agent `mode: subagent` and `model: provider/model#variant`, and rewrite `disallowedTools` as `permissions` deny rules. Don't write `name`
  3. `~/.config/opencode/opencode.jsonc`: `model` (the variant goes in `agents.build.model`); in `skills`, list the plugins' skill folders first and `~/.claude/skills` after them (so personal skills win when IDs collide); MCP servers under `mcp.servers`; hooks only where they can be replaced by `permissions`
  4. For each skill that takes arguments through `$ARGUMENTS`, a command in `~/.config/opencode/commands/` that does nothing but make the model load that skill
- Don't write API keys or tokens in config files (use `{env:NAME}` if needed). Tell me if skill IDs collide
- At the end, check with `opencode debug agents` and `opencode mcp list`, and report in a table what you migrated and what you couldn't (hooks, etc.)
Enter fullscreen mode Exit fullscreen mode

If you'd rather not have it rewrite files right away, switch the agent to plan first (Shift+Tab or /agents) and have it produce only a plan. The plan agent doesn't edit ordinary files.

I tried this prompt as a dry run. In the plan agent on Sonnet 5.5, on my machine, it came back with a plan that covered rewriting 10 agents, the plugins' skill folders, the context7 MCP server and replacing the hooks, plus a table of what can't be moved (the statusLine, and the notification and usage-guard hooks). I did my own migration by hand, following the steps below, before this prompt existed. After a migration, compare the result against the sections below.

What maps to what

Copy a V1 config example and some names will be wrong. In V2, permission is permissions, bash is shell, task is subagent, and MCP servers live under mcp.servers.<name>, not mcp.<name> (Permissions, MCP servers).

Item Claude Code OpenCode V2
Instructions CLAUDE.md AGENTS.md only
Subagents ~/.claude/agents/*.md ~/.config/opencode/agents/*.md (different frontmatter)
Skills ~/.claude/skills, plugins ~/.claude/skills is picked up automatically; plugin ones go in skills
MCP plugin (context7, in my case) mcp.servers.<name>
Hooks and permissions hooks, permissions in settings.json permissions; hooks are plugins
Slash commands skills, commands/ commands/*.md ($ARGUMENTS is expanded here)

CLAUDE.md isn't read

V2 reads only AGENTS.md; it doesn't fall back to CLAUDE.md (Instructions). In a throwaway git repository, I asked Haiku 5.5 to answer with a secret word from the instructions alone, without using tools. The word in CLAUDE.md didn't come back, and after I added an AGENTS.md, its word did.

# CLAUDE.md only (PINEAPPLE)
NONE

# AGENTS.md added too (MANGO)
MANGO
Enter fullscreen mode Exit fullscreen mode

Putting CLAUDE.md in the instructions setting doesn't help: V2 accepts the entry but doesn't load it (Config). So I added one line to my global AGENTS.md. It's the model that reads it, so whether it follows the line is up to the model.

<!-- ~/.config/opencode/AGENTS.md -->
- Most of my repos were set up for Claude Code. When a repo has a `CLAUDE.md` and no `AGENTS.md` says otherwise, read that `CLAUDE.md` before working: it is the project's instructions, and its rules apply here.
Enter fullscreen mode Exit fullscreen mode

You can also put an AGENTS.md in each repository that says only Read CLAUDE.md in this repository before working.

Subagents use different frontmatter

Compare the two using coder.

---
# ~/.claude/agents/coder.md
name: coder
description: Use for coding tasks delegated to a subagent: ...
model: sonnet
effort: max
---
Enter fullscreen mode Exit fullscreen mode
---
# ~/.config/opencode/agents/coder.md
description: "Use for coding tasks delegated to a subagent: ..."
mode: subagent
model: "anthropic/claude-sonnet-5-5#max"
permissions:
  - action: question
    resource: "*"
    effect: deny
---
Enter fullscreen mode Exit fullscreen mode
  • Don't write name; the file name becomes the ID
  • Without mode: subagent, the agent becomes primary (Agents)
  • model is provider/model#variant. sonnet and effort: max collapse into it. For model: inherit, delete the line and the agent inherits the parent's model
  • I deny question because the built-in general agent has the same setting

Copying a Claude Code agent as it is doesn't raise an error. I copied coder, reviewer, review-lead and Plan from ~/.claude/agents/ into .opencode/agents/ in a throwaway git repository, prefixing them with cc- so they wouldn't mix with global agents of the same name, and looked at them with opencode debug agents.

cc-coder        primary  (none)
cc-Plan         primary  (none)
cc-review-lead  primary  (none)
cc-reviewer     primary  (none)
Enter fullscreen mode Exit fullscreen mode

All four are primary, and the model is empty. name, model and effort weren't applied. On top of that, cc-Plan has no edit deny at all, so an agent you meant to make read-only with disallowedTools can edit files. Rewrite disallowedTools as permissions denies.

# Claude Code (Plan.md)
disallowedTools: Edit, Write, NotebookEdit, Agent, ExitPlanMode, Artifact
Enter fullscreen mode Exit fullscreen mode
# OpenCode (planner.md)
permissions:
  - action: edit
    resource: "*"
    effect: deny
  - action: subagent
    resource: "*"
    effect: deny
Enter fullscreen mode Exit fullscreen mode

The main session's effort can't go in the root model. The root model keeps only the provider and model, and #variant doesn't survive (Models). Put it in agents.build.model.

// ~/.config/opencode/opencode.jsonc
"model": "anthropic/claude-opus-5-5",
"agents": {
  "build": { "model": "anthropic/claude-opus-5-5#max" }
}
Enter fullscreen mode Exit fullscreen mode

Check the agents you migrated by hand with opencode debug agents.

# Piping straight into `| jq` cut the JSON off partway (5 out of 5 times here), so go through a file
opencode debug agents > /tmp/agents.json
jq -r '.[] | select(.id | IN("build","coder","planner","review-lead")) | [.id, .mode, (.model | if . then "\(.providerID)/\(.id)#\(.variant // "")" else "(inherit)" end)] | @tsv' /tmp/agents.json | column -t -s$'\t'
Enter fullscreen mode Exit fullscreen mode
build        primary   anthropic/claude-opus-5-5#max
coder        subagent  anthropic/claude-sonnet-5-5#max
planner      subagent  anthropic/claude-opus-5-5#max
review-lead  subagent  (inherit)
Enter fullscreen mode Exit fullscreen mode

Skills: add only the plugin ones

~/.claude/skills and .claude/skills are read as they are (Skills). What isn't read is plugin skills. Add the skills directory inside the plugin's cache to the skills setting. The path contains the version, so rewrite it when the plugin updates.

// ~/.config/opencode/opencode.jsonc
"skills": [
  "~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/skills",
  "~/.claude/skills",          // on duplicate IDs the later entry wins, so put personal skills after plugins
  "~/.config/opencode/skills"  // skills rewritten for OpenCode go last (mine: delegate and implement-orchestrated)
]
Enter fullscreen mode Exit fullscreen mode

A skill's ID comes from its path, without the plugin namespace (the name in frontmatter is a display name). On my machine, my personal code-review collided with the code-review from the mattpocock-skills plugin. Since the later entry wins, I kept the plugin's version under another name, as a directory containing only a symlink to its SKILL.md.

SRC=~/.claude/plugins/cache/claude-plugins-official/mattpocock-skills/1.2.3/skills/engineering/code-review/SKILL.md
mkdir -p ~/.config/opencode/skills/mattpocock-code-review
ln -s "$SRC" ~/.config/opencode/skills/mattpocock-code-review/SKILL.md
Enter fullscreen mode Exit fullscreen mode

~/.claude/skills and the plugin cache are outside the working directory, so allow external_directory for them. Then skills can read their supporting files.

{ "action": "external_directory", "resource": "~/.claude/skills/*", "effect": "allow" },
{ "action": "external_directory", "resource": "~/.claude/plugins/cache/*", "effect": "allow" }
Enter fullscreen mode Exit fullscreen mode

MCP goes under servers

// ~/.config/opencode/opencode.jsonc
"mcp": {
  "servers": {
    "context7": { "type": "remote", "url": "https://mcp.context7.com/mcp", "oauth": false }
  }
}
Enter fullscreen mode Exit fullscreen mode

Remote MCP servers use OAuth by default. context7 works without an account, so I set oauth: false. If opencode mcp list shows ✓ context7 connected, it's connected. Tool names are <server>_<tool>, not Claude Code's mcp__plugin_context7_context7__…. In the default Code Mode, tools are called through execute (set codemode: false to expose them as regular tools).

Hooks split into permissions and plugins

In Claude Code I had a PreToolUse hook (subagent-irreversible-guard.sh) that stopped only subagents from running git push and deploys. The main session was exempt.

In OpenCode V2 I replaced it with permissions. Rules are evaluated from the top, and the last match wins. Top-level rules apply to every agent, and a subagent doesn't inherit its parent's permissions but runs only on its own (Permissions). So I deny at the top level and re-open it only for the main build agent.

// ~/.config/opencode/opencode.jsonc
{
  "permissions": [
    // a deny that applies to every agent, subagents included
    { "action": "shell", "resource": "git push*", "effect": "deny" },
    { "action": "shell", "resource": "git -C * push", "effect": "deny" },
    { "action": "shell", "resource": "npm publish*", "effect": "deny" },
    { "action": "shell", "resource": "npm run *deploy*", "effect": "deny" }
  ],
  "agents": {
    "build": {
      "permissions": [
        // the last match wins: allow everything first, then set the commands that go outward back to ask
        { "action": "shell", "resource": "*", "effect": "allow" },
        { "action": "shell", "resource": "git push*", "effect": "ask" },
        { "action": "shell", "resource": "git -C * push", "effect": "ask" },
        { "action": "shell", "resource": "npm publish*", "effect": "ask" },
        { "action": "shell", "resource": "npm run *deploy*", "effect": "ask" }
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode
  • The default is allow-all. A V2 agent starts from an allow on *; only reading .env and anything outside the working directory asks. So you add denies and asks rather than adding allows
  • A pattern is matched against the whole command string. * matches anything, including spaces and quotes, so a broad pattern like git * push* would even stop git commit -m "fix push bug". I kept mine narrow: git push* and git -C * push
  • The docs also say it's better to narrow down the commands you allow than to try to catch every dangerous command with patterns. This deny is a fence against accidents, not a sandbox

There's no setting that corresponds to the hooks I ran after edits and on stop (PostToolUse, Stop), so I rewrote them as plugins (~/.config/opencode/plugins/*.js, Plugins). I didn't migrate the usage-guard hooks, because an API key has no 5-hour or weekly plan window.

Slash commands are thin wrappers around skills

A skill is loaded through the skill tool, or by writing @skill-id in a prompt. It's the command that expands $ARGUMENTS (Commands). My delegate skill took its arguments by ending with ARGUMENTS: $ARGUMENTS. I checked how that behaves with opencode run --format json, using a throwaway skill called argtest: the input to the skill tool was only {"id": "argtest"}, and the body that reached the model still contained $ARGUMENTS as is. The model guesses the arguments from the conversation and fills them in, so it can look like it works.

So I add a thin command that only makes the model load the skill.

---
# ~/.config/opencode/commands/delegate.md
description: Hand a task to one background worker subagent (OpenCode version of /delegate)
---

Load the `delegate` skill and follow it. The task to hand off:

$ARGUMENTS
Enter fullscreen mode Exit fullscreen mode

Claude Code-only frontmatter (context: fork, agent:, background:, and so on) isn't in the V2 docs. My /code-review skill had context: fork and agent: review-lead. I replaced them with the command's own agent and subagent: true (it runs in a background child session).

---
# ~/.config/opencode/commands/code-review.md
description: "Bug-hunting review in a background review-lead: [low|medium|high|xhigh|max] [--comment] [<pr#>|<branch>|<path>|<base>...<head>]"
agent: review-lead
subagent: true
---

Load the `code-review` skill and follow it. You are the review lead it describes; ...

Arguments:

$ARGUMENTS
Enter fullscreen mode Exit fullscreen mode

Claude Code's own tools need translating

OpenCode has no Agent tool, SendMessage or isolation: worktree. So that skills written for Claude Code can be read as they are, I keep a translation table in my global AGENTS.md.

Claude Code OpenCode
subagent_type: X in the Agent tool agent: X in the subagent tool
run_in_background: true background: true
SendMessage call subagent again with the same sessionID
isolation: worktree run git worktree add yourself and put the path in the instructions
fork none (hand over a self-contained brief)

git worktree add doesn't bring over .gitignored files. The .worktreeinclude copying that Claude Code did automatically is also yours to do.

What I checked, and what I didn't

  • Credit consumption: I confirmed in the Console's Billing that Promotional credits went down after I used OpenCode. The official pages say nothing about third-party clients, so the treatment may change.
  • On-screen wording: the claude.ai and Console steps follow what the official pages describe.
  • Permission patterns: that git * push* would even stop a commit message containing push follows from the docs' matching rules. I didn't run it for this post.
  • Aliased skill links: I link only SKILL.md, so I haven't checked whether relative paths resolve for a skill that has supporting files.
  • Slash commands: $ARGUMENTS expansion is from reading the docs only (opencode run didn't expand /name).
  • Not tested: other operating systems, the Desktop app, the Team plan.

Wrap-up

The monthly API credit is for Max 5x, Max 20x and Team only. You get it by linking a Console organization, and interactive Claude Code can't spend it. In OpenCode, register a Console API key, not a Pro/Max login. Keep ANTHROPIC_API_KEY out of ~/.zshrc: Claude Code can pick it up and answer with Credit balance is too low. On my machine, OpenCode usage did draw from Promotional credits, but the official pages don't say so, so check your own balance.

To move your Claude Code setup, paste the prompt into OpenCode and check the result with opencode debug agents: agents and CLAUDE.md files copied over as they are get ignored. Split hooks between permissions (deny at the top level, re-open for build) and plugins.

It's one option for when Claude Code's limit stops you.

References

This post is also on Zenn, in Japanese: zenn.dev/daydreamer/articles/opencode-claude-max-api-credits

Top comments (0)