Skip to content

Quickstart

github-actions[bot] edited this page Sep 30, 2026 · 38 revisions

Quickstart

Capture your first profile

From a shell where Claude Code is logged in:

clauth capture work

or launch the TUI (clauth), open the Setup tab, pick + new, press ⏎ on the + capture current login row, name it work, and ⏎ on create account. Either way clauth snapshots the OAuth token and endpoint settings your running session is using. Log into a second account in Claude Code and capture that one too.

To add an account without touching the session you are in, use clauth login instead: it opens a browser, runs Claude Code's own OAuth flow, and writes the minted tokens into a fresh profile.

clauth login personal                                   # browser login
clauth login deepseek --base-url https://api.deepseek.com --api-key sk-...

For a third-party endpoint clauth recognises, open provider console in the TUI action menu opens the page that key is minted on (Configuration).

Switch

In the TUI: move to the account, ⏎, confirm. From the shell:

clauth work
# switched to 'work'

A switch repoints the credentials your global claude reads. A session already running adopts the new account on its next token refresh.

Run two accounts at once

clauth start personal                  # claude under personal's own config dir
clauth start personal -- --model haiku # flags for claude go after --

clauth start gives the session its own CLAUDE_CONFIG_DIR, so identity, settings, and billing caches never mix between accounts, and the global session is untouched.

For a session that keeps the account's auth while dropping your global CLAUDE.md, plugins, and hooks:

clauth start --isolated personal -p < prompt.txt

Pass the prompt on stdin when you use -p. A variadic claude flag would otherwise swallow a trailing positional prompt forwarded through clauth. Run it in an empty directory to skip project memory too.

Check what is loaded

clauth which          # profile that owns the current session's credentials
clauth which --json   # plus plan tier and endpoint
clauth list           # account table with cached usage, no network

Commands

Command Flags Does
clauth open the TUI (with stdout not a terminal: command help on stderr, exit 2)
clauth <profile> switch to that profile and exit — deprecated, use clauth switch <name>; a codex name moves the codex active marker instead (Codex)
clauth start <profile> [claude args…] --isolated, --with-fallback, --explain run claude under that profile's own config dir; a codex profile runs codex under its own CODEX_HOME instead, and --with-fallback is refused there (Codex)
clauth start --auto [claude args…] --isolated, --with-fallback, --explain start on the first fallback-chain member with headroom for the models the session will run
clauth login <profile> --base-url, --api-key, --setup-token, --yes, --model add an account, or re-authenticate one in place
clauth login <profile> --codex --browser adopt the codex login in your ~/.codex as a codex profile; --browser mints a fresh ChatGPT login in the browser instead and leaves ~/.codex alone (Codex)
clauth capture <profile> save the login Claude Code is using now as a new profile; the first one becomes the active account
clauth rolling-token <profile> serve the profile's sessions a rolling token re-stamped from its usage chain
clauth static-token <profile> --clear, --yes bare: restore the preserved mint a rolling token superseded; --clear removes the long-lived token entirely
clauth delete <profile> --yes, --force remove a profile and every credential it holds, a codex profile included (Codex)
clauth disable <profile> --yes hide it from auto-switch, polling, and the status feed; files stay
clauth enable <profile> put a disabled profile back
clauth limit-reset <profile> --list, --yes spend one of a codex account's banked usage-limit resets; --list shows them and spends nothing (Codex)
clauth which --json print the profile owning the loaded credentials; inside a clauth start codex session, that codex profile
clauth list --all (--disabled) account table from the on-disk caches, never fetches; codex accounts follow in their own CODEX section, which --all leaves alone
clauth jobs --json what the delegates are doing: account, elapsed, last output, live runs first; --json also carries each run's session_id, the handle delegate({session_id}) takes after a crash, and whether the run was isolated, which is what decides whether that id is a handle at all
clauth switch <name> / clauth switch <sid> <profile> one name switches the global account (the bare clauth <name> form, deprecated); two names move a live session, picked up at its next request
clauth sessions --json, --tokens list Claude Code sessions, newest first
clauth resume <id|latest> --profile <name> resume a session under a chosen account
clauth info <id|latest> print a session's resume command, workspace, and storage path
clauth daemon --status, --standby, --replace, --no-standby, --listen [ADDR:PORT], --cert <path>, --key <path>, --dump-openapi run the refresh + auto-switch loop with no TUI
clauth devices --json; pair <name> [--control] [--sessions], add <name> [--control] [--sessions], revoke <name>, allow-sessions <name> list, pair, add, revoke, and grant sessions to the devices that may call the REST API
clauth status --json --all, --disabled print the daemon's status shape once, from disk, codex accounts included
clauth mcp stdio MCP server; Claude Code launches this, not you
clauth completions <bash|zsh|fish|install> [shell] print or install a completion script
clauth herdr install --key <spec>, --no-config, --yes install the herdr plugin and bind a key to it
clauth herdr uninstall --no-config, --yes remove that plugin and the config lines it added
clauth herdr config get <key> print one herdr knob: popup_width, pane_tag, tag_watch_secs, border_label, delegate_dot, delegate_row_text
clauth proxy check <url | service> --admin-token-file <path>, --key-file <path>, --destructive <account> check a running clauth-compatible proxy against the clauth proxy contract: one line per departure, exit 1 when there is any. The target is a base URL (both files required) or a registered proxy's service, whose admin token and the key of the one profile whose base_url is its bind stand in for any file not given. Safe on a live proxy (mutating routes only hit an account id no proxy holds, the one login flow it starts is cancelled, one real inference request is sent); --destructive also changes and restores each setting it can, runs each action, re-binds a login, re-mints the key and deletes the named account — needs --key-file in both forms — for a proxy's CI. The files hold the secret alone and must be readable by you only
clauth proxy enable <service> --port <port> record a clauth-<service>-proxy found on PATH for the daemon to run: reads its manifest, refuses a contract major clauth does not speak, picks a free loopback port and mints its admin token. --port is the first enable only — a later one refuses a different --port and keeps the recorded port, token and state dir, since the proxy's profiles carry the port in their base_url
clauth proxy disable <service> stop that proxy and keep its row, port, admin token and state dir, so its profiles work again after a re-enable; nothing is deleted
clauth proxy list --json one row per clauth-<service>-proxy on PATH or registered, joined with the daemon's live state: service, version, contract, enabled, port, state; --json emits an array of objects

--theme <full\|compatible> is global and forces a color depth for the TUI.

Rules worth knowing

  • start argument order. clauth's own flags go before the profile name. Anything clauth does not recognize is forwarded to claude verbatim, leading hyphens included. Use -- for a spelling both programs own, like --help.
  • start --with-fallback hands the session its own fallback chain. Refused by name when combined with --isolated, on Windows without symlink privilege, or for a non-OAuth account.
    • Also refused for an account outside the chain, when the chain has no other member, or when no clauth daemon is running.
  • start --auto picks the account instead of you naming one: the first fallback-chain member with headroom for the models the session will run (Auto-switch). It takes the profile name's place, so separate claude's own args with -- whenever the first of them starts with a hyphen: clauth start --auto -- -p "hi". With no name in that slot there is nothing to tell a passthrough -p from a misspelled clauth flag. Refused when the fallback chain is empty, or when no member of it can start.
  • start --explain prints the account a start would launch on and the walk behind it, then exits without launching. It runs the refusals a real launch runs and dates every usage reading it judged, so a stale cache shows as one.
  • start --isolated keeps the session. Its transcripts and session state are lifted into your global store before the throwaway runtime is discarded, so the run stays resumable and its tokens are counted. A hard kill (SIGKILL) skips that teardown; the next stale-runtime sweep lifts the tree into the global store before deleting it, so a killed session is rescued too. The --rescue/--no-rescue flags and the auto_rescue setting that used to decide this are gone; there is nothing to opt into and no way to opt out.
  • delete, disable and limit-reset want a TTY. Each prompts [y/N]; on a non-TTY stdin they refuse unless you pass --yes. --force is the only way past delete's live-session guard, and --yes alone does not override it.
  • Bare names span both rosters. clauth <name>, delete and start try the Claude Code profiles first, then the codex ones; an unknown name lists both (available: … · codex: …). disable, enable, rolling-token and static-token refuse a codex name as one (Codex), and limit-reset refuses a Claude Code name the same way.
  • login <existing> re-authenticates in place. The chain slot, env block, and model settings survive; a browser re-login replaces the subscription login after a confirm. On an account that has an endpoint and a key it can still authenticate with, whether or not clauth recognises the provider, a browser re-login replaces the subscription login alone and leaves the endpoint and key where they are: it is the stored OAuth chain you came to renew, and the key is what that account's inference actually runs on. An endpoint with nothing left behind it is cleared as before, so a re-login never leaves a bare endpoint standing in front of a fresh subscription login. An api-key re-login replaces the endpoint set, and so does any capture that brings one of the fields; a headless one (non-interactive stdin) with no --base-url reuses the stored endpoint instead of prompting. The stored OAuth chain survives an api-key re-login: it is what usage polling and rolling-token roll from.
  • login <alibaba account> opens the Alibaba Model Studio console instead, because that plan's usage figures run on a console session its api key cannot stand in for. It replaces that session and nothing else: endpoint, api key and model settings all stay put. There is no confirm either, since re-running it is the routine repair. The window it captures is measured from your aliyun console sign-in (Configuration). Passing --base-url or --api-key still takes the ordinary api-key path. Starting one from nothing is two steps for that reason: give the account a Model Studio endpoint first (a Qwen preset on the Setup tab, or --base-url here), then run a bare clauth login <name>. The console a session comes from is read off the endpoint, so a name that has none yet has no console to open.
  • login on a box with no browser (or over ssh): the same login prints the link under Browser didn't open? Use the url below to sign in and prompts Paste code here if prompted:; open the link on any device, sign in, and paste the code the page shows back into the prompt (read echo-off). The browser callback still wins if it lands first. It is Claude Code's own "Browser didn't open?" path, so it mints exactly what a browser login mints: usage polling, plan tier, and rolling-token all work. The Setup tab's login modal has the same: c copies the link for another device to your local clipboard through the terminal (OSC 52), p turns its row into a code field: type or paste the code, ⏎ submits, esc brings the row back.
    • A non-TTY stdin is read as one line, for a driver that takes the link off stdout and feeds the code back to the same process; EOF just leaves the browser door open. The code is bound to that process, so it cannot be piped in from an earlier run.
  • login --setup-token captures a claude setup-token mint (echo-off, or piped on stdin) as the profile's long-lived login.
    • That token never races clauth's refresher. It engages only for a genuinely long-lived token; a rotating pair pasted here is ignored and called out on the card.
  • rolling-token <profile> points the profile's sidecar at its own clauth-private usage chain instead of a static mint: the daemon re-stamps it with the chain's current access token — full scopes, the account's subscriptionType and its rateLimitTier, but no refresh token — so sessions hold nothing rotatable (the split's whole point) while running a bearer the API recognizes as the plan it is, and plan-gated models work in a clauth-managed session. A claude setup-token mint carries neither user:profile nor a subscription stamp and gets capped. Arming widens what a session's credential can reach, and the command says so. It needs the daemon running: the bearer dies in hours, and the daemon's scan is what re-stamps it before then. The mint it supersedes is preserved at session-token.static.json; the bare clauth static-token <profile> — or a terminally dead usage chain — restores it rather than signing sessions out. The Setup tab's token row switches to an hours-scale rolling · re-stamps in ~Nh countdown and reads rolling token stalled if the re-stamping ever stops.
  • static-token --clear is the way back out. A stored long-lived token is what every switch installs, so a plain clauth login <profile> refreshes only the OAuth pair clauth polls usage with, and never reaches a session. The login prints a note saying so. Clearing is the FULL exit: it drops the token, the preserved mint backup, and the rolling_token flag together (a lingering flag would have the daemon re-stamp a fresh sidecar over the removal, and a lingering backup keeps a year-scale credential on disk under a command that just said "cleared"), then relinks the live credentials when the profile is active. It is refused when clearing would strip the profile's last credential — a stored token (or preserved mint) with no other login behind it; a profile whose only rolling piece is the flag disarms regardless, since no credential is touched. An api key counts as that other login, so an api-key profile clears with no OAuth pair to fall back to: the live credentials are removed rather than relinked, Claude Code is signed out (on macOS, out of the Keychain too), and the profile carries on authenticating by api key. A flag-only profile has no login at all behind it, so the sign-out leaves nothing serving and the line says to log in before switching to it. Every line clauth prints for the clear names which of those three happened.
  • resume latest refuses rather than silently picking the second-newest when a live isolated session holds a newer one. clauth info names where any transcript actually lives.
  • daemon --listen also serves the REST API over TLS: the status feed, the OpenAPI document, the account switch, and device pairing. It is off unless asked for, and every route but the pairing needs the token of a device paired on this machine. clauth devices pair <name> [--control] [--sessions] prints a one-time code (5 minutes, one use) for the device to enter, clauth devices add <name> [--control] [--sessions] mints a token here and prints it once, --control on either lets that device switch accounts rather than only read, and --sessions (requires --control) grants it session creation once [serve] session_creation is on; clauth devices allow-sessions <name> grants that later. clauth devices revoke <name> refuses its next request, no restart needed. The token from before pairing keeps working as the device legacy. TLS comes from this host's lego certificate, or from --cert/--key when the host's own name resolves to no certificate. Full detail in Daemon.
  • sessions --tokens parses every transcript in full to total tokens and cost. On a large store that takes a while, which is why it is opt-in.
  • herdr install runs herdr's own installer and passes its preview and confirm straight through, then adds the two things a herdr plugin cannot declare for itself: the key that opens the clauth dashboard, and the sidebar row that renders which account each Claude Code pane burns. Both land in your herdr config.toml, appended after a diff and a [y/N], and herdr validates the result before anything is written. Run it a second time and it adds nothing. --yes skips both prompts, herdr's install preview included, and is required on a non-TTY stdin. herdr uninstall reverses both halves behind one confirm, and declining leaves both alone; it removes only the blocks clauth marked as its own. For either command --no-config covers the plugin and leaves config.toml untouched. After that, clauth keeps the plugin current on its own: it lands the plugin at the latest release and compares the installed checkout's commit against that release's commit, reinstalling when they differ, up to once per 30 minutes (CLAUTH_NO_UPDATE=1 opts out). The whole surface, including the per-pane account tag: herdr plugin.

Environment variables

Variable Effect
CLAUTH_NO_UPDATE=1 disables the background update check and self-replacement even when the Config tab's auto-update toggle is on
CLAUTH_NO_COMPLETIONS=1 skips the first-run completions prompt
CLAUTH_NO_API=1 disables the daemon's REST listener whatever --listen says
CLAUDE_CONFIG_DIR scopes which and start to that config dir's credentials
CODEX_HOME set by clauth start on a codex profile to the session's own home, which is how which answers inside one; read by login --codex as the codex home to capture from, when it is not a clauth session home
SHELL how completions install detects your shell when you do not name one
COLORTERM what the TUI auto-detects its color depth from: truecolor or 24bit picks full, anything else compatible. --theme and the theme key in profiles.toml both beat it
HERDR_CONFIG_PATH which config file herdr install writes into, matching how herdr itself reads the override
HERDR_BIN_PATH which herdr binary clauth runs, else herdr on PATH. herdr injects it into every pane process itself

Exit codes

0 success, 1 failure, 2 usage error (unknown profile, bad flags). clauth daemon --status exits 0 when a daemon is running and 1 when none is.

Clone this wiki locally