Sync your existing Claude CLI credentials to OpenCode — with cross-platform multi-account support.
The only tool that supports multi-account on Linux, macOS, and Windows. Manage multiple Claude accounts with quota tracking, automatic rotation, and one-command switching — on any platform.
- Cross-platform multi-account — Store and switch between multiple Claude accounts on Linux, macOS, and Windows. Not limited to macOS Keychain.
- Quota visibility — See your 5h / 7d usage at a glance with
claude-sync --status - Account rotation — Round-robin switching when one account hits rate limits
- Zero dependencies — Plain shell scripts. No npm, no node_modules, no supply chain risk. Read the source before you run it.
- Auto-refresh — Expired tokens are refreshed via Claude CLI automatically
⚠️ OpenCode 1.3.0+ users: This tool only syncs credentials. You must also install a separate Anthropic auth plugin. See v1.3+ compatibility.
🔧 Getting 429 errors?
The old built-in opencode-anthropic-auth@0.0.13 plugin may still be cached. Remove it:
rm -rf ~/.cache/opencode/node_modules/opencode-anthropic-authIf it keeps coming back, also remove opencode-anthropic-auth from ~/.cache/opencode/package.json. Then restart OpenCode.
🤔 Why not an npm plugin?
When auth breaks, npm packages pop up fast — but installing unknown packages that handle your OAuth tokens is a risk. This tool is a plain shell script you can read in full before running. No node_modules, no dependency tree, no trust required.
npm-based alternatives like opencode-claude-auth work well for single-account setups on macOS. If you need multi-account on Linux or Windows, this is the tool.
curl -fsSL https://raw.githubusercontent.com/lehdqlsl/opencode-claude-auth-sync/main/install.sh | bashirm https://raw.githubusercontent.com/lehdqlsl/opencode-claude-auth-sync/main/install.ps1 | iexDon't want a scheduler? Install without automatic syncing:
# Linux / macOS curl -fsSL https://raw.githubusercontent.com/lehdqlsl/opencode-claude-auth-sync/main/install.sh | bash -s -- --no-scheduler # Windows (PowerShell) & { irm https://raw.githubusercontent.com/lehdqlsl/opencode-claude-auth-sync/main/install.ps1 -OutFile $env:TEMP\install.ps1; & $env:TEMP\install.ps1 --no-scheduler }Then just run the sync manually whenever you need it:
claude-sync # Linux / macOS (after install) ~/.local/bin/sync-claude-to-opencode.sh # Linux / macOS direct path claude-sync # Windows (after install) & "$HOME\.local\bin\sync-claude-to-opencode.ps1" # Windows direct pathopencode providers list # Should show: Anthropic oauth opencode models anthropic # Should list Claude models (e.g. claude-opus-4-6)# Normal sync (default, also runs via scheduler) claude-sync # Check token status without syncing claude-sync --status # Force refresh token via Claude CLI regardless of expiry claude-sync --forceManage multiple Claude accounts with quota visibility, automatic rotation, and the shorter claude-sync command.
Important: Claude CLI itself only supports one logged-in account at a time. Multi-account here means this tool stores multiple credential sets in its own account store, then switches which one is written into OpenCode's auth.json.
Account store:
~/.config/opencode-claude-auth-sync/accounts.json There are two ways to add an account.
If claude is already authenticated with the account you want to save, just capture the current session:
claude-sync --add personal claude-sync --add workWindows:
claude-sync --add personal claude-sync --add workThis is the most reliable path on remote servers because Claude's login flow can be interactive.
Use --login if you want the script to trigger Claude login and then save the result:
claude-sync --login personal claude-sync --login work claude-sync --login backupWindows:
claude-sync --login personal claude-sync --login workEach --login logs out the current Claude session, starts Claude login, then saves the credentials under the given label.
If you're on SSH and --login feels awkward, use this flow instead:
claude # run /login inside Claude if needed exit claude-sync --add work# List stored accounts claude-sync --list # Show active account status + current 5h / 7d usage claude-sync --status # Switch active account immediately claude-sync --switch work # Rotate to the next account (round-robin) claude-sync --rotate # Remove a stored account claude-sync --remove backupExample --status output:
Account: work (2 total) Status: valid (7h 56m remaining) Expires: 2026-03-21T10:55:26.162Z Plan: max Usage: 5h 2% (reset: 2026-03-21T07:00:00.152Z) 7d 0% (reset: 2026-03-28T02:00:00.153Z) sonnet 3% - OpenCode still uses a single Anthropic entry in
auth.json - This tool switches which stored account is written into that slot
- If the active account is expired, the script first tries another non-expired stored account
- If all stored accounts are expired, it falls back to Claude CLI refresh for the currently logged-in Claude account
- 429 rate limits are not auto-detected yet; if one account is rate-limited, run
claude-sync --rotatemanually --statusshows the current account's 5h / 7d usage so you can decide when to rotate- The same Claude account can still be saved under two different labels if you add it twice
{ "accounts": { "personal": { "accessToken": "...", "refreshToken": "...", "expiresAt": 1774027458398, "subscriptionType": "max", "rateLimitTier": "default_claude_max_20x", "addedAt": "2026-03-20T09:55:32.366Z" } }, "active": "personal", "rotationIndex": 0 }| Platform | Claude credentials | Scheduler | Install command |
|---|---|---|---|
| Linux / WSL | ~/.claude/.credentials.json | cron | curl | bash |
| macOS | macOS Keychain → file fallback | LaunchAgent | curl | bash |
| Windows (native) | %USERPROFILE%\.claude\.credentials.json | Task Scheduler | PowerShell |
This tool is not an npm package — it's a plain shell script you can read before running.
- No
node_modules, no dependency tree, no supply chain risk - Single-file scripts:
sync-claude-to-opencode.sh(bash) /.ps1(PowerShell) - Credentials are passed via stdin, never exposed in process arguments
- All JSON writes are atomic (temp file + rename) to prevent corruption
- Review the source before installing:
sync-claude-to-opencode.sh(~846 lines) /.ps1(~619 lines)
# Inspect before running curl -fsSL https://raw.githubusercontent.com/lehdqlsl/opencode-claude-auth-sync/main/sync-claude-to-opencode.sh | less- OpenCode v1.2.27+
- Claude CLI — authenticated (run
claudeat least once) - Node.js (bundled with OpenCode, or standalone)
OpenCode no longer provides built-in Anthropic login. If you want to use Claude models (Opus, Sonnet, Haiku, etc.) in OpenCode, you need to bring your own credentials.
This tool bridges the gap: it reads your existing Claude CLI OAuth tokens and writes them into OpenCode's auth store, letting an opencode-anthropic-auth plugin handle the rest (see v1.3+ compatibility).
Paste this to your AI coding agent (Claude Code, OpenCode, Cursor, etc.):
Install opencode-claude-auth-sync from https://github.com/lehdqlsl/opencode-claude-auth-sync 1. Run the install script: # Linux / macOS curl -fsSL https://raw.githubusercontent.com/lehdqlsl/opencode-claude-auth-sync/main/install.sh | bash # Windows (PowerShell as Admin) irm https://raw.githubusercontent.com/lehdqlsl/opencode-claude-auth-sync/main/install.ps1 | iex 2. Check the sync output. If it says "EXPIRED", the stored token is stale. The script will try to refresh it automatically via Claude CLI. If that still fails, run `claude` manually, then re-run the sync: # Linux / macOS claude-sync # Windows claude-sync 3. Verify — the output should show remaining time, not EXPIRED: opencode providers list # Should show: Anthropic oauth opencode models anthropic # Should list Claude models 4. If you see "Token refresh failed: 429", that means expired tokens were used. Re-authenticate with `claude` first, then sync again. 5. If already installed and just need to refresh tokens (no reinstall needed): Run `claude` to re-authenticate, then sync: # Linux / macOS claude-sync # Windows claude-sync 6. If the user doesn't want a background scheduler, install with --no-scheduler: # Linux / macOS curl -fsSL https://raw.githubusercontent.com/lehdqlsl/opencode-claude-auth-sync/main/install.sh | bash -s -- --no-scheduler # Windows Download and run install.ps1 with --no-scheduler flag Then sync manually whenever needed. mkdir -p ~/.local/bin curl -fsSL https://raw.githubusercontent.com/lehdqlsl/opencode-claude-auth-sync/main/sync-claude-to-opencode.sh \ -o ~/.local/bin/sync-claude-to-opencode.sh chmod +x ~/.local/bin/sync-claude-to-opencode.sh ln -sf ~/.local/bin/sync-claude-to-opencode.sh ~/.local/bin/claude-sync claude-sync(Optional) Set up automatic syncing (every 15 minutes):
# macOS — LaunchAgent (recommended, catches up after sleep) # Use the install script: curl ... | bash # Linux — cron (crontab -l 2>/dev/null; echo "*/15 * * * * \$HOME/.local/bin/sync-claude-to-opencode.sh >> \$HOME/.local/share/opencode/sync-claude.log 2>&1") | crontab -New-Item -ItemType Directory -Force -Path "$HOME\.local\bin" | Out-Null Invoke-WebRequest -Uri "https://raw.githubusercontent.com/lehdqlsl/opencode-claude-auth-sync/main/sync-claude-to-opencode.ps1" ` -OutFile "$HOME\.local\bin\sync-claude-to-opencode.ps1" @" @echo off setlocal powershell.exe -ExecutionPolicy Bypass -File "%~dp0sync-claude-to-opencode.ps1" %* "@ | Set-Content -Path "$HOME\.local\bin\claude-sync.cmd" claude-sync| Environment Variable | Default | Description |
|---|---|---|
CLAUDE_CREDENTIALS_PATH | ~/.claude/.credentials.json (Linux/Win) or Keychain (macOS) | Path to Claude CLI credentials |
OPENCODE_AUTH_PATH | ~/.local/share/opencode/auth.json | Path to OpenCode auth store |
curl -fsSL https://raw.githubusercontent.com/lehdqlsl/opencode-claude-auth-sync/main/uninstall.sh | bashirm https://raw.githubusercontent.com/lehdqlsl/opencode-claude-auth-sync/main/uninstall.ps1 | iexIf you're using opencode-claude-auth (v0.5+), you don't need this tool — that plugin syncs credentials in-process. Choose one or the other, not both.
Early versions (v0.2.x) had issues that have since been fixed. If you're on an old version, update or remove it.
The sync script attempts an automatic refresh via Claude CLI once the token is expired. If Claude CLI can refresh successfully, the next sync writes fresh credentials back to OpenCode.
Note: If the token expired while OpenCode was running, you may need to restart OpenCode after the sync to pick up the new credentials. This is rare — normally Claude CLI refreshes tokens before they expire, so OpenCode reads them seamlessly.
If auto-refresh fails (e.g. claude CLI not in PATH, or network issues):
- Re-authenticate manually:
claude
- Re-run the sync:
# Linux / macOS claude-sync # Windows claude-sync
This means OpenCode tried to use an expired token. The sync script's auto-refresh should prevent this, but if it occurs, re-authenticate with claude and sync again.
If the deprecated built-in plugin keeps being reinstalled, remove both:
rm -rf ~/.cache/opencode/node_modules/opencode-anthropic-authand the opencode-anthropic-auth dependency entry from ~/.cache/opencode/package.json, then restart OpenCode.
If you're on OpenCode v1.2.27 and the deprecated plugin keeps coming back on every startup, that's an upstream built-in plugin issue. A practical CLI-side workaround is:
- Start OpenCode with
OPENCODE_DISABLE_DEFAULT_PLUGINS=true - Explicitly register
opencode-claude-auth@latestinopencode.json
Example:
{ "plugin": [ "opencode-claude-auth@latest" ] }This disables the old built-in plugin injection while still loading a Claude auth provider explicitly.
Check the sync history:
cat ~/.local/share/opencode/sync-claude.logOpenCode v1.3 removes the built-in opencode-anthropic-auth plugin (PR #18186) per Anthropic's legal request.
This tool only syncs credentials into auth.json. On OpenCode 1.3.0+, synced credentials alone are no longer enough because the Anthropic provider is no longer built in.
If you're on OpenCode 1.3.0+, you need to register a separate Anthropic auth plugin manually in your opencode.json. Pick one:
The original plugin is still available on npm (deprecated):
{ "plugin": ["opencode-anthropic-auth@0.0.13"] }If the npm packages get unpublished, this repo includes a bundled copy of the original plugin (opencode-anthropic-auth-0.0.13.tgz). Extract it and reference the local file:
{ "plugin": ["/path/to/index.mjs"] }Important: This tool only handles credential sync (copying OAuth tokens into auth.json). It does not handle Anthropic API request transformation (headers, User-Agent, beta flags, etc.). If Anthropic changes how requests must be sent, this tool alone will not be enough — you will need an auth plugin that also handles request-level changes.
This tool itself only copies credentials and has no legal concerns. The compatibility risk is with the auth plugin that actually uses them.
MIT