New
Apps 232Makers 232This week 232
Promote your app−30%
HatSwap screenshot 1
0views in
the last 30 days

HatSwap

Wear a different hat for each client: run several Claude Code accounts side by side, move a live con

Built with Claude/Claude Code/Codex

by orvi2014 · from BDBangladesh · added Oct 29, 2026
no ratings0 comments
Open app Code

hatswap

Every client's Claude Code account, signed in at once. Swap mid-conversation.

hatswap keeps each Claude Code account signed in at the same time and moves work between them — by resuming a conversation, or by starting a fresh session from a compact, repository-aware handoff brief. The same brief can restart an overgrown session on the same account, or seed an OpenAI Codex session.

hatswap: the account picker showing each account's email and 5-hour and weekly usage, setting the default and pinning the folder from it, claude starting on the pinned account inside the folder and on the default outside it, switching a conversation to another account, and handing the task to Codex

Recorded in a sandbox with example accounts and a stand-in for claude; reproduce with bash demo/setup.sh && vhs demo/demo.tape.


Contents


Features

  • Concurrent accounts. Every account stays signed in; run two accounts in two terminals at once.
  • Shared environment. Settings, agents, skills, plugins, hooks, rules, output styles, keybindings, memory and conversation history are shared across accounts. Only the login differs.
  • Switch in place. switch moves the current conversation to another account. In tmux (including desktop apps that host tabs in tmux), Terminal.app and iTerm2, the same tab restarts on the new login with its history intact.
  • Default account. default (or --default) picks the account plain claude starts on; setup-shell installs the one-line hook for zsh, bash or fish.
  • Per-folder accounts. pin acme in a client's folder and every claude started there uses that client's account.
  • Account picker. Type hatswap on its own for a list of every account with its email, limits, default and pin; pick one with the arrow keys and start Claude, set the default or pin the folder with one key.
  • Usage per account. usage shows every account's 5-hour and weekly limits in one table, the numbers /usage shows inside Claude.
  • Account in the status line. statusline --install puts the account and email at the bottom of every session, ahead of any status line you already have.
  • VS Code, Cursor and Claude Desktop. vscode acme makes the Claude extension use acme's login in that folder; desktop acme opens Claude Desktop signed in as acme, in its own window.
  • Bots follow the default. exec (or the claude/codex shims from shim) looks the account up on every call, so a long-running bot that starts claude -p per job moves to a new default without a restart.
  • Codex per account. Each account can have its own Codex login; handoff codex uses the one that belongs to the session's account.
  • Private history. Accounts can keep their conversations and memory to themselves, for client work that must stay separate.
  • One-line install and update. The installer sets up PATH, the shell hook and the slash commands; outdated slash commands are flagged.
  • Session handoff. Continue a conversation on another account with --resume, or fork a copy of it.
  • Brief handoff. Start a fresh session from a structured summary instead of replaying the full history.
  • Refresh. Restart a session that has grown too long, on the same account, from its brief.
  • Repository-aware briefs. Branch, uncommitted changes, recent commits and your open pull requests are collected at handoff time and treated as ground truth.
  • Review before launch. Open the brief in your editor and correct it before the new agent sees it.
  • In-session /handoff and /switch. A running Claude Code session writes its own brief, from full context, at no extra cost, or moves itself to another account.
  • Codex handoff. Seed an OpenAI Codex session with the same brief.
  • Live-session protection. Refuses to resume a conversation that is still open in another window.
  • Secret redaction. Passwords, API keys, tokens and private keys are removed before a transcript is summarised.

Requirements

Operating system macOS or Linux
Shell Bash 3.2 or later (the macOS default works)
Runtime Python 3
Claude Code claude on your PATH
Optional gh for open pull requests in briefs · codex for handoff codex · tmux for switching a session in place

Setup

1. Install

curl -fsSL https://raw.githubusercontent.com/orvi2014/hatswap/main/install.sh | bash

This installs hatswap to ~/.local/bin, adds that folder to your PATH if needed, installs the default-account shell hook and the /handoff and /switch commands. Open a new terminal afterwards. Every change is marked and reversible (see Uninstall).

Options go after bash -s --, for example curl -fsSL …/install.sh | bash -s -- --no-shell:

Option Effect
--no-shell Do not edit shell startup files (no PATH line, no default-account hook).
--no-commands Do not install /handoff and /switch.
--bin-dir <dir> Install somewhere other than ~/.local/bin.

Update later with hatswap update. It also refreshes the slash commands.

Install by hand
mkdir -p ~/.local/bin
curl -fsSL https://raw.githubusercontent.com/orvi2014/hatswap/main/bin/hatswap \
  -o ~/.local/bin/hatswap
chmod +x ~/.local/bin/hatswap

If ~/.local/bin is not on your PATH, add it to your shell profile.

Install from a clone instead
git clone https://github.com/orvi2014/hatswap.git
ln -s "$PWD/hatswap/bin/hatswap" ~/.local/bin/hatswap

git pull in the clone (or hatswap update) then updates the command.

2. Verify

hatswap list

Your existing Claude Code login appears as main. It is used as-is and never modified.

3. Add a second account

hatswap add work

A browser window opens. Sign in with the other account — if the browser is already signed in to your main account, use a private window. Pass --email you@company.com to prefill the address, or --console to use an Anthropic Console (API billing) login.

hatswap list
#   main   you@personal.com   (~/.claude)
#   work   you@company.com

4. Let plain claude follow a default account (optional)

hatswap setup-shell          # adds a guarded hook to your shell's startup file
hatswap default work         # plain `claude` now starts on "work"

setup-shell detects zsh, bash or fish (override with --shell), is safe to run twice, and is undone with setup-shell --remove. Open a new terminal afterwards.

5. Enable /handoff inside Claude Code (optional)

hatswap install-command

This adds ~/.claude/commands/handoff.md and switch.md, which every account shares. In any Claude Code session you can then run /switch work, /handoff work, /handoff codex or /handoff.

The same commands also come as a Claude Code plugin, which adds /hatswap:accounts (every account's usage) as well. It still needs the CLI installed:

/plugin marketplace add orvi2014/hatswap
/plugin install hatswap@hatswap

Upgrading from claude-account

Formerly claude-account. Renamed in 0.5.0 to avoid confusion with an unrelated project of the same name. Old links redirect here, and the claude-account command keeps working as an alias.

claude-account update        # installs hatswap next to it; claude-account becomes an alias

Or re-run the installer. Nothing else changes: your accounts, logins, briefs, default account, pins and shell hook keep working. The data folder is still ~/.claude-accounts, because Claude Code ties each account's Keychain login to that path; moving it would sign every account out. Older names are still honoured:

New Still accepted
hatswap claude-account (alias)
.hatswap pin files .claude-account (pin converts it when you re-pin)
HATSWAP_DIR CLAUDE_ACCOUNTS_DIR
HATSWAP_KEEP_AUTH_ENV, HATSWAP_SWITCH_DELAY CLAUDE_ACCOUNT_KEEP_AUTH_ENV, CLAUDE_ACCOUNT_SWITCH_DELAY
# >>> hatswap >>> hook block # >>> claude-account >>>

Run hatswap install-command once to update /handoff and /switch (they now call hatswap); hatswap list reminds you.

Uninstall

hatswap setup-shell --remove # if you added the shell hook
hatswap remove work          # repeat for each added account (also signs out its Codex login)
rm -f ~/.local/bin/hatswap ~/.local/bin/claude-account ~/.claude/commands/handoff.md ~/.claude/commands/switch.md
rm -r ~/.claude-accounts            # saved briefs

The installer's PATH line is marked # hatswap PATH in your shell profile; delete that line too.

Usage

Work on another account

hatswap use work             # or simply: hatswap work
hatswap main                 # back to the main account (~/.claude)

Run each in its own terminal to use both at once. hatswap whoami shows which account the current shell or Claude session is on, and which one a new claude starts on (inside Claude Code, ! hatswap whoami or /status).

Switch the account of the current conversation

Inside Claude Code:

! hatswap switch work            # or /switch work (after install-command)
! hatswap switch work --default  # also make "work" the default for new sessions
hatswap switch work --all         # move every open session (busy ones are skipped unless --force)

A running Claude Code process cannot change its login, so switch restarts it: the same conversation (full history, same ID) resumes on the other account, in the same tab:

Where the session runs What happens
tmux, including desktop apps that host each tab in tmux The pane restarts in place, keeping its original flags, hooks and MCP config.
Terminal.app or iTerm2 (macOS) Claude exits and the resume command is typed into that tab. macOS asks once to let your terminal control Terminal/iTerm2.
Anything else Type /exit, then run hatswap switch work in that terminal.

Run from a different terminal, switch restarts the session in its own tab when it can, and otherwise closes it there and resumes it in the terminal you ran it from.

Choose the default account

hatswap default work         # plain `claude` now starts on "work"
hatswap use work --default   # set it and start a session
hatswap default main         # back to ~/.claude
hatswap default              # show the current default

The first time you set a default, hatswap offers to add a one-line hook to your shell's startup file (~/.zshenv, ~/.bash_profile / ~/.bashrc, or fish conf.d) so plain claude follows it. For zsh it goes in ~/.zshenv rather than ~/.zshrc so that sessions an app reopens after a restart (with zsh -l -c claude …) also get it; an older hook in ~/.zshrc moves itself there the next time a terminal opens. The hook reads the default on every call, so changing it later needs no reload. An explicit CLAUDE_CONFIG_DIR always wins.

Pin a folder to an account

cd ~/clients/acme && hatswap pin acme   # plain `claude` here, and in every subfolder, starts on "acme"
hatswap pin                             # show which pin applies here
hatswap pin main                        # this folder uses main, whatever the default
hatswap pin --clear                     # remove this folder's pin

pin writes a one-line .hatswap file. Inside a git repository it is added to the repository's local ignore (.git/info/exclude), so it is never committed. The nearest pin wins, so a subfolder can pin a different account. Order of precedence for a plain claude: an explicit CLAUDE_CONFIG_DIR, then the nearest pin, then the default account, then main. whoami shows which one applies and why, and refresh and handoff codex follow it too. Pins work through the same shell hook as the default.

Move a task to another account

hatswap sessions             # conversations in this folder, and where each is open
hatswap handoff work --brief # fresh session on "work", seeded with a brief
hatswap handoff work         # or resume the full conversation (close the original first)

Restart a session that has grown too long

hatswap refresh              # brief + fresh session on the same account
hatswap refresh --edit       # review the brief in $EDITOR first

Hand off from inside a running session

/handoff work

Claude writes the brief from its own context, saves it, and prints the command to continue — for example hatswap handoff work --from ~/.claude-accounts/.briefs/….md.

Continue in Codex

hatswap handoff codex

Give each account its own Codex login

hatswap codex-login acme      # sign "acme" in to its Codex (ChatGPT/OpenAI) account
hatswap codex acme            # start Codex on acme's login
hatswap handoff codex         # uses the session's account's Codex login when it has one
hatswap handoff codex --as acme

Each account's Codex login lives in its own CODEX_HOME (~/.claude-accounts/<name>/codex). config.toml, AGENTS.md, prompts, rules, skills and plugins are shared with ~/.codex; the login, history and sessions are not. main uses ~/.codex. add acme --codex signs in to both at once, and list shows each account's Codex email.

Keep a client's conversations to its own account

hatswap add acme --private    # new account with its own history and memory
hatswap private acme          # or convert an existing one
hatswap private acme --off    # share history again (only while its own history is empty)

By default every account shares conversation history. A private account keeps its conversations and memory in its own projects/ folder, so other accounts never read them; settings, skills and MCP servers are still shared. sessions, brief and handoff see private conversations too. When you deliberately hand one to another account, it is copied into that account's history and the command says so.

Pick an account from a list

Type hatswap with nothing after it in a terminal:

hatswap ─ new sessions in ~/clients/acme start on acme

   main     you@personal.com    5h    0% ░░░░░░  week  100% ██████
 ▸ acme     you@acme.com        5h   10% █░░░░░  week   27% ██░░░░  ★ default  codex

 ↑↓ choose   ⏎ start claude   d default   p pin folder   s continue last chat   c codex   l sign in   q quit

It draws in place rather than taking over the screen, so it behaves in tmux and terminal apps. Scripts, pipes and ! inside Claude still get the help text; HATSWAP_NO_PICKER=1 turns it off.

See every account's limits

hatswap usage            # all accounts
hatswap usage acme       # one; --json for scripts
ACCOUNT        EMAIL                          5-HOUR  RESETS      WEEK  RESETS
main           you@personal.com                   0%              100%  Fri 14:00
acme           you@acme.com                       5%  in 0h44m     23%  Sat 16:00

The numbers come from the same endpoint Claude's /usage reads. It is not a public API, so it may change; results are cached for 3 minutes because it is rate-limited. hatswap reads each login from the Keychain (or .credentials.json on Linux) only to make that request: tokens are never printed, written or refreshed. An expired one says so; starting Claude on that account refreshes it. hatswap never switches accounts for you.

Show the account in Claude's status line

hatswap statusline --install   # ⎈ acme · you@acme.com  │ <your existing status line>
hatswap statusline --remove    # put back what you had

All accounts share settings.json, so one install covers every account. A status line you already had keeps running, after the account.

Use an account in VS Code, Cursor or Claude Desktop

cd ~/clients/acme
hatswap vscode acme        # the Claude extension uses acme in this folder
hatswap vscode             # same, using this folder's pin or the default
hatswap vscode --clear
hatswap desktop acme       # Claude Desktop as acme, in its own window

vscode sets CLAUDE_CONFIG_DIR in the folder's .vscode/settings.json (claudeCode.environmentVariables), keeping your other settings, and adds the file to the repository's local ignore. Reload the window afterwards and open that folder itself, not a parent. For main it removes the entry, because Claude finds main's login only when the variable is unset. A settings.json with comments is left alone and the line to add is printed. The extension's own session list may still show ~/.claude conversations (anthropics/claude-code#30538).

desktop starts a separate Claude Desktop with its own profile folder (~/.claude-accounts/<name>/desktop), so each account has its own window and login. Sign in once; it stays signed in. desktop main opens the app as usual.

Run bots and scripts on the current default

The shell hook only covers claude typed in a terminal. A bot started by launchd, cron or pm2 runs the claude binary directly, so it stays on whatever account it started with. Route it through hatswap instead:

hatswap exec claude -p "summarise today's issues"   # runs on the pin, then the default, at call time
hatswap shim                                        # writes ~/.claude-accounts/bin/claude and codex

Point the bot at ~/.claude-accounts/bin/claude (or put ~/.claude-accounts/bin first on its PATH). Each call looks up the account again, so hatswap default acme applies to the bot's next call, with no restart. The lookup uses the bot's working folder, so a pinned folder still wins. To keep one bot on one account whatever the default is, set HATSWAP_ACCOUNT=acme in its environment (or use exec --account acme).

exec ignores a CLAUDE_CONFIG_DIR the bot inherited, because following it would keep the bot on its old account. It clears ANTHROPIC_API_KEY and the other login variables for named accounts, quietly, and sets CODEX_HOME when the account has its own Codex login. A process that is already running keeps the account it started on: a bot that holds one Claude session open for hours picks up the new default only when it next starts claude. Keep the shim folder off your interactive PATH; the shell hook is the right tool there.

Work with saved briefs

hatswap briefs                          # list, with each brief's goal
hatswap handoff work --from <file>      # start any account from a saved brief
hatswap brief --edit                    # write, review and print a brief without switching

Command reference

Command Description
`add

Description taken from the repository README.

Ratings

–
0 ratings
5 0
4 0
3 0
2 0
1 0

Rate this app

Sign in to rate

Comments 0

Sign in to comment

No comments yet.

Related apps

#agentic-ai · #ai-agents · #anthropic