aith 0.1.0

Account profile switching for AI coding tools
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
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
# aith

`aith` is a native CLI for managing account profiles for AI coding tools.

The goal is to make work, personal, and client identities explicit across tools
like Codex CLI, Codex Desktop, Claude Code, Claude Desktop, Cursor Agent, and
Cursor Desktop without repeated logout/login flows.

## Supported Surfaces

`aith` treats each auth surface separately. A terminal tool and a desktop app can
be logged into different accounts, so they should not share one profile target.

Current command keys:

- `codex-cli`: Codex CLI. Legacy alias: `codex`.
- `codex-desktop`: Codex desktop app.
- `claude-code`: Claude Code. Legacy alias: `claude`.
- `claude-desktop`: Claude desktop app.
- `cursor-agent`: Cursor Agent or terminal Cursor auth through `CURSOR_API_KEY`.
  Legacy alias: `cursor`.
- `cursor-desktop`: Cursor desktop app.

Desktop app targets are read-only today. They support `status` and `doctor`
discovery, but profile switching is intentionally not implemented until their
auth stores are understood well enough to mutate safely.

## Status

`aith` is early. Codex CLI profile management is implemented first because
Codex CLI stores its active auth state in a local `auth.json` file.

Implemented:

- Tool status checks for Codex CLI, Claude Code, and Cursor Agent.
- Read-only desktop app status checks for Codex Desktop, Claude Desktop, and
  Cursor Desktop.
- Read-only doctor diagnostics for auth/profile readiness.
- Claude Code auth/config discovery.
- Claude Code env-profile save/list/remove.
- Claude Code one-command and shell-scoped env-profile sessions.
- Cursor Agent env-profile save/list/remove.
- Cursor Agent one-command and shell-scoped env-profile sessions.
- Codex CLI profile save/list/current/use/remove.
- Codex CLI backup list/restore.
- Codex CLI one-command temporary profile execution.
- Codex CLI shell-scoped temporary profile sessions.
- Automatic backup before replacing active Codex CLI auth.
- Private Unix permissions for stored profile directories, auth files, and env
  profile files.

Not implemented yet:

- Claude Code global login switching, including subscription/Keychain account
  switching.
- Cursor Agent global login switching beyond terminal API-key sessions.
- Desktop app profile switching for Codex, Claude, or Cursor.

## Quick Start

Use `devenv` to enter the pinned Rust development environment:

```sh
devenv shell
cargo run -- status
cargo run -- status codex-desktop
```

## Installation

While the repository is private, install from GitHub with SSH access:

```sh
cargo install --git git@github.com:sadjow/aith.git --locked
```

After public releases are available:

```sh
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/sadjow/aith/releases/download/v0.1.0/aith-installer.sh | sh
brew install sadjow/tap/aith
npm install @sadjow/aith@0.1.0
cargo install aith --locked
nix run github:sadjow/aith
```

Release process details live in [docs/releasing.md](docs/releasing.md).

Save the current Codex CLI login as a profile:

```sh
cargo run -- save codex-cli personal
```

Inspect and switch Codex CLI profiles:

```sh
cargo run -- list codex-cli
cargo run -- current codex-cli
cargo run -- doctor codex-cli
cargo run -- use codex-cli personal
```

Inspect backups created by profile switches:

```sh
cargo run -- backups codex-cli
cargo run -- restore codex-cli auth-1778702155-74626.json
```

Run one command with a saved Codex CLI profile without switching your active
login:

```sh
cargo run -- exec codex-cli personal -- codex
```

Start a shell with a saved Codex CLI profile without switching your active login:

```sh
cargo run -- shell codex-cli personal
```

Save a Claude Code env profile without storing the secret value:

```sh
export ANTHROPIC_API_KEY_WORK=sk-ant-...
cargo run -- save claude-code work --from-env ANTHROPIC_API_KEY=ANTHROPIC_API_KEY_WORK
cargo run -- exec claude-code work -- claude
```

Save a Cursor Agent env profile without storing the secret value:

```sh
export CURSOR_API_KEY_WORK=...
cargo run -- save cursor-agent work --from-env CURSOR_API_KEY=CURSOR_API_KEY_WORK
cargo run -- exec cursor-agent work -- cursor-agent
```

Remove a saved Codex CLI profile:

```sh
cargo run -- remove codex-cli old-client
```

## Commands

### Tools

List supported tools:

```sh
aith tools
```

### Status

Show safe auth/config status. This checks whether expected files and
environment variables exist, but does not print credential values.

```sh
aith status
aith status codex-cli
aith status codex-desktop
aith status claude-code
aith status claude-desktop
aith status cursor-agent
aith status cursor-desktop
```

### Doctor

Show a read-only diagnostic report for tool auth paths, relevant environment
variables, saved profile counts, backup counts, and current profile detection.
Credential file contents are never printed.

```sh
aith doctor
aith doctor codex-cli
aith doctor codex-desktop
aith doctor claude-code
aith doctor claude-desktop
aith doctor cursor-agent
aith doctor cursor-desktop
```

For Claude Code and Cursor Agent, `doctor` reports both safe path/env status and
saved env profiles. It still warns that global login switching is not
implemented for those tools.

For desktop app targets, `doctor` reports known app/data paths as read-only and
marks profiles, backups, and current profile detection as unsupported.

### Save

Save the current auth state as a named profile.

```sh
aith save codex-cli personal
```

`add` is an alias for `save`:

```sh
aith add codex-cli work
```

Profiles can be overwritten explicitly:

```sh
aith save codex-cli personal --force
```

Claude Code and Cursor Agent profiles are env-based. `aith` stores references to
source environment variables, not their values:

```sh
export ANTHROPIC_API_KEY_WORK=sk-ant-...
aith save claude-code work --from-env ANTHROPIC_API_KEY=ANTHROPIC_API_KEY_WORK
aith save cursor-agent work --from-env CURSOR_API_KEY=CURSOR_API_KEY_WORK
```

Non-secret settings can be stored as literals:

```sh
aith save claude-code work \
  --from-env ANTHROPIC_API_KEY=ANTHROPIC_API_KEY_WORK \
  --set-env ANTHROPIC_BASE_URL=https://api.anthropic.com \
  --force
```

`aith` refuses literal values for sensitive names such as `ANTHROPIC_API_KEY`;
use `--from-env` for secrets.

### List

List saved profiles for a tool:

```sh
aith list codex-cli
aith list claude-code
aith list cursor-agent
```

Desktop app targets do not support saved profiles yet.

### Current

Detect which saved profile matches the active auth state:

```sh
aith current codex-cli
aith current claude-code
aith current cursor-agent
```

Possible outputs:

```text
codex-cli: personal
codex-cli: unknown
codex-cli: ambiguous
  matches personal, duplicate
```

`ambiguous` means more than one saved profile has the same auth snapshot. Env
profiles are session-scoped, so `aith current claude-code` and
`aith current cursor-agent` report `unknown` instead of trying to infer a global
active account.

Desktop app targets do not support current profile detection yet.

### Use

Switch a tool to a saved profile:

```sh
aith use codex-cli personal
```

For Codex CLI, this replaces the active `auth.json` with the saved profile
snapshot. The previous active `auth.json` is backed up first.

### Remove

Remove a saved profile:

```sh
aith remove codex-cli old-client
aith remove claude-code old-client
aith remove cursor-agent old-client
```

By default, `remove` refuses to delete a profile that matches the active auth
state:

```text
Error: profile 'personal' is currently active for codex-cli; pass --force to remove it
```

Force removal when you intentionally want to delete the saved profile:

```sh
aith remove codex-cli personal --force
```

This removes only the saved profile directory. It does not touch active Codex
CLI auth and does not delete backups.

### Backups

List backups created before profile switches or restores:

```sh
aith backups codex-cli
aith backups claude-code
aith backups cursor-agent
```

Env profiles do not replace active auth files, so there are no Claude Code or Cursor Agent
backups to list.

Example output:

```text
auth-1778702155-74626.json      /Users/sadjow/Library/Application Support/aith/backups/codex/auth-1778702155-74626.json
```

Backup IDs use this generated form:

```text
auth-<timestamp>-<pid>.json
```

### Restore

Restore a backup into the active auth location:

```sh
aith restore codex-cli auth-1778702155-74626.json
```

For Codex CLI, this copies the selected backup to the active `auth.json`. The
current active `auth.json` is backed up first, so restore is reversible.

### Exec

Run a command with a temporary profile-scoped auth environment:

```sh
aith exec codex-cli personal -- codex
aith exec codex-cli work -- codex exec "review this repo"
aith exec claude-code work -- claude
aith exec cursor-agent work -- cursor-agent
```

For Codex CLI, `exec` creates a temporary `CODEX_HOME`, copies the selected
profile's `auth.json` into it, copies the current Codex CLI `config.toml` when
one exists, and runs the command with that temporary `CODEX_HOME`.

The active Codex CLI auth file is not modified, and the temporary directory is
removed after the command exits. `aith exec` exits with the same status code as
the child command.

For Claude Code and Cursor Agent, `exec` resolves saved env references at runtime and
starts the child command with those target variables set. Config files, login
state, and Keychain entries are not modified.

### Shell

Start a shell with a temporary profile-scoped auth environment:

```sh
aith shell codex-cli personal
aith shell claude-code work
aith shell cursor-agent work
```

For Codex CLI, `shell` stages the selected profile exactly like `exec`, then
starts your configured shell with `CODEX_HOME` pointing at the temporary profile
home. This lets separate terminal tabs use different Codex CLI profiles at the
same time.

The active Codex CLI auth file is not modified, and the temporary directory is
removed when the shell exits. `aith shell` exits with the same status code as
the shell.

For Claude Code and Cursor Agent, `shell` resolves saved env references and starts your
configured shell with those variables set. This lets separate terminal tabs use
different API-key profiles at the same time when the upstream command honors
terminal auth env vars.

## Storage

Profiles are stored under `AITH_HOME` when it is set. Otherwise, `aith` uses the
platform data directory:

- macOS: `~/Library/Application Support/aith`
- Linux: `${XDG_DATA_HOME:-~/.local/share}/aith`
- Windows: `%LOCALAPPDATA%\aith`

Codex CLI profiles are stored as:

```text
profiles/codex/<profile>/auth.json
```

Codex CLI backups are stored as:

```text
backups/codex/auth-<timestamp>-<pid>.json
```

Env profiles for Claude Code and Cursor Agent are stored as:

```text
profiles/<storage-key>/<profile>/profile.toml
```

Storage keys remain the short legacy names for compatibility with existing
profiles: `codex`, `claude`, and `cursor`.

Example Claude Code profile:

```toml
[env]
ANTHROPIC_API_KEY = { from_env = "ANTHROPIC_API_KEY_WORK" }
ANTHROPIC_BASE_URL = "https://api.anthropic.com"
```

Example Cursor Agent profile:

```toml
[env]
CURSOR_API_KEY = { from_env = "CURSOR_API_KEY_WORK" }
```

On Unix, profile directories are created with `0700` permissions and auth files
or profile files are written with `0600` permissions.

## Claude Code Discovery and Env Profiles

`aith status claude-code` and `aith doctor claude-code` check known Claude Code
settings and auth surfaces without reading credential contents.

Claude Code discovery checks:

- User config directory: `CLAUDE_CONFIG_DIR` or `~/.claude`
- User settings: `settings.json`
- User state: `~/.claude.json`
- Project settings: `.claude/settings.json` and local `.claude/settings.local.json`
- Managed settings path for the current platform
- Terminal auth environment variables such as `ANTHROPIC_API_KEY`,
  `ANTHROPIC_AUTH_TOKEN`, `CLAUDE_CODE_OAUTH_TOKEN`, and cloud-provider mode
  variables

Credential storage differs by platform. On macOS, Claude Code subscription
credentials are stored in Keychain and `aith` does not inspect Keychain. On
Linux and Windows, Claude Code uses `.credentials.json` under the Claude config
directory, including `CLAUDE_CONFIG_DIR` when set.

Claude Code env profiles are intentionally narrower than Codex CLI file-backed
profiles. They do not switch the logged-in Claude Code subscription account.
They only set terminal auth environment variables for
`aith exec claude-code ...` and `aith shell claude-code ...` sessions.

References:

- [Claude Code settings]https://code.claude.com/docs/en/settings
- [Claude Code authentication]https://code.claude.com/docs/en/team
- [Claude Code CLI reference]https://code.claude.com/docs/en/cli-reference

## Cursor Agent Env Profiles

`aith status cursor-agent` and `aith doctor cursor-agent` check the Cursor user
data path and terminal auth environment without printing credential values.

Cursor Agent env profiles set terminal auth environment variables for
`aith exec cursor-agent ...` and `aith shell cursor-agent ...` sessions. They do
not modify Cursor user data or any global login state.

## Desktop App Discovery

`aith` tracks desktop apps separately from CLI and terminal agent targets:

- `codex-desktop`
- `claude-desktop`
- `cursor-desktop`

Desktop targets are read-only today. `aith status <desktop-target>` and
`aith doctor <desktop-target>` check known app bundle, app support, settings,
browser storage, and user-data paths without opening credential-bearing files or
printing credential values.

Desktop discovery intentionally does not inspect macOS Keychain, cookies,
LevelDB, IndexedDB, SQLite databases, or app-managed session stores. Those
stores may contain sensitive or app-version-specific auth state, so switching is
blocked until each desktop auth model has a dedicated, reversible implementation.

## Safety Model

- Credential file contents are never printed by status/doctor/current/list
  commands.
- Profile names are limited to ASCII letters, numbers, `-`, and `_`.
- `use` and `restore` create a backup before replacing active Codex CLI auth.
- `exec` runs with a temporary `CODEX_HOME` and does not modify active Codex CLI
  auth.
- `shell` starts a temporary `CODEX_HOME` session and does not modify active
  Codex CLI auth.
- Env profiles store source env variable names for secrets, not secret values.
  Secret values are resolved only when `exec` or `shell` starts.
- Claude Code and Cursor Agent env sessions do not modify config files,
  credential files, user data, or macOS Keychain entries.
- Desktop app auth stores are read-only in current profile operations.
- `remove` refuses to delete the active matching profile unless `--force` is
  passed.
- `restore` only accepts generated backup IDs in the form
  `auth-<timestamp>-<pid>.json`.
- Claude Code, Cursor Agent, and desktop global login switching intentionally
  return “not implemented yet” until their auth models are handled explicitly.

## Development

This project uses [devenv](https://devenv.sh/) to provide a pinned Rust
toolchain matching `rust-version` in `Cargo.toml`.

```sh
devenv shell
cargo check
cargo test
cargo run -- status
```

Common one-off checks can run without entering an interactive shell:

```sh
devenv shell cargo check
devenv shell cargo fmt -- --check
devenv shell cargo clippy --all-targets -- -D warnings
devenv shell cargo test
devenv shell ci
```

Integration tests run the real `aith` binary against temporary fake `AITH_HOME`,
`CODEX_HOME`, `CLAUDE_CONFIG_DIR`, and `HOME` directories. They do not read or
modify real tool credentials.

## Continuous Integration

GitHub Actions runs the same checks as the local CI script on pushes to `main`
and pull requests:

```sh
devenv shell ci
```

The workflow installs Nix and `devenv`, then runs the pinned Rust toolchain from
`devenv.nix`.

Release automation uses `cargo-dist` through [dist-workspace.toml](dist-workspace.toml).

## Project Structure

- `src/cli.rs`: command parsing and user-facing output.
- `src/doctor.rs`: read-only diagnostic report generation.
- `src/profiles/`: shared profile storage, result types, validation, backups,
  and filesystem safety helpers.
- `src/tools/`: tool metadata and tool-specific adapters.
- `src/tools/claude.rs`: Claude Code auth/config discovery and env-profile
  sessions.
- `src/tools/codex.rs`: Codex CLI auth/profile behavior.
- `src/tools/cursor.rs`: Cursor Agent auth discovery and env-profile sessions.
- `src/tools/desktop.rs`: read-only desktop app discovery.
- `src/tools/env_session.rs`: shared env-profile session behavior.

## Design Direction

- Local-first: credentials never leave the machine.
- Tool-native: use each upstream tool's supported auth and config mechanisms.
- Explicit: profile switches should be visible and reversible.
- Session-friendly: support one-command and shell-scoped temporary identities.