Skip to main content

textaccounts

Manage multiple Claude Code accounts with full directory isolation. Each profile is a complete ~/.claude/ config directory — sessions, memory, settings, and auth stay separate.

Why?

Claude Code stores everything in a single directory tree (~/.claude/). If you use multiple accounts (work + personal), you need separate directories. textaccounts registers and switches between them by setting CLAUDE_CONFIG_DIR.

Install

pip install textaccounts

Then install shell integration:

textaccounts install

This writes a fish function and completions to ~/.config/fish/. Open a new shell to activate.

Quick start

# Register existing directories — nothing is moved or copied
textaccounts adopt work ~/.claude-work
textaccounts adopt personal ~/.claude-personal

# Switch profile (sets CLAUDE_CONFIG_DIR in your shell)
textaccounts switch work

# Check status
textaccounts status

# Interactive view
textaccounts view

Commands

textaccounts list                        # show all profiles
textaccounts status                      # active profile + sync state
textaccounts adopt <name> <path>         # register an existing dir
textaccounts create <name>               # snapshot current config dir
textaccounts create <name> --shallow \
  --from <parent>                        # shallow clone — copy only .claude.json + settings.json
textaccounts create <name> \
  --clone-from <src>                     # deep clone — auth + settings + agents/hooks/plugins,
                                         # strip state (sessions/projects/history/caches)
textaccounts create <name> --shallow \
  --from <parent> --ephemeral \
  [--owner <run-id>]                     # mark for sweep by `gc` / `destroy`
textaccounts gc [--max-age 7d] \
  [--owner <run-id>] [--dry-run]         # sweep ephemeral profiles older than max-age
textaccounts destroy <name>              # remove a single ephemeral profile
textaccounts adopt-token <name> \
  [--path <dir>]                         # register a token-auth profile (CLAUDE_CODE_OAUTH_TOKEN)
textaccounts switch <name>               # switch profile (sets CLAUDE_CONFIG_DIR)
textaccounts show <name>                 # print shell command without executing
textaccounts rename <old> <new>          # rename a profile
textaccounts alias <profile> <alias>     # add a shorthand alias
textaccounts describe <name> [text]      # set/clear a per-profile description (omit text to clear)
textaccounts desc                        # print current profile's description (for statuslines)
textaccounts view                        # interactive profile view
textaccounts doctor                      # check stale paths + Claude Code version
textaccounts install [--shell fish]      # install shell integration
textaccounts export [output.zip]         # export registry + settings to encrypted zip
textaccounts import <backup.zip>         # import profiles from an export zip

Export and import

textaccounts export creates a password-protected AES-256 zip containing your profiles.yaml registry and each profile's .claude.json and settings.json. A .sha256 hash file is written alongside for integrity verification. Auth tokens are not included — they live exclusively in the macOS Keychain and are never written to disk by textaccounts.

# Export (password prompted)
textaccounts export
# → textaccounts-20260514.zip
# → textaccounts-20260514.zip.sha256

# Export to a specific path
textaccounts export ~/backups/ta-backup.zip

# Import on another machine (password prompted, skips existing profiles)
textaccounts import ta-backup.zip

# Import and overwrite any conflicting profiles
textaccounts import ta-backup.zip --overwrite

After importing, run textaccounts switch <name> for each profile and re-authenticate via /login — Keychain tokens are machine-local.

Shallow clones and ephemeral lifecycle

--shallow --from <parent> creates a minimal copy: just .claude.json and settings.json, no agents/, hooks/, plugins/, sessions/, etc. Useful when an orchestrator (e.g. a parallel-agents batch leader) needs many isolated worker profiles cheaply. --clone-from <src> is the deeper variant that also copies agents/, hooks/, plugins/, and symlinks.

Disposable runs. Add --ephemeral (or --owner <run-id>, which implies ephemeral) to flag the profile for cleanup:

# Orchestrator: spawn a worker for a specific run-id
textaccounts create bot-1 --shallow --from work --owner run-42

# When the run is done, sweep everything it created
textaccounts gc --owner run-42

# Or destroy a single one immediately
textaccounts destroy bot-1

gc defaults to --max-age 7d and ignores anything not flagged ephemeral: true — so it can't accidentally remove your real profiles. Every removal is appended to ~/.local/state/textaccounts/gc.log for auditing.

Token-auth profiles

Some Claude accounts use a long-lived CLAUDE_CODE_OAUTH_TOKEN (service-account style) instead of the interactive OAuth flow. textaccounts supports these as first-class profiles — the token is stored in the macOS Keychain and injected automatically at switch time.

# Register a token-auth profile (you will be prompted for the token, no shell history)
textaccounts adopt-token my-service-account

# Optionally specify a config dir (created if absent)
textaccounts adopt-token my-service-account --path ~/.claude-svc

# Switch — injects both CLAUDE_CONFIG_DIR and CLAUDE_CODE_OAUTH_TOKEN into your shell
textaccounts switch my-service-account

# The profile shows [token-auth] in the list
textaccounts list

The config dir (~/.claude-<name> by default) still holds settings, sessions, and MCP config — only the auth part changes. Tooling that calls env_for_profile("my-service-account") gets both CLAUDE_CONFIG_DIR and CLAUDE_CODE_OAUTH_TOKEN automatically.

To rotate the token, run adopt-token again with a new value (coming in a future release; for now, delete and re-adopt the profile).

Per-profile descriptions

Each profile can carry a free-text description (a one-liner like "day job" or "hobby + paperworlds"). It shows up:

  • In the interactive view bottom bar when a profile is highlighted (n to edit)
  • In your Claude Code statusline via textaccounts desc, which resolves the description for the current CLAUDE_CONFIG_DIR — so subprocesses launched by tools like textsessions show the right description automatically

Wire it into your statusline script:

ta_desc=$(textaccounts desc 2>/dev/null)
[ -n "$ta_desc" ] && parts+=("$ta_desc")

Interactive view

textaccounts view provides a Textual TUI for managing profiles:

Key Action
s Switch to selected profile
a Adopt a new directory
r Rename selected profile
l Edit aliases
n Edit description (shown in bottom bar)
q Quit

Auto-discovers unregistered ~/.claude*/ directories and shows them as adoption suggestions.

Config

Profiles are stored in ~/.textaccounts/profiles.yaml:

version: '1.0'
active: work

profiles:
  work:
    path: /Users/you/.claude-work
    email: yo***@company.com
    adopted: 2026-04-12T10:00:00Z
    worker: false
    description: day job
  personal:
    path: /Users/you/.claude-personal
    email: y***@gmail.com
    adopted: 2026-04-12T10:00:00Z
    worker: false
    description: hobby projects
    aliases:
      - p

defaults:
  profiles_dir: ~/.textaccounts/profiles

New profiles created with textaccounts create go into ~/.textaccounts/profiles/.

How it works

textaccounts switch sets CLAUDE_CONFIG_DIR in your shell via a fish function that evals the output of textaccounts show. A Python subprocess can't modify the parent shell's environment directly — the fish function bridges that gap.

Claude Code reads CLAUDE_CONFIG_DIR natively. No patches, no wrappers around claude itself.

Public API

textaccounts.api is the stable import surface for tools that integrate with textaccounts (see textsessions for an example consumer). Functions: available, list_profiles, active_profile, profile_dir, env_for_profile, profile_description. Full contract: docs/specs/textaccounts-api.md.

Roadmap

  • Publish to PyPI (under Paperworlds org — account TBD)
  • Upgrade to Python 3.13
  • d key in view to remove/unregister a profile
  • Bash/zsh shell integration (currently fish only)

License

MIT

Metadata

Release files for textaccounts 0.5.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for textaccounts 0.5.3
File Size Uploaded Provenance
textaccounts-0.5.3.tar.gz 61.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for textaccounts 0.5.3
File Interpreter ABI Platform
textaccounts-0.5.3-py3-none-any.whl Python 3 none any Details

Total release size: 88.9 kB

Release files / textaccounts-0.5.3.tar.gz

Download URL textaccounts-0.5.3.tar.gz
Size 61.3 kB
Tags Source
SHA-256 checksum
How to use checksums
b90e083b6015f3415f0930764cc3ac745ab92ef146e75826882d9e00f6d9dd73
BLAKE2b-256 checksum
How to use checksums
3209356d398a1954959b73dd5b65065fa152aeaa34014d88aebaf0baf0afb449
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / textaccounts-0.5.3-py3-none-any.whl

Download URL textaccounts-0.5.3-py3-none-any.whl
Size 27.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a87e0372f3039aa106f851df9f9a1c559ea8834532497df9036cecc52a74eb98
BLAKE2b-256 checksum
How to use checksums
b356bb504178e83ceb7c2a87adf93e1da4e818c5c7e3cec63721d31d6514c1ab
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for textaccounts 0.5.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page