aimgr (CLI: aim) is a small AI account manager for one job:
- keep labeled paid-account truth in AIM
- keep browser ownership in AIM
- compile that truth into downstream targets like OpenClaw, local Codex CLI, local Claude CLI, and local Pi CLI
The operating model is intentionally simple:
~/.aimgr/secrets.jsonis the durable SSOT- browser binding is explicit per label:
aim-profile->~/.aimgr/browser/<label>/user-datachrome-profile-> explicit raw Chromeuser-data-diragent-browser-> explicitprofile+sessionmanual-callback-> no local browser binding
- OpenClaw assignments plus local Codex/Claude/Pi auth stores are derived outputs
- operators think in labels like
boss,lessons, andqa, not raw tokens or profile IDs
One AIM-owned account pool, one obvious operator path, and no legacy drift.
That means:
aim <label>is the primary human pathaim rebalance openclawis the canonical OpenClaw assignment commandaim codex useis the canonical local Codex selection commandaim codex watchis the canonical local Codex guardrail for overnight rotationaim claude use [label]is the canonical local Claude selection commandaim pi useis the canonical local Pi selection commandaim pin,aim autopin openclaw, and label-firstaim codex use/aim pi useare removed
- AIM is the only durable credential SSOT.
- OpenClaw, Codex CLI, Claude CLI, and Pi CLI are derived targets, not competing truth.
- Operator-facing account state collapses to
ready,reauth, orblocked. - Labels are explicit; there is no steady-state
defaultaccount semantics. - Codex target management is file-backed only in v1.
keyringandautofail loud. - The current human-facing authority for the shared Codex pool is
agents@amirs-mac-studio.
- macOS
- Node.js
>= 20 - Google Chrome installed
openclawonPATHif you are using the OpenClaw workflow- a file-backed Codex home if AIM will manage your real
~/.codex
For local iteration:
cd /Users/agents/workspace/agents/work/aimgr/repo/aimgr
npm install
npm link
which aim
aim --helpFor a fixed snapshot instead of a live symlink:
cd /Users/agents/workspace/agents/work/aimgr/repo/aimgr
npm install -g .For a login-shell-stable install that does not depend on the current NVM global bin path:
cd /Users/agents/workspace/agents/work/aimgr/repo/aimgr
npm install
npm run install:local
which aim
aim --helpThis writes aim and aimgr wrappers into ~/.local/bin (or $XDG_BIN_HOME), which is usually a better fit than npm link when Node is managed by nvm.
aim status
aim status --json | jq .Status answers the core operator questions:
- which labels are
ready,reauth, orblocked - what OpenClaw currently has assigned
- how the last weighted rebalance spread agents across accounts
- what the local Codex target currently has selected
- what the local Claude target currently has selected
- what the local Pi target currently has selected
- what the Hermes fleet currently has mapped across live homes
- what the next-best eligible account would be
- whether the pool needs more capacity
- what the last Codex watch receipt decided
- what the last Hermes rebalance/watch receipts decided
aim bossOn a TTY, aim <label> is the human front door. It opens a guided label panel with numbered choices:
$ aim boss
boss · openai-codex
Status: ready
ChatGPT login: valid
Browser: agent-browser / agent-boss
What do you want to do?
1. Open browser
2. Reauth / refresh login
3. Change browser setup
4. Show details
0. Done
Claude labels use a different panel because they are native-bundle-first instead of browser-bound:
$ aim claudalyst
claudalyst · anthropic
Status: reauth
Why: Credentials are expired.
Stored tokens: expired
Native bundle: complete
What do you want to do?
1. Use this label in Claude
2. Refresh native bundle
3. Capture current native Claude login
4. Import native Claude bundle
5. Export current live native bundle
6. Show details
0. Done
Use explicit aim login <label> only when you want the one-shot maintenance/admin lane:
aim login boss
aim login claudalystThe maintenance flow:
- ensures the label has a provider
- uses the label's configured login rail
- refreshes if possible, otherwise runs the provider's maintenance path
- writes credentials into
~/.aimgr/secrets.json - records account-maintenance facts for status and automation
Important behavior:
- Browser-managed labels use the label's explicit binding, not a guessed browser lane.
aim-profileuses~/.aimgr/browser/<label>/user-data.chrome-profileuses the exact--user-data-diryou configured and, when present, the exact Chromeprofile-directory.agent-browseruses the exact--profileand--sessionyou configured.- Manual-callback labels print the OAuth URL and prompt for the final callback URL.
- Claude labels do not use browser bindings or manual-callback anymore; they capture/import native Claude bundles instead.
- For Claude labels, non-TTY
aim <label>andaim login <label>do the one-shot maintenance path: refresh the stored native bundle if it is already complete, otherwise capture the current live native Claude login from this host. - Claude label maintenance updates
~/.aimgr/secrets.jsononly. It does not sync Hermes homes, browser bindings, OpenClaw assignments, or Claude sessions that are already running. - Reauth does not rebalance OpenClaw or mutate downstream assignments.
When you pick Use another Chrome profile from the guided panel, AIM now lists the discovered raw Chrome-style browser homes on this Mac, including OpenClaw browser homes and host Chrome profiles. It tells you the exact user-data-dir + profile-directory each choice would save, and lets you confirm before writing the binding.
Daily operators should memorize aim status, aim <label>, aim rebalance openclaw, aim rebalance hermes, aim codex use, aim codex watch, aim hermes watch, aim claude use [label], and aim pi use.
When you need to inspect or repair the browser substrate explicitly, use the advanced/admin surface:
aim browser show <label>
aim browser set <label> --mode aim-profile [--seed-from-openclaw <profileId>]
aim browser set <label> --mode chrome-profile --user-data-dir <abs-path> [--profile-directory <name>]
aim browser set <label> --mode agent-browser --profile <abs-path> --session <name>
aim browser set <label> --mode manual-callbackNon-negotiables:
- AIM never guesses from a workspace-local
agent-browser.json. - AIM never uses the implicit
defaultagent-browsersession. - There is no supported "generic Chrome somehow" mode.
Claude-native surfaces live outside the browser-binding lane:
aim claude capture-native <label> [--source-home <dir>]
aim claude export-live --out <file> [--source-home <dir>]
aim claude import-native <label> --in <file>capture-nativereads the live native Claude login from a same-host home and stores it on a label.export-livewrites a portable bundle file from the live native Claude login on this host.import-nativeloads that bundle file into a label on another AIM home.
Use this when you want AIM to choose assignments across the eligible Codex pool:
aim rebalance openclawThis command:
- evaluates pooled label readiness plus live usage
- refreshes AIM’s per-agent demand ledger from OpenClaw session token counters
- spreads agents many-to-one across remaining account headroom instead of burning one label per agent
- keeps current assignments when they stay within weighted hysteresis
- writes the derived OpenClaw assignments
- records an explicit receipt with
allocationModeplusperAccountLoad:appliednoopapplied_with_warningsblocked
When recent session history exists, rebalance is demand-weighted. When it does not, cold-start agents use an explicit equal-share baseline until AIM has real usage.
If you only want to recompile the current recorded assignments into OpenClaw without reselection:
aim sync openclaw
# alias
aim applyUse this when you want AIM to choose labels across the eligible Codex pool for the live Hermes homes that already exist on this machine:
aim rebalance hermesThis command:
- discovers live Hermes homes under
~/.hermes/profiles/* - reads each home's native
auth.jsonand infers the current AIM label from auth readback - refreshes AIM's per-home demand ledger from Hermes
state.dbsession tokens when available - reuses the same weighted many-to-one allocator that OpenClaw already uses
- writes only the changed Hermes
auth.jsonfiles - records an explicit fleet receipt under
pool.openaiCodex.hermesFleet.lastApplyReceipt
Non-negotiables:
- AIM still owns Hermes auth only
- Hermes
config.yaml,.env,SOUL.md, and service lifecycle remain outside AIM aim rebalance hermesfails loud on unreadable/missing live-home auth instead of inventing a fallback- if you need live runtime confirmation after a rebalance/watch write, use
HERMES_HOME=~/.hermes/profiles/<agent_id> hermes status --deep
First sync the portable pool if needed:
aim sync codex --from agents@amirs-mac-studioThen activate the next-best eligible label:
aim codex useThis command:
- validates the local Codex home is file-backed
- probes current pool usage
- selects the next-best eligible pooled label
- writes managed
auth.json - verifies readback
- records a selection receipt:
activatednoopactivated_with_warningsblocked
The contract is "next Codex process", not hot-swapping an already-running long-lived process.
If you locally reauth one of those imported Codex labels and want to publish that refresh back to the authority, use:
aim promote codex --to agents@amirs-mac-studio <label> [<label>...]Later imports will not silently clobber unpublished local refreshes. aim sync codex --from ... now fails loud on those dirty imported labels unless you explicitly add --discard-dirty.
Use this when you want AIM to keep checking the current local Codex target and rotate through the existing selector before the active label falls too low in the 5h window.
Scheduler-safe one-shot:
aim codex watch --once --rotate-below-5h-remaining-pct 20Foreground loop:
aim codex watch --interval-seconds 300 --rotate-below-5h-remaining-pct 20Important behavior:
- watch mode decides from the current active local Codex label's live 5h remaining percentage
- when the active label drops below threshold, watch delegates to the same selection/apply path as
aim codex use - watch records
targets.codexCli.lastWatchReceiptin AIM state and surfaces it inaim status --onceis the only scheduler contract;launchd,systemd, and plain cron should all wake the same one-shot command- do not enable both a foreground loop and an OS scheduler on the same host
- do not use OpenClaw cron for this; AIM owns local Codex auth truth
Simplest install path:
cd /path/to/aimgr
bash ./scripts/install-codex-watch.sh
# or
npm run codex-watch:installThat script works from a standalone aimgr clone or the nested Mac-host checkout, detects macOS vs Linux, installs the right system scheduler with sudo when needed, starts it, and prints the follow-up status/log command.
Rerunning the installer is safe. It refreshes the same single scheduler definition instead of creating parallel watches, and on macOS it also cleans up old GUI/user launchd copies before bootstrapping the canonical system daemon.
When multiple Node installs exist, the installer prefers a Node >=20 binary automatically and fails loud if it cannot find one. Use --node-bin /absolute/path/to/node to override.
Installed scheduler artifacts:
- macOS:
/Library/LaunchDaemons/com.funcountry.agents_host.aim_codex_watch.plist - Ubuntu:
/etc/systemd/system/aim-codex-watch.serviceand/etc/systemd/system/aim-codex-watch.timer
Plain cron is acceptable only as a thin wake-up lane:
# Replace both absolute paths first:
# - `/absolute/path/to/node` from `command -v node`
# - `/absolute/path/to/aimgr` with your aimgr checkout root
*/5 * * * * /absolute/path/to/node /absolute/path/to/aimgr/bin/aimgr.js codex watch --once --rotate-below-5h-remaining-pct 20If you want to inspect or remove the installed scheduler later:
bash ./scripts/install-codex-watch.sh --status
bash ./scripts/install-codex-watch.sh --uninstallPi uses the same pooled OpenAI/Codex account selector as local Codex CLI, but writes Pi's canonical auth store instead of ~/.codex/auth.json.
By default AIM targets:
- Pi agent dir:
~/.pi/agent - Pi auth path:
~/.pi/agent/auth.json
You can override the Pi target dir with PI_CODING_AGENT_DIR.
aim pi useThis command:
- probes current pooled usage
- selects the next-best eligible pooled label with the same weighted ranking and hysteresis rules as
aim codex use - writes Pi's canonical
auth.json - preserves unrelated non-OpenAI Pi providers already present in that file
- verifies readback
- records a selection receipt:
activatednoopactivated_with_warningsblocked
The contract is "next Pi process", not mutating an already-running Pi session in place.
Claude uses AIM's Anthropic labels and writes Claude's canonical local auth store:
- Claude dir:
~/.claude - Claude credentials path:
~/.claude/.credentials.json - Claude app-state path:
~/.claude.json(oauthAccountonly; AIM preserves unrelated keys)
aim claude use
aim claude use claudalyst
aim claude capture-native claudalyst
aim claude export-live --out ~/claude-bundles/claudalyst.json
aim claude import-native claudalyst --in ~/claude-bundles/claudalyst.jsonaim claude use without a label:
- probes current Claude subscription usage
- selects the next-best eligible pooled label with the same weekly-first local selector AIM uses for Codex/Pi
- writes Claude's canonical
.credentials.json - patches only
oauthAccountinside~/.claude.json - verifies readback from Claude's local auth files and does not call
claude auth status, because some Claude builds mutate auth files during status reads - records a selection receipt:
activatednoopactivated_with_warningsblocked
aim claude use <label>:
- bypasses usage ranking and directly activates the requested label
- writes Claude's canonical
.credentials.json - patches only
oauthAccountinside~/.claude.json - verifies readback from Claude's local auth files and does not call
claude auth status, because some Claude builds mutate auth files during status reads - records a selection receipt:
activatednoopactivated_with_warningsblocked
Claude-native switching is bundle-first:
- every Claude-switchable label must have a complete stored native Claude bundle:
~/.claude/.credentials.json~/.claude.jsonoauthAccount
aim <label>refreshes an existing stored bundle when possible, or captures the current live native Claude login from this hostaim claude capture-native <label>captures the current live native Claude login from this host without going through OAuth in AIMaim claude export-live --out <file>andaim claude import-native <label> --in <file>are the cross-host transport pathaim claude use [label]only switches labels that already have that complete stored bundle- AIM does not treat env-token auth or
.credentials.json-only projection as native Claude parity
Anthropic refresh tokens rotate on every successful refresh: Claude CLI performs its own refreshes and writes the rotated tokens into the live files in place. Before aim claude use [label] overwrites those files, it reads the live bundle, matches it to a stored label by accountUuid/email+org identity, and — if the live tokens differ from stored — persists the rotated tokens back into that label's stored bundle. The activation receipt surfaces this as preSwitchSync = { synced, label, rotatedFields } so day-to-day label switching no longer silently invalidates refresh tokens.
The contract is "next Claude process", not mutating an already-running Claude session in place.
These commands are intentionally removed and now hard-error with migration guidance:
aim pin <openclaw_agent_id> <label>
aim autopin openclaw --pool ...
aim codex use <label>
aim pi use <label>Use:
aim <label>for reauthaim rebalance openclawfor OpenClaw assignment selectionaim codex usefor local Codex selectionaim claude use [label]for local Claude selectionaim pi usefor local Pi selection
AIM only manages file-backed Codex homes in v1.
By default AIM targets:
- AIM state:
~/.aimgr/secrets.json - Codex home:
~/.codex
Check the effective store mode:
grep -n 'cli_auth_credentials_store' ~/.codex/config.tomlIf that is set to keyring or auto, AIM will refuse to manage the home.
You can also point AIM at an alternate managed Codex home:
export CODEX_HOME="$HOME/.codex"If you want to test without touching your real ~/.aimgr or ~/.codex:
cd /Users/agents/workspace/agents/work/aimgr/repo/aimgr
TMP_HOME="$(mktemp -d /tmp/aimgr-smoke.XXXXXX)"
export CODEX_HOME="$TMP_HOME/.codex"
node ./bin/aimgr.js sync codex --from agents@amirs-mac-studio --home "$TMP_HOME"
node ./bin/aimgr.js status --json --home "$TMP_HOME"
node ./bin/aimgr.js codex use --home "$TMP_HOME"
node ./bin/aimgr.js status --home "$TMP_HOME"
cat "$CODEX_HOME/auth.json"What you want to see:
sync codexsucceeds and creates$TMP_HOME/.aimgr/secrets.jsonstatusshows imported labels and the authority sourcecodex usesucceeds or clearly reportsblocked$CODEX_HOME/auth.jsonexists after a successful activation and contains the selected account id
On the host that owns the shared AIM pool:
aim status
aim boss
aim rebalance openclaw
aim statusOn the machine that wants to consume the shared Codex pool:
aim sync codex --from agents@amirs-mac-studio
aim codex use
aim statusThen start a new Codex or codex_local process and verify it picks up the selected identity.
Human-readable or JSON summary of:
- labels and operator states
- warnings
- OpenClaw assignments and last rebalance receipt
- weighted spread details (
allocationMode,perAccountLoad) - Codex authority source, active label, last selection receipt, and dirty imported labels pending promote
- Claude authority source, active label, auth method, last selection receipt, and dirty imported labels pending promote
- Hermes fleet spread, live-home warnings, and last apply/watch receipts
- next-best candidate and capacity projection
aim status
aim status --jsonPrimary human path plus explicit admin lane:
aim boss
aim login boss
aim claudalyst
aim login claudalystRules:
aim <label>opens the guided label panel on a TTY- non-TTY
aim <label>behaves like explicitaim login <label> aim login <label>keeps the one-shot JSON-style maintenance contract for scripts/tests/admin use- for Claude labels, TTY
aim <label>exposes native-bundle actions (use,refresh,capture,import,export,details) instead of browser/setup actions - for Claude labels,
aim login <label>refreshes the stored native bundle when it is complete, otherwise it captures the current live Claude login from this host - if an imported Codex label changes locally, AIM marks it pending promote instead of pretending the authority already knows
Selects pooled Codex labels for configured OpenClaw agents and writes the derived assignment/auth/session state:
aim rebalance openclawThe rebalance planner is intentionally different from Codex next-best label selection:
- it imports per-agent OpenClaw session token counters into AIM’s demand ledger
- it can assign multiple agents to the same account when remaining headroom supports that
- it only skips agents when projected weighted demand exceeds remaining eligible supply
Recompiles already-recorded OpenClaw target state:
aim sync openclaw
aim applyImports or refreshes the portable Codex pool from an authority source:
aim sync codex --from agents@amirs-mac-studioSupported locator forms:
agents@amirs-mac-studiossh://agents@amirs-mac-studio/~/.aimgr/secrets.json/absolute/path/to/secrets.json
Safety rules:
- if the import would overwrite or remove a locally refreshed imported label, AIM refuses the sync and tells you which labels are dirty
- publish those local updates first with
aim promote codex --to <authority> <label>... - or rerun the pull with
--discard-dirtyif you intentionally want the authority copy to win
Publishes locally refreshed imported Codex credentials back to the same authority they originally came from:
aim promote codex --to agents@amirs-mac-studio boss
aim promote codex --to agents@amirs-mac-studio boss lessonsPromotion is intentionally narrow:
- it only works for imported
openai-codexlabels from the exact same authority source - it updates only the requested labels on the authority
- it uses compare-and-swap protection, so the push fails if the authority copy changed since your last import
- it does not create labels, delete labels, or push machine-local target state back upstream
Imports or refreshes the portable Claude label set from an authority source:
aim sync claude --from agents@amirs-mac-studioSupported locator forms are the same as sync codex:
agents@amirs-mac-studiossh://agents@amirs-mac-studio/~/.aimgr/secrets.json/absolute/path/to/secrets.json
Safety rules:
- if the import would overwrite or remove a locally refreshed imported Claude label, AIM refuses the sync and tells you which labels are dirty
- publish those local updates first with
aim promote claude --to <authority> <label>... - or rerun the pull with
--discard-dirtyif you intentionally want the authority copy to win - authority Claude labels without a complete native bundle still import as labels, so the consumer keeps the label topology and can capture or import the native bundle later
Publishes locally refreshed imported Claude credentials back to the same authority they originally came from:
aim promote claude --to agents@amirs-mac-studio claudalyst
aim promote claude --to agents@amirs-mac-studio claudalyst amir_claude_personalPromotion is intentionally narrow:
- it only works for imported
anthropiclabels from the exact same authority source - it updates only the requested labels on the authority
- it uses compare-and-swap protection, so the push fails if the authority copy changed since your last import
- it does not create labels, delete labels, or push machine-local target state back upstream
Activates the next-best eligible pooled label for the local managed Codex home:
aim codex useRuns the Codex watch decision once for schedulers, or continuously in the foreground:
aim codex watch --once --rotate-below-5h-remaining-pct 20
aim codex watch --interval-seconds 300 --rotate-below-5h-remaining-pct 20Selects pooled Codex labels for the live Hermes homes on this machine and writes only their native auth.json files:
aim rebalance hermesThe Hermes rebalance path is intentionally not a new allocator:
- it discovers live homes from
~/.hermes/profiles/* - it refreshes Hermes demand from
state.db - it reuses the same weighted planner that backs
aim rebalance openclaw - it records receipts in
pool.openaiCodex.hermesFleet
Runs the Hermes watch decision once for schedulers, or continuously in the foreground:
aim hermes watch --once --rotate-below-5h-remaining-pct 20
aim hermes watch --interval-seconds 300 --rotate-below-5h-remaining-pct 20This is the scheduler-safe Hermes guardrail. It never writes auth directly; it only decides when to call aim rebalance hermes.
Activates Claude from AIM's stored native Claude bundles:
aim claude use
aim claude use <label>
aim claude capture-native <label>
aim claude export-live --out <file>
aim claude import-native <label> --in <file>Operator model:
aim claude usewithout a label selects the next-best eligible Claude label from the local Anthropic pool.aim claude use <label>bypasses ranking and directly activates the requested label.- activation writes both
~/.claude/.credentials.jsonand~/.claude.jsonoauthAccount, then verifies readback from those files - activation affects the next Claude process; it is not a live hot-swap for an already-running Claude session
- if the current host is logged into the wrong Claude account and you want to recapture a different one, use
claude auth logout, log into the intended account in native Claude, then runaim claude capture-native <label>or rerunaim <label>
Default durable AIM state lives at:
~/.aimgr/secrets.json
Backups are created automatically on write:
~/.aimgr/secrets.json.bak.<timestamp>
Current shape:
Durable truth lives in:
accountscredentialsimports.authority.codeximports.authority.anthropic- minimal pool history
For imported Codex labels, imports.authority.codex.labelsByName tracks the imported baseline per label. aim status --json also derives imports.authority.codex.dirtyLabels so operators can see which local refreshes still need promotion back to the authority.
For imported Claude labels, imports.authority.anthropic.labelsByName plays the same role for native bundle capture/import/refresh work and pending aim promote claude follow-through.
Derived target state lives in:
targets.openclawtargets.codexClitargets.claudeClipool.openaiCodex.hermesFleet
Bootstrap the local replica:
aim sync codex --from agents@amirs-mac-studioThere is no eligible pooled account right now.
Fix readiness or capacity first:
aim statusThen reauth a label with aim <label> or add more pool capacity.
Your local AIM replica has a newer refresh for one or more imported labels that has not been published back to the authority yet.
Promote those labels:
aim promote codex --to agents@amirs-mac-studio <label> [<label>...]Or, if you intentionally want to throw away the local refresh and trust the authority copy instead:
aim sync codex --from agents@amirs-mac-studio --discard-dirtyaim status also surfaces this state as authority-dirty labels pending promote.
Someone refreshed that label on the authority after your last import, or your local base snapshot is stale.
Start by pulling again:
aim sync codex --from agents@amirs-mac-studioThen decide whether to keep the authority copy or re-run local reauth and promote again from the refreshed base.
Your local AIM replica has a newer native Claude capture, import, or refresh for one or more imported labels that has not been published back to the authority yet.
Promote those labels:
aim promote claude --to agents@amirs-mac-studio <label> [<label>...]Or, if you intentionally want to throw away the local native Claude refresh and trust the authority copy instead:
aim sync claude --from agents@amirs-mac-studio --discard-dirtyaim status also surfaces this state as authority-dirty labels pending promote.
Someone refreshed that Claude label on the authority after your last import, or your local base snapshot is stale.
Start by pulling again:
aim sync claude --from agents@amirs-mac-studioThen decide whether to keep the authority copy or re-capture the local native Claude login and promote again from the refreshed base.
Either the current active Codex target could not be trusted for a watch decision, or the selector had no eligible pooled account when rotation was triggered.
Start with:
aim statusThen inspect codexCli.lastWatchReceipt and codexCli.lastSelectionReceipt:
- if the blocker is about target mismatch or unreadable auth, repair the current Codex target first
- if the blocker is
no_eligible_pool_account, fix readiness or add capacity before rerunning the watcher
There is no eligible pooled Claude account right now.
Fix readiness or capacity first:
aim statusThen reauth a Claude label with aim <label> or add more Anthropic pool capacity.
The label exists, but AIM is refusing to project stale Claude credentials into the managed Claude files.
Refresh the label first:
aim claudalyst
# or
aim login claudalystThen rerun:
aim claude use claudalystAIM has tokens for the label, but it does not yet have the full native Claude login bundle it needs to switch cleanly.
Fastest fixes:
- log that account into native Claude on this machine so both of these exist for the right identity:
~/.claude/.credentials.json~/.claude.jsonoauthAccount
- run
aim claude capture-native <label>on the same host, or rerunaim <label>so AIM captures that live native login - if the login happened on another host, run
aim claude export-live --out <file>there andaim claude import-native <label> --in <file>here - rerun
aim claude use
Something in the environment is overriding native Claude file-based auth, so AIM can no longer prove the local Claude target is using the projected native bundle.
Common override env vars:
CLAUDE_CODE_OAUTH_TOKENANTHROPIC_AUTH_TOKENANTHROPIC_API_KEYCLAUDE_CODE_USE_BEDROCKCLAUDE_CODE_USE_VERTEXCLAUDE_CODE_USE_FOUNDRY
Clear the override, start a fresh Claude process, and recheck:
aim statusUse a file-backed Codex home instead, or test with a temp CODEX_HOME.
Verify the authority host is reachable and has AIM state:
ssh agents@amirs-mac-studio 'test -f ~/.aimgr/secrets.json && echo ok'Start a new Claude, Codex, or Pi process for the target you just switched. AIM guarantees next-process behavior, not live hot-swap.
Status output is redacted. The durable state file itself is not.
npm testCurrent tests cover:
- secret redaction in
aim status --json - migration and import boundaries
- AIM-owned login state, browser binding, and native-Claude bundle behavior
- OpenClaw auth/profile writes and rebalance helpers
- Codex, Claude, and Pi local activation flows
- model/session helper logic for OpenClaw
{ "schemaVersion": "0.2", "accounts": { "boss": { "provider": "openai-codex", "expect": { "email": "[email protected]" }, "reauth": { "mode": "manual-callback", "lastVerifiedAt": "2026-03-21T03:21:00.000Z" }, "pool": { "enabled": true } } }, "credentials": { "openai-codex": { "boss": { "access": "...", "refresh": "...", "idToken": "...", "expiresAt": "2026-03-21T05:21:00.000Z", "accountId": "acct_123" } }, "anthropic": {} }, "imports": { "authority": { "codex": { "source": "agents@amirs-mac-studio", "importedAt": "2026-03-21T03:21:00.000Z", "labels": ["boss", "lessons"], "labelsByName": { "boss": { "importedAt": "2026-03-21T03:21:00.000Z", "baseAccountId": "acct_123", "dirtyLocal": false } } }, "anthropic": { "source": "agents@amirs-mac-studio", "importedAt": "2026-03-21T03:21:00.000Z", "labels": ["claudalyst"], "labelsByName": { "claudalyst": { "importedAt": "2026-03-21T03:21:00.000Z", "dirtyLocal": false } } } } }, "pool": { "openaiCodex": { "history": [], "agentDemand": {}, "hermesFleet": { "demandByHome": {}, "lastApplyReceipt": { "status": "applied" }, "lastWatchReceipt": { "status": "noop" } } }, "anthropic": { "history": [] } }, "targets": { "openclaw": { "assignments": { "agent_boss": "boss" }, "exclusions": {}, "lastApplyReceipt": { "status": "applied" } }, "codexCli": { "activeLabel": "boss", "homeDir": "/Users/you/.codex", "expectedAccountId": "acct_123", "lastSelectionReceipt": { "status": "activated" }, "lastWatchReceipt": { "status": "noop" } }, "claudeCli": { "activeLabel": "claudalyst", "credentialsPath": "/Users/you/.claude/.credentials.json", "appStatePath": "/Users/you/.claude.json", "lastSelectionReceipt": { "status": "activated" } } } }