ultraclaude-agent 0.0.19 → 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,83 @@
1
+ import type { ClaudeOAuthCredentials, ClaudeProfile, ClaudeProfileActive, ClaudeAuthIdentity } from '@ultra-claude/shared';
2
+ declare const CREDENTIALS_FILE: string;
3
+ declare const PROFILES_DIR: string;
4
+ declare const BACKUPS_DIR: string;
5
+ declare const ACTIVE_FILE: string;
6
+ export { CREDENTIALS_FILE, PROFILES_DIR, BACKUPS_DIR, ACTIVE_FILE };
7
+ export declare function setSelfTriggerFlag(): void;
8
+ export declare function clearSelfTriggerFlag(): void;
9
+ export declare function isSelfTriggered(): boolean;
10
+ /**
11
+ * Run `claude auth status` to get the current account identity.
12
+ * Tries JSON output first, falls back to text parsing.
13
+ */
14
+ export declare function runClaudeAuthStatus(): Promise<ClaudeAuthIdentity | null>;
15
+ export declare function profilePath(name: string): string;
16
+ export declare function loadProfile(name: string): Promise<ClaudeProfile | null>;
17
+ export declare function saveProfile(profile: ClaudeProfile): Promise<void>;
18
+ export declare function deleteProfileFile(name: string): Promise<boolean>;
19
+ export declare function listProfiles(): Promise<ClaudeProfile[]>;
20
+ export declare function loadActiveProfile(): Promise<ClaudeProfileActive | null>;
21
+ export declare function setActiveProfile(name: string): Promise<void>;
22
+ export declare function clearActiveProfile(): Promise<void>;
23
+ export declare function readCredentialsFile(): Promise<ClaudeOAuthCredentials | null>;
24
+ /**
25
+ * Write credentials to ~/.claude/.credentials.json using atomic temp+rename.
26
+ * Pure write — does NOT manage the self-trigger flag. Callers that need to
27
+ * suppress watcher processing (e.g., switchProfile) must call setSelfTriggerFlag()
28
+ * themselves before calling this function.
29
+ */
30
+ export declare function writeCredentialsFile(credentials: ClaudeOAuthCredentials): Promise<void>;
31
+ export declare function createBackup(credentials: ClaudeOAuthCredentials): Promise<string>;
32
+ export declare function pruneBackups(maxAgeDays?: number): Promise<number>;
33
+ export interface ExpiryStatus {
34
+ label: string;
35
+ status: 'valid' | 'expiring' | 'expired';
36
+ }
37
+ export declare function getExpiryStatus(profile: ClaudeProfile): ExpiryStatus;
38
+ /**
39
+ * Switch to a named credential profile.
40
+ * Atomically writes the profile's credentials to ~/.claude/.credentials.json,
41
+ * updates active.json, then runs `claude auth status` to verify and refresh tokens.
42
+ */
43
+ export declare function switchProfile(name: string): Promise<{
44
+ success: boolean;
45
+ message: string;
46
+ }>;
47
+ /**
48
+ * Managed login flow: spawn `claude auth login`, wait for completion,
49
+ * capture identity via `claude auth status`, save as named profile.
50
+ */
51
+ export declare function loginProfile(name: string, email?: string): Promise<{
52
+ success: boolean;
53
+ message: string;
54
+ }>;
55
+ /**
56
+ * Save current credentials as a named profile without login.
57
+ */
58
+ export declare function saveCurrentAsProfile(name: string): Promise<{
59
+ success: boolean;
60
+ message: string;
61
+ }>;
62
+ /**
63
+ * Delete a named profile. Warns if it's the active profile.
64
+ */
65
+ export declare function deleteProfileByName(name: string): Promise<{
66
+ success: boolean;
67
+ message: string;
68
+ wasActive: boolean;
69
+ }>;
70
+ /**
71
+ * Get current Claude auth status for display.
72
+ */
73
+ export declare function getClaudeStatus(): Promise<{
74
+ success: boolean;
75
+ message: string;
76
+ identity?: ClaudeAuthIdentity;
77
+ }>;
78
+ /**
79
+ * Handle an external credential file change detected by the daemon watcher.
80
+ * Creates a backup, identifies the account, and updates the matching profile.
81
+ */
82
+ export declare function handleCredentialChange(): Promise<void>;
83
+ //# sourceMappingURL=claude-profiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-profiles.d.ts","sourceRoot":"","sources":["../src/claude-profiles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,499 @@
1
+ // Claude Code credential profile management
2
+ // Manages named profiles for Claude Code's OAuth credentials (~/.claude/.credentials.json)
3
+ import { homedir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { readFile, writeFile, rename, mkdir, unlink, readdir, stat } from 'node:fs/promises';
6
+ import { spawn, execFileSync } from 'node:child_process';
7
+ import { logger } from './logger.js';
8
+ // --- Paths ---
9
+ const CLAUDE_DIR = join(homedir(), '.claude');
10
+ const CREDENTIALS_FILE = join(CLAUDE_DIR, '.credentials.json');
11
+ const PROFILES_DIR = join(homedir(), '.claude', 'ultra', 'claude-profiles');
12
+ const BACKUPS_DIR = join(PROFILES_DIR, 'backups');
13
+ const ACTIVE_FILE = join(PROFILES_DIR, 'active.json');
14
+ export { CREDENTIALS_FILE, PROFILES_DIR, BACKUPS_DIR, ACTIVE_FILE };
15
+ // --- Self-trigger flag ---
16
+ // Set before switch-initiated credential writes, checked by the daemon watcher
17
+ // to skip processing for self-initiated changes.
18
+ let selfTriggered = false;
19
+ export function setSelfTriggerFlag() {
20
+ selfTriggered = true;
21
+ }
22
+ export function clearSelfTriggerFlag() {
23
+ selfTriggered = false;
24
+ }
25
+ export function isSelfTriggered() {
26
+ return selfTriggered;
27
+ }
28
+ // --- Atomic write helper ---
29
+ async function atomicWriteJson(filePath, data) {
30
+ const dir = join(filePath, '..');
31
+ await mkdir(dir, { recursive: true, mode: 0o700 });
32
+ const tmpFile = `${filePath}.tmp`;
33
+ await writeFile(tmpFile, JSON.stringify(data, null, 2), { encoding: 'utf8', mode: 0o600 });
34
+ await rename(tmpFile, filePath);
35
+ }
36
+ // --- JSON read helper ---
37
+ async function readJsonFile(filePath) {
38
+ try {
39
+ const content = await readFile(filePath, 'utf8');
40
+ if (!content.trim())
41
+ return null;
42
+ return JSON.parse(content);
43
+ }
44
+ catch (e) {
45
+ if (e.code === 'ENOENT')
46
+ return null;
47
+ logger.warn({ err: e, filePath }, 'Failed to read/parse JSON file');
48
+ return null;
49
+ }
50
+ }
51
+ // --- Claude CLI detection ---
52
+ function findClaudeBinary() {
53
+ try {
54
+ return execFileSync('which', ['claude'], {
55
+ encoding: 'utf8',
56
+ stdio: 'pipe',
57
+ }).trim();
58
+ }
59
+ catch {
60
+ return null;
61
+ }
62
+ }
63
+ // --- Identity resolution ---
64
+ /**
65
+ * Run `claude auth status` to get the current account identity.
66
+ * Tries JSON output first, falls back to text parsing.
67
+ */
68
+ export async function runClaudeAuthStatus() {
69
+ const log = logger.child({ op: 'claudeAuthStatus' });
70
+ if (!findClaudeBinary()) {
71
+ log.error('Claude CLI not found in PATH. Install from https://docs.anthropic.com/en/docs/claude-code');
72
+ return null;
73
+ }
74
+ return new Promise((resolve) => {
75
+ const child = spawn('claude', ['auth', 'status'], { stdio: 'pipe' });
76
+ let stdout = '';
77
+ let stderr = '';
78
+ child.stdout.on('data', (d) => { stdout += d.toString(); });
79
+ child.stderr.on('data', (d) => { stderr += d.toString(); });
80
+ const timer = setTimeout(() => {
81
+ child.kill('SIGTERM');
82
+ log.error('claude auth status timed out');
83
+ resolve(null);
84
+ }, 10_000);
85
+ child.on('error', (err) => {
86
+ clearTimeout(timer);
87
+ log.error({ err }, 'Failed to spawn claude auth status');
88
+ resolve(null);
89
+ });
90
+ child.on('close', (code) => {
91
+ clearTimeout(timer);
92
+ if (code !== 0) {
93
+ log.warn({ code, stderr }, 'claude auth status exited with non-zero code');
94
+ // Still try to parse — some versions return non-zero when not logged in
95
+ }
96
+ const combined = stdout + stderr;
97
+ // Try JSON parse first (if --json flag was used or output is JSON)
98
+ try {
99
+ const json = JSON.parse(combined.trim());
100
+ const email = json.email ?? json.primaryEmail ?? json.emailAddress ?? null;
101
+ if (email) {
102
+ resolve({
103
+ email,
104
+ orgName: json.orgName ?? json.org_name ?? '',
105
+ subscriptionType: json.subscriptionType ?? json.subscription_type ?? '',
106
+ loggedIn: json.loggedIn ?? json.logged_in ?? true,
107
+ });
108
+ return;
109
+ }
110
+ }
111
+ catch {
112
+ // Not JSON — fall through to text parsing
113
+ }
114
+ // Text parsing fallback
115
+ const identity = parseAuthStatusText(combined);
116
+ if (identity) {
117
+ resolve(identity);
118
+ }
119
+ else {
120
+ log.warn({ output: combined.slice(0, 500) }, 'Could not parse claude auth status output');
121
+ resolve(null);
122
+ }
123
+ });
124
+ });
125
+ }
126
+ /**
127
+ * Parse text output from `claude auth status`.
128
+ * Handles various output formats:
129
+ * "Logged in as: user@example.com"
130
+ * "Email: user@example.com"
131
+ * "Org: MyOrg"
132
+ * "Subscription: team"
133
+ */
134
+ function parseAuthStatusText(text) {
135
+ const emailMatch = text.match(/(?:Logged in as|Email)[:\s]+(\S+@\S+)/i);
136
+ if (!emailMatch)
137
+ return null;
138
+ const orgMatch = text.match(/Org(?:anization)?[:\s]+(.+)/i);
139
+ const subMatch = text.match(/Subscription[:\s]+(\S+)/i);
140
+ const notLoggedIn = /not logged in/i.test(text);
141
+ return {
142
+ email: emailMatch[1],
143
+ orgName: orgMatch?.[1]?.trim() ?? '',
144
+ subscriptionType: subMatch?.[1]?.trim() ?? '',
145
+ loggedIn: !notLoggedIn,
146
+ };
147
+ }
148
+ // --- Profile CRUD ---
149
+ export function profilePath(name) {
150
+ return join(PROFILES_DIR, `${name}.json`);
151
+ }
152
+ export async function loadProfile(name) {
153
+ return readJsonFile(profilePath(name));
154
+ }
155
+ export async function saveProfile(profile) {
156
+ await atomicWriteJson(profilePath(profile.name), profile);
157
+ }
158
+ export async function deleteProfileFile(name) {
159
+ try {
160
+ await unlink(profilePath(name));
161
+ return true;
162
+ }
163
+ catch (e) {
164
+ if (e.code === 'ENOENT')
165
+ return false;
166
+ throw e;
167
+ }
168
+ }
169
+ export async function listProfiles() {
170
+ const profiles = [];
171
+ try {
172
+ const entries = await readdir(PROFILES_DIR);
173
+ for (const entry of entries) {
174
+ if (!entry.endsWith('.json') || entry === 'active.json')
175
+ continue;
176
+ const profile = await readJsonFile(join(PROFILES_DIR, entry));
177
+ if (profile?.name) {
178
+ profiles.push(profile);
179
+ }
180
+ }
181
+ }
182
+ catch (e) {
183
+ if (e.code !== 'ENOENT') {
184
+ logger.warn({ err: e }, 'Failed to list profiles');
185
+ }
186
+ }
187
+ return profiles.sort((a, b) => a.name.localeCompare(b.name));
188
+ }
189
+ // --- Active profile tracking ---
190
+ export async function loadActiveProfile() {
191
+ return readJsonFile(ACTIVE_FILE);
192
+ }
193
+ export async function setActiveProfile(name) {
194
+ const active = {
195
+ profile: name,
196
+ switchedAt: new Date().toISOString(),
197
+ };
198
+ await atomicWriteJson(ACTIVE_FILE, active);
199
+ }
200
+ export async function clearActiveProfile() {
201
+ try {
202
+ await unlink(ACTIVE_FILE);
203
+ }
204
+ catch (e) {
205
+ if (e.code !== 'ENOENT')
206
+ throw e;
207
+ }
208
+ }
209
+ // --- Credential file I/O ---
210
+ export async function readCredentialsFile() {
211
+ return readJsonFile(CREDENTIALS_FILE);
212
+ }
213
+ /**
214
+ * Write credentials to ~/.claude/.credentials.json using atomic temp+rename.
215
+ * Pure write — does NOT manage the self-trigger flag. Callers that need to
216
+ * suppress watcher processing (e.g., switchProfile) must call setSelfTriggerFlag()
217
+ * themselves before calling this function.
218
+ */
219
+ export async function writeCredentialsFile(credentials) {
220
+ await atomicWriteJson(CREDENTIALS_FILE, credentials);
221
+ }
222
+ // --- Backup management ---
223
+ export async function createBackup(credentials) {
224
+ await mkdir(BACKUPS_DIR, { recursive: true, mode: 0o700 });
225
+ const timestamp = new Date().toISOString().replace(/:/g, '-').replace(/\.\d+Z$/, 'Z');
226
+ const backupPath = join(BACKUPS_DIR, `${timestamp}.json`);
227
+ await writeFile(backupPath, JSON.stringify(credentials, null, 2), { encoding: 'utf8', mode: 0o600 });
228
+ return backupPath;
229
+ }
230
+ export async function pruneBackups(maxAgeDays = 7) {
231
+ const log = logger.child({ op: 'pruneBackups' });
232
+ const maxAgeMs = maxAgeDays * 24 * 60 * 60 * 1000;
233
+ const cutoff = Date.now() - maxAgeMs;
234
+ let pruned = 0;
235
+ try {
236
+ const entries = await readdir(BACKUPS_DIR);
237
+ for (const entry of entries) {
238
+ if (!entry.endsWith('.json'))
239
+ continue;
240
+ const filePath = join(BACKUPS_DIR, entry);
241
+ try {
242
+ const fileStat = await stat(filePath);
243
+ if (fileStat.mtimeMs < cutoff) {
244
+ await unlink(filePath);
245
+ pruned++;
246
+ }
247
+ }
248
+ catch (statErr) {
249
+ log.debug({ err: statErr, filePath }, 'Could not stat backup file — skipping');
250
+ }
251
+ }
252
+ if (pruned > 0) {
253
+ log.info({ pruned }, `Pruned ${pruned} old backup(s)`);
254
+ }
255
+ }
256
+ catch (e) {
257
+ if (e.code !== 'ENOENT') {
258
+ log.warn({ err: e }, 'Failed to prune backups');
259
+ }
260
+ }
261
+ return pruned;
262
+ }
263
+ export function getExpiryStatus(profile) {
264
+ const expiresAt = profile.credentials.claudeAiOauth?.expiresAt;
265
+ if (!expiresAt)
266
+ return { label: '? unknown', status: 'valid' };
267
+ const now = Date.now();
268
+ const diff = expiresAt - now;
269
+ if (diff < 0) {
270
+ return { label: '\u2717 expired', status: 'expired' };
271
+ }
272
+ if (diff < 2 * 60 * 60 * 1000) {
273
+ const minutes = Math.round(diff / 60_000);
274
+ if (minutes < 60) {
275
+ return { label: `\u26a0 expires in ${minutes}m`, status: 'expiring' };
276
+ }
277
+ const hours = Math.round(minutes / 60);
278
+ return { label: `\u26a0 expires in ${hours}h`, status: 'expiring' };
279
+ }
280
+ return { label: '\u2713 valid', status: 'valid' };
281
+ }
282
+ // --- High-level operations ---
283
+ /**
284
+ * Switch to a named credential profile.
285
+ * Atomically writes the profile's credentials to ~/.claude/.credentials.json,
286
+ * updates active.json, then runs `claude auth status` to verify and refresh tokens.
287
+ */
288
+ export async function switchProfile(name) {
289
+ const log = logger.child({ op: 'switchProfile', name });
290
+ const profile = await loadProfile(name);
291
+ if (!profile) {
292
+ return { success: false, message: `Profile "${name}" not found` };
293
+ }
294
+ // Set self-trigger flag so the daemon watcher skips this write
295
+ setSelfTriggerFlag();
296
+ log.info({ email: profile.email }, 'Switching to profile');
297
+ await writeCredentialsFile(profile.credentials);
298
+ await setActiveProfile(name);
299
+ // Verify and potentially refresh tokens via auth status
300
+ const identity = await runClaudeAuthStatus();
301
+ if (!identity || !identity.loggedIn) {
302
+ log.warn('Auth status verification failed after switch — profile may need re-login');
303
+ return {
304
+ success: false,
305
+ message: `Switched to "${name}" but verification failed. Tokens may be expired — run \`claude login ${name}\` to re-authenticate.`,
306
+ };
307
+ }
308
+ // Update profile with potentially refreshed credentials and identity
309
+ const freshCredentials = await readCredentialsFile();
310
+ if (freshCredentials) {
311
+ const updatedProfile = {
312
+ ...profile,
313
+ email: identity.email,
314
+ orgName: identity.orgName,
315
+ subscriptionType: identity.subscriptionType,
316
+ savedAt: new Date().toISOString(),
317
+ credentials: freshCredentials,
318
+ };
319
+ await saveProfile(updatedProfile);
320
+ }
321
+ return {
322
+ success: true,
323
+ message: `Switched to "${name}" (${identity.email})`,
324
+ };
325
+ }
326
+ /**
327
+ * Managed login flow: spawn `claude auth login`, wait for completion,
328
+ * capture identity via `claude auth status`, save as named profile.
329
+ */
330
+ export async function loginProfile(name, email) {
331
+ const log = logger.child({ op: 'loginProfile', name });
332
+ if (!findClaudeBinary()) {
333
+ return {
334
+ success: false,
335
+ message: 'Claude CLI not found in PATH. Install from https://docs.anthropic.com/en/docs/claude-code',
336
+ };
337
+ }
338
+ // Backup current credentials before login
339
+ const currentCreds = await readCredentialsFile();
340
+ if (currentCreds) {
341
+ await createBackup(currentCreds);
342
+ }
343
+ // Build args — add --email if profile already has one or caller provides it
344
+ const args = ['auth', 'login'];
345
+ const existingProfile = await loadProfile(name);
346
+ const loginEmail = email ?? existingProfile?.email;
347
+ if (loginEmail) {
348
+ args.push('--email', loginEmail);
349
+ }
350
+ log.info({ email: loginEmail }, 'Starting managed login');
351
+ // Spawn interactive login
352
+ const exitCode = await new Promise((resolve, reject) => {
353
+ const child = spawn('claude', args, { stdio: 'inherit' });
354
+ const timer = setTimeout(() => {
355
+ child.kill('SIGTERM');
356
+ reject(new Error('Login timed out after 2 minutes'));
357
+ }, 120_000);
358
+ child.on('error', (err) => {
359
+ clearTimeout(timer);
360
+ reject(err);
361
+ });
362
+ child.on('close', (code) => {
363
+ clearTimeout(timer);
364
+ resolve(code ?? 1);
365
+ });
366
+ });
367
+ if (exitCode !== 0) {
368
+ return { success: false, message: `Login process exited with code ${exitCode}` };
369
+ }
370
+ // Capture identity
371
+ const identity = await runClaudeAuthStatus();
372
+ if (!identity || !identity.loggedIn) {
373
+ return { success: false, message: 'Login completed but could not verify identity' };
374
+ }
375
+ // Read new credentials and save profile
376
+ const credentials = await readCredentialsFile();
377
+ if (!credentials) {
378
+ return { success: false, message: 'Login completed but could not read credentials file' };
379
+ }
380
+ const profile = {
381
+ name,
382
+ email: identity.email,
383
+ orgName: identity.orgName,
384
+ subscriptionType: identity.subscriptionType,
385
+ savedAt: new Date().toISOString(),
386
+ credentials,
387
+ };
388
+ await saveProfile(profile);
389
+ await setActiveProfile(name);
390
+ log.info({ email: identity.email, org: identity.orgName }, 'Login complete, profile saved');
391
+ return {
392
+ success: true,
393
+ message: `Logged in and saved as "${name}" (${identity.email}, ${identity.orgName})`,
394
+ };
395
+ }
396
+ /**
397
+ * Save current credentials as a named profile without login.
398
+ */
399
+ export async function saveCurrentAsProfile(name) {
400
+ const credentials = await readCredentialsFile();
401
+ if (!credentials) {
402
+ return { success: false, message: 'No credentials file found at ~/.claude/.credentials.json' };
403
+ }
404
+ const identity = await runClaudeAuthStatus();
405
+ if (!identity) {
406
+ return { success: false, message: 'Could not determine account identity — is Claude CLI installed?' };
407
+ }
408
+ const profile = {
409
+ name,
410
+ email: identity.email,
411
+ orgName: identity.orgName,
412
+ subscriptionType: identity.subscriptionType,
413
+ savedAt: new Date().toISOString(),
414
+ credentials,
415
+ };
416
+ await saveProfile(profile);
417
+ await setActiveProfile(name);
418
+ return {
419
+ success: true,
420
+ message: `Saved current credentials as "${name}" (${identity.email})`,
421
+ };
422
+ }
423
+ /**
424
+ * Delete a named profile. Warns if it's the active profile.
425
+ */
426
+ export async function deleteProfileByName(name) {
427
+ const profile = await loadProfile(name);
428
+ if (!profile) {
429
+ return { success: false, message: `Profile "${name}" not found`, wasActive: false };
430
+ }
431
+ const active = await loadActiveProfile();
432
+ const wasActive = active?.profile === name;
433
+ await deleteProfileFile(name);
434
+ if (wasActive) {
435
+ await clearActiveProfile();
436
+ }
437
+ return {
438
+ success: true,
439
+ message: wasActive
440
+ ? `Deleted profile "${name}" (was active — no profile is now active)`
441
+ : `Deleted profile "${name}"`,
442
+ wasActive,
443
+ };
444
+ }
445
+ /**
446
+ * Get current Claude auth status for display.
447
+ */
448
+ export async function getClaudeStatus() {
449
+ const identity = await runClaudeAuthStatus();
450
+ if (!identity) {
451
+ return { success: false, message: 'Could not get Claude auth status — is Claude CLI installed and in PATH?' };
452
+ }
453
+ return { success: true, message: '', identity };
454
+ }
455
+ // --- Credential watcher handler (called from daemon.ts) ---
456
+ /**
457
+ * Handle an external credential file change detected by the daemon watcher.
458
+ * Creates a backup, identifies the account, and updates the matching profile.
459
+ */
460
+ export async function handleCredentialChange() {
461
+ const log = logger.child({ op: 'credentialChange' });
462
+ // Check self-trigger flag
463
+ if (isSelfTriggered()) {
464
+ clearSelfTriggerFlag();
465
+ log.debug('Skipping self-triggered credential change');
466
+ return;
467
+ }
468
+ // Read the new credentials
469
+ const credentials = await readCredentialsFile();
470
+ if (!credentials) {
471
+ log.warn('Credential file changed but could not be read');
472
+ return;
473
+ }
474
+ // Create backup
475
+ await createBackup(credentials);
476
+ // Identify the account
477
+ const identity = await runClaudeAuthStatus();
478
+ if (!identity) {
479
+ log.warn('Could not identify account after credential change');
480
+ return;
481
+ }
482
+ // Compare against saved profiles
483
+ const profiles = await listProfiles();
484
+ const matchingProfile = profiles.find((p) => p.email === identity.email);
485
+ if (matchingProfile) {
486
+ // Update the matching profile's credentials and savedAt
487
+ const updated = {
488
+ ...matchingProfile,
489
+ savedAt: new Date().toISOString(),
490
+ credentials,
491
+ };
492
+ await saveProfile(updated);
493
+ log.info({ profile: matchingProfile.name, email: identity.email }, `Updated profile "${matchingProfile.name}" with refreshed credentials`);
494
+ }
495
+ else {
496
+ log.warn({ email: identity.email }, `Unknown Claude account detected: ${identity.email}. Run \`claude save <name>\` to save it.`);
497
+ }
498
+ }
499
+ //# sourceMappingURL=claude-profiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-profiles.js","sourceRoot":"","sources":["../src/claude-profiles.ts"],"names":[],"mappings":"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"}