All notable changes to this project are documented here. Each entry links to the corresponding PR or issue.Documentation Index
Fetch the complete documentation index at: https://cac.nextmind.space/docs/llms.txt
Use this file to discover all available pages before exploring further.
v1.5.7
2026-04-27 Fix:cac env create --clone was missing agents/
~/.claude/agents/ (subagent definitions) was not in the clone list, so newly created environments via --clone never inherited custom subagents — only commands/hooks/skills/plugins/CLAUDE.md were symlinked.
- Added
agentstoclone_dirsincac env create. From v1.5.7 onwards,--clone hostand--clone <env>both symlink (or copy with--no-link)~/.claude/agents/alongside the other shared resources. - Existing environments are not auto-fixed — relink manually if needed:
ln -s ~/.claude/agents ~/.cac/envs/<name>/.claude/agents.
v1.5.6
2026-04-27 Fix: SOCKS5 diagnostics were using local DNS instead of proxy DNScac env create timezone detection and cac env check exit-IP detection previously called curl --proxy socks5://... directly. With SOCKS5, that makes curl resolve probe domains locally instead of through the remote proxy.
In environments with DNS pollution, split-DNS, captive enterprise resolvers, or synthetic test ranges such as 198.18.0.0/15, that created a bad failure mode:
- the proxy itself was healthy
- real proxied traffic still worked
- but diagnostic requests resolved to the wrong address locally and failed during TLS
-
cac env checkthen reported✗ exit IP unable to verify via proxy - new environments could also inherit the wrong timezone during creation
-
Added an internal helper that rewrites curl-based SOCKS5 probes to
socks5h://..., forcing remote DNS resolution. -
Fixed timezone geo-detection during
cac env create. -
Fixed false-negative exit-IP and timezone diagnostics in
cac env check. -
Added a shell regression test to ensure SOCKS5 probe paths keep using
socks5h://.
v1.5.5
2026-04-22 Fix: proxy startup and diagnostics consistency This release promotes the1.5.5 beta line to stable after validating the new proxy-path behavior end to end.
- Legacy SOCKS5 proxy URIs stored as
socks5://host:port:user:passare now normalized to the standardsocks5://user:pass@host:portform before startup checks, relay startup, and environment diagnostics. cac env checkno longer reports a configured proxy as healthy when exit IP detection fails across all probe endpoints. Failed exit-IP verification now surfaces as a real problem instead of a retry hint.- The generated
claudewrapper now performs proxy normalization without depending on helper functions from the maincacscript, fixing the beta.1 startup regression. - CI now fails if
package.json,src/utils.sh, and committedcacdrift out of sync on version metadata.
v1.5.5-beta.2
2026-04-22 Fix: wrapper startup regression in beta.1v1.5.5-beta.1 normalized legacy SOCKS5 proxy URIs inside the generated claude wrapper, but the wrapper accidentally called helper functions that only exist in the main cac script. Any proxied claude launch could fail immediately with _parse_proxy: command not found.
- Inline proxy normalization inside the generated wrapper so proxied
claudestartup no longer depends on main-script helper functions. - Preserves the legacy SOCKS5 compatibility fix from beta.1 while restoring wrapper startup.
v1.5.5-beta.1
2026-04-22 Fix: legacy SOCKS5 proxy URI compatibility Some environments already stored SOCKS5 proxies in the legacy formsocks5://host:port:user:pass. Startup pre-flight treated the last field as the TCP port, so cac <env> could reject a reachable proxy as “unreachable” before Claude even launched.
- Normalize legacy protocol-prefixed proxy strings to the standard form
socks5://user:pass@host:port. - Reuse the same normalization for startup pre-flight,
cac env check, relay startup, and environment listing so old saved environments behave consistently.
cac env check false positive when exit IP cannot be verified
When a proxy was configured but every exit-IP probe failed, cac env check still printed a green exit IP line and could end with all good, hiding a broken proxy path behind a retry hint.
- Exit IP detection now reports
✗ exit IP unable to verify via proxywhen all probe endpoints fail. - Failed exit-IP verification is added to the problem summary, so a configured-but-unverified proxy can no longer pass as healthy.
build-checknow fails ifpackage.json,src/utils.sh, and committedcacdisagree on the release version.
v1.5.4
2026-04-02 Fix: Claude auto-updater bypasses cac wrapper mid-session — PR #62 Claude Code’s auto-updater re-execs a new binary directly, skipping the cac wrapper entirely — fingerprint spoofing, dns-guard, and timezone settings all stop working for the remainder of the session. The UI still shows the old version, but/usage reveals the real timezone.
Root cause: Claude migrated the “disable auto-updates” setting from autoUpdates: false in .claude.json to DISABLE_AUTOUPDATER=1 in settings.json. cac’s settings.json template didn’t include this field, so new environments were left unprotected.
- New environments get
DISABLE_AUTOUPDATER: "1"insettings.jsonfrom creation. - Existing environments are patched automatically on the next
cacinvocation (_ensure_initialized). Agrepshort-circuit prevents repeated python3 forks once already patched.
v1.5.3
2026-04-01 Fix:sudo cac corrupts ~/.cac/ file ownership — PR #59
Running cac as root (e.g. sudo cac <env>) overwrites hook files (fingerprint-hook.js, cac-dns-guard.js, etc.) with root-owned copies. Subsequent normal-user runs load the stale root-owned version, causing claude to hang at startup with no error output.
- Self-healing writes:
rm -fbefore each hook file write — user owns~/.cac/directory so can always unlink files in it, even root-owned ones. Nextcaccommand automatically replaces any stale root-owned files with the current version. - Readability checks: wrapper now uses
[[ -r ... ]]instead of[[ -f ... ]]for hook files — skips injection gracefully if a file exists but is unreadable (mode 600), rather than crashing silently. - Root warning:
_ensure_initializednow prints a warning when running as root.
user_id mismatch false positive after /login — PR #59
After OAuth login, Claude Code writes the real account userID to .claude.json, which cac env check flagged as a mismatch against the environment’s stored fake ID — confusing and misleading.
- Removed fake
userIDgeneration onenv create— the fake ID provided no real protection (account_uuidis still sent via OAuth token and cannot be spoofed). cac env checknow auto-syncsenv/user_idfrom.claude.jsonafter login instead of reporting an error.
v1.5.1
2026-03-31 Fix: Relay crash recovery regression — Issue #49 v1.5.0 removed the relay watchdog along with the EXIT trap, leaving no auto-recovery when the relay process crashes mid-session. Affected users would see Connection Refused until manually restarting the session.- Env-level watchdog singleton (
relay.watchdog.pid): shared across all sessions, auto-restarts relay within 5s of crash. Exits automatically when relay is intentionally stopped — no orphaned processes. - Connectivity check: watchdog now verifies TCP reachability in addition to process liveness. If the relay port is unresponsive (process alive but frozen), it kills and restarts.
cac stop / cac env stop
Pause cac entirely — claude runs natively without any injection (no proxy, no fingerprint spoofing, no CLAUDE_CONFIG_DIR override). Resume with cac <name>. Useful when troubleshooting or temporarily bypassing cac.
v1.5.0
2026-03-29 Anti-fingerprint overhaul based on v2.1.86 reverse engineering — Issue #47 Based on comprehensive static analysis of Claude Code v2.1.86 (679,353 lines deobfuscated JS) by @mo-xiaoxi:- Repository hash (rh) spoofing [P0]: Claude computes
rh = SHA256(git_remote_url).hex.slice(0,16)and sends it with every event — cross-account linkage even after device/account changes. Now intercepted viachild_process.execSync/execmonkey-patch, returning per-environment fake remote URLs. - Git email spoofing [P1]: Claude runs
git config --get user.emailon startup, exposing real developer identity. Wrapper now setsGIT_AUTHOR_EMAIL+GIT_COMMITTER_EMAIL+ process-level interception viaCAC_GIT_EMAIL. - Telemetry strategy redesign [P1]: Zero telemetry is itself a risk signal — “no 1p_events but active API usage” strongly correlates with anti-detection tools. New three-tier model:
stealth(new default): onlyDISABLE_TELEMETRY=1— blocks 1p_events but GrowthBook/Statsig/feature flags work normally. Indistinguishable from normal user; all reported fingerprints are fake.paranoid(wasaggressive): full 12-layer telemetry kill — maximum privacy, potentially detectable.transparent(wasoff): no intervention — for when fingerprint coverage is complete.- Backward compatible: old names (
conservative/aggressive/off) auto-mapped. Existing environments migrated on upgrade.
- Persona presets [P1]: Claude analyzes terminal environment (TERM_PROGRAM, CURSOR_TRACE_ID, __CFBundleIdentifier, etc.) and deployment context (Docker, K8s, Codespaces) to profile developer setup.
--persona macos-vscode|macos-cursor|macos-iterm|linux-desktopinjects desktop terminal env vars and hides Docker signals (/.dockerenv,/proc/1/cgroup) — critical when running in containers or servers to avoid being flagged as non-personal-developer environment. Usecac env create <name> --persona macos-vscodeto apply a preset. - Trusted Device Token [P1]:
tengu_sessions_elevated_auth_enforcementgate is currently off but mechanism is ready (stores token in macOS Keychain). Per-environmentCLAUDE_TRUSTED_DEVICE_TOKENpreemptively overrides.cac env checknow detects Keychain residuals. - Billing header disabled [P2]:
CLAUDE_CODE_ATTRIBUTION_HEADER=0suppressesx-anthropic-billing-header(cc_version, cc_entrypoint, cc_workload). - Datadog domain blocked [P2]:
http-intake.logs.us5.datadoghq.comadded to DNS block list (event dual-write target, 48 whitelisted events only). - metadata.user_id tracking [P2]:
cac env checktracks the logged-in accountuserIDper environment (removed in v1.5.2 — see above).
cac env create <name> --persona <preset>— create environment with terminal personacac env set <name> telemetry <stealth|paranoid|transparent>— change telemetry modecac env set <name> persona <preset|--remove>— change or remove persona
- Existing environments auto-migrated on
npm upgrade: new files (fake_git_remote,git_email,device_token) generated, telemetry mode names updated.
v1.4.4
2026-03-29 Critical fix: Relay killed on every session exit — PR #45- Any
claude -pone-shot invocation (e.g. from a Feishu/Slack auto-reply pipeline) killed the shared relay process via_cleanup_all, breaking all other active sessions with Connection Refused. Relay lifecycle changed from session-level to environment-level — persists across sessions, only stopped bycac env activate(switch) orcac self delete. - Added
relay.proxyfile to detect proxy mismatch on startup — if relay is running with a different proxy, it’s automatically restarted. postinstall.jsnow patches old wrappers to remove thetrap _cleanup_all EXIT INT TERMline on upgrade.
cac env check incomplete — PR #45
- Same
pgreppipefail bug as the wrapper —cac env checkcrashed at the concurrent session check, skipping proxy connectivity, exit IP detection, and TUN conflict checks.
- Systematic audit of all
set -euo pipefailfailures: unguardedgrepin subshells,killrace conditions, empty arrays on bash 3.2, missingpython3fallbacks, broken symlinks, invalid network interfaces,opensslpipeline failures. Each now has explicit error handling instead of silently exiting.
v1.4.3
2026-03-27 Critical fix: Claude silently fails to launch — commit- Under
set -euo pipefail,pgrepreturns exit code 1 when noclaudeprocess is running. Withpipefail, the entire pipeline fails, andset -eexits the wrapper before"$_real" "$@"executes — Claude appears to do nothing with no output. postinstall.jsnow directly patches existing~/.cac/bin/claudeon upgrade, so the fix takes effect immediately without requiring the user to run anycaccommand first.cac env lsnow triggers_ensure_initialized, enabling automatic wrapper regeneration on version upgrade.
v1.4.0
2026-03-27 Critical fix:body.cancel is not a function — PR #44
- dns-guard.js replaced native
fetchwithnode-fetch, whoseResponse.bodyis a Node.js Readable stream lackingReadableStream.cancel(). Claude Code runs on Bun and expects native fetch — every streaming response broke. Now uses URL-checking wrapper instead of replacing the entire fetch implementation.
- Heartbeat: Upstream proxy connectivity check every 30s, logs state changes (unreachable → recovered)
- Crash recovery:
uncaughtException/unhandledRejectionhandlers prevent single-connection errors from killing the relay process - Watchdog: Wrapper monitors relay process every 10s, auto-restarts on crash — no more manual session restart
- Streaming timeout: Idle timeout 120s → 30min, reset on data activity — long streaming responses no longer killed
- Fail-closed: Dead relay → HTTPS_PROXY points to dead port → connection refused (no IP leak)
- Removed deprecated
cac setupcommand (auto-bootstrap via_ensure_initializedremains) - Updated stale error messages referencing
cac setup
- Telemetry modes: Three modes —
off(no intervention, for pure API Key users) /conservative(new default, blocks non-essential traffic) /aggressive(12-layer full block) - Block
CLAUDE_CODE_ENHANCED_TELEMETRY_BETA: Preemptively prevent enhanced telemetry activation via future feature flags - Persist
firstStartTimeper environment: Each environment maintains consistent “device age”, avoiding the “perpetual new device” detection pattern - Concurrent session warning: Warns when claude process count exceeds threshold (default 10, configurable via
~/.cac/settings.json) LANGauto-adaptation: Locale now auto-detected from exit IP country code (e.g. JP→ja_JP.UTF-8, SG→en_SG.UTF-8)cac env checkenhancements: Runtime fingerprint verification, IPv6 leak detection, TZ/IP consistency check, residual telemetry file detection
--cloneflag:cac env create work --cloneinherits config from~/.claude/(commands, hooks, skills, plugins via symlink; CLAUDE.md via symlink; settings.json via layered merge)--clone <env>: Clone from another cac environment instead of host--no-link: Copy files instead of symlink for independent customization- CAC Meta Prompt:
--clonewith symlink skips CLAUDE.md injection;--clone --no-linkappends cac instructions to copied CLAUDE.md settings.override.json: Environment-specific settings layered on top of shared base config, auto-merged on each startup~/.cac/settings.json: New cac-level config file for global preferences (max_sessions, telemetry_mode)
- Wrapper auto-upgrade:
CAC_WRAPPER_VERstamp detects version mismatch → wrapper auto-regenerated on next command - Wrapper optimizations: Settings merge skipped when inputs unchanged (mtime check), session count reads file instead of spawning python3
- macOS fixes:
pgrep -cfunavailable on macOS →pgrep -f | wc -l;pgrep -xfor exact claude binary match (avoids MCP subprocess false positives) --clonearg parsing fix:--no-linkno longer consumed as clone source name
v1.3.3
2026-03-27 Critical fix: Bun runtime support — Issue #30- Claude Code standalone binaries (installed via
curlorcac claude install) are compiled with Bun v1.3.11, not Node.js NODE_OPTIONS --requireis silently ignored by Bun —fingerprint-hook.jsandcac-dns-guard.jswere never injected in standalone builds- Wrapper now sets both
NODE_OPTIONS(Node.js) andBUN_OPTIONS --preload(Bun) to ensure hooks are always injected regardless of runtime - Verified: all 7 monkey-patch points work correctly under Bun (os.hostname, os.networkInterfaces, dns.lookup, child_process.execSync, fetch, https.request, net.connect)
v1.3.2
2026-03-27 i18n- All terminal output translated to English for international users — source files fully English, no more Chinese in CLI output
v1.3.1
2026-03-27 Hotfix- Fixed shell function hardcoding
$HOME/bin/cac— now dynamically findscacviacommand -v, compatible with npm/nvm global installs
v1.3.0
2026-03-26 Security enhancements — PR #28 / Issue #27 Based on reverse engineering of Claude Code 2.1.83, fixed multiple fingerprint collection points:- anonymousId: A second persistent identifier in
.claude.json(format:claudecode.v1.<uuid>) — now auto-reset on environment switch - statsig.stable_id: Fixed silent failure when no existing file; creates fallback
statsig.stable_id.local - GrowthBook: New A/B testing framework discovered —
cdn.growthbook.ioadded to DNS block list - Per-interface MAC spoofing: Different network interfaces now get different derived MACs (XOR with interface index), avoiding the “all interfaces share identical MAC” anomaly
- Stale field cleanup:
numStartups,firstStartTime,cachedGrowthBookFeatures,cachedStatsigGatescleared on environment switch
cac env check — PR #28
- Each check result displays immediately — no more 20-second blank wait
- Animated dots during IP detection
- Multi-source exit IP detection with fast retry: api.ip.sb, ip.3322.net, ipify, ipinfo
- TUN conflict detection with relay bypass status
- Prerelease versions (e.g.
1.3.1-beta.1) auto-publish to npmbetatag
v1.2.0
2026-03-25 Environment management overhaul — PR #25cac env set: Modify existing environments — proxy, version, timezone, language- Auto-activate on create:
cac env createautomatically activates; removedactivate/deactivate - Table output:
cac env lsandcac claude lsuse aligned table format - Shell function wrapper: Solves PATH conflicts with nvm, pyenv, and other version managers
- Auto-resolve latest version:
cac env createwithout-cautomatically uses the latest installed version
- README rewrite for v1.2+ command structure
- Mintlify docs site launched at cac.nextmind.space/docs
- Buffer accumulation prevents binary data corruption — Issue #9
Proxy-Authorizationheader for authenticated upstream — Issue #11- Fix
upstreamExtraforwarded to wrong direction — Issue #10 - Colon support in proxy passwords — Issue #12
- Complete
ChildProcessmock (stdio, exitCode, signalCode) — Issue #13
- Native Claude settings no longer leak into cac environments
- Kill relay and port-forward processes on
cac delete— Issue #21 - CI: ShellCheck + build consistency checks
v1.1.x
2026-03-24 npm ecosystem- Published to npm:
npm install -g claude-cac - nvm/npm global install compatibility: symlink resolution,
command -vlookup CAC_VERSIONauto-synced withpackage.jsonin CI
- Conclusion-first output,
-dflag for full details - Skip TUN conflict check when proxy is unreachable
- Verify relay connectivity before reporting TUN bypass success
- JS hooks synced on every command, not just first init
- Relay auto-bypass shown instead of alarming TUN conflict warning
v1.0.0
2026-03-23 Initial architecture — PR #20 Rewrite from proxy management script to uv-style Claude Code manager:- Version management:
cac claude install/ls/pin/uninstall - Environment isolation:
cac env create/ls/rmwith per-environmentCLAUDE_CONFIG_DIR - Node.js fingerprint hook: Intercepts
os.hostname(),os.networkInterfaces(),child_process.execSync('wmic/ioreg')— PR #5 - DNS guard: Blocks telemetry domains via
dns.lookup+net.connect+fetchmonkey-patching — PR #3 - Health check bypass: In-process Node.js interception, no
/etc/hostsor root needed - Local relay: Auto-bypasses TUN interfaces via loopback forwarding
- mTLS: Self-signed CA + per-environment client certificates
- Docker mode: sing-box TUN network isolation + cac identity protection — PR #8