Repository navigation
Releases: orvi2014/hatswap
Release list
v0.7.0: account picker, logo, and the right account after a restart
Account picker
Type hatswap with nothing after it to see every account with its email, 5-hour and weekly usage, the default (★) and the account this folder starts on (●).
↑↓ choose · ⏎ start Claude · d set the default · p pin this folder · s continue the last conversation here · c Codex · l sign in
It draws in place, so it works in tmux. Scripts and pipes still get the help text; HATSWAP_NO_PICKER=1 turns it off.
Logo
Two top hats turned around the same centre: one comes off as the other goes on. The README has a light and dark header, and docs/brand/ holds the marks, lockups, app and browser icons and a 1280×640 social card. The demo GIF is re-recorded with the picker.
Fixed
- After a restart, sessions started on the wrong account. Apps that reopen sessions run
zsh -l -c claude …, which never reads~/.zshrc, so those sessions ignored your default. The zsh hook now lives in~/.zshenv. An existing hook moves itself there the next time a terminal opens, or onhatswap update. switch/handoffafter the shell moved into a subfolder or worktree: hatswap now finds the folder the session started in and resumes it from there.use <name> --defaulttyped with!inside Claude now saves the default and tells you to runswitch, instead of refusing.
Upgrade
hatswap update
New install:
curl -fsSL https://raw.githubusercontent.com/orvi2014/hatswap/main/install.sh | bash
Full list: CHANGELOG
v0.6.0: usage, status line, VS Code/Desktop per account, bots follow the default
Added
hatswap exec [--account <name|main>] <command> [args]runs a command on the
account a new session would get at that moment (--account, then
HATSWAP_ACCOUNT, then the folder pin, then the default). Bots and scripts
that startclaude -pper job now followhatswap defaultwithout being
restarted; before, onlyclaudetyped in a terminal did, through the shell hook.hatswap shimwritesclaudeandcodexwrappers to
~/.claude-accounts/binthat do the same, for bots that call a fixed path or
searchPATH.shim --removedeletes them.HATSWAP_ACCOUNT=<name>keeps one bot on one account.hatswap usage [name…] [--json]: every account's 5-hour and weekly limits
and reset times, from the endpoint Claude's/usagereads. Read-only, cached
for 3 minutes; tokens are never printed, stored or refreshed.hatswap statusline --install: the account and email in Claude Code's status
line, ahead of any status line you already had (--removerestores it).hatswap vscode [name|main|--clear]: the Claude extension in VS Code or
Cursor uses that account in this folder, through
claudeCode.environmentVariablesin.vscode/settings.json.hatswap desktop [name|main]: Claude Desktop signed in to that account, in
its own window, with its own profile folder (macOS).rules/,output-styles/andkeybindings.jsonare now shared across
accounts like the rest of~/.claude.
Changed
binis no longer accepted as an account name (the shims live there), and
usage,statusline,vscodeanddesktopare reserved.
v0.5.0: claude-account is now hatswap
Changed
- Renamed to hatswap (repository
orvi2014/hatswap, commandhatswap), to
avoid confusion with an unrelated project also called claude-account. Old
GitHub links redirect. - New names:
.hatswappin files,HATSWAP_DIR,HATSWAP_KEEP_AUTH_ENV,
HATSWAP_SWITCH_DELAY,HATSWAP_SOURCE/HATSWAP_REF(installer), and
# >>> hatswap >>>/# hatswap PATHmarkers. /handoffand/switchnow callhatswap; existing copies are flagged as
outdated untilhatswap install-commandis run.
Kept compatible
claude-accountkeeps working: the installer adds it as an alias, and
bin/claude-accountin the repository is a stand-in that runs hatswap
(fetching it once if needed), soclaude-account updateon older installs
moves them to hatswap.- The data folder stays
~/.claude-accounts: Claude Code ties each account's
Keychain login to that path, so moving it would sign every account out. .claude-accountpins,CLAUDE_ACCOUNTS_DIR,CLAUDE_ACCOUNT_*variables
and old hook blocks are still honoured; re-pinning converts a pin file.
Added
- README sections: upgrading from claude-account, and how hatswap differs from
other account switchers. - Demo GIF and how-it-works diagram updated for the new name.
Install:
curl -fsSL https://raw.githubusercontent.com/orvi2014/hatswap/main/install.sh | bashAlready have claude-account? Run claude-account update. Your accounts, logins, pins and defaults carry over.
Full changelog: v0.4.2...v0.5.0
v0.4.2: API keys no longer override account logins
Fixed
- An exported
ANTHROPIC_API_KEY,ANTHROPIC_AUTH_TOKENor
CLAUDE_CODE_OAUTH_TOKENoverrode the account's own login, so every account
silently used that key. They are now cleared, with a one-line note, whenever
Claude starts on a named account:use,switch(including in-place
restarts),handoff,refresh, brief writing, and the shell hook for
defaults and pins. Your shell keeps them;mainis untouched;
CLAUDE_ACCOUNT_KEEP_AUTH_ENV=1opts out.
Already installed? claude-account update.
Full changelog: v0.4.1...v0.4.2
v0.4.1: new demo, history-link fix
Fixed
- Handing off or switching to a shared account whose history link was missing
(for example, added before~/.claude/projectsexisted) copied the
conversation into a separate, unmarked history. It now links the shared
history first. - "Codex account: main ((not signed in))" double brackets.
pinshows~paths.
Changed
- Demo GIF re-recorded:
listwith Codex logins,whoami,switch,pin
(inside and outside the pinned folder) andhandoff codexon the pinned
account's Codex login.
Already installed? claude-account update.
Full changelog: v0.4.0...v0.4.1
v0.4.0: per-folder accounts
Added
- Per-folder accounts:
pin <name|main>writes a.claude-accountfile, and
plainclaudein that folder or any subfolder starts on that account. The
nearest pin wins; precedence isCLAUDE_CONFIG_DIR, pin, default,main.
Inside a git repository the file is added to.git/info/exclude.pin
shows the active pin andpin --clearremoves it. whoami,refreshandhandoff codexfollow the folder's pin.- CI installs fish and zsh on Linux so the shell-hook tests run for all three
shells.
Install or upgrade:
curl -fsSL https://raw.githubusercontent.com/orvi2014/claude-account/main/install.sh | bashAlready installed? claude-account update.
Full changelog: v0.3.0...v0.4.0
v0.3.0: Codex per account, private history, one-line install
Added
- Codex per account:
codex-login <name>,codex <name>,add --codex.
Each account gets its ownCODEX_HOMEwith shared configuration;
handoff codexuses the session's account's Codex login (or--as <name>),
andlistshows each Codex email. - Private history:
add --privateandprivate <name> [--off]. A private
account keeps its conversations and memory to itself; handing one off
deliberately copies it to the target and says so. switchrestarts the session in its own tab in Terminal.app and iTerm2
(macOS), not only in tmux.- One-line installer (
install.sh): installs the script, addsPATH, the
default-account hook and the slash commands;--no-shell,--no-commands,
--bin-dir. update: updates the script (orgit pullfor a clone) and the slash
commands.- Outdated
/handoffand/switchare detected and flagged;install-command
now updates its own files without--force.
Fixed
- A conversation that existed in two histories was listed twice and broke
brief/handofffor it. - The second confirmation prompt in
switchno longer appears after the
first was answered, and no longer crashes without input.
Install or upgrade:
curl -fsSL https://raw.githubusercontent.com/orvi2014/claude-account/main/install.sh | bashAlready installed? claude-account update.
Full changelog: v0.2.0...v0.3.0
v0.2.0: switch accounts in place, default account, better briefs
Added
switch <account|main> [id]: continue the current conversation on another
account. Inside tmux (including desktop apps that host tabs in tmux) the same
tab restarts in place with its original flags, hooks and MCP config;
otherwise the open session is closed and resumed in the calling terminal./switch <account>slash command, installed byinstall-command.default [name|main], plus--defaultonuseandswitch: choose the
account plainclaudestarts on.setup-shell [--remove] [--shell zsh|bash|fish]andshell-init: a guarded
hook that makes plainclaudefollow the default. Offered automatically the
first time a default is set; the default is read on every call, so changing
it needs no reload.- "Tried and rejected" section in handoff briefs (
brief,handoff --brief,
refresh,/handoff): approaches that were dropped, with the reason, so the
next session or Codex does not repeat them. whoami: the account the current shell or Claude session is on, and the one
new sessions start on.--version.
Fixed
helpcrashed when$EDITORwas unset.removecrashed when its confirmation prompt got no input.- A failed in-place switch now cleans up its temporary restart scripts.
Upgrade: re-run the install command (or git pull in a clone). If you use /handoff, run claude-account install-command --force to get /switch and the new brief section.
Full changelog: v0.1.0...v0.2.0
v0.1.0
Added
- Multiple Claude Code accounts side by side, each with its own login;
settings, skills, plugins, MCP servers, memory and history shared. add,use,main,login,list,remove,sessions.handoff <account|main> [--fork]: resume a conversation on another account,
refusing while it is still open.handoff <account|main|codex> --brief,refreshandbrief: start a fresh
session from a compact, repository-aware handoff brief, with--edit,
--from,--modeland--no-repo./handoffslash command viainstall-command;save-brief,briefs.- Secret redaction in condensed transcripts.
