claudswap
Switch Claude Code to any model — including the old ones /model doesn't show you.
Claude Code's built-in /model picker only lists the models Anthropic currently promotes. But the API supports every model your account has access to, and /model <exact-id> still works if you know the ID. claudswap bridges the gap: a /swap command that lists everything, resolves fuzzy aliases, and actually switches the running session.
Why reach for an older model? They aren't just cheaper or faster — they behave differently. If you tuned a prompt against a specific version, you're comparing behavior across versions, or you need to reproduce something a particular model did, "whatever is newest" is the wrong tool. The API keeps serving them; only the picker moved on.
The problem
Claude Code's live model is in-process state. No file, socket, or API can change it from outside — only the CLI's own /model command, dispatched through stdin. Most terminals have no way to programmatically type into their own input. The kernel mechanism that used to allow this (TIOCSTI) is dead since Linux 6.2.
The solution
claudswap is a transparent pty wrapper. It runs claude under a pseudo-terminal and exposes a FIFO. Anything inside the session can inject input by writing to the FIFO. The terminal is out of the equation — it works in VS Code, GNOME Terminal, Windows Terminal, Terminal.app, Alacritty, bare SSH, everywhere ptys exist.
For tmux, screen, and zellij users, /swap works without the wrapper — their APIs can target their own pane. claudswap is the universal path for everything else.
Install
pip install claudswap
claudswap install
pip install gives you the claudswap wrapper. claudswap install writes the /swap slash command and its backend into ~/.claude/ — run it once. (pip can't do that step itself; post-install hooks are unreliable and effectively deprecated.)
From source, without pip
git clone https://github.com/brandonrthomas/claudswap.git
cd claudswap
bash install.sh
Either route puts:
claudswapin~/.local/bin/switch-model.shin~/.claude/scripts//swapslash command in~/.claude/commands/
Usage
Start a session with claudswap
claudswap # same as: claude
claudswap -c # same as: claude -c (resume)
claudswap --model opus # same as: claude --model opus
claudswap --200k # use 200K context on models that support it
claudswap --run bash # wrap any command, not just claude
Or make it the default:
# add to .bashrc / .zshrc
alias claude=claudswap
/swap — list models
Type /swap with no argument inside a Claude Code session. Example output — the real list is fetched live from the API, so yours will differ:
Context: 1M
# alias name released
── Fable ─────────────────────────────────────
1 fable Claude Fable 5 2026-06-07
── Opus ──────────────────────────────────────
2 opus Claude Opus 5 2026-07-24
3 opus-4.8 Claude Opus 4.8 2026-05-28
4 opus-4.7 Claude Opus 4.7 2026-04-14
5 opus-4.6 Claude Opus 4.6 2026-02-04 ← current
6 opus-4.5 Claude Opus 4.5 2025-11-24
── Sonnet ────────────────────────────────────
...
── Haiku ─────────────────────────────────────
...
Numbers and aliases auto-update when Anthropic adds new models. When launched with claudswap --200k, the context mode shows "200K" instead of "1M".
/swap — switch models
/swap 2 → switches to model #2
/swap opus → switches to newest Opus
/swap haiku → switches to newest Haiku
/swap opus 4.7 → switches to Opus 4.7
The switch fires the moment Claude's current turn ends.
How it works
-
claudswap allocates a pty, runs
claudeon it, and mirrors I/O in raw mode (window resizes, signals, exit status — all transparent). It also opens a per-session FIFO at$CLAUDSWAP_FIFO. -
/swap fetches the full model list from
GET /v1/modelsusing the Claude Code OAuth token, resolves the user's input (number, alias, substring), and writes/model <resolved-id>\rto the FIFO. -
Claude Code sees
/model ...as typed input, queued during the current turn. When the turn ends, it executes — switching the live model.
Injection backends
| Backend | When it's used | Needs claudswap? |
|---|---|---|
| claudswap | $CLAUDSWAP_PID in process ancestry |
Yes |
| tmux | tmux in process ancestry |
No |
| screen | screen in process ancestry |
No |
| zellij | zellij in process ancestry |
No |
| (manual) | Everything else | Prints /model command for you |
Backend detection walks the process tree (not env vars — those get inherited across terminal boundaries and cause mis-targeting). The nearest multiplexer or wrapper wins.
Credentials
/swap reads your Claude Code OAuth token from ~/.claude/.credentials.json in order to call GET /v1/models. It is sent only to api.anthropic.com over HTTPS — the same endpoint Claude Code itself uses, and the only host this project contacts.
The token is never printed, logged, or written to disk, and it is never placed in a command line. Passing a credential as a process argument would expose it through /proc/<pid>/cmdline, which any process running as you — and root — can read for the duration of the call. Instead it is piped to curl on stdin via --config -. The claudswap wrapper never touches the token at all; it only moves bytes between your terminal and the pty.
Requirements
- Python 3.9+ (the pty wrapper is standard library only — no runtime dependencies)
jqandcurl(for the API call)- Claude Code with an active OAuth session (
~/.claude/.credentials.json)
Authors
- Brandon Thomas — author
- Claude — co-author (written with Claude Code)
License
Apache-2.0 © 2026 Brandon Thomas
Metadata
Release files for claudswap 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| claudswap-0.2.0.tar.gz | 16.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| claudswap-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 34.6 kB
Release files / claudswap-0.2.0.tar.gz
| Download URL | claudswap-0.2.0.tar.gz |
|---|---|
| Size | 16.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ee3f5f7f05721598775b690c8f69fabe018ec4f3fd6cb378a5f0f2eed2d02ac8
|
|
BLAKE2b-256 checksum How to use checksums |
bf91b52dd4144ab2a63e6f583232fa27145d3e483f1a1e661b28abe560152487
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.
Transparency logRelease files / claudswap-0.2.0-py3-none-any.whl
| Download URL | claudswap-0.2.0-py3-none-any.whl |
|---|---|
| Size | 18.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
94c8a80091cbcdf3a07283f736203310cb53c0b5fe4e51f6d9191dca6cbd25b9
|
|
BLAKE2b-256 checksum How to use checksums |
c0770e4e84b3d7e7e0c331f6d8eb88284df6b7a0a06f081be3c9ba737848e0fd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.
Transparency log