Metadata-Version: 2.5
Name: overclaude
Version: 1.7.0
Summary: Claude Code, overclocked — multi-account hot-swap, context-threshold handoff, instrumented statusline, and model routing for multi-agent workflows
Project-URL: Homepage, https://github.com/arthur-bump-pm/overclaude
Project-URL: Repository, https://github.com/arthur-bump-pm/overclaude
Project-URL: Issues, https://github.com/arthur-bump-pm/overclaude/issues
Author: arthur-bump-pm
License: MIT
License-File: LICENSE
Keywords: claude,claude-code,cli,dotfiles
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# overclaude

[![PyPI version](https://img.shields.io/pypi/v/overclaude)](https://pypi.org/project/overclaude/)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
![Platform: macOS](https://img.shields.io/badge/platform-macOS-lightgrey)

**Claude Code, overclocked.** Hot-swap between Claude accounts without leaving your session, hand off to a fresh session before context fills up, and watch every usage meter live:

```text
Fable 5 (high) | myproject (master*) | 3 sessions | 👤 work [1/2] ↻ Thu Oct 9 23:59 (1d 6h)
└ model+effort   └ folder+branch*      └ live count └ account     └ when its weekly limit resets

ctx [████░░░░░░] 42% | 5h [███████░░░] 71% | week [██░░░░░░░░] 18% | Fable [███████░░░] 73%
└ context window       └ 5-hour limit         └ weekly limit           └ model-scoped bucket

↳ personal [2] 5h 10% · week 85% · Fable 100% ↻ Thu Oct 9 17:59 (1d 1h)
└ every OTHER account: its limits + weekly reset, so you know where to swap next

bars and percentages turn yellow at 50% · red at 80%
```

## Versions

| Version | Status | Highlights |
|---|---|---|
| **1.7.0** | ✅ released 2026-10-16 | Memory guard: this Mac's memory on the statusline (`mem 48% · swap 3.6G`, ⚠ when tight), `/swap mem` (what is using it, per session with its tests and builds, what to close), a watcher that cleans up orphaned helper processes (MCP servers, test runners whose session is gone) and notifies when memory gets tight, every session told to hold back, and new subagents refused while memory is critical. Re-login on a worker Mac and the job queue moved to 1.8 |
| 1.6.2 | ✅ released 2026-10-15 | Checkpoint before the limit: a running session is told once, mid-run, to wrap up and save progress when the account nears its limit (week 95%, 5h/Fable 90%). Fix: `auto install` silently dropped `--strategy` and `--cooldown` |
| 1.6.1 | ✅ released 2026-10-15 | Artifacts follow you only when needed: after an account change each session is told which of its own artifacts stay on the old account, and copies one to the new account (from its saved source, linked old → new) only when it needs to change it; `/swap artifacts carry` copies them all at once |
| 1.6.0 | ✅ released 2026-10-14 | Run-out forecast with "use this account first" (`/swap forecast`, statusline `⏳ use first`), re-login in the right Chrome profile (`swap-guard browser`), start idle accounts' 5-hour windows early (opt-in, experimental: needs long-lived tokens), `fleet auto on\|off`, scrub self-test / history scan / pre-push hook. Re-login on a worker Mac and the job queue moved to 1.7 — see [docs/plan-1.6.md](docs/plan-1.6.md) |
| 1.5.1 | ✅ released 2026-10-14 | Login end dates: every login ends about 30 days after sign-in, whatever keepalive does — overclaude now shows each account's date (statusline, doctor, `swap-guard logins`), warns 3 days ahead, and never swaps onto a login with under 6 hours left. QA fixes for 1.5: a token job's limit no longer switches the logged-in account, fleet swap leaves a Mac with instant swap off alone, a late "continue" after a server error is dropped once you've moved on, `token rm` reports a keychain that refused, doctor flags a Claude Code too old for keepalive |
| 1.5.0 | ✅ released 2026-10-14 | Logins that stay alive (keepalive, dead-login alert), resume after server errors, loop guard, instruction-size check. Experimental: long-lived tokens for headless jobs (not yet run against a real sign-in), and, not yet tested on real Macs, your other Macs over Tailscale (fleet status, moving them off a capped account), sessions on another Mac that you drive from claude.ai/code, `/handoff <mac>`. Re-login on another Mac and the job queue moved to 1.6 — see [docs/plan-1.5.md](docs/plan-1.5.md) |
| 1.4.0 | released 2026-10-09 | Codex as a fallback and a reviewer (`/handoff codex`, Codex limits on the statusline, `swap-guard codex-review`), model-routing guard for subagents, spend report with API-price value of your usage, works with overcodex 0.3 (Codex skills) |
| 1.3.1 | released 2026-10-09 | QA fixes for 1.3: `/swap` from plain requests (behind a consent gate), artifact links, terminal y/N during re-login, accurate token status in doctor |
| 1.3.0 | released 2026-10-09 | Instant swap on usage caps, safe re-login, usage notes for the model, artifact registry, `overclaude update`, `doctor --fix`, release gate |
| 1.2.0 | released 2026-10-09 | Busy-aware auto-swap, `overclaude doctor`, handoff history/restore, handoff size budget, tests + CI |
| 1.1.0 | released 2026-10-08 | Weekly reset + other accounts on the statusline, artifacts carried through handoffs |
| 1.0.x | released 2026-07-17/18 | First release: `/swap`, `/handoff`, statusline, ULTRACODE routing, PyPI package |

Install or upgrade: `pipx install overclaude && overclaude install` (upgrade: `overclaude update`, or `pipx upgrade overclaude && overclaude install` from versions before 1.3).

## What's new in 1.5

Plans: [docs/plan-1.5.md](docs/plan-1.5.md) (logins, Mac fleet), [docs/plan-1.6.md](docs/plan-1.6.md) (forecast, Chrome re-login, pre-warm). The multi-Mac features (fleet, sessions on another Mac, `/handoff <mac>`) are **experimental**: they are tested against simulated Macs only, not yet on real ones, and do nothing until you run `overclaude fleet add`.

- **Logins that stay alive** — a small background job (`swap-guard keepalive`, on by default) fetches every account's usage every 2 hours, which is what makes cswap refresh a login, so a login no longer dies just because you didn't use that account for a while. It never switches accounts and never writes a credential itself. When a login does die (revoked, or used on two machines), you get one notification a day with the fix (`swap-guard login N`). Off: `swap-guard keepalive off` (remembered across reinstalls).
- **Login end dates** — every login also has a fixed end date, about 30 days after you signed in, and refreshing does not move it: only a new sign-in starts a new login. Claude Code warns 3 days ahead, but only for the account it is logged into. overclaude covers every account: `swap-guard logins --text` lists each end date; the statusline shows `⚠ login ends 2d 4h` next to an account inside 3 days (red inside a day, `⚠ login ended` after); keepalive sends one notification a day from 3 days out; `overclaude doctor` lists them all. A swap never moves you onto a login with under 6 hours left: preflight answers `login-ending`, the instant swap and fleet swap pick another account, and auto-swap holds off (cswap chooses its target, so it waits rather than switch you there). Renew an account you're not on with `swap-guard login N`; the one you're on with `/login` (same account) and then `cswap add`. Only the two dates are read out of the keychain, never the token.
- **Run-out forecast (1.6)** — `swap-guard forecast --text` (or `/swap forecast`) tells you when your accounts run out at the pace of the last week, or that they last the week, for the weekly limit and the Fable limit. It names the account to use first: the one with room whose week resets soonest, because what's left at a reset is lost. The statusline marks an account `⏳ use first` when it has at least 30% left and its week resets within a day and before the one you're on and warns `⚠ accounts out ~Sat 14:00` when everything runs out within a day. `swap-guard auto install --strategy consume-first` follows the advice by itself. It reads cswap's usage cache only (no network); numbers that are hours old are marked.
- **Checkpoint before the limit (1.6.2)** — a long autonomous run never saw the usage notes (they arrive when you type). Now, after a tool call, the first time the active account crosses its line (5-hour window 90%, week 95%, Fable or another per-model limit 90%), the running session is told once to finish the step it's on, save progress (files, a commit, a short "where I am" note for long tasks) and not start a new batch of subagents; a subagent is told to return its result. Pair it with `swap-guard auto install --threshold 95` so switches happen between tasks; the instant swap still catches anything that reaches 100%. On by default (it spends nothing); `swap-guard checkpoint off` silences it. `auto install` now also passes `--strategy` and `--cooldown` (they were silently dropped before) and refuses options it doesn't know.
- **Artifacts follow you, only when needed (1.6.1)** — an artifact belongs to the account that published it, so after a switch the session can't update it. Now every session is told, the first time it notices the account changed (in the instant swap's wake-up message, or with your next message after `/swap`, auto-swap or a terminal switch), which of the artifacts *it* published stay behind. Nothing is copied up front: only when the session needs to change one again does it publish it as a new artifact on the account you're on, from its saved source, and link old → new (`swap-guard artifacts link`). `/swap artifacts carry` copies them all at once. Artifacts from other sessions are never touched; shared data (database rows, comments) stays with the original.
- **Re-login in the right Chrome profile (1.6)** — `swap-guard login N` (and `/swap relogin`) opens the sign-in page in the Chrome profile that belongs to that account: the one you chose with `swap-guard browser set <account> <profile>`, else the profile signed in to the same Google address. `swap-guard browser list` shows your profiles and which account uses which; `login N --profile <name>` picks one for a single run. You still click Approve yourself. Only the profile's folder name is saved; without Chrome (or with `SWAP_NO_CHROME_PROFILE=1`) the default browser opens as before.
- **Start an idle account's 5-hour window early (1.6, opt-in)** — a 5-hour window starts at an account's first message. With `swap-guard prewarm on` (or `/swap auto prewarm on`), the keepalive tick sends one one-word `claude -p` reply on each account that is not active, has no window running and has weekly room, at most once per 5 hours, so when you switch to it its window resets sooner. It uses that account's long-lived token (`swap-guard token add`, so it never switches or touches a login) from an empty folder with settings, hooks and MCP servers off, and spends a negligible share of the window. `swap-guard prewarm status` shows why each account is or isn't warmed. Experimental, like long-lived tokens.
- **Long-lived tokens for headless jobs (experimental)** — `swap-guard token add <account>` runs `claude setup-token` with its output hidden (you see only the sign-in link), checks that the one-year token works with one direct request to the API, and stores it in the keychain. The token never appears on screen, in a file or in a process list. `swap-guard token run <account> -- claude -p "…"` runs one command with it: Claude Code reads it from `CLAUDE_CODE_OAUTH_TOKEN`, so that command and everything it starts (its tools, hooks and MCP servers) can see it. A token job that hits its limit never triggers the instant swap: its limit belongs to the token's account, not the one you're logged into. These tokens only make model requests (no Remote Control, no usage figures), so they are for scripts and worker Macs; interactive sessions keep their normal logins. `overclaude doctor` warns 30 days before one expires.
- **Your other Macs, from this one (experimental)** — `overclaude fleet add <mac>` registers a Mac on your Tailscale network (SSH with a key, never a password prompt). `overclaude fleet` then shows every Mac: sessions (and how many are busy), which accounts are logged in and which is active, dead logins, load and memory, overclaude version. The statusline gets a `↳ fleet 3/3 macs · 7 sessions` line (refreshed in the background every 10 minutes; `SWAP_HIDE_FLEET=1` hides it), and `overclaude doctor` flags offline Macs, outdated kits and dead logins there. When an account hits its limit, the instant swap now also moves your other Macs off it, each to the account with the most room among those logged in there (`/swap fleet swap` does it by hand, after showing the plan). A Mac where you turned the instant swap off (`swap-guard auto instant off`) is left alone; to keep it on here without moving the other Macs: `swap-guard fleet auto off` (remembered; `on` to undo). Logins are never copied between Macs: each Mac logs in to its own accounts.
- **A session on another Mac (experimental)** — `/swap remote <mac> <goal>` (or `overclaude remote start <mac> <goal>`) starts Claude on that Mac in the background with Remote Control, named after the Mac and the goal, so you drive it from claude.ai/code or the Claude app. `remote list|logs|stop|attach <mac>` manage it. It uses that Mac's own login (a normal `/login`; setup-tokens can't do Remote Control) and starts in a folder you have trusted there: pass `--dir <project>`, because the home folder usually isn't trusted for this. The goal is passed as `Task: <goal>`, so it can never be taken as a command-line option. `/handoff <mac>` continues the current conversation there instead: the handoff package travels in the same SSH call that starts the session, lands where that Mac's startup hook loads it (with a lasting copy the session is pointed at, in case the hook isn't installed there), and starts in the same folder relative to home.
- **Resume after server errors (opt-in)** — `/swap auto retry on`: when a turn dies on a temporary server error (`server_error` / `overloaded`), the session waits (30 s, 2 min, 5 min) and continues by itself, at most 3 times per session per hour. Off by default.
- **Loop guard (opt-in, experimental)** — `/swap auto loop on`: when the same tool call fails the same way 3 times in a row (timings and line numbers don't hide a repeat; successful calls in between don't reset it, a different failure does; repeats more than 30 min apart don't count), Claude is told to stop repeating it and try a different approach; at 6, to stop and tell you. Silent otherwise. Off by default; `SWAP_LOOP_MAX` changes the 3.
- **Instruction-size check** — `overclaude doctor` reports how big your global instructions are (CLAUDE.md plus its `@` imports, loaded into every session), warns past ~40 KB, and flags imports that point at missing files.

## What's new in 1.4

- **Codex as the next place to work** — `/handoff codex` (or `/swap codex`) writes the handoff where overcodex's Codex hook loads it, so work continues in the Codex CLI when every Claude account is out; typing `$handoff-claude` in Codex (overcodex 0.3) hands it back. The usage note and the instant-swap notification suggest it when no Claude account has room.
- **Codex limits on the statusline** — `↳ codex 5h 12% · week 18% ↻ …` (every window that Codex account has), read from Codex's own session logs, one line per Codex account. `SWAP_HIDE_CODEX=1` hides them.
- **Codex as an independent reviewer** — `swap-guard codex-review` runs a read-only, ephemeral `codex exec` with a timeout (optional JSON verdict schema, `--stdin` for a diff). ULTRACODE now recommends one cross-family voter on verdicts that matter.
- **Routing guard** — on a Fable session, a subagent launched without a model (or a Workflow `agent()` call without one) is blocked with the fix, so the scarce tier is only spent on purpose. `/swap guard off` (or `OVERCLAUDE_ROUTE_GUARD=off`) disables it; the installer says when it turns on.
- **Spend report** — `/swap spend`: what your usage would cost at API list prices, by model, account, day and session, against what your plans cost; the statusline shows `💵 $1.8k/7d · 19.2× plan` (refreshed in the background every 15 minutes; `SWAP_HIDE_SPEND=1` hides it). The plan cost counts every registered account; plan prices come from each account's tier and can be overridden in `~/.claude-swap-backup/plans.json`.
- **Smarter instant swap and leaner snapshots** — ties go to the account with more of the capped model left; artifact snapshots are copy-on-write clones on APFS (identical content shares disk space, every copy stays independently editable).
- **Fixes** — `uninstall` refuses (instead of deleting everything below it) when the `.zshrc` block's end marker was edited or is missing, and keeps a symlinked `.zshrc`/`CLAUDE.md` and its file mode; the update badge re-checks PyPI right after an upgrade instead of showing a day-old "latest". Maintainers: `sync.sh --dry-run` no longer writes live copies into the repo.

## What's new in 1.3.1

QA fixes for 1.3, found by an audit of the released package:
- `/swap` can now be started by plain requests ("my work account says relogin — fix it"): the skill is model-invocable behind the same explicit-consent gate as `/handoff`, so the paste-a-prompt rows below actually run the safe flows.
- `swap-guard artifacts link <old-url> <new-url>` now connects republished copies (tool responses carry UUID ids while URLs end in a short code; both are matched, and `find` shows the linked URL).
- A cswap y/N confirmation during `/swap relogin` or `/swap add` (an organization change) now reaches you when you run `swap-guard login` in a terminal; `/swap add` reports the slot it registered.
- An expired-but-refreshing token (`token_expired`) is no longer reported as dead; accounts without an alias show their real status in `doctor`.
- The installer says when it turns instant swap on, and the update badge suggests `git pull && ./install.sh` for git-checkout installs.

## What's new in 1.3

- **Instant swap on a usage cap** — the moment "You've reached your Fable limit" stops a session, a hook switches to the account with the most room on that limit and wakes the session to carry on. Sessions that hit the cap together share one swap; a short-lived 429 slowdown never swaps; dead, disabled and API-key accounts are never targets. On by default (`/swap auto instant off` to disable), independent of the opt-in background auto-swap.
- **Re-login that doesn't kill your other account** — refresh tokens are single-use, so a plain `/login` over the live account overwrote its newest token and that account died next: re-logging one account killed the other, in turn. `/swap relogin <account>` (or `swap-guard login <account>` in a terminal) saves the live account's token first and signs in inside a throwaway profile, so the live login is never touched. `/swap add` uses the same flow and no longer needs `/logout`.
- **The model sees your usage** — when the active account crosses 75/90/100% of a model limit (or 85/95/100% weekly, 90/100% 5-hour), one line tells Claude, so ULTRACODE's budget rules (cut fan-out, keep the top tier for the final synthesis) actually kick in — with a pointer to an account that has room. One more line when the pressure clears; silent otherwise.
- **One list of every artifact** — every publish is recorded with the account that owns it and a durable copy of its source. `/swap artifacts villa` finds it from any account; `swap-guard artifacts index` backfills artifacts published before 1.3 (owner inferred from cswap's switch history).
- **Same link across accounts** — handoffs now say which account owns each artifact and suggest sharing it to the next account with edit access, so the new session updates it in place instead of republishing a copy at a new URL.
- **`overclaude update`** — upgrades however you installed it (pipx, uv or pip) and reinstalls the kit. The statusline shows `⬆ overclaude X available` when a release is out (checked in the background once a day; `OVERCLAUDE_NO_UPDATE_CHECK=1` hides it).
- **`overclaude doctor --fix`** (or `/swap doctor fix`) — reinstalls drifted or missing files and hooks, offers to restart a stopped auto-swap agent and to run the safe re-login for dead tokens (both only when run in a terminal), then checks again.
- **Safer releases** — the release script runs shellcheck and the full test suite before anything is committed or tagged, and the publish job reuses the push's test run instead of queueing a second macOS job.

## What's new in 1.2

- **Busy-aware auto-swap (opt-in)** — `/swap auto on` installs a background agent that switches accounts *before* you hit a wall. It never flips credentials while a session is mid-task (proactive switches wait); at-limit switches go through, dead tokens are skipped, bad settings are refused at install, and a macOS notification tells you what happened.
- **`overclaude doctor`** — one read-only command that checks dependencies, installed files, hooks, statusline, account tokens, sessions running stale hooks, and the auto-swap agent, with the exact fix for each problem. Also `/swap doctor`.
- **Recover expired handoffs** — `/handoff history` lists past packages; `/handoff restore [n]` re-arms one (packages expire 10 minutes after you leave a session). A package it replaces is archived, never discarded.
- **Handoffs never get truncated** — Claude Code caps hook output at 10,000 characters; oversized packages now inject section by section with a pointer to the full file, and the skill writes to a size budget.
- **cswap 0.26** bundled (was 0.21), and `overclaude install` upgrades an older copy.
- **Tests + CI** — a plain-bash suite (statusline, handoff budget, history/restore, auto-swap decisions, artifact snapshots) runs on macOS for every push, and releases only publish when it passes.

## What's new in 1.1

- **Weekly reset on the statusline** — `↻ Thu Oct 9 23:59 (1d 6h)` next to the account, in local time.
- **See every account's limits** — one compact line per other account (5h / week / Fable + reset), with `⚠ relogin` when a token has died.
- **Artifacts survive a handoff** — claude.ai artifacts the session made are snapshotted (sources + URLs + owner) before an account switch and handed to the next session, which keeps editing them or re-homes them on the new account.
- **Handoff packages before it switches** — so nothing that needs the old account (artifacts, artifact data) is lost to the credential flip.

## Install

```bash
pipx install overclaude && overclaude install
```

> **Fresh machine?** If you get `command not found: overclaude`, pipx's bin folder isn't on your PATH yet — run `pipx ensurepath && source ~/.zshrc`, then `overclaude install`. (Use `source`, not `exec zsh`: replacing the shell swallows any commands you pasted after it.)

Then register your accounts (once):

```bash
cswap add             # registers the account you're logged in as
cswap alias 1 work    # name your slots
cswap alias 2 personal
exec zsh              # reload shell
```

Start a **new** Claude Code session (hooks load at session start) and check the statusline shows `👤 work [1/2]`. Adding a second account is guided — run `/swap add` inside Claude Code. Anything look wrong? `overclaude doctor` checks the whole setup and prints the fix for each problem.

<details>
<summary>Other install methods, requirements, upgrading</summary>

```bash
# uv
uv tool install overclaude && overclaude install

# from source
git clone https://github.com/arthur-bump-pm/overclaude && cd overclaude && ./install.sh

# track unreleased main
pipx install git+https://github.com/arthur-bump-pm/overclaude.git
```

Or paste this into any Claude Code session and let it install itself:

> Install overclaude (https://github.com/arthur-bump-pm/overclaude) on this machine, fix anything its preflight complains about, and tell me what post-install steps I need to do myself.

**Requirements:** macOS, zsh, `jq`, `pipx` or `uv`, Max-style Claude subscription accounts. The credential engine (cswap) ships inside the package and installs automatically.

**Upgrade:** `pipx upgrade overclaude && overclaude install`

**Uninstall:** `overclaude uninstall` — removes exactly what install added (backed up, settings merged out); account state in `~/.claude-swap-backup/` survives.

The installer is idempotent and conservative: timestamped backups of everything it touches, jq-merge into your existing `settings.json` (other hooks survive), never overwrites an existing statusLine, re-running is a no-op.

</details>

## What you get

### `/swap` — hot account switching
Every live Claude Code session on the machine adopts the new account's credential within ~30 s — mid-conversation, no restart, context preserved. Hit a rate limit? `/swap work` and keep typing. A preflight blocks the swap while another session is mid-task (`force` overrides).

### `/handoff` — escape context bloat, keep the thread

```mermaid
flowchart LR
    A[Context fills up] --> B[Hook offers handoff at 60/75/85%]
    B --> C[You accept]
    C --> D[Claude packages goals, state, next steps, artifacts]
    D --> E[Session exits, shell wrapper relaunches]
    E --> F[SessionStart hook auto-injects the package]
    F --> G[Fresh session, ctx near zero]
    G --> A
```

You lose the token bloat, not the thread. Works same-account (`/handoff`) or combined with a switch (`/swap work handoff`).

**Artifacts travel too.** Before switching accounts, handoff runs `swap-guard artifacts`: it reads the session transcript (subagents and workflows included), finds every claude.ai artifact the session published or touched, copies each source out of the session's temporary scratchpad into `~/.claude-swap-backup/handoff-artifacts/<session>/`, and lists them in the package with their URLs and owner account. Artifacts belong server-side to the account that published them, so the next session updates them in place on the same account, and on a different account republishes from the saved source as a new artifact (or updates in place if you shared the original with edit access). Artifact database rows can be exported before the switch on request.

### Statusline
The display at the top. Line 1 ends with the active account and when its **weekly limit resets** (local time + countdown). Line 2 is the live meters. Below that, each **other account** gets a compact line with its 5h / week / Fable usage and weekly reset, so you can see where to swap before you hit a wall — `⚠ relogin` flags a dead token, a dim `(2h old)` flags stale numbers, and `SWAP_HIDE_OTHERS=1` hides these lines.

Usage numbers come from cswap's per-account cache, kept ≤ ~5 min fresh by a debounced background refresh (the render itself never waits on the network). It is also the kit's data spine: it publishes each session's context % to a relay the threshold hooks read. **Skip the kit's statusline and handoff offers never fire.**

### Memory guard — many sessions, one Mac *(1.7)*
Several sessions, each with its own test runs, builds and MCP servers, can push a Mac into heavy swapping, and then every session stops responding at once. A small background agent checks memory every minute (`swap-guard mem watch on|off`, on by default; it reads `sysctl`, `memory_pressure` and `vm_stat`, which takes milliseconds):

- **Statusline:** `mem 48% · swap 3.6G`, turning into a yellow `⚠` when memory is tight and a red `⚠ … critical`. `SWAP_HIDE_MEM=1` hides it.
- **`/swap mem`** (or `swap-guard mem --text`): memory in use, swap, the biggest apps, each Claude session with what its child processes use, orphaned helpers, and what to close.
- **When it gets tight** (warn: kernel pressure raised or under 20% free; critical: kernel pressure critical or under 10% free, or, while memory is tight, swap over half of RAM. Swap alone never counts, because macOS keeps it allocated for hours after the pressure is gone):
  - **Cleanup** (`mem autoclean`, on): stops *orphaned helpers* whose session is provably gone. A process counts only when all of these hold:
    - it is your own, its parent is now launchd, and it is not a launchd job or a Claude session;
    - it looks like something a session starts: an MCP server, `npx`/`uvx`, a test runner, `esbuild`, `ffmpeg-static`, a headless browser;
    - **its stdin was a pipe or socket from whatever started it, and nothing holds the other end any more** (how a session talks to a stdio MCP server). A live session's own `cmd &` has stdin `/dev/null`, so it never qualifies;
    - it is idle, at least 10 minutes old, and not listening on a port.

    An idle orphaned MCP server can hold hundreds of MB in compressed memory while showing 15 MB.
  - **A notification** with the reason, what was freed, the biggest users and the top suggestion; it repeats every 15 minutes while memory stays critical (a level flapping around a line notifies once), and says when memory has been back to normal for 5 minutes.
  - **Every session is told once** (`mem nudge`, on) to hold back: no new subagents, workflows or parallel test runs, and save progress. Subagents are told to finish and return.
  - **At critical, new subagents and workflows are refused** (`mem gate`, on; `OVERCLAUDE_MEM_GATE=off` for one session), so one session's fan-out can't freeze the rest.

It never quits an app or ends a live session: those stay suggestions. Orphans it can't prove dead (a dev server on a port, something still working, a background job a live session may own) are only listed, with `swap-guard mem clean --pid N` to stop one. `swap-guard mem clean --dry-run` shows what a cleanup would stop.

### `ULTRACODE.md` — model routing for multi-agent workflows
A policy loaded into every session: bulk work rides cheap models, verification rides opus, only final judgment spends the top tier. Routing table, hard floors, escalation rules included.

## Cheat sheet

| Command | Effect |
|---|---|
| `/swap` | Dashboard: accounts, usage, token health, live sessions |
| `/swap <target>` | Hot-swap all sessions to `<target>` (alias, slot, or email) |
| `/swap <target> force` | Same, bypassing the busy-session guard |
| `/swap <target> handoff` | Package this session (+ its artifacts), switch account, resume fresh |
| `/swap <target> restart` | Switch + restart this session in place (auth edge cases) |
| `/swap add` | Register a new account (browser sign-in; live sessions untouched) |
| `/swap relogin <account>` | Revive a dead token without killing the live account's |
| `/handoff` | Package this session and continue fresh, same account |
| `/handoff status` | Context %, thresholds fired, pending package state |
| `/handoff cancel` | Cancel a pending handoff |
| `/handoff history` | List archived handoff packages for this folder |
| `/handoff restore [n]` | Re-arm an archived package (default: newest), then Ctrl+D |
| `/swap auto on\|off\|status` | Busy-aware background auto-swap (`threshold N`, `model Fable`) |
| `/swap auto instant on\|off` | Instant swap the moment a usage cap stops a session (default on) |
| `/swap artifacts [words]` | Search every artifact you published, with its owning account |
| `/swap doctor [fix]` *(or `overclaude doctor [--fix]`)* | Health check with fixes; `fix` applies the safe ones |
| `/swap codex` *(or `/handoff codex`)* | Continue this work in the Codex CLI *(1.4)* |
| `/swap spend [days N]` | API-price value of your usage vs your plans *(1.4)* |
| `/swap guard on\|off\|status` | Routing guard for subagents on Fable *(1.4)* |
| `swap-guard keepalive on\|off\|status` *(shell)* | Background refresh that keeps idle accounts' logins alive (default on) *(1.5)* |
| `swap-guard browser list\|set\|clear` *(shell)* | Which Chrome profile a re-login opens in *(1.6)* |
| `/swap auto prewarm on\|off` | Start idle accounts' 5-hour windows early (opt-in) *(1.6, experimental)* |
| `/swap auto checkpoint on\|off` | Tell a running session to wrap up once when the account nears its limit (default on) *(1.6.2)* |
| `/swap artifacts carry` | Copy this session's artifacts to the account you're on now, after a switch *(1.6.1)* |
| `/swap forecast` | When your accounts run out at this pace, and which one to use first *(1.6)* |
| `/swap mem [clean]` | This Mac's memory: what is using it, sessions with their tests and builds, what to close; `clean` stops orphaned helpers *(1.7)* |
| `swap-guard mem watch\|autoclean\|nudge\|gate on\|off` *(shell)* | The memory watcher and what it does when memory gets tight (all on by default) *(1.7)* |
| `swap-guard logins [--text]` *(shell)* | Each account's login end date (a new sign-in starts a new one) *(1.5.1)* |
| `overclaude fleet [add <mac>\|rm <mac>\|list\|swap\|auto on\|off]` *(shell)* | Your other Macs over Tailscale: sessions, accounts, dead logins, load; `swap` moves them off a capped account; `auto off` stops the instant swap here from moving them *(1.5, experimental)* |
| `/swap remote <mac> [goal]` | Start a Claude session on another Mac, driven from claude.ai/code; `overclaude remote list\|logs\|stop\|attach` *(1.5, experimental)* |
| `/handoff <mac>` | Continue this conversation in a session on another Mac *(1.5, experimental)* |
| `/swap auto retry on\|off` | Resume a session after a temporary server error (opt-in, max 3 tries/hour) *(1.5)* |
| `/swap auto loop on\|off` | Tell Claude to rethink when one tool call keeps failing the same way (opt-in) *(1.5)* |
| `swap-guard token add\|list\|rm\|run` *(shell)* | One-year tokens for `claude -p` jobs, kept in the keychain, never shown *(1.5, experimental)* |
| `overclaude update` *(shell)* | Upgrade from PyPI and reinstall the kit |
| `swap-guard artifacts find <words>` *(shell)* | Search every artifact published from this machine, with its owner |
| `swap <alias>` *(shell)* | Panic-switch from any terminal, even with sessions hung |

Or skip memorizing and **paste a prompt**:

| Paste into Claude Code | Runs |
|---|---|
| "Swap me to my work account" | `/swap work` |
| "Context is getting full — hand off to a fresh session" | `/handoff` |
| "Swap to personal and hand off in one shot" | `/swap personal handoff` |
| "What's my context and account usage right now?" | `/handoff status` + `/swap` dashboard |
| "Switch accounts automatically before I hit my Fable limit" | `/swap auto on model Fable` |
| "Something's off with my setup — check it" | `/swap doctor` |
| "My work account says relogin — fix it" | `/swap relogin work` |
| "Where's that villa comparison artifact?" | `/swap artifacts villa` |
| "My handoff expired — bring it back" | `/handoff restore` |
| "My Mac is slow — what's eating memory?" | `/swap mem` |
| "Install overclaude on this machine" | the whole install flow (works before the kit exists) |
| "Upgrade overclaude and refresh the hooks" | `overclaude update` |

## How it fits together

```mermaid
flowchart TD
    SL[Statusline publishes ctx relay] --> HK[ctx-watch and ctx-notify hooks]
    HK --> SK[swap and handoff skills]
    SK --> GD[swap-guard busy preflight]
    GD --> CS[cswap vendored engine]
    CS --> KC[macOS keychain credential]
    KC --> AS[All live sessions adopt within 30s]
```

The heavy lifting — credential storage, keychain switching, OAuth refresh, usage polling — is **[claude-swap](https://github.com/realiti4/claude-swap)** by [Onur Cetinkol](https://github.com/realiti4) (MIT), vendored unmodified in `vendor/claude-swap/` and installed automatically. Go star it.

<details>
<summary>Caveats worth knowing</summary>

- A swap flips **all** live Claude Code sessions on the machine — it's the shared keychain credential, not per-terminal.
- Hooks load at session start; sessions already open at install time won't offer handoffs until restarted (hot-swap works everywhere immediately).
- Usage meters read cswap's cache for the active account (correct the moment a swap lands) and are refreshed in the background every ~5 min while any statusline renders; past 10 min a dim `(usage Nm old)` marker appears. The ctx meter is real-time.
- An inactive account whose reset time has passed is shown at 0% — nothing on this machine has used it since. Usage from elsewhere (claude.ai web, another machine) appears on the next refresh.
- claude.ai artifacts are owned by the account that published them. After a cross-account handoff the old URLs stay viewable from the owner account but aren't editable from the new one — the next session re-homes them from the saved source (new URL), unless you share the original with edit access.
- Instant swap wakes the stopped session through Claude Code's `asyncRewake` hook mechanism; if your Claude Code version doesn't resume it, the notification tells you to send any message. Each session is woken at most once per 10 minutes, so an account that is still capped can't loop.
- Never re-login a dead account with a plain `/login` while another account is live — use `/swap relogin` (see 1.3 notes). `cswap run` profiles hold a second copy of an account's token chain and can fork it the same way.
- Legacy clients that don't report status (older VS Code extension builds) are judged busy/idle by transcript mtime during swap preflight.
- claude.ai connectors (Gmail/Drive/…) are per-account server-side and don't follow a swap.
- Context thresholds re-arm 10 points below a fired threshold; Claude Code's auto-compact stays as the backstop.
- Auto-swap: a session that Claude Code paused at a usage limit doesn't resume by itself after a background switch (Claude Code only re-checks after `/model`, `/usage-credits`, or `/upgrade`) — send any message and it continues on the new account. Proactive switches wait while any session is busy, so a machine that is never idle only switches at the limit. The agent doesn't do cswap's "failover" for an account whose usage can't be read — that needs a long-running `cswap auto` loop.

</details>

<details>
<summary>Components (file → destination)</summary>

| File | Installs to | Role |
|---|---|---|
| `bin/swap-guard` | `~/.local/bin/` | State/guard engine: whoami, live-session table, busy preflight, per-directory handoff state, handoff history/restore, artifact snapshots + registry, busy-aware auto-swap, instant swap on a usage cap, usage-band notes for the model, safe re-login |
| `skills/swap/SKILL.md` | `~/.claude/skills/swap/` | The `/swap` skill |
| `skills/handoff/SKILL.md` | `~/.claude/skills/handoff/` | The `/handoff` skill |
| `hooks/handoff-inject.sh` | `~/.claude/hooks/` | SessionStart: auto-loads a pending handoff package (10-min TTL, per-directory) |
| `hooks/ctx-watch.sh` | `~/.claude/hooks/` | UserPromptSubmit: fires the 60/75/85% offers with re-arm hysteresis |
| `hooks/ctx-notify.sh` | `~/.claude/hooks/` | Stop: threshold banners |
| `statusline/statusline-command.sh` | `~/.claude/statusline-command.sh` | Renders the statusline; publishes the ctx relay |
| `claude/ULTRACODE.md` | `~/.claude/` + `CLAUDE.md` import | Model/effort routing policy |
| `settings/settings-fragment.json` | merged into `~/.claude/settings.json` | hooks (SessionStart handoff inject; UserPromptSubmit ctx-watch + usage bands; Stop banners; StopFailure `rate_limit` instant swap; PostToolUse `Artifact` registry), statusLine, 2 permission allows |
| `shell/zshrc-snippet.sh` | `~/.zshrc` (markers) | `claude()` relaunch wrapper, `swap` alias, PATH guard |
| `vendor/claude-swap/` | pipx/uv-installed if absent or older | The bundled credential engine (0.26.0) |
| `doctor.sh` | run by `overclaude doctor` | Read-only health check |
| `~/Library/LaunchAgents/com.overclaude.autoswap.plist` | only via `/swap auto on` | Runs `swap-guard auto tick` every 3 min (opt-in; removed by uninstall) |

</details>

<details>
<summary>Maintainer workflow</summary>

```bash
./sync.sh            # live setup -> repo: scrub-gated diff, commit, push
./sync.sh --release  # + version bump + GitHub release -> PyPI (trusted publishing)
./sync.sh --dry-run  # preview either
bash scrub.sh --install-hook   # once per clone: pre-push check for commits made outside sync.sh
bash scrub.sh --history        # scan every commit for personal data
```

`bash tests/run.sh` runs the suite locally (throwaway `$HOME`, never touches your live setup); CI runs it plus shellcheck and a wheel-payload check on macOS for every push, and the PyPI publish job waits for it.

A plain `git push` updates git installs only — **PyPI users get changes only via releases**. The scrub gate aborts any commit whose diff contains usernames, emails, or `/Users/…` paths, and first proves it still works (`scrub.sh --self-test`). See `CLAUDE.md` for the full protocol.

</details>

## Roadmap

1.8: re-login on a worker Mac and a job queue (Part B of [docs/plan-1.6.md](docs/plan-1.6.md)), once the multi-Mac features have been tried on real Macs. Also on the list:

1. **Titled relaunch after handoff** — `claude -n "↪ <goal>" "Continue from the handoff"`.
2. **Compaction awareness** — re-inject handoff state and artifact links after `/compact`.
3. **Per-directory accounts** via cswap `map`/`run` (needs every component to honor `CLAUDE_CONFIG_DIR`).

## License

MIT — see [LICENSE](LICENSE). Vendored claude-swap retains its own MIT license and copyright (Onur Cetinkol).

Login end dates (1.5.1) and several roadmap items were prompted by [claude-cockpit](https://github.com/christianjohnston-ai/claude-cockpit) (MIT), whose notes measured that a refresh never moves a login's end date. No code was copied; overclaude's version is its own.
