agyswap • Architecture & Lifecycle Map

agyswap — Antigravity CLI Account Switcher

Per-session account isolation · Zero-interaction token rotation · One-command session resume. Powered by native macOS Keychain with zero external dependencies.

⚡ Switching Speed
~0.1s
Instant profile & session swap
🪟 Session Isolation
Per-Window
Parallel independent accounts
🔄 Token Rotation
No Browser
Background OAuth refresh
🔐 Native Security
C API Binding
CWE-214 safe · 0600 POSIX mode

A · Interactive Architecture Topology Full System

Click presets on the left or nodes below to inspect components across CLI runtime, macOS Keychain, and Google OAuth endpoints.

💻 Developer / Shell $ agyswap 2 $ agyswap switch work $ agyswap health $ agyswap audit zsh · bash · fish 🔄 agyswap Engine Core (v0.3.0) ⚡ Native C API Binding SecKeychain APIs (0% argv leak) 🔒 StorageManager & File Lock fcntl.flock + Mode 0600 / 0700 🚨 Expired Token Guard & Health 30-min soon warning + --force 🌐 Google UserInfo & JWT Claims Offline parsing + Bearer API Zero Dependencies · Pure Python 3 🔐 macOS Keychain service: gemini / acct: antigravity go-keyring-base64:<JSON> 🤖 Google Antigravity (agy) Gemini / Code Execution Agent ~/.gemini/antigravity-cli/ 📁 Local Slot Store (0600) ~/.agy-swap/slots/slot-*.json config.json + rolling backups .agyswap.lock (fcntl barrier) 🌐 Google OAuth Endpoints oauth2/v3/userinfo & token

B · Account Slot Inventory 3 Profiles Loaded

Interactive preview of registered profile slots. Run agyswap viz --open locally on macOS to view your real accounts.

Slot Account / Alias Status Token Expiry Auth Method

C · Profile Switching Sequence ~0.1s Fast Path

Detailed execution flow triggered during an account switch operation.

1

Concurrency Lock & Target Resolution

Acquires fcntl.flock on .agyswap.lock and resolves target slot by number, email, or alias.

2

Expired Token Guard

Compares token.expiry with system UTC clock. If expired without --force, switch is safely blocked with a renewal guide.

3

Native C API Keychain Injection

Directly modifies macOS Keychain using SecKeychainItemModifyAttributesAndData via ctypes without touching process argv.

4

Atomic Config Update & Session Notice

Atomically saves config.json and scans for running agy processes via lsof to emit session restart guidance.

# Example 1: Quick Switch $ agyswap switch work ✓ Switched Antigravity profile to #2 (work@company.com). ⚠️ Detected 1 running agy session: • PID 45920 ~/projects/agyswap (1 session) Start a new terminal session to apply the profile. # Example 2: Expired Token Guard in Action $ agyswap switch 3 ✗ Slot #3 (dev@project.org) token has expired (expired 2h ago). Try refreshing: agyswap rotate 3 Force switch: agyswap switch 3 --force

D · Command Reference

agyswap [list|ls]
Displays account slots with tree-style token validity view, active session indicators, and sync timestamps.
agyswap <slot> [-r|-n] [-y]
Quick-switch profile. -r: resume last session (agy -c). -n: launch fresh session. -y: pass --dangerously-skip-permissions to agy for fully automated no-prompt workflows.
agyswap add [alias]
Registers currently active agy login session as a managed slot with Google profile metadata.
agyswap health [--json]
Overview dashboard of token expiry status across all registered profiles with warning flags.
agyswap audit
Audits and auto-corrects filesystem permissions (0700/0600) and verifies Keychain integrity.
agyswap rotate [--all | slot]
Background OAuth token refresh. --all rotates every slot simultaneously — no browser interaction required.
agyswap export [file]
Exports slot metadata to JSON format for migration (sensitive live tokens excluded for security).
agyswap import <file>
Imports slot metadata from JSON with automatic slot conflict resolution.
agyswap completion <shell>
Generates shell auto-completion scripts for zsh, bash, and fish with dynamic slot completion.

E · Security Architecture & Threat Model

Security Layer Implementation Mechanism Threat Mitigated
Keychain Binding macOS Security.framework Native C API via ctypes Process argument sniffing (ps aux / CWE-214)
Storage Isolation Files 0600, Dirs 0700 (opener=secure_opener) Cross-user access & Umask race conditions
Concurrency Lock fcntl.flock on .agyswap.lock Lost updates during concurrent terminal runs
Template Escaping safe_json_for_script Unicode character sanitization Stored XSS inside HTML <script> blocks

F · POSIX Storage Layout

~/.agy-swap/ # Mode 0700 (Owner rwx only) ├── config.json # Mode 0600 (active_slot, accounts metadata) ├── .agyswap.lock # Mode 0600 (flock concurrency barrier) ├── slots/ # Mode 0700 (Isolated slot directory) │ ├── slot-1.json # Mode 0600 (OAuth token credentials) │ └── slot-2.json # Mode 0600 └── backup/ # Mode 0700 (Directory) └── config-YYYYMMDD-HHMMSS.json # Mode 0600 (Rolling automated backups)

G · Installation & Shell Completion

# Install via Homebrew Tap (Shell completions automatically configured): brew install g1mn/tap/agyswap
# Install via official installer script: curl -fsSL https://raw.githubusercontent.com/g1mn/agyswap/main/install.sh | bash
# Install from cloned repository via pip/pipx: git clone https://github.com/g1mn/agyswap.git cd agyswap pip install .
# Add to ~/.zshrc: echo 'eval "$(agyswap completion zsh)"' >> ~/.zshrc && source ~/.zshrc
# Add to ~/.bashrc: echo 'eval "$(agyswap completion bash)"' >> ~/.bashrc && source ~/.bashrc
# Install to fish completions directory: agyswap completion fish > ~/.config/fish/completions/agyswap.fish

H · Troubleshooting FAQ

Do running agy CLI sessions switch immediately? +
macOS caches Keychain reads in memory for short durations. While the Keychain is updated instantly in ~0.1s, starting a new terminal prompt or restarting existing agy sessions guarantees active credential activation.
How do I safely migrate to a new Mac? +
Run agyswap export backup.json on your old Mac. On your new Mac, run agyswap import backup.json. Live tokens are excluded from export for security; simply log into each profile once via agy and run agyswap sync.
What should I do if a token expires? +
Run agyswap rotate <slot> to initiate a token refresh, or log into the expired account using agy and run agyswap sync.