feat(cliproxy): add Claude (Anthropic) OAuth provider support

Add Claude as a first-class OAuth provider in CCS CLI and dashboard.
Backend support already exists in CLIProxyAPIPlus (port 54545).

Changes:
- Add 'claude' to CLIProxyProvider type and profile detector
- Add Claude OAuth config (port 54545, --anthropic-login flag)
- Add Claude to oauth-port-diagnostics flow types
- Add Claude token discovery prefixes (claude-, anthropic-)
- Add Claude model catalog (Opus 4.5, Sonnet 4.5/4, Haiku 4.5)
- Add Claude logo and provider display name
- Update variant config types and adapters

Closes #380
This commit is contained in:
kaitranntt
2026-01-27 15:43:21 -05:00
parent 687f2e6541
commit 28d8bd84a5
12 changed files with 134 additions and 6 deletions
+1
View File
@@ -28,6 +28,7 @@ export const CLIPROXY_PROFILES = [
'iflow',
'kiro',
'ghcp',
'claude',
] as const;
export type CLIProxyProfileName = (typeof CLIPROXY_PROFILES)[number];
+10
View File
@@ -27,6 +27,7 @@ export const OAUTH_CALLBACK_PORTS: Partial<Record<CLIProxyProvider, number>> = {
codex: 1455,
agy: 51121,
iflow: 11451,
claude: 54545,
// qwen: Device Code Flow - no callback port
// ghcp: Device Code Flow - no callback port
};
@@ -121,6 +122,13 @@ export const OAUTH_CONFIGS: Record<CLIProxyProvider, ProviderOAuthConfig> = {
scopes: ['copilot'],
authFlag: '--github-copilot-login',
},
claude: {
provider: 'claude',
displayName: 'Claude (Anthropic)',
authUrl: 'https://console.anthropic.com/oauth/authorize',
scopes: ['user:inference', 'user:profile'],
authFlag: '--anthropic-login',
},
};
/**
@@ -136,6 +144,7 @@ export const PROVIDER_AUTH_PREFIXES: Record<CLIProxyProvider, string[]> = {
iflow: ['iflow-'],
kiro: ['kiro-', 'aws-', 'codewhisperer-'],
ghcp: ['github-copilot-', 'copilot-', 'gh-'],
claude: ['claude-', 'anthropic-'],
};
/**
@@ -150,6 +159,7 @@ export const PROVIDER_TYPE_VALUES: Record<CLIProxyProvider, string[]> = {
iflow: ['iflow'],
kiro: ['kiro', 'codewhisperer'],
ghcp: ['github-copilot', 'copilot'],
claude: ['claude', 'anthropic'],
};
/**
+1
View File
@@ -299,6 +299,7 @@ const PROVIDER_DISPLAY_NAMES: Record<CLIProxyProvider, string> = {
iflow: 'iFlow',
kiro: 'Kiro (AWS)',
ghcp: 'GitHub Copilot (OAuth)',
claude: 'Claude (Anthropic)',
};
/**
+49
View File
@@ -166,6 +166,55 @@ export const MODEL_CATALOG: Partial<Record<CLIProxyProvider, ProviderCatalog>> =
},
],
},
claude: {
provider: 'claude',
displayName: 'Claude (Anthropic)',
defaultModel: 'claude-sonnet-4-5-20250514',
models: [
{
id: 'claude-opus-4-5-20250220',
name: 'Claude Opus 4.5',
description: 'Most capable Claude model',
thinking: {
type: 'budget',
min: 1024,
max: 128000,
zeroAllowed: false,
dynamicAllowed: true,
},
},
{
id: 'claude-sonnet-4-5-20250514',
name: 'Claude Sonnet 4.5',
description: 'Balanced performance and speed',
thinking: {
type: 'budget',
min: 1024,
max: 128000,
zeroAllowed: false,
dynamicAllowed: true,
},
},
{
id: 'claude-sonnet-4-20250514',
name: 'Claude Sonnet 4',
description: 'Previous generation Sonnet',
thinking: {
type: 'budget',
min: 1024,
max: 128000,
zeroAllowed: false,
dynamicAllowed: true,
},
},
{
id: 'claude-haiku-4-5-20250514',
name: 'Claude Haiku 4.5',
description: 'Fast and efficient',
thinking: { type: 'none' },
},
],
},
};
/**
@@ -132,7 +132,7 @@ export function saveVariantUnified(
if (!config.cliproxy) {
config.cliproxy = {
oauth_accounts: {},
providers: ['gemini', 'codex', 'agy', 'qwen', 'iflow', 'kiro', 'ghcp'],
providers: ['gemini', 'codex', 'agy', 'qwen', 'iflow', 'kiro', 'ghcp', 'claude'],
variants: {},
};
}
+10 -1
View File
@@ -118,8 +118,17 @@ export interface DownloadResult {
* - iflow: iFlow via OAuth
* - kiro: Kiro (AWS CodeWhisperer) via OAuth
* - ghcp: GitHub Copilot via Device Code (OAuth through CLIProxyAPIPlus)
* - claude: Claude (Anthropic) via OAuth
*/
export type CLIProxyProvider = 'gemini' | 'codex' | 'agy' | 'qwen' | 'iflow' | 'kiro' | 'ghcp';
export type CLIProxyProvider =
| 'gemini'
| 'codex'
| 'agy'
| 'qwen'
| 'iflow'
| 'kiro'
| 'ghcp'
| 'claude';
/**
* CLIProxy backend selection
+1 -1
View File
@@ -61,7 +61,7 @@ export type OAuthAccounts = Record<string, string>;
*/
export interface CLIProxyVariantConfig {
/** Base provider to use */
provider: 'gemini' | 'codex' | 'agy' | 'qwen' | 'iflow' | 'kiro' | 'ghcp';
provider: 'gemini' | 'codex' | 'agy' | 'qwen' | 'iflow' | 'kiro' | 'ghcp' | 'claude';
/** Account nickname (references oauth_accounts) */
account?: string;
/** Path to settings file (e.g., "~/.ccs/gemini-custom.settings.json") */
+13 -2
View File
@@ -34,6 +34,7 @@ export const OAUTH_CALLBACK_PORTS: Record<CLIProxyProvider, number | null> = {
iflow: 11451, // Authorization Code Flow
kiro: 9876, // Authorization Code Flow
ghcp: null, // Device Code Flow - no callback port
claude: 54545, // Authorization Code Flow (Anthropic OAuth)
};
/**
@@ -52,6 +53,7 @@ export const OAUTH_FLOW_TYPES: Record<CLIProxyProvider, OAuthFlowType> = {
iflow: 'authorization_code',
kiro: 'authorization_code',
ghcp: 'device_code',
claude: 'authorization_code',
};
/**
@@ -138,7 +140,16 @@ export async function checkOAuthPort(provider: CLIProxyProvider): Promise<OAuthP
* Check OAuth ports for all providers
*/
export async function checkAllOAuthPorts(): Promise<OAuthPortDiagnostic[]> {
const providers: CLIProxyProvider[] = ['gemini', 'codex', 'agy', 'qwen', 'iflow', 'kiro', 'ghcp'];
const providers: CLIProxyProvider[] = [
'gemini',
'codex',
'agy',
'qwen',
'iflow',
'kiro',
'ghcp',
'claude',
];
const results: OAuthPortDiagnostic[] = [];
for (const provider of providers) {
@@ -153,7 +164,7 @@ export async function checkAllOAuthPorts(): Promise<OAuthPortDiagnostic[]> {
* Check OAuth ports for providers that use Authorization Code flow only
*/
export async function checkAuthCodePorts(): Promise<OAuthPortDiagnostic[]> {
const providers: CLIProxyProvider[] = ['gemini', 'codex', 'agy', 'kiro'];
const providers: CLIProxyProvider[] = ['gemini', 'codex', 'agy', 'kiro', 'claude'];
const results: OAuthPortDiagnostic[] = [];
for (const provider of providers) {
+1 -1
View File
@@ -18,7 +18,7 @@ export interface ProfilesConfig {
*/
export interface CLIProxyVariantConfig {
/** CLIProxy provider to use */
provider: 'gemini' | 'codex' | 'agy' | 'qwen' | 'iflow' | 'kiro' | 'ghcp';
provider: 'gemini' | 'codex' | 'agy' | 'qwen' | 'iflow' | 'kiro' | 'ghcp' | 'claude';
/** Path to settings.json with custom model configuration (optional) */
settings?: string;
/** Account identifier for multi-account support (optional, defaults to 'default') */
+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Claude</title><path d="M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z" fill="#D97757" fill-rule="nonzero"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -20,6 +20,7 @@ const PROVIDER_IMAGES: Record<string, string> = {
iflow: '/assets/providers/iflow.png',
kiro: '/assets/providers/kiro.png',
ghcp: '/assets/providers/copilot.svg',
claude: '/assets/providers/claude.svg',
};
/** Provider color configuration (for fallback only - no background for image logos) */
+45
View File
@@ -311,4 +311,49 @@ export const MODEL_CATALOGS: Record<string, ProviderCatalog> = {
},
],
},
claude: {
provider: 'claude',
displayName: 'Claude (Anthropic)',
defaultModel: 'claude-sonnet-4-5-20250514',
models: [
{
id: 'claude-opus-4-5-20250220',
name: 'Claude Opus 4.5',
description: 'Most capable Claude model',
presetMapping: {
default: 'claude-opus-4-5-20250220',
opus: 'claude-opus-4-5-20250220',
sonnet: 'claude-sonnet-4-5-20250514',
haiku: 'claude-haiku-4-5-20250514',
},
},
{
id: 'claude-sonnet-4-5-20250514',
name: 'Claude Sonnet 4.5',
description: 'Balanced performance and speed',
presetMapping: {
default: 'claude-sonnet-4-5-20250514',
opus: 'claude-opus-4-5-20250220',
sonnet: 'claude-sonnet-4-5-20250514',
haiku: 'claude-haiku-4-5-20250514',
},
},
{
id: 'claude-sonnet-4-20250514',
name: 'Claude Sonnet 4',
description: 'Previous generation Sonnet',
presetMapping: {
default: 'claude-sonnet-4-20250514',
opus: 'claude-opus-4-5-20250220',
sonnet: 'claude-sonnet-4-20250514',
haiku: 'claude-haiku-4-5-20250514',
},
},
{
id: 'claude-haiku-4-5-20250514',
name: 'Claude Haiku 4.5',
description: 'Fast and efficient',
},
],
},
};