Keep Claude Code's Remote Control and Artifacts on one account while inference follows cswap's account swap
Project description
cswap-pin
Keep Claude Code's Remote Control and Artifacts on one account while
inference keeps following cswap's
account swap.
The problem
cswap swaps the on-disk credential, so everything follows the swap — including two things that are not inference and that you usually want to stay put:
- Remote Control — a session's owner is fixed at creation by whichever bearer created it. Swap accounts and the phone/web loses the session; stale "ghost" sessions pile up on the old account.
- Artifacts — owned by the publishing bearer. After a swap a republish 403s and the artifact "disappears" from the account you are logged into.
Claude Code resolves all of these through one credential accessor and has no per-operation token selector, so splitting auth per operation inside one session means intercepting the requests.
How it works
A local MITM forward proxy that swaps the Authorization bearer on exactly
the routes whose server-side ownership is decided by it, and passes everything
else — /v1/messages above all — through untouched.
claude session
HTTPS_PROXY ─► cswap pin proxy ──► (whatever HTTPS_PROXY was already set) ──► api.anthropic.com
swaps bearer on: /v1/code/sessions*, /v1/sessions/*,
/api/frame/*, /v1/ultrareview/*
passes through: /v1/messages, /api/oauth/usage, everything else
Inference keeps billing whichever account cswap has swapped onto. Only the claude.ai-side assets are pinned.
Install
uv tool install 'claude-swap[pin]' # or: pipx install 'claude-swap[pin]'
The pin is an optional extra of claude-swap, not a standalone tool: it reads
cswap's account store and rewrites the config cswap already manages. Installing
cswap-pin on its own does nothing useful.
Use
cswap pin 2 # RC / artifacts / ultrareview → account 2
cswap pin # show the current pin
cswap pin --clear # remove it
The pinned account is re-read per request, so cswap pin <other> takes effect
under a live daemon — no session restart. The one thing a re-pin cannot move is
a Remote Control session that is already open: the server fixed its owner
when it was created, so reconnecting inside it is what mints a new one under
the new pin.
Requirements
- Python 3.10+
claude-swap— a peer, not a dependency: this package is loaded by it (seesrc/cswap_pin/_host.pyfor the exact surface it borrows)cryptography(installed automatically) for the MITM CA
Why a separate package
Upstream did not want a MITM proxy shipped inside claude-swap itself and asked for a companion distribution exposed through an optional extra. See realiti4/claude-swap#198.
Trust
The proxy generates its own CA to re-sign api.anthropic.com and names it in
NODE_EXTRA_CA_CERTS. Node accepts exactly one file there, so an existing CA
(a corporate MITM, another local proxy) is merged, never replaced —
otherwise the session silently loses trust in every host the other proxy
re-signs.
The proxy also requires a per-daemon credential on CONNECT: it listens on
loopback, which carries no identity, and without one any local process could
have a junk bearer replaced with the pinned account's real token.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cswap_pin-0.1.1.tar.gz.
File metadata
- Download URL: cswap_pin-0.1.1.tar.gz
- Upload date:
- Size: 91.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d77c53aa50f0a30b4cf434ff2ec48b540411d24aa09156f4a5e0abb4f23017b
|
|
| MD5 |
074d46fa0c38c583fe213396c08aa841
|
|
| BLAKE2b-256 |
73c41535ee1c47391626ebeec55b66ad595f56292d40ff1359ed297d9e48e3cf
|
File details
Details for the file cswap_pin-0.1.1-py3-none-any.whl.
File metadata
- Download URL: cswap_pin-0.1.1-py3-none-any.whl
- Upload date:
- Size: 48.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ff707482e29aebab6c157651af44d47dc9725f1e168fd5a5dab46bc4d7be4f3
|
|
| MD5 |
6aa83efae9e7c0d96d27a7d7aaebec5d
|
|
| BLAKE2b-256 |
f2f83f5ee753a7a5c0d6ab0bc6c1f5b7cccdebb01c74679c1b362137e6c261b8
|