Files
ccs/docs/system-architecture/provider-flows.md
T
BbChip0103andClaude Opus 4.6 fedb4d4cde feat(api): add Anthropic direct API key support
Support native Anthropic API keys (sk-ant-...) via `ccs api create --preset anthropic`.
Profiles use ANTHROPIC_API_KEY env var without BASE_URL, letting Claude CLI
authenticate natively with x-api-key header instead of proxy Bearer token.

- Add anthropic preset to provider catalog
- Branch profile-writer env structure (native vs proxy)
- Add validateAnthropicKey() preflight with x-api-key header
- Auto-detect api.anthropic.com URL in interactive flow
- Fix hasApiKey/isConfigured to recognize ANTHROPIC_API_KEY
- Update delegation-validator for native mode profiles
- Add Droid target API key fallback (ANTHROPIC_API_KEY)

Closes #688

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 13:13:10 +09:00

18 KiB

Provider Integration Flows

Last Updated: 2026-02-16

Detailed provider integration flows including CLIProxyAPI, GLMT proxy, remote CLIProxy, quota management, and authentication.


CLIProxyAPI Flow

Overview

CLIProxyAPI is a local OAuth proxy binary that enables seamless integration with multiple AI providers. CCS manages the binary and configuration automatically.

+===========================================================================+
|                      CLIProxyAPI Integration                               |
+===========================================================================+

  Claude CLI
        |
        | ANTHROPIC_BASE_URL = localhost:XXXX
        v
  +------------------+
  |   CLIProxyAPI    |  Local proxy binary (CLIProxyAPIPlus for kiro/ghcp)
  |   (binary)       |
  +------------------+
        |
        +---> OAuth Authentication
        |           |
        |           +---> Authorization Code Flow (port-based)
        |           |         - Gemini, Codex, Antigravity, Kiro (port 9876)
        |           |         - Opens browser for user auth
        |           |         - Callback to localhost:PORT
        |           |
        |           +---> Device Code Flow (no port needed)
        |                     - GitHub Copilot (ghcp)
        |                     - User enters code at github.com/login/device
        |                     - Polls for token completion
        |           |
        |           v
        |     +------------------+
        |     |   OAuth Server   |  Browser-based auth
        |     +------------------+
        |
        +---> Request Transformation
        |           |
        |           v
        |     Anthropic Format --> Provider Format
        |
        +---> Image Analysis Hook (v7.34)
        |           |
        |           v
        |     Vision Model Proxying (gemini, codex, agy, clipproxy)
        |           - Auto-injected via claude-hooks
        |           - Skip for Claude Sub accounts (native vision)
        |           - Fallback with deprecated block-image-read
        |
        +---> Provider APIs
                    |
                    +---> Google (Gemini)
                    +---> GitHub (Codex)
                    +---> Antigravity (AGY)
                    +---> AWS Kiro (Claude-powered)
                    +---> GitHub Copilot (ghcp)
                    +---> OpenAI-compatible endpoints

Supported Hardcoded Providers

Provider ID Auth Method Port Binary
Gemini gemini Authorization Code 9876 CLIProxyAPI
Codex codex Authorization Code 9876 CLIProxyAPI
Antigravity agy Authorization Code 9876 CLIProxyAPI
Kiro (AWS) kiro Method-aware (default: Device Code) 9876 CLIProxyAPIPlus
GitHub Copilot ghcp Device Code none CLIProxyAPIPlus

Hardcoded Provider Detection

CCS detects hardcoded providers via profile-detector.ts and routes through execClaudeWithCLIProxy().

// Profile name matching
const hardcodedProviders = ['gemini', 'codex', 'agy', 'kiro', 'ghcp'];

if (hardcodedProviders.includes(profileName)) {
  return execClaudeWithCLIProxy(claudeCli, profileName, args);
}

GLMT Proxy Flow

Overview

GLMT proxy enables seamless integration with GLM-compatible APIs (Z.AI, Kimi, OpenRouter, etc.) using a Node.js-based embedded proxy.

+===========================================================================+
|                        GLMT Proxy Integration                              |
+===========================================================================+

  Claude CLI
        |
        | ANTHROPIC_BASE_URL = localhost:XXXX
        v
  +------------------+
  |   GLMT Proxy     |  Embedded Node.js proxy (src/glmt/)
  |   (glmt-proxy.ts)|
  +------------------+
        |
        v
  +------------------+
  | Delta Accumulator|  Stream transformation
  +------------------+
        |
        v
  +------------------+
  |   Pipeline       |  Request/Response transformation
  +------------------+
        |
        v
  +------------------+
  |   GLM API        |  Z.AI / Kimi API
  +------------------+

Supported GLM Providers

Provider Config Key Endpoint Auth
Z.AI (GLM) glmt https://open.bigmodel.cn/api/paas/v4/ API key
Kimi kimi https://api.moonshot.cn/v1/ API key
OpenRouter openrouter https://openrouter.ai/api/v1/ API key

Note for config/base-kimi.settings.json: the default base URL is http://127.0.0.1:8317/api/provider/kimi (local CLIProxy route). For direct Moonshot API access, override ANTHROPIC_BASE_URL to https://api.moonshot.cn/v1/.

GLMT Profile Detection

CCS detects GLMT profiles and routes through execClaudeWithProxy():

// Settings-based profile detection
const settings = loadSettings(profileName);
if (settings.env?.ANTHROPIC_BASE_URL?.includes('glm') ||
    settings.env?.ANTHROPIC_BASE_URL?.includes('moonshot') ||
    settings.env?.ANTHROPIC_BASE_URL?.includes('openrouter')) {
  return execClaudeWithProxy(claudeCli, profileName, args);
}

Remote CLIProxy Flow (v7.1)

Overview

Remote CLIProxy enables CCS to delegate authentication to a central proxy server instead of spawning a local binary.

+===========================================================================+
|                    Remote CLIProxy Architecture (v7.1)                    |
+===========================================================================+

  Config Resolution (proxy-config-resolver.ts)
        |
        +---> Priority: CLI flags > ENV vars > config.yaml > defaults
        |
        v
  +------------------+
  | ResolvedProxyConfig |
  | mode: local|remote |
  +------------------+
        |
        +---> [mode = local] ---> Spawn local CLIProxyAPI binary
        |                              |
        |                              v
        |                        localhost:8317
        |
        +---> [mode = remote] ---> Connect to remote server
                                       |
                                       v
                                 +------------------+
                                 | Health Check     |  remote-proxy-client.ts
                                 | /v1/models       |  2s timeout
                                 +------------------+
                                       |
                                       +---> [reachable] ---> Use remote
                                       |                           |
                                       |                           v
                                       |                      protocol://host:port
                                       |
                                       +---> [unreachable] ---> Fallback decision
                                                                     |
                                       +-----------------------------+
                                       |
                                       +---> [fallbackEnabled] ---> Start local
                                       |
                                       +---> [remoteOnly] ---> Fail with error

  CLI Flags:
    --proxy-host <host>         Remote hostname/IP
    --proxy-port <port>         Port (default: 8317 HTTP, 443 HTTPS)
    --proxy-protocol <proto>    http or https
    --proxy-auth-token <token>  Bearer authentication
    --local-proxy               Force local mode
    --remote-only               Fail if remote unreachable

  Environment Variables:
    CCS_PROXY_HOST              Remote hostname
    CCS_PROXY_PORT              Remote port
    CCS_PROXY_PROTOCOL          Protocol (http/https)
    CCS_PROXY_AUTH_TOKEN        Auth token
    CCS_PROXY_FALLBACK_ENABLED  Enable fallback (true/false)

Configuration Resolution

// proxy-config-resolver.ts: Priority order
const resolved = {
  ...DEFAULT_CONFIG,                    // 4. Defaults (lowest)
  ...yamlConfig,                        // 3. config.yaml
  ...envConfig,                         // 2. Environment variables
  ...cliFlags,                          // 1. CLI flags (highest)
};

Health Check

// remote-proxy-client.ts
async function checkRemoteProxyHealth(config: ResolvedProxyConfig): Promise<boolean> {
  try {
    const url = `${config.protocol}://${config.host}:${config.port}/v1/models`;
    const response = await fetch(url, {
      headers: config.authToken ? { Authorization: `Bearer ${config.authToken}` } : {},
      timeout: 2000,
    });
    return response.ok;
  } catch {
    return false;
  }
}

Quota Management Flow (v7.14)

Overview

Hybrid quota management enables automatic detection of exhausted accounts and failover to next available account.

+===========================================================================+
|                      Quota Management Architecture (v7.14)                |
+===========================================================================+

  Pre-Flight Check (before session start)
        |
        v
  +------------------+
  | quota-manager.ts |  Hybrid quota management
  +------------------+
        |
        +---> Get all active accounts for provider
        |
        +---> For each account:
        |           |
        |           v
        |     +------------------+
        |     | quota-fetcher.ts |  Provider-specific API calls
        |     +------------------+
        |           |
        |           +---> Check isPaused flag --> Skip if paused
        |           |
        |           +---> Fetch quota from provider API
        |           |       - Gemini: /models endpoint
        |           |       - Codex: /api/v1/account
        |           |       - Kiro: /api/usage
        |           |
        |           +---> Detect tier (free/paid/unknown)
        |           |
        |           +---> Check exhaustion status
        |
        +---> Select best account (not paused, not exhausted)
        |
        +---> Auto-failover to next account if current exhausted

  CLI Commands:
    ccs cliproxy pause <account>   --> Set isPaused=true in account-manager
    ccs cliproxy resume <account>  --> Set isPaused=false
    ccs cliproxy status [account]  --> Display quota + tier info

  Dashboard UI:
    - Pause/Resume toggle per account
    - Tier badge (free/paid/unknown)
    - Quota usage display

Account Selection Algorithm

// quota-manager.ts: Best account selection
function selectBestAccount(accounts: AccountInfo[]): AccountInfo | null {
  // Priority:
  // 1. Not paused
  // 2. Not exhausted
  // 3. Paid tier over free tier
  // 4. Highest remaining quota

  return accounts
    .filter(acc => !acc.isPaused && !acc.isExhausted)
    .sort((a, b) => {
      if (a.tier !== b.tier) return (a.tier === 'paid' ? -1 : 1);
      return (b.remainingQuota || 0) - (a.remainingQuota || 0);
    })[0] || null;
}

Authentication Flow

OAuth Providers - Authorization Code Flow

Providers: Gemini, Codex, Antigravity, Kiro (aws method)

+===========================================================================+
|              OAuth - Authorization Code Flow (Port-based)                 |
+===========================================================================+

  1. User runs: ccs gemini
        |
        v
  2. Check token cache (~/.ccs/cliproxy/auth/)
        |
        +---> [Valid token] ---> Use cached token
        |
        +---> [No/Expired token]
                    |
                    v
  3. Start local OAuth server (localhost:9876)
        |
        v
  4. Open browser with OAuth request
        |     https://oauth-provider/authorize?redirect_uri=http://localhost:9876/callback
        v
  5. User authorizes in browser
        |
        v
  6. OAuth provider redirects to localhost:9876/callback?code=XXXX
        |
        v
  7. Exchange auth code for access token
        |
        v
  8. Cache token locally (~/.ccs/cliproxy/auth/gemini.json)
        |
        v
  9. Proceed with Claude CLI

OAuth Providers - Device Code Flow

Providers: GitHub Copilot (ghcp)

+===========================================================================+
|               OAuth - Device Code Flow (No Port Needed)                   |
+===========================================================================+

  1. User runs: ccs ghcp
        |
        v
  2. Check token cache (~/.ccs/cliproxy/auth/)
        |
        +---> [Valid token] ---> Use cached token
        |
        +---> [No/Expired token]
                    |
                    v
  3. Request device code from GitHub
        |
        v
  4. Display user code + verification URL
        |     "Enter code XXXX-XXXX at github.com/login/device"
        v
  5. User opens URL in browser and enters code
        |
        v
  6. Poll GitHub for token completion
        |
        v
  7. Receive and cache token locally
        |
        v
  8. Proceed with Claude CLI

Kiro OAuth - Method-Aware Flow

Supported methods:

  • aws: Device Code (default, AWS org friendly)
  • aws-authcode: Authorization Code via CLI flow
  • google: Social OAuth via management API
  • github: Social OAuth via management API (Dashboard flow)
+===========================================================================+
|                    Kiro OAuth - Method-Aware Flow                         |
+===========================================================================+

  Configuration:
    ccs_profile:
      target: claude
      cliproxy:
        provider: kiro
        kiro_method: aws  # or aws-authcode, google, github

  Flow:
    Device Code (aws)
      → /start endpoint (no callback port)
      → Opens browser
      → User enters code
      → Poll /status

    Authorization Code (aws-authcode, google, github)
      → /start-url endpoint
      → Returns auth_url
      → User visits URL
      → Callback handled
      → Poll /status for completion

  Key behavior:
    - Device Code method uses /start route (no callback port)
    - Callback/social methods use /start-url + status polling
    - Some management flows return state first, auth_url later

API Key Profiles (GLM, Kimi)

+===========================================================================+
|                     API Key Profile (Non-OAuth)                          |
+===========================================================================+

  1. User configures API key in settings
        |
        v
  2. Key stored in ~/.ccs/<profile>.settings.json
        |
        v
  3. Profile detection: APIKeyProfile
        |
        v
  4. Key passed via ANTHROPIC_AUTH_TOKEN env var
        |
        v
  5. Target adapter (Claude/Droid) handles delivery
        |
        └─ Claude: env var
        └─ Droid: config file (~/.factory/settings.json)

Anthropic Direct API Key

+===========================================================================+
|                  Anthropic Direct API Key (Native Auth)                   |
+===========================================================================+

  1. User creates profile: ccs api create --preset anthropic
        |
        v
  2. Key stored in ~/.ccs/<profile>.settings.json
        |  env: { ANTHROPIC_API_KEY: "sk-ant-..." }
        |  (NO ANTHROPIC_BASE_URL, NO ANTHROPIC_AUTH_TOKEN)
        v
  3. Profile detection: settings-based
        |
        v
  4. Key passed via ANTHROPIC_API_KEY env var
        |  Claude CLI uses native endpoint (api.anthropic.com)
        v
  5. Claude CLI authenticates with x-api-key header

  Detection logic (profile-writer.ts):
    - apiKey.startsWith('sk-ant-') -> native mode
    - baseUrl.includes('api.anthropic.com') -> native mode
    - Otherwise -> proxy mode (existing behavior)

Image Analysis Hook Flow (v7.34)

Overview

Image Analysis Hook enables vision model proxying through CLIProxy with automatic injection for all profile types.

+===========================================================================+
|                    Image Analysis Hook Flow (v7.34)                       |
+===========================================================================+

  Claude CLI with image input
        |
        v
  Hook Installer (ensureProfileHooks)
        |
        +---> Check ~/.claude/hooks/openai-vision-hook.cjs exists
        |
        +---> If missing: auto-install via image-analyzer-hook-installer
        |
        v
  Hook Configuration
        |
        +---> Set ANTHROPIC_IMAGE_HOOK_URL
        |           (proxy endpoint URL)
        |
        v
  Claude CLI processes image request
        |
        v
  Hook intercepts image request
        |
        v
  Vision Model Proxying (via CLIProxyAPI)
        |
        +---> Gemini, Codex, AGY support vision
        |
        +---> Kiro (Claude native vision)
        |
        +---> Skip for Claude Sub accounts (native vision)
        |
        v
  Vision response returned to Claude CLI

Hook Environment

// getImageAnalysisHookEnv()
{
  ANTHROPIC_IMAGE_HOOK_URL: 'http://localhost:8317/api/image-analysis',
  // or for remote proxy:
  ANTHROPIC_IMAGE_HOOK_URL: 'https://proxy.example.com:8317/api/image-analysis',
}

Provider Support

Provider Vision Support Notes
Gemini Via CLIProxy image analysis
Codex Via CLIProxy image analysis
Antigravity Via CLIProxy image analysis
Kiro Native Claude vision (no proxy needed)
Copilot Not supported
GLM/Kimi Requires direct API implementation

Session Tracking

All execution paths record session metadata including target CLI used:

{
  profileName: 'gemini',
  profileType: 'clipproxy',
  provider: 'google-gemini',
  targetCli: 'claude',        // NEW: which target was used
  timestamp: '2026-02-16T10:40:00Z',
  duration: 12345,
  exitCode: 0,
  model: 'claude-opus-4-6',
}

This enables analytics on target CLI usage and adoption.