Skip to content

lehdqlsl/opencode-claude-auth-sync

Repository files navigation

opencode-claude-auth-sync

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.

Key Features

  • 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-auth

If 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.

Quick Start

Linux / macOS / WSL

curl -fsSL https://raw.githubusercontent.com/lehdqlsl/opencode-claude-auth-sync/main/install.sh | bash

Windows (PowerShell as Administrator)

irm https://raw.githubusercontent.com/lehdqlsl/opencode-claude-auth-sync/main/install.ps1 | iex

Don'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 path

Verify

opencode providers list    # Should show: Anthropic  oauth
opencode models anthropic  # Should list Claude models (e.g. claude-opus-4-6)

Usage

# 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 --force

Multi-Account

Manage 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

Add accounts

There are two ways to add an account.

Option A: already logged in via claude (recommended on SSH / remote machines)

If claude is already authenticated with the account you want to save, just capture the current session:

claude-sync --add personal
claude-sync --add work

Windows:

claude-sync --add personal
claude-sync --add work

This is the most reliable path on remote servers because Claude's login flow can be interactive.

Option B: login + save in one command

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 backup

Windows:

claude-sync --login personal
claude-sync --login work

Each --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

Manage accounts

# 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 backup

Example --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%

Rotation behavior

  • 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 --rotate manually
  • --status shows 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

Store format

{
  "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 Support

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

Security

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

Prerequisites

  • OpenCode v1.2.27+
  • Claude CLI — authenticated (run claude at least once)
  • Node.js (bundled with OpenCode, or standalone)

Why?

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).

Install (detailed)

Automatic (with AI agent)

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.

Linux / macOS (manual)

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 -

Windows (manual)

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

Configuration

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

Uninstall

Linux / macOS

curl -fsSL https://raw.githubusercontent.com/lehdqlsl/opencode-claude-auth-sync/main/uninstall.sh | bash

Windows (PowerShell as Administrator)

irm https://raw.githubusercontent.com/lehdqlsl/opencode-claude-auth-sync/main/uninstall.ps1 | iex

Known Issues

Using alongside opencode-claude-auth npm plugin

If 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.

Token expiration / "EXPIRED" status

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):

  1. Re-authenticate manually:
    claude
  2. Re-run the sync:
    # Linux / macOS
    claude-sync
    
    # Windows
    claude-sync

Token refresh failed: 429

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-auth

and 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:

  1. Start OpenCode with OPENCODE_DISABLE_DEFAULT_PLUGINS=true
  2. Explicitly register opencode-claude-auth@latest in opencode.json

Example:

{
  "plugin": [
    "opencode-claude-auth@latest"
  ]
}

This disables the old built-in plugin injection while still loading a Claude auth provider explicitly.

Sync log

Check the sync history:

cat ~/.local/share/opencode/sync-claude.log

OpenCode v1.3+ compatibility

OpenCode 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.

License

MIT

About

Sync Claude CLI credentials to OpenCode — no separate Anthropic login needed

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors