AgentSwap
Agent Config Switch — multi-platform config switcher & launcher for coding agents.
Manage multiple agent configurations (different providers, models, relays, hooks, permissions) as profiles. Switch between them instantly, launch several configs side by side in different panes, and edit everything through a local web UI.
- macOS, Linux, Windows — one Node.js codebase, no native deps
- Two launch modes — sticky (machine default) or per-launch (parallel-safe)
- Safe by default — whole-file profiles, drift detection, conflict guards, secret masking, 0600 files
- Local web UI —
agentswap webfor visual profile editing - Agent-friendly —
--jsoncontracts everywhere, plus a skill that teaches agents to use AgentSwap and open herdr panes with a specific profile
Install
Requires Node.js ≥ 20. The CLI command is agentswap (short alias aswap).
# from a clone of this repo
npm install -g .
# or run directly without installing
node bin/agentswap.mjs <command>
The agent CLI must be on your PATH for launch commands.
Quick start
# Snapshot your current settings into a profile
agentswap add work --from-current
# Create an empty profile and edit it ($EDITOR)
agentswap add personal
# Switch (overwrites the agent's settings.json) and launch
agentswap work
# List / inspect
agentswap list
agentswap show personal # secrets masked
agentswap diff work personal
# Launch a one-off config without touching global state (great for panes)
agentswap run personal
# Visual management
agentswap web
Concepts
A profile is a complete settings.json snapshot. The whole file — env, model, hooks, permissions, statusLine, anything. Switching is a verbatim whole-file overwrite: no field merging, no managed keys, no partial updates. This means AgentSwap never needs to understand the settings format, and new agent settings keys work automatically.
Trade-off: shared config is not auto-propagated across profiles. Each profile carries its own full settings. agentswap save writes live changes back into the active profile so nothing is silently lost.
Two modes:
Sticky (agentswap <name> / agentswap use) |
Per-launch (agentswap run <name>) |
|
|---|---|---|
| Effect | Overwrites the agent's settings.json |
Writes a private 0600 temp file, passed via --settings |
| Scope | Machine default — affects new sessions | One process only |
| Parallel-safe | No | Yes |
| Best for | Interactive terminals | herdr panes, scripts, multi-agent work |
run precedence note: --settings is the agent's CLI layer, which beats project/local settings; sticky mode sits at the user layer, so repo settings override it. agentswap run x ≠ agentswap use x followed by launching the agent.
Drift detection. AgentSwap records a content-hash baseline of what it last applied. On every switch/save it compares three hashes — live settings, active profile, baseline — to tell which side changed:
- live changed, profile didn't →
agentswap savestores live into the profile - profile changed, live didn't → next switch just applies it
- both changed → conflict: switch and save refuse until you pick a side (
--discarddrops live,--overwrite-profilekeeps live)
Launch env hygiene. Both modes strip the inherited auth/routing env namespace (provider tokens, base URLs, and agent-specific auth keys) before injecting the profile's own env, so a stale token from a parent shell can't shadow the profile's provider. Profile env values of null explicitly delete a key.
Commands
agentswap <name> [args…] switch + launch (args pass through to the agent)
agentswap [args…] relaunch with the active profile
agentswap <name> --discard drop unsaved live changes and switch
agentswap <name> --overwrite-profile save live into the active profile, then switch
agentswap use <name> [--json] sticky switch without launching
agentswap save [--json] save live settings → active profile
agentswap run <name> [--json-cmd] [--save-on-exit] [-- args…]
agentswap current [--json] active profile + drift status
agentswap list [--json]
agentswap show <name> [--reveal] [--json]
agentswap diff <a> [b] [--json] two profiles, or profile vs live
agentswap add <name> [--from-current]
agentswap edit <name> open in $EDITOR
agentswap rm <name> [--force]
agentswap import <file> [--apply] import profiles from a JSON export (dry-run default)
agentswap backup list [--json]
agentswap restore <file> [--yes]
agentswap web [--port N] [--no-open] local web UI
agentswap skill install [--force] install the agent skill
agentswap doctor [--json] environment diagnostics
agentswap version
All --json outputs share a stable { "version": 2, ... } contract — see the skill for the full schema.
Web UI
agentswap web # picks a free port, opens your browser
agentswap web --port 47831 --no-open
- Sidebar with all profiles, active marker, and live drift status
- One-screen provider editing: base URL, credential (token or API key), model
- Raw settings JSON editor with validation
- Switch / save / create / delete — every change lands on disk immediately
- Binds to
127.0.0.1only; every API call (reads included) requires a per-session token delivered via the#fragmentof the startup URL, and the Host header must be loopback (CSRF / DNS-rebinding safe)
Agent skill
agentswap skill install installs the bundled skill from skills/agentswap/ into the agent's skills directory. The skill teaches agents to:
- discover and switch profiles via the
--jsoncontracts - choose sticky vs
runcorrectly - open their own herdr panes running a specific profile (
herdr pane split+agentswap run) - respect the red lines (never reveal secrets, never sticky-switch for one-off tasks)
Cross-platform
| macOS | Linux | Windows | |
|---|---|---|---|
| Config dir | ~/.config/agentswap |
~/.config/agentswap |
%APPDATA%\agentswap |
| Editor | $EDITOR / $VISUAL |
same | notepad fallback |
| Launch | direct spawn | direct spawn | cmd.exe shim wrapper for npm .cmd bins |
Override AgentSwap's config dir with AGENTSWAP_HOME (handy for tests and isolated setups). The agent's own config directory is independent and follows the agent's usual override.
Windows notes
- Tested design, not yet battle-tested on a real Windows box — please open an issue if something misbehaves.
- Atomic writes retry on
EPERM(transient AV file locks). - PowerShell: everything runs through
node, so profile/args handling is identical; no shell-specific quoting in the CLI itself. - Launching through an npm
.cmdshim goes viacmd.exe, which expands%VAR%in arguments before the agent sees them — a cmd.exe layer behavior no launcher can disable. AgentSwap only ever passes through your own profile name, launchArgs, and command line.
Layout
<AGENTSWAP_HOME>/
├── config.json # defaults + per-profile metadata (notes, launchArgs, unsetEnv)
├── state.json # active profile + applied-hash baseline
├── profiles/<name>.json # one complete settings snapshot each (0600)
├── run/ # per-launch temp settings (GC'd by owner pid)
└── backups/
├── settings/ # live-settings backups (rotated)
└── profiles/<name>/ # per-profile backups (rotated independently)
Security
- Profile and settings files are written
0600; dirs0700. show/diff/ list mask secrets best-effort (key-name taint, env-wide masking, format heuristics).--revealis opt-in.run --json-cmdemits env key names only — never values — and writes no temp file.- The web UI binds to loopback and requires a per-session token for every API
call; the token is delivered via the startup URL's
#fragmentand never appears in the page HTML or server logs. - AgentSwap only ever reads the agent's credentials file (for diagnostics); it never writes or copies it.
Development
node --test # full suite (unit + CLI e2e in isolated temp dirs)
npm run check # repo guardrails: zero deps, skill contract, doc routing, redlines
The codebase is dependency-free Node.js ESM. src/ is the library + commands, bin/agentswap.mjs is the entry, src/web/ is the local UI, skills/agentswap/ is the bundled agent skill.
See docs/architecture.md for the design, docs/v1.md for what v1 does and doesn't cover, and docs/index.md for the doc routing table (which docs to update when a path changes).
License
MIT