On macOS, pitboard stow and Put Away put away a Claude Code login left in ~/.claude/.credentials.json, parking it if Pitboard has none.
Pitboard warns with config_names_another when Claude Code's config names another account than the one whose login is stored.
Pitboard warns with in_use_unconfirmed when Claude Code's config has named another account since Anthropic last identified the stored login.
pitboard doctor has an in use check.
pitboard use on the account in use, and Update Claude Code's Config in the app, write that account into Claude Code's config.
pitboard log records why the automatic switch did not switch, as auto-stay, which Activity shows as Automatic switch not made.
pitboard watch --json has the event waiting, and more fields on idle, no_room and skipped.
Changed
Breaking: The public API of pitboard-core changes; its documentation shows the new one.
Breaking:pitboard watch --json reports switch_interrupted and custom_oauth_endpoint with the new event not_watching, not with skipped.
The account index is schema 6, which earlier versions cannot read, so update the command line and the app together.
While ~/.claude/.credentials.json is behind the keychain on macOS, every read warns with fallback_login.
While ~/.claude/.credentials.json is behind the keychain on macOS, a switch says running sessions keep their account until they renew their login or restart.
The app and pitboard watch say once why Pitboard is not switching.
The app decides whether to switch every 30 seconds, as pitboard watch does.
Switch when a limit reaches shows which account the automatic switch watches.
After a failed switch, the automatic switch waits a minute, doubling up to 15 minutes, before it tries again.
The status line labels a session's usage work? or ? while it cannot be sure whose it is.
Removed
Breaking:pitboard status --json no longer gives "source": "claude_code_cache", since Pitboard no longer reads Claude Code's usage cache.
Breaking:pitboard doctor no longer has the usage_cache check.
Pitboard no longer has the error code switch_overtaken, which it never printed.
Fixed
A sign-in outside Pitboard that replaces the login of the account in use shows as login replaced outside Pitboard, not nothing parked.
An account just switched to no longer shows the previous account's usage.
Numbers filed under the wrong Claude Code account go at that account's next answer from Anthropic.
The status line files a session's usage under the account the numbers belong to.
The app no longer offers an account whose reading may leave out a limit the account in use has.
The automatic switch and the app's offer can choose an account with fewer limits, such as a Team seat.
The automatic switch switches at the share the menu shows, so 95% shown counts as 95%.
Every front end rounds a half up and changes colour at 70% and 90%.
Pitboard takes the account in use from what Anthropic last said of the stored login, not from Claude Code's config.
The automatic switch identifies the stored login before it decides, and when it cannot tell, it decides nothing and says so.
The automatic switch judges every limit of the account in use.
The automatic switch says and records each reason it does not switch once.
A Claude Code switch no longer leaves the account switched from with a refused login when a session renews it at the same moment.
The app and pitboard watch see a change made in the same second as the last one, such as a pitboard use in a terminal.
The app and pitboard watch no longer report a switch that another pitboard is making as interrupted.
A login too large to pass without the argument line, under PITBOARD_NO_ARGV, counts as one of the automatic switch's three attempts.
On macOS, pitboard doctor and each Claude Code change warn with fallback_login when ~/.claude/.credentials.json holds a login besides the keychain's, which Claude Code over SSH uses.
pitboard status, the app and, as ▲ or ▼, the status line compare each limit's use with an even pace to its reset, such as 27% over pace.
--json gives each limit's pace.
pitboard status --json gives each account's organization_uuid, the Claude organisation its login belongs to.
Changed
Breaking: A keychain locked where it cannot ask for its password stops a command with credential_store_locked, not credential_store_unreadable. A script that checks for the old code should check for both.
The account index is schema 5, which earlier versions cannot read, so update the command line and the app together.
How long the account in use lasts follows its limits' paces, as in weekly limit runs out in 11h 05m at this pace.
Accounts not in use no longer say how long they last.
Removed
Pitboard no longer keeps readings/ in its directory, and deletes the files it wrote there.
Fixed
pitboard doctor and This Mac report a locked keychain once, as a failed credential check, not as parked logins that need a new sign-in.
While the login in use cannot be read, the account Pitboard last switched to shows login could not be read, not Needs signing in again.
Pitboard enrols one person's Claude accounts in two organisations, such as a claude.ai plan and a Team plan, as two accounts, where it refused the second.
pitboard watch switches Claude Code automatically while it runs in a terminal, whatever the app's setting.
pitboard watch takes --at for the share it switches at, --once to decide once and exit, and --json for one event per line.
Settings > General has Switch Claude Code automatically, off by default, with the share it switches at; the app switches only while open.
The app posts a notification for each automatic switch and for what stops one.
pitboard doctor and This Mac have a network check that names the proxy Pitboard's requests go through, and warns about a SOCKS proxy or a proxy variable it cannot read.
The daily renewal schedule goes through the proxy of the Pitboard that installed it.
pitboard doctor's schedule_proxy check warns when the schedule's proxy differs from yours.
Changed
Breaking: The public API of pitboard-core changes; its documentation shows the new one.
Breaking: On macOS and Linux, Pitboard changes nothing as root or with sudo and stops with elevated, though pitboard status still answers as with --offline. Run it as yourself.
Breaking: Pitboard refuses SOCKS proxies: while ALL_PROXY, HTTPS_PROXY or HTTP_PROXY names one, requests fail as unreachable unless NO_PROXY names their host.
Breaking:pitboard schedule install and Renew parked logins daily refuse with schedule_not_default_home while PITBOARD_HOME names a directory other than ~/.pitboard. Unset PITBOARD_HOME to turn it on.
On Windows, pitboard builds and refuses every command but --version, --help, completions and manpage with windows_not_released.
The product is called Pitboard, with a capital P, and the pitboard command and every key it reads or prints stay the same.
pitboard status names a limit that is not a whole number of hours by its minutes or seconds, such as 90m.
The app writes spans as pitboard status does, such as resets in 2h 05m.
The app says resetting now once a reset is due.
Under a minute, pitboard status says about to run out or resets any moment, as the app does.
pitboard doctor sums up in the same words as This Mac, and pitboard renew as Renew Now.
The command line runs the claude or codex that PITBOARD_CLAUDE or PITBOARD_CODEX names, as the app does.
pitboard doctor reports the build of the claude or codex that PITBOARD_CLAUDE or PITBOARD_CODEX names.
An empty PITBOARD_CLAUDE or PITBOARD_CODEX names nothing.
Pitboard reads a few rare shared links differently, such as c%EF%BD%8Caude.ai, which it now takes for claude.ai.
The app's preferences, such as the tools you said Not Now to, follow PITBOARD_HOME.
The app posts that the account in use has run out once per reset, even across relaunches.
The app updates text that depends only on the time, such as used up until 14:05, once a minute.
The app's settings update what they offer each time they are shown.
The Activity list names a switch Switch, where it said Use.
When the app cannot read its record of the account windows, it deletes no window's data and never writes over the record.
--json output is ASCII only, with other characters as \u escapes that a JSON parser reads as before.
Pitboard's own Codex sign-ins keep the new login in auth.json, even when a Codex config chooses the keychain.
pitboard doctor and This Mac say which setting chose Codex's login store, such as file (Codex's default).
Fixed
Breaking: With HOME, PITBOARD_HOME or CLAUDE_CONFIG_DIR empty or relative, or CODEX_HOME relative, Pitboard refuses every command but completions, manpage and doctor with home_not_absolute. Set a full path or unset the variable.
When the account in use runs out, the app offers only an account with room in every limit.
Where Pitboard cannot list running processes, a Codex switch, or a sign-in that puts a new login in use, warns with sessions_unknown.
Pitboard reads Codex's login store from every config layer Codex reads, such as /etc/codex and managed preferences.
Codex changes stop with live_store_unsupported where a Codex config layer chooses a store other than the file.
Codex changes stop with live_store_unsupported where a Codex config layer cannot be read, names an unknown store or has an unmatched profile.
Pitboard no longer refuses a Codex account where config.toml chooses another store but a managed setting or a requirement chooses the file.
An account's window opens again on the page before a sign-in page, or on the site's home, not on the sign-in page.
After Claude Code refuses a pasted code, the sign-in sheet asks for the code again.
Sign In pressed right after Cancel no longer says another sign-in is already waiting.
The app reads again right after you add, rename or forget an account, give up on a switch or press Renew Now.
The window says when a sign-in fails, or a name cannot be saved, after its sheet has closed.
Quitting Pitboard stops a sign-in under way, and the tool's own sign-in with it.
The window shows two warnings with the same words as two notices.
This Mac gives each account's parked login check its own row.
This Mac says it is checking until the last check is in, not Checked at beside checks still running.
After an interrupted switch Pitboard cannot finish, the app shows An interrupted switch is waiting, with Give Up.
After an interrupted switch Pitboard cannot finish, pitboard status warns with recovery_undetermined.
pitboard abandon and Give Up give up on an interrupted Codex switch while CLAUDE_CODE_CUSTOM_OAUTH_URL is set.
pitboard doctor and the app's checks no longer warn that a parked login could not be read after a switch, an enrolment or a renewal.
pitboard doctor's advice about a login others can read is one sentence again.
The note under the sign-in sheet's Code field says Claude Code takes the code shown after you sign in.
The sign-in sheet links the right address when Claude Code prints it as a terminal hyperlink.
With HOME unset, the command line uses your account's home directory, as the app does.
The daily renewal schedule renews ~/.pitboard, even when PITBOARD_HOME reaches it through launchctl setenv or systemd's user environment.
On Linux, the daily renewal timer runs pitboard renew --scheduled once pitboard schedule install rewrites it.
The command line and the app take a claude or codex only when it is a regular file you may run.
The app honours the environment it was started with, such as ANTHROPIC_API_KEY, though opened from Finder it sees only what launchctl setenv sets.
The Open Link window and the Share sheet name claude.ai and chatgpt.com in English, whatever the Mac's language.
Security
Breaking: Pitboard refuses any folder in ~/Library/CloudStorage or ~/Library/Mobile Documents as its directory, with state_on_synced_drive.
Breaking: Pitboard refuses a ~/.pitboard with a sync client's folder name, such as Dropbox or Sync, anywhere in its path, in any case. Set PITBOARD_HOME to a folder outside it.
Pitboard writes the daily renewal schedule's files so only you can read them, since they can hold a proxy's password.
Pitboard refuses a site's sign-in link, or a link with a . or .. path segment, however the rest of its path is written.
Pitboard refuses a link that names a user or a port, and a pitboard:// link with a user, a port or a path.
Switching Codex in the app while the ChatGPT app is open offers Quit ChatGPT and Switch, which quits ChatGPT, switches and opens it again; the command line never quits an app.
Changed
Breaking: The public API of pitboard-core changes; its documentation shows the new one.
After a Codex switch, Pitboard names each program still running the old login and how to make it take the new one.
pitboard doctor's codex_running check lists the programs still running the old Codex login.
Fixed
A switch counts only your own codex processes, not every user's.
pitboard status --fresh and the app's Refresh no longer ask again during a wait the service asked for with Retry-After.
An account whose service never answered and then could not be reached no longer shows as rate limited.
With PITBOARD_NO_ARGV=1, renewing a parked login too large for security's standard input no longer loses it.
A switch whose login could not be read back names the pitboard use that finishes or undoes it.
With Codex's auth.json missing, pitboard doctor says to run codex login.
The man page covers every command on its one page, instead of naming pages that were never installed.
The app says Claude Code is not installed when it finds neither claude nor codex, and no login or enrolled account.
Security
The app, and a renewal schedule installed while PITBOARD_NO_ARGV is set, honour it, so a large login never reaches security as an argument another process running as you could read.
Pitboard keeps one usage reading per account that only moves forward, so a session's older numbers no longer replace newer ones.
The app's Documentation item opens docs.usepitboard.com.
Fixed
Every session on one account, pitboard status and the menu bar show the same, newest numbers, and idle sessions follow with "refreshInterval": 10 in the status line settings.
A session still holding the previous account's numbers after a switch or a /login no longer records them as the new account's.
The advice to switch stays for as long as the account in use is out, not only until the app's next read.
Settings > Advanced shows which pitboard a terminal runs.
Install command line tool… in Settings > Advanced links /usr/local/bin/pitboard to the app's own, and never replaces a pitboard someone else installed.
An account whose parked login has expired has a Sign in again button in its row.
Changed
Breaking: In the tap, pitboard is the command line's cask and the app's cask is pitboard-app. Upgrade from 0.3.0 or earlier has the commands to move.
Breaking: The public API of pitboard-core changes; its documentation shows the new one.
The app carries the command line inside it, so an update moves both.
brew install datlechin/tap/pitboard installs the release's own command line as a cask, on macOS and Linux, without compiling.
From the old formula, brew update leaves Pitboard at 0.3.0, so uninstall the formula before you install the cask.
From the old app cask, brew update replaces the app with the command line once, and keeps your settings and ~/.pitboard.
Removing the old app cask with --zap moves ~/.pitboard to the Trash, so leave --zap out.
Removed
Releases no longer publish a source tarball; the source is on crates.io and in the tag.
Fixed
Daily renewal turned on from the app runs the command line inside the app, instead of starting a second copy of the app every day.
Opening the app points a 0.3.0 renewal schedule at the command line inside it.
The app no longer turns daily renewal on from the temporary copy macOS runs before the app is in Applications.
pitboard doctor and Check this machine fail when the renewal schedule runs a pitboard that is gone or is an app.
On Linux, a renewal schedule turned on from the command line keeps working after brew upgrade.
pitboard uninstall removes the renewal schedule first, as schedule_removed in --json.
Both casks remove the renewal schedule only on brew uninstall --zap, and neither touches ~/.pitboard, so run pitboard uninstall before removing Pitboard.
Advice about upgrading or removing Pitboard no longer assumes Homebrew.
On Homebrew 6 and later, the app's cask installs without the formula installed first.
cargo binstall pitboard no longer falls back to a third party's build when it cannot fetch the release's.
Pitboard switches Codex accounts too, with pitboard enroll codex/<label> and pitboard use codex/<label>.
pitboard enroll codex/<label> --sign-in runs codex login in a private CODEX_HOME.
pitboard shows each Codex account's five-hour and weekly limits.
Pitboard handles Codex's auth.json store, and refuses Codex's keychain stores with a reason.
Until a Codex account is enrolled, Pitboard reads nothing of Codex's and asks OpenAI nothing.
A Codex switch says that running codex sessions keep the old account until restarted, and how many it found.
A Codex switch warns that signing out in a running codex would revoke the login just parked.
A Codex switch writes nothing over a login that a running codex renewed meanwhile.
A Codex switch refuses to park a login that names two accounts.
The app's panel groups accounts by tool.
The menu bar follows the signed-in account closest to running out, of either tool.
When an account runs out, the app offers only an account of the same tool.
Add another account asks which tool when both are installed.
A Codex sign-in in the app shows the address codex login printed.
Labels belong to a tool: work can name a Claude Code and a Codex account, and codex/work says which.
A bare label means Claude Code for a new account, and is refused as label_ambiguous where it matches both tools.
pitboard adopt takes over a ~/.pitboard written on another computer, keeping each account's label, email and usage and dropping every parked login.
pitboard repair finds every parked login in the keychain or vault, and gives it back to its account, deletes it or reports it.
pitboard repair deletes only logins this Pitboard recorded.
On macOS, a login pitboard repair gave back that this Pitboard never recorded is deleted only once Pitboard has used it.
pitboard uninstall says how many parked logins it left that this Pitboard never recorded, as parks_left in --json.
A failed request to Anthropic carries a cause beside its code, such as unreachable, rate_limited or login_refused, in --json and the app.
A failed request to Anthropic says whether asking again can help, and pitboard status tells the causes apart.
The app has a window with each account's usage history, the full change log and what doctor found.
The app has a Settings window, opened with Command-comma, that can turn on scheduled renewal.
On a first run, the app says what state the machine is in and offers the next step.
The app's first launch opens its window.
The app can give up on an interrupted switch that recovery cannot finish.
pitboard doctor fails when anyone but the owner can read a stored login.
pitboard doctor lists what fills a login too large to store, largest first.
pitboard doctor says when an account has gone unused longer than its refresh token lasts.
pitboard doctor reports Claude Code's supervisor daemon, which also writes the login.
pitboard doctor shows the installed Claude Code version, beside the version Pitboard's facts about it were checked against.
pitboard doctor has environment.codex, and Codex checks whose codes start codex_.
pitboard doctor fails or warns about a Codex keychain store or API key login only where it stands in the way of enrolled Codex accounts.
pitboard doctor says what Pitboard holds back from asking Anthropic.
Pitboard keeps two weeks of each account's usage, and says how long the account lasts at its recent rate.
pitboard status names the credential slot it reports on, which CLAUDE_CONFIG_DIR selects.
pitboard renew renews every parked login that is due.
pitboard status --fresh and the app's Refresh ask at once, but never during a wait the service asked for with Retry-After.
pitboard schedule install runs pitboard renew on a schedule, through a LaunchAgent on macOS or a systemd user timer on Linux.
Pitboard warns when Claude Code's settings set an env block, an apiKeyHelper or a third-party provider that makes sessions ignore the login it switches.
A custom OAuth endpoint set in Claude Code's settings refuses a switch.
PITBOARD_NO_ARGV=1 refuses a login too large for security's standard input, instead of passing it as an argument.
What Pitboard removes from Claude Code's config goes into pitboard log.
In --json, use, enrolments and renewals give provider.
pitboard use --json gives adoption, which says whether running sessions follow on their own or need restarting.
pitboard status --json gives each account provider and qualified, such as codex/work.
pitboard status --json gives login_unreadable for a login Pitboard cannot read, and login_unusable for one it cannot switch, such as an API key.
Each limit in --json gives length_seconds.
Each release artefact comes with a CycloneDX bill of materials.
The bills of materials, SHA256SUMS and appcast.xml are attested like the artefacts.
Changed
Breaking: A Claude Code credential with no account, as /logout leaves, makes use and enroll exit 1 with live_credential_absent, not 3 with live_credential_shape_unexpected.
Breaking: The public API of pitboard-core changes; its documentation shows the new one.
The account index is schema 4, which earlier versions cannot read; they say which of the command line and the app to update.
Pitboard brings a schema 3 account index forward on first read.
pitboard doctor warns, instead of failing, when Claude Code's credential holds no account.
Messages name the tool, service and sign-in command of the account they are about.
Messages qualify a label to type, such as claude/work, where a bare one would be ambiguous.
CLAUDE_CODE_CUSTOM_OAUTH_URL refuses changes to Claude Code accounts only, not to Codex ones.
pitboard doctor warns about the storage v5 flag only when it is on and the login is in the fallback store.
Pitboard asks Anthropic about an account again only once its tightest limit could have moved by a percentage point.
Every front end waits out a refusal for as long as Retry-After says.
An interrupted switch is recovered without a network in most cases.
The app shows the last measured numbers when Anthropic cannot be reached, not an empty panel.
Text in the app grows with the system text size without clipping.
VoiceOver reads each account row as one item, and says whether each check passed.
A login too large for security's standard input is passed as an argument, as Claude Code does, and the switch says so.
Homebrew serves each release as it is published, not up to a day later.
Fixed
The app follows a switch made elsewhere on the machine, such as in a terminal, within seconds, not up to five minutes later.
A run killed while parking a login no longer leaves a live login that nothing names, and pitboard doctor reports any left.
A parked Claude Code login keeps the account's other credential keys, such as its device token, and a switch back restores them.
Cancelling a sign-in no longer holds the app.
The app shows every warning, not only the first.
A failed read in the app shows its own warnings, not those of the last read that worked.
VoiceOver no longer calls the status item "speedometer".
The app finds claude and codex installed through a Node version manager such as nvm or volta, or a custom npm prefix.
pitboard enroll <label> --sign-in for the account in use puts the new login in use, where it parked it.
When Pitboard cannot confirm a new sign-in is in use, it parks the login rather than lose it, and says why.
A renewal interrupted after writing the fresh login no longer loses that login on the next run.
Recovering an interrupted switch from another CODEX_HOME or CLAUDE_CONFIG_DIR stops with recovery_elsewhere.
A command refused over a mistyped name still finishes or undoes an interrupted switch, and reports it.
Labels written by 0.1.x that contain a slash can be switched to, forgotten, renamed and signed in to again.
Pitboard no longer asks about an account as often as once a minute over limit kinds it did not know, such as session.
Changing Claude Code's config no longer loses what Claude Code wrote to it meanwhile, such as project history.
A renewed login's expiry follows Anthropic's clock, not this machine's.
When Claude Code's config names a signed-in account whose login no store Pitboard reads holds, Pitboard refuses with live_credential_elsewhere.
A switch checks the incoming login with Anthropic first, and drops a refused login and stops.
A switch refuses an incoming login filed under the wrong account.
A switch renews an incoming login's expired access token.
A switch undone by a Claude Code /logout at the same moment fails with switch_did_not_hold, not with success.
A switch notices when the machine slept long enough for Claude Code to take back the credential lock, and stops.
A locked keychain no longer reads as a lost login: the switch keeps every copy and fails with switch_unverified.
Security
pitboard doctor --json no longer prints the signed-in email, organisation uuid, login name, a value derived from the refresh token or home paths with the username.
Renewing a parked login whose answer has no refresh-token lifetime keeps the deadline it had, as Claude Code does.
Pitboard refuses to act while CLAUDE_CODE_CUSTOM_OAUTH_URL is set, where a switch would restore into an item nobody reads.
Security
A switch no longer leaves the outgoing account's trustedDeviceToken, organizationUuid, enterpriseGateway or designOauth for the incoming account to present as its own.