> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ccs.kaitran.ca/llms.txt
> Use this file to discover all available pages before exploring further.

# Token Management

> Manage OAuth tokens, API keys, and credentials across CCS profiles

## Overview

CCS implements sophisticated token management to provide seamless authentication:

* **Proactive Refresh** - Tokens renewed 5min before expiry (no interruptions)
* **Session Persistence** - Reference counting tracks active sessions
* **Automatic Recovery** - Handles network errors, token expiry gracefully
* **Multi-Account Support** - Separate tokens per account

## Token Lifecycle

### OAuth Flow (Initial Authentication)

```
┌─────────┐     ┌─────────┐     ┌──────────┐     ┌─────────┐
│ ccs CLI │────▶│ Browser │────▶│ Provider │────▶│ Consent │
└─────────┘     └─────────┘     │  OAuth   │     │  Page   │
     ▲                           └──────────┘     └─────────┘
     │                                 │
     │          Access Token           │
     │        + Refresh Token          │
     └─────────────────────────────────┘
```

**Files Created:**

* `~/.ccs/cliproxy/gemini-{account}.json` - Access + refresh tokens
* `~/.ccs/cliproxy/sessions.json` - Session metadata

### Proactive Token Refresh

CCS checks token expiry **before every request**:

```
Token expires at: 14:00:00
Current time:     13:54:00
Time remaining:   6 minutes

Action: Refresh now (threshold: 5 minutes)
```

**Why 5 minutes?**

* Accounts for network latency
* Prevents mid-request expiry
* Ensures smooth user experience

**Refresh Process:**

1. Send refresh\_token to provider
2. Receive new access\_token (expires in 1 hour)
3. Receive new refresh\_token (expires in 7 days)
4. Update `{provider}-{account}.json`
5. Continue with original request

## Session Persistence

### Session Files

**Location:** `~/.ccs/cliproxy/sessions.json`

**Structure:**

```json theme={null}
{
  "gemini": {
    "primary": {
      "email": "user@gmail.com",
      "tokenPath": "~/.ccs/cliproxy/gemini-primary.json",
      "expiresAt": "2026-01-12T14:00:00Z",
      "refreshedAt": "2026-01-05T13:55:00Z",
      "referenceCount": 2,
      "lastError": null
    }
  }
}
```

**Key Fields:**

| Field            | Purpose                                    |
| ---------------- | ------------------------------------------ |
| `expiresAt`      | Access token expiry (1 hour from issue)    |
| `refreshedAt`    | Last refresh timestamp                     |
| `referenceCount` | Number of active sessions using this token |
| `lastError`      | Most recent error (for debugging)          |

### Reference Counting

**Purpose:** Track multiple active CCS sessions reusing the same CLIProxy proxy/session state

**How it works:**

```bash theme={null}
# Terminal 1
ccs codex "Task 1"  # referenceCount: 1

# Terminal 2 (while Terminal 1 running)
ccs codex "Task 2"  # referenceCount: 2

# Terminal 1 completes
# referenceCount: 1

# Terminal 2 completes
# referenceCount: 0
```

**Why it matters:**

* Prevents premature token cleanup
* Supports shared proxy sessions without tearing down token state too early
* Tracks active usage

<Note>
  This is not the same thing as full per-session isolation. Multiple sessions
  can reuse the same CLIProxy session/proxy state while still sharing provider
  runtime state.
</Note>

### Session Cleanup

**Automatic cleanup when:**

* `referenceCount` reaches 0
* Session idle for >7 days
* Manual logout via `ccs codex --logout`

**Cleanup process:**

1. Revoke refresh token with provider
2. Delete token file
3. Remove from `sessions.json`
4. Update `accounts.json` registry

## File Structure

### Token Files

**Per-account token storage:**

```bash theme={null}
~/.ccs/cliproxy/
├── gemini-primary.json       # First account tokens
├── gemini-work.json          # Second account tokens
├── codex-default.json        # Codex tokens
└── agy-enterprise.json       # Antigravity tokens
```

**Token file format:**

```json theme={null}
{
  "access_token": "ya29.a0AfB...",
  "refresh_token": "1//0gZ...",
  "expires_at": 1704463200000,
  "token_type": "Bearer",
  "scope": "email profile openid"
}
```

### Account Registry

**Location:** `~/.ccs/cliproxy/accounts.json`

**Purpose:** Map nicknames to email addresses

```json theme={null}
{
  "gemini": {
    "primary": {
      "email": "user@gmail.com",
      "tokenPath": "~/.ccs/cliproxy/gemini-primary.json",
      "createdAt": "2026-01-01T10:00:00Z",
      "lastUsed": "2026-01-05T14:30:00Z"
    },
    "work": {
      "email": "work@company.com",
      "tokenPath": "~/.ccs/cliproxy/gemini-work.json",
      "createdAt": "2026-01-03T09:00:00Z",
      "lastUsed": "2026-01-05T11:15:00Z"
    }
  }
}
```

### Config Reference

**Location:** `~/.ccs/config.yaml`

**Relevant sections:**

```yaml theme={null}
cliproxy:
  oauth_accounts:
    primary: user@gmail.com
    work: work@company.com

  variants:
    gemini:
      account: primary  # Default account for gemini
```

## Manual Token Operations

<Steps>
  <Step title="View Token Status">
    Use the `tokens` command to inspect current state:

    ```bash theme={null}
    ccs tokens
    ```

    **Output:**

    ```
    [i] OAuth Token Status

    Gemini:
      primary (user@gmail.com)
        Status: Valid
        Expires: 2026-01-05 15:30:00 (in 25 minutes)
        Last Refreshed: 2026-01-05 14:25:00
        Active Sessions: 1

      work (work@company.com)
        Status: Valid
        Expires: 2026-01-05 16:00:00 (in 55 minutes)
        Last Refreshed: 2026-01-05 14:50:00
        Active Sessions: 0

    Codex:
      default (dev@example.com)
        Status: Expired
        Expires: 2026-01-05 13:00:00 (1 hour ago)
        Last Refreshed: 2026-01-05 12:00:00
        Active Sessions: 0
        Note: Will auto-refresh on next use
    ```
  </Step>

  <Step title="Force Token Refresh">
    Manually trigger refresh without waiting for threshold:

    ```bash theme={null}
    ccs tokens --refresh gemini
    ```

    **Use cases:**

    * Debugging refresh issues
    * Pre-warming tokens before long task
    * Recovering from network errors
  </Step>

  <Step title="Clear Expired Tokens">
    Remove tokens that can't be refreshed:

    ```bash theme={null}
    ccs tokens --cleanup
    ```

    This removes:

    * Tokens expired >7 days (refresh token expired)
    * Tokens with persistent errors
    * Orphaned session entries
  </Step>

  <Step title="Export Tokens (Advanced)">
    For migration or backup:

    ```bash theme={null}
    ccs tokens --export gemini > gemini-backup.json
    ```

    **Security warning:** Exported files contain sensitive tokens. Encrypt before storage:

    ```bash theme={null}
    gpg -c gemini-backup.json
    rm gemini-backup.json
    ```
  </Step>

  <Step title="Import Tokens (Advanced)">
    Restore from backup or migrate between machines:

    ```bash theme={null}
    # Decrypt first
    gpg -d gemini-backup.json.gpg > gemini-backup.json

    # Import
    ccs tokens --import gemini < gemini-backup.json

    # Clean up
    shred -u gemini-backup.json
    ```

    **Note:** Only works for same provider. Cross-provider imports not supported.
  </Step>
</Steps>

## Troubleshooting

### UND\_ERR\_SOCKET Error

**Full error:**

```
[X] Network error: UND_ERR_SOCKET - The socket connection was aborted
```

**Common causes:**

1. **Network interruption during refresh**
   ```bash theme={null}
   # Check if provider auth endpoint is reachable
   curl -I https://auth.openai.com

   # Force new auth flow
   ccs codex --auth
   ```

2. **Proxy interference**
   ```bash theme={null}
   # Bypass proxy for OAuth
   unset HTTP_PROXY HTTPS_PROXY

   # Re-authenticate
   ccs codex --auth
   ```

3. **Firewall blocking OAuth endpoints**
   ```bash theme={null}
   # Test connectivity
   curl -v https://auth.openai.com/authorize

   # Whitelist required domains:
   # - auth.openai.com
   ```

4. **Concurrent refresh attempts**

   * Multiple sessions trying to refresh simultaneously
   * Session files locked by another process

   **Solution:**

   ```bash theme={null}
   # Wait a few seconds and retry
   sleep 5 && ccs codex "Task"
   ```

### Token Refresh Fails

**Symptom:** `[X] Auth error: Failed to refresh token`

**Causes:**

1. **Refresh token expired (>7 days)**
   ```bash theme={null}
   # Check session age
   stat ~/.ccs/cliproxy/sessions.json

   # Re-authenticate
   ccs codex --auth
   ```

2. **Provider revoked access**

   * User revoked app permissions
   * Provider detected suspicious activity

   **Solution:**

   ```bash theme={null}
   # Clear old tokens
   ccs codex --logout

   # Fresh authentication
   ccs codex --auth
   ```

3. **Clock skew**
   ```bash theme={null}
   # Sync system time
   sudo ntpdate pool.ntp.org

   # Or manually set timezone
   sudo timedatectl set-timezone America/New_York
   ```

### Session File Corruption

**Symptom:** `[X] Config error: Failed to parse sessions.json`

**Recovery steps:**

```bash theme={null}
# Backup corrupted file
cp ~/.ccs/cliproxy/sessions.json ~/.ccs/cliproxy/sessions.json.backup

# Remove corrupted file
rm ~/.ccs/cliproxy/sessions.json

# Re-authenticate (recreates session file)
ccs codex --auth
```

**Prevention:** Enable debug logging to catch issues early:

```bash theme={null}
export CCS_DEBUG=1
ccs codex "Test"
```

### Multiple Accounts Conflict

**Symptom:** Wrong account used despite `--use` flag

**Cause:** Default account set in config overrides flag

**Solution:**

```bash theme={null}
# Verify default account
grep -A5 "variants:" ~/.ccs/config.yaml

# Update default permanently
ccs codex --use correct-account

# Or override per-session
ccs codex --use correct-account "Task"
```

### Token Not Found After Re-Auth

**Symptom:** `[X] Profile error: Account 'xyz' not found`

**Cause:** Account registry out of sync with token files

**Solution:**

```bash theme={null}
# Rebuild account registry
ccs tokens --rebuild

# Or manually verify files
ls -la ~/.ccs/cliproxy/*.json
cat ~/.ccs/cliproxy/accounts.json
```

## Advanced Patterns

### Pre-Warming Tokens

For long-running tasks, refresh tokens before starting:

```bash theme={null}
#!/bin/bash
# Pre-warm all accounts
ccs tokens --refresh gemini
ccs tokens --refresh codex

# Now run long task without interruption
ccs codex "Analyze entire codebase in /project"
```

### Monitoring Token Health

Create a cron job to check token status:

```bash theme={null}
#!/bin/bash
# check-tokens.sh

STATUS=$(ccs tokens --json)
EXPIRED=$(echo "$STATUS" | jq -r '.[] | select(.status == "expired") | .account')

if [ -n "$EXPIRED" ]; then
  echo "⚠️  Expired tokens detected: $EXPIRED"
  # Send notification
  curl -X POST https://hooks.slack.com/... -d "{\"text\": \"CCS tokens expired: $EXPIRED\"}"
fi
```

```cron theme={null}
# Crontab entry (check daily at 9 AM)
0 9 * * * /path/to/check-tokens.sh
```

### Shared Team Tokens

For teams using [Remote Proxy](/tutorials/remote-proxy-deployment):

**On server:**

```bash theme={null}
# Authenticate with team account
ccs codex --auth --nickname team-codex

# Verify token valid
ccs tokens --refresh team-codex
```

**Clients automatically inherit server's tokens** - no local auth needed.

## Environment Variables

| Variable                     | Purpose                          | Example                               |
| ---------------------------- | -------------------------------- | ------------------------------------- |
| `CCS_DEBUG`                  | Show token refresh logs          | `export CCS_DEBUG=1`                  |
| `CCS_SKIP_PREFLIGHT`         | Skip token validation            | `export CCS_SKIP_PREFLIGHT=1`         |
| `CCS_PROXY_FALLBACK_ENABLED` | Fallback behavior on token error | `export CCS_PROXY_FALLBACK_ENABLED=0` |

## Security Best Practices

### Protect Token Files

```bash theme={null}
# Set restrictive permissions
chmod 600 ~/.ccs/cliproxy/*.json

# Prevent accidental commits
echo "*.json" >> ~/.ccs/.gitignore
```

### Rotate Tokens Regularly

```bash theme={null}
# Logout all accounts
ccs codex --logout
ccs kimi --logout

# Re-authenticate with fresh tokens
ccs codex --auth
ccs kimi --auth
```

**Recommended:** Rotate every 30 days, or immediately if compromise suspected.

### Monitor Token Usage

Enable request logging to track token usage:

```yaml theme={null}
# ~/.ccs/config.yaml
cliproxy:
  logging:
    enabled: true
    request_log: true
```

**Logs location:** `~/.ccs/logs/cliproxy-requests.log`

## Next Steps

<CardGroup cols={2}>
  <Card title="Multi-Account Setup" icon="users" href="/tutorials/multi-account-setup">
    Configure and switch between multiple accounts
  </Card>

  <Card title="Headless CI/CD" icon="robot" href="/tutorials/headless-ci-cd">
    Use persistent sessions in automation workflows
  </Card>
</CardGroup>
