cc-sdk 0.8.0

Rust SDK for Claude Code CLI with full interactive capabilities
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
# Account Information Retrieval

This guide explains how to retrieve and display Claude account information in your applications using the cc-sdk.

## Overview

The `get_account_info()` method allows you to programmatically retrieve the current Claude account details through multiple methods:

1. **Environment Variable** (`ANTHROPIC_USER_EMAIL`) - Most reliable for SDK mode
2. **Config File** - Reads from Claude CLI configuration
3. **CLI Query** - Interactive `/status` command (may not work in SDK mode)

This is useful for:
- Verifying the correct account is being used
- Displaying account info in application UIs
- Logging session information
- Debugging authentication issues

## ⚠️ Important Notes

### Which Account Does cc-sdk Use?

**cc-sdk uses the same account that Claude CLI is currently logged in with.**

- Claude CLI stores authentication at the **system level** (in `~/.config/claude/` or similar)
- All terminal sessions share the **same authentication**
- When you use cc-sdk, it spawns the Claude CLI process, which uses the currently logged-in account
- **Not session-specific**: The account is system-wide, not per-terminal

**Example:**
```bash
# In any terminal, check current Claude account
echo "/status" | claude

# cc-sdk will use the SAME account
cargo run --example check_current_account
```

### ANTHROPIC_USER_EMAIL Purpose

The `ANTHROPIC_USER_EMAIL` environment variable is **NOT for authentication**. It's for:

1. **SDK identification**: Helps cc-sdk identify which account is being used (since `/status` doesn't work reliably in SDK mode)
2. **Logging/debugging**: Track which account made which API calls
3. **Multi-account scenarios**: Label SDK operations by account

**It does NOT change which account is used** - that's determined by Claude CLI's authentication.

### Switching Accounts

To use a different account with cc-sdk:

```bash
# Method 1: Interactive login (changes system-wide account)
claude
# Then use /login command in the interactive session

# Method 2: Logout and re-login
# (This is a Claude CLI operation, not cc-sdk specific)
```

### Recommended Setup

For reliable SDK operation:

```bash
export ANTHROPIC_USER_EMAIL="your-email@example.com"
```

This should match the account Claude CLI is logged in with.

## Basic Usage

```rust
use cc_sdk::{ClaudeSDKClient, ClaudeCodeOptions, Result};

#[tokio::main]
async fn main() -> Result<()> {
    let mut client = ClaudeSDKClient::new(ClaudeCodeOptions::default());

    // Connect to Claude CLI
    client.connect(None).await?;

    // Get account information
    let account_info = client.get_account_info().await?;
    println!("Account: {}", account_info);

    client.disconnect().await?;
    Ok(())
}
```

## How It Works

The `get_account_info()` method attempts to retrieve account information through multiple fallback methods:

1. **Environment Variable Check**: First checks `ANTHROPIC_USER_EMAIL` environment variable
2. **Config File Reading**: Attempts to read from Claude CLI config files at:
   - `~/.config/claude/config.json`
   - `~/.claude/config.json`
3. **CLI Query**: As a last resort, sends `/status` command to Claude CLI

**Note**: This method requires an active connection. Make sure to call `connect()` before calling `get_account_info()`.

## Examples

### Example 1: Using Environment Variable (Recommended)

```rust
use cc_sdk::{ClaudeSDKClient, ClaudeCodeOptions, Result};

#[tokio::main]
async fn main() -> Result<()> {
    // Set environment variable before creating client
    std::env::set_var("ANTHROPIC_USER_EMAIL", "user@example.com");

    let mut client = ClaudeSDKClient::new(ClaudeCodeOptions::default());
    client.connect(None).await?;

    match client.get_account_info().await {
        Ok(info) => println!("✅ Account: {}", info),
        Err(e) => eprintln!("❌ Error: {}", e),
    }

    client.disconnect().await?;
    Ok(())
}
```

Or set it from your shell before running:

```bash
export ANTHROPIC_USER_EMAIL="user@example.com"
cargo run --example account_info
```

### Example 2: Simple Account Info Display with Fallback

```rust
use cc_sdk::{ClaudeSDKClient, ClaudeCodeOptions, Result};

#[tokio::main]
async fn main() -> Result<()> {
    let mut client = ClaudeSDKClient::new(ClaudeCodeOptions::default());
    client.connect(None).await?;

    match client.get_account_info().await {
        Ok(info) => println!("✅ Account: {}", info),
        Err(e) => {
            eprintln!("❌ Error: {}", e);
            eprintln!("Tip: Set ANTHROPIC_USER_EMAIL environment variable");
        }
    }

    client.disconnect().await?;
    Ok(())
}
```

### Example 2: Session Startup with Account Verification

```rust
use cc_sdk::{ClaudeSDKClient, ClaudeCodeOptions, Result};

async fn start_session_with_verification() -> Result<()> {
    let options = ClaudeCodeOptions::builder()
        .model("claude-sonnet-4-5-20250929")
        .build();

    let mut client = ClaudeSDKClient::new(options);

    println!("🔌 Connecting...");
    client.connect(None).await?;

    // Display account info at session start
    println!("📋 Verifying account...");
    if let Ok(account_info) = client.get_account_info().await {
        println!("Current account:\n{}", account_info);
    }

    // Continue with session...

    Ok(())
}
```

### Example 3: Error Handling

```rust
use cc_sdk::{ClaudeSDKClient, ClaudeCodeOptions, Result, SdkError};

async fn get_account_with_fallback() -> Result<String> {
    let mut client = ClaudeSDKClient::new(ClaudeCodeOptions::default());

    client.connect(None).await?;

    match client.get_account_info().await {
        Ok(info) => Ok(info),
        Err(SdkError::InvalidState { message }) => {
            eprintln!("Warning: {}", message);
            Ok("Account info not available".to_string())
        }
        Err(e) => Err(e),
    }
}
```

### Example 4: Logging Account Info

```rust
use cc_sdk::{ClaudeSDKClient, ClaudeCodeOptions, Result};
use tracing::{info, error};

#[tokio::main]
async fn main() -> Result<()> {
    // Initialize logging
    tracing_subscriber::fmt::init();

    let mut client = ClaudeSDKClient::new(ClaudeCodeOptions::default());
    client.connect(None).await?;

    match client.get_account_info().await {
        Ok(account_info) => {
            info!("Session started with account: {}", account_info);
        }
        Err(e) => {
            error!("Failed to retrieve account info: {}", e);
        }
    }

    // Continue with application logic...

    Ok(())
}
```

### Example 5: Multi-Account Verification

```rust
use cc_sdk::{ClaudeSDKClient, ClaudeCodeOptions, Result};

async fn verify_expected_account(expected_email: &str) -> Result<bool> {
    let mut client = ClaudeSDKClient::new(ClaudeCodeOptions::default());
    client.connect(None).await?;

    let account_info = client.get_account_info().await?;
    let is_correct = account_info.contains(expected_email);

    if !is_correct {
        eprintln!("⚠️  Warning: Expected account '{}', but got:", expected_email);
        eprintln!("{}", account_info);
    }

    client.disconnect().await?;
    Ok(is_correct)
}

#[tokio::main]
async fn main() -> Result<()> {
    let expected = "user@example.com";

    if verify_expected_account(expected).await? {
        println!("✅ Correct account verified");
    } else {
        println!("❌ Account mismatch detected");
    }

    Ok(())
}
```

## Common Use Cases

### 1. Application Startup Verification

Display account information when your application starts to ensure users are logged in with the correct account:

```rust
async fn initialize_app() -> Result<()> {
    let mut client = ClaudeSDKClient::new(ClaudeCodeOptions::default());
    client.connect(None).await?;

    println!("╔════════════════════════════════════╗");
    println!("║  Application Starting...          ║");
    println!("╠════════════════════════════════════╣");

    if let Ok(account) = client.get_account_info().await {
        println!("║  Account: {:<24}║", account);
    }

    println!("╚════════════════════════════════════╝");

    Ok(())
}
```

### 2. Debug Logging

Include account information in debug logs:

```rust
use tracing::debug;

async fn start_debug_session() -> Result<()> {
    let mut client = ClaudeSDKClient::new(ClaudeCodeOptions::default());
    client.connect(None).await?;

    if let Ok(account) = client.get_account_info().await {
        debug!("Session account: {}", account);
    }

    // Continue with session...
    Ok(())
}
```

### 3. Cost Tracking by Account

Track costs per account for billing or analytics:

```rust
use cc_sdk::token_tracker::BudgetLimit;

async fn track_usage_by_account() -> Result<()> {
    let mut client = ClaudeSDKClient::new(ClaudeCodeOptions::default());
    client.connect(None).await?;

    let account = client.get_account_info().await?;

    // Set budget tracking
    client.set_budget_limit(
        BudgetLimit::with_cost(10.0),
        Some(move |msg| {
            eprintln!("Account '{}': {}", account, msg);
        })
    ).await;

    // Continue with work...

    let usage = client.get_usage_stats().await;
    println!("Account '{}' used ${:.4}", account, usage.total_cost_usd);

    Ok(())
}
```

## Error Handling

The `get_account_info()` method can return the following errors:

### InvalidState Error

Occurs when the client is not connected:

```rust
match client.get_account_info().await {
    Err(SdkError::InvalidState { message }) => {
        eprintln!("Connection error: {}", message);
        // Make sure to call connect() first
    }
    _ => {}
}
```

### Empty Response

If no account information is returned:

```rust
match client.get_account_info().await {
    Ok(info) if info.is_empty() => {
        eprintln!("No account information available");
    }
    Ok(info) => println!("Account: {}", info),
    Err(e) => eprintln!("Error: {}", e),
}
```

## Best Practices

1. **Call After Connect**: Always ensure the client is connected before calling `get_account_info()`
   ```rust
   client.connect(None).await?;
   let account = client.get_account_info().await?;
   ```

2. **Handle Errors Gracefully**: Account info retrieval may fail; handle errors appropriately
   ```rust
   let account = client.get_account_info().await
       .unwrap_or_else(|_| "Unknown".to_string());
   ```

3. **Cache When Appropriate**: The account doesn't change during a session, so you can cache it
   ```rust
   let account_info = client.get_account_info().await?;
   // Store and reuse account_info instead of calling again
   ```

4. **Use for Verification**: Verify expected accounts in production environments
   ```rust
   let account = client.get_account_info().await?;
   assert!(account.contains("production@company.com"),
           "Wrong account! Expected production account.");
   ```

## Limitations

- Requires an active connection to Claude CLI
- The `/status` command must be supported by your Claude CLI version
- Account information format may vary depending on Claude CLI version
- Network latency may affect retrieval time

## See Also

- [Client API Documentation]https://docs.rs/cc-sdk/latest/cc_sdk/struct.ClaudeSDKClient.html
- [Examples Directory]../examples/ - Complete working examples
- [Error Handling Guide]../README.md#error-handling