claude-multiacc 2.0.38 → 2.0.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -0
- package/bin/claude +122 -6
- package/bin/claude-accounts +139 -2
- package/bin/codex +116 -7
- package/bin/codex-accounts +131 -2
- package/docs/ACCOUNT_OPERATIONS.md +34 -0
- package/docs/CODEX.md +26 -0
- package/lib/__pycache__/audit.cpython-312.pyc +0 -0
- package/lib/__pycache__/claude_reset.cpython-312.pyc +0 -0
- package/lib/__pycache__/codex_config_edit.cpython-312.pyc +0 -0
- package/lib/__pycache__/codex_python.cpython-312.pyc +0 -0
- package/lib/__pycache__/keychain.cpython-312.pyc +0 -0
- package/lib/__pycache__/mcp_registry.cpython-312.pyc +0 -0
- package/lib/__pycache__/selector_policy.cpython-312.pyc +0 -0
- package/lib/__pycache__/selector_primitives.cpython-312.pyc +0 -0
- package/lib/__pycache__/shim_path.cpython-312.pyc +0 -0
- package/lib/common.sh +19 -0
- package/lib/mcp_registry.py +1372 -0
- package/package.json +2 -2
- package/tests/__pycache__/packaged_command_support.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_claude_reset.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_codex_reset.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_codex_reset_polling.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_codex_reset_reporting.cpython-312.pyc +0 -0
- package/tests/__pycache__/test_codex_reset_windows.cpython-312.pyc +0 -0
- package/tests/run-tests.sh +588 -0
- package/tests/test_account_seeding.py +40 -0
- package/tests/test_mcp_registry.py +597 -0
package/bin/codex-accounts
CHANGED
|
@@ -100,6 +100,32 @@ USAGE
|
|
|
100
100
|
codex-accounts health limits + full verify; logs to health.log
|
|
101
101
|
codex-accounts self-update update this npm/git install; logs to update.log
|
|
102
102
|
codex-accounts post-sync (server side) seed dirs, fix perms, quick verify
|
|
103
|
+
codex-accounts mcp add <name> [--provider claude|codex|both] [--scope user]
|
|
104
|
+
[-e KEY=VAL]... [-H 'Header: v']... [--transport stdio|http]
|
|
105
|
+
-- <command> [args...] (or a URL)
|
|
106
|
+
register an MCP server for EVERY account: writes the pool's mcp-servers.json
|
|
107
|
+
registry ([mcp_servers.<name>] in every account's config.toml), syncs the
|
|
108
|
+
registry to the server and peers (their post-sync applies it). Default
|
|
109
|
+
--provider both: the same server is registered in the claude pool too.
|
|
110
|
+
A stock `codex mcp add|remove` run under the shim is mirrored into the
|
|
111
|
+
registry the same way — it no longer lands in one random account.
|
|
112
|
+
Project scope is claude-only: Codex reads no per-project MCP config.
|
|
113
|
+
-e takes ONE variable per flag (KEY=VAL). Exit 3 = registry saved, but an account
|
|
114
|
+
could not be reconciled (named on stderr): the change still syncs; fix the account
|
|
115
|
+
and run `mcp apply`. On a replica pool the change lands in the machine-local
|
|
116
|
+
overlay instead of the synced registry — make registry changes on the source.
|
|
117
|
+
The codex registry syncs only to codex sync targets; a runner Mac's local-only
|
|
118
|
+
codex pool is fed by app-robot's overlay (`mcp import-local --owner app-robot`).
|
|
119
|
+
codex-accounts mcp add-json <name> '<json>' [--provider ...]
|
|
120
|
+
codex-accounts mcp remove <name> [--provider ...] [--user-only]
|
|
121
|
+
unregister AND retire EVERYWHERE: every account (fleet-wide after sync) drops the
|
|
122
|
+
server, even one that was hand-added to a single account (--user-only spares a
|
|
123
|
+
claude project-local copy in the claude pool).
|
|
124
|
+
codex-accounts mcp list [--json] effective registry (+ machine-local overlay)
|
|
125
|
+
codex-accounts mcp apply [--account-dir DIR]... [--all]
|
|
126
|
+
re-apply the registry now (repair drift)
|
|
127
|
+
codex-accounts mcp import-local --owner NAME (stdin JSON) machine-local overlay for
|
|
128
|
+
a runner daemon; applied here, never synced
|
|
103
129
|
|
|
104
130
|
ENV
|
|
105
131
|
CODEX_ACCOUNTS_ROOT pool root, overriding ~/.codex-accounts — one isolated pool
|
|
@@ -112,6 +138,7 @@ ENV
|
|
|
112
138
|
CODEX_SHIM_RETRY=0 disable the `codex exec` auto-retry
|
|
113
139
|
CODEX_MULTIACC_DISABLE=1 bypass the shim entirely
|
|
114
140
|
CODEX_MULTIACC_AUTO_RESET=0 disable automatic usage-reset redemption
|
|
141
|
+
CODEX_MULTIACC_MCP=0 disable the MCP registry (no reconcile at seed/launch, no mirror)
|
|
115
142
|
EOF
|
|
116
143
|
}
|
|
117
144
|
|
|
@@ -2001,6 +2028,14 @@ sync_push_target() {
|
|
|
2001
2028
|
|| fail "cannot reach $server"
|
|
2002
2029
|
rsync -az "$MANIFEST" "$server:$sroot/accounts.json" >>"$ACC_ROOT/sync.log" 2>&1 \
|
|
2003
2030
|
|| fail "manifest push to $server failed"
|
|
2031
|
+
# The pool's MCP registry rides with the manifest; the target's post-sync reconciles it
|
|
2032
|
+
# into every account dir there. A missing local registry leaves the target's alone,
|
|
2033
|
+
# and the machine-local overlay (mcp-servers.local.json, a runner daemon's own view
|
|
2034
|
+
# of THIS Mac) never travels.
|
|
2035
|
+
if [ -f "$ACC_ROOT/mcp-servers.json" ]; then
|
|
2036
|
+
rsync -az "$ACC_ROOT/mcp-servers.json" "$server:$sroot/mcp-servers.json" >>"$ACC_ROOT/sync.log" 2>&1 \
|
|
2037
|
+
|| fail "MCP registry push to $server failed"
|
|
2038
|
+
fi
|
|
2004
2039
|
|
|
2005
2040
|
local id d
|
|
2006
2041
|
for id in $(account_ids); do
|
|
@@ -2188,6 +2223,97 @@ EOF
|
|
|
2188
2223
|
fi
|
|
2189
2224
|
}
|
|
2190
2225
|
|
|
2226
|
+
# MCP servers for EVERY account (lib/mcp_registry.py) — the codex twin of
|
|
2227
|
+
# claude-accounts' cmd_mcp. `add`/`add-json`/`remove` edit this pool's registry under
|
|
2228
|
+
# the mutate lock, reconcile every account's config.toml, auto-sync, and by default
|
|
2229
|
+
# (--provider both) make the same change in the claude pool. `list`/`apply`/
|
|
2230
|
+
# `import-local` act on this pool alone; the overlay `import-local` writes is
|
|
2231
|
+
# machine-local by definition, so it is applied here and never synced.
|
|
2232
|
+
mcp_sibling_root() { # the other provider's pool root, by the same env precedence
|
|
2233
|
+
if [ "$MULTIACC_PROVIDER" = "codex" ]; then
|
|
2234
|
+
printf '%s\n' "${CLAUDE_ACCOUNTS_ROOT:-${CLAUDE_ACCOUNTS_DIR:-$HOME/.claude-accounts}}"
|
|
2235
|
+
else
|
|
2236
|
+
printf '%s\n' "${CODEX_ACCOUNTS_ROOT:-${CODEX_ACCOUNTS_DIR:-$HOME/.codex-accounts}}"
|
|
2237
|
+
fi
|
|
2238
|
+
}
|
|
2239
|
+
cmd_mcp() {
|
|
2240
|
+
require_manifest
|
|
2241
|
+
local sub="${1:-}" provider=both before_dd=1 a rc=0 sibling sibling_root
|
|
2242
|
+
local args=()
|
|
2243
|
+
case "$sub" in
|
|
2244
|
+
add|add-json|remove|list|apply|import-local) shift ;;
|
|
2245
|
+
"") usage; return 1 ;;
|
|
2246
|
+
*) die "unknown mcp subcommand: $sub (add, add-json, remove, list, apply, import-local)" ;;
|
|
2247
|
+
esac
|
|
2248
|
+
[ -f "$LIB_DIR/mcp_registry.py" ] || die "lib/mcp_registry.py is missing from this install"
|
|
2249
|
+
case "$sub" in
|
|
2250
|
+
list|apply|import-local)
|
|
2251
|
+
"$PYBIN" "$LIB_DIR/mcp_registry.py" --root "$ACC_ROOT" --provider "$MULTIACC_PROVIDER" "$sub" "$@"
|
|
2252
|
+
return $? ;;
|
|
2253
|
+
esac
|
|
2254
|
+
# --provider is OUR option: strip it, but only before a literal `--` — after it every
|
|
2255
|
+
# word belongs to the MCP server's own command line and is passed through untouched.
|
|
2256
|
+
while [ $# -gt 0 ]; do
|
|
2257
|
+
a="$1"
|
|
2258
|
+
if [ "$before_dd" = 1 ]; then
|
|
2259
|
+
case "$a" in
|
|
2260
|
+
--) before_dd=0 ;;
|
|
2261
|
+
--provider)
|
|
2262
|
+
[ $# -ge 2 ] || die "--provider needs a value: claude, codex or both"
|
|
2263
|
+
provider="$2"; shift 2; continue ;;
|
|
2264
|
+
--provider=*) provider="${a#--provider=}"; shift; continue ;;
|
|
2265
|
+
esac
|
|
2266
|
+
fi
|
|
2267
|
+
args+=("$a"); shift
|
|
2268
|
+
done
|
|
2269
|
+
case "$provider" in
|
|
2270
|
+
claude|codex|both) ;;
|
|
2271
|
+
*) die "--provider must be claude, codex or both (got '$provider')" ;;
|
|
2272
|
+
esac
|
|
2273
|
+
if [ "$provider" = "$MULTIACC_PROVIDER" ] || [ "$provider" = both ]; then
|
|
2274
|
+
mutate_lock || die "could not acquire the account lock — try again"
|
|
2275
|
+
trap mutate_unlock EXIT
|
|
2276
|
+
"$PYBIN" "$LIB_DIR/mcp_registry.py" --root "$ACC_ROOT" --provider "$MULTIACC_PROVIDER" "$sub" \
|
|
2277
|
+
${args[@]+"${args[@]}"}
|
|
2278
|
+
rc=$?
|
|
2279
|
+
mutate_unlock
|
|
2280
|
+
trap - EXIT
|
|
2281
|
+
# 3 = the registry WAS saved and some account could not be reconciled (a corrupt
|
|
2282
|
+
# config, a layout the TOML editor refuses): the change still has to reach the
|
|
2283
|
+
# server, the peers and the sibling pool, and `mcp apply` repairs the account once
|
|
2284
|
+
# it is fixed. 1/2 = nothing was saved: stop here.
|
|
2285
|
+
case "$rc" in
|
|
2286
|
+
0) ;;
|
|
2287
|
+
3) printf '%s: registry saved; some accounts were not reconciled — run: %s mcp apply\n' \
|
|
2288
|
+
"$PROVIDER_CLI" "$PROVIDER_CLI" >&2 ;;
|
|
2289
|
+
*) return "$rc" ;;
|
|
2290
|
+
esac
|
|
2291
|
+
auto_sync
|
|
2292
|
+
fi
|
|
2293
|
+
if [ "$provider" != "$MULTIACC_PROVIDER" ]; then
|
|
2294
|
+
if [ "$MULTIACC_PROVIDER" = "codex" ]; then sibling=claude; else sibling=codex; fi
|
|
2295
|
+
sibling_root="$(mcp_sibling_root)"
|
|
2296
|
+
# With the DEFAULT (both), a machine without the sibling pool or CLI has nothing to
|
|
2297
|
+
# mirror, and silently so — a claude-only Mac must not warn on every codex
|
|
2298
|
+
# change. An EXPLICIT --provider claude asked for that pool by name: refuse loudly.
|
|
2299
|
+
if [ ! -f "$sibling_root/accounts.json" ]; then
|
|
2300
|
+
[ "$provider" = both ] && return "$rc"
|
|
2301
|
+
die "no $sibling pool on this machine ($sibling_root/accounts.json is missing)"
|
|
2302
|
+
fi
|
|
2303
|
+
if [ ! -x "$BIN_DIR/$sibling-accounts" ]; then
|
|
2304
|
+
[ "$provider" = both ] && return "$rc"
|
|
2305
|
+
die "$sibling-accounts is not installed beside $PROVIDER_CLI"
|
|
2306
|
+
fi
|
|
2307
|
+
# The caller's no-sync request travels with the hop, in the sibling's spelling.
|
|
2308
|
+
if [ "${CODEX_MULTIACC_NO_SYNC:-0}" = "1" ]; then export CLAUDE_MULTIACC_NO_SYNC=1; fi
|
|
2309
|
+
local sib_rc=0
|
|
2310
|
+
MULTIACC_PROVIDER="$sibling" "$BIN_DIR/$sibling-accounts" mcp "$sub" --provider "$sibling" \
|
|
2311
|
+
${args[@]+"${args[@]}"} || sib_rc=$?
|
|
2312
|
+
[ "$rc" -eq 0 ] && rc="$sib_rc"
|
|
2313
|
+
fi
|
|
2314
|
+
return "$rc"
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2191
2317
|
cmd_post_sync() {
|
|
2192
2318
|
require_manifest
|
|
2193
2319
|
local_pool_fixup
|
|
@@ -2306,11 +2432,13 @@ PYEOF
|
|
|
2306
2432
|
# distribution for as long as the arg loops rejected the flag. An UNKNOWN verb must still
|
|
2307
2433
|
# FAIL, or the probe stops meaning what it says — so this list must hold exactly the verbs
|
|
2308
2434
|
# the dispatcher below implements, and a test pins that both ways.
|
|
2309
|
-
_KNOWN_VERBS="list status add import export-credential export-cred import-credential import-cred adopt dedupe remove login expired relogin re-login sync configure verify limits post-sync health self-update init-pool"
|
|
2435
|
+
_KNOWN_VERBS="list status add import export-credential export-cred import-credential import-cred adopt dedupe remove login expired relogin re-login sync configure verify limits post-sync health self-update init-pool mcp"
|
|
2310
2436
|
case " $_KNOWN_VERBS " in
|
|
2311
2437
|
*" ${1:-help} "*)
|
|
2438
|
+
# ...but never past a literal `--`: from there on the words belong to an MCP
|
|
2439
|
+
# server's own command line (`mcp add … -- node s.js -h 127.0.0.1`).
|
|
2312
2440
|
for _arg in "$@"; do
|
|
2313
|
-
case "$_arg" in --help|-h) usage; exit 0 ;; esac
|
|
2441
|
+
case "$_arg" in --) break ;; --help|-h) usage; exit 0 ;; esac
|
|
2314
2442
|
done ;;
|
|
2315
2443
|
esac
|
|
2316
2444
|
|
|
@@ -2335,6 +2463,7 @@ case "${1:-help}" in
|
|
|
2335
2463
|
health) shift; cmd_health "$@" ;;
|
|
2336
2464
|
self-update) shift; cmd_self_update "$@" ;;
|
|
2337
2465
|
init-pool) shift; cmd_init_pool "$@" ;;
|
|
2466
|
+
mcp) shift; cmd_mcp "$@" ;;
|
|
2338
2467
|
help|--help|-h) usage ;;
|
|
2339
2468
|
*) usage; exit 1 ;;
|
|
2340
2469
|
esac
|
|
@@ -165,6 +165,40 @@ set, which is what prevents two machines from overwriting each other's manifests
|
|
|
165
165
|
Make account changes on the source; sign-ins (`login`/`relogin`) still happen on
|
|
166
166
|
whichever machine needs the credential.
|
|
167
167
|
|
|
168
|
+
### MCP servers for every account
|
|
169
|
+
|
|
170
|
+
MCP servers live in the config dir, i.e. per account. Never register one with a stock
|
|
171
|
+
`claude mcp add` on a pool Mac and expect it everywhere — under the shim that command is
|
|
172
|
+
mirrored into the registry (see below), but the registry is the source of truth, and it is
|
|
173
|
+
edited on the **source** machine (a replica's own changes land in its machine-local overlay
|
|
174
|
+
and are not pushed anywhere):
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
claude-accounts mcp add appinspire-mcp -- npx -y appinspire-mcp@latest serve
|
|
178
|
+
# writes ~/.claude-accounts/mcp-servers.json AND ~/.codex-accounts/mcp-servers.json,
|
|
179
|
+
# reconciles every account of both pools, auto-syncs the registry to server + peers
|
|
180
|
+
claude-accounts mcp add --provider claude --scope project --project "$HOME/design-lab/run1" appinspire -e APPINSPIRE_LIBRARY_DIR="$HOME/.appinspire-mcp/library" -- node "$HOME/appinspire-mcp/bin/appinspire-mcp.mjs" serve
|
|
181
|
+
# a checkout, registered for ONE project (claude only: codex reads no project config);
|
|
182
|
+
# one -e per variable, and $HOME rather than ~ inside a value
|
|
183
|
+
claude-accounts mcp remove adspower-local-api # retire EVERYWHERE: user scope + every project entry, hand-added copies too
|
|
184
|
+
claude-accounts mcp remove foo --user-only # user scope only
|
|
185
|
+
claude-accounts mcp list # effective registry (+ machine-local overlay)
|
|
186
|
+
claude-accounts mcp apply # re-apply to every account now (exit 3 from add/remove = do this after fixing the account it named)
|
|
187
|
+
codex-accounts mcp list # the codex pool's view
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
How a fleet Mac receives it: `sync` (and every claude limits pass) pushes the claude
|
|
191
|
+
`mcp-servers.json` next to the manifest to the server and every peer; the target's
|
|
192
|
+
`post-sync` re-seeds its account dirs, which applies the registry; and the shim there
|
|
193
|
+
re-applies it to the picked account right before exec whenever the file changed. The codex
|
|
194
|
+
registry travels only to codex sync targets (the server, gas-mini) — runner Macs' codex pools
|
|
195
|
+
are local-only and are fed by app-robot's runner overlay (`codex-accounts mcp import-local
|
|
196
|
+
--owner app-robot`) or a direct `codex-accounts mcp add --provider codex …` on that Mac. A
|
|
197
|
+
runner daemon's overlay (`<provider>-accounts mcp import-local --owner NAME`, JSON on stdin)
|
|
198
|
+
is applied on the Mac and never synced. `--help` on `mcp` lists every option;
|
|
199
|
+
`CLAUDE_MULTIACC_MCP=0` / `CODEX_MULTIACC_MCP=0` stop the reconcile at seed and launch and the
|
|
200
|
+
shim's mirror (the CLI, sync and fan-out keep working).
|
|
201
|
+
|
|
168
202
|
### Pointing sync somewhere else (or nowhere)
|
|
169
203
|
|
|
170
204
|
The target is no longer baked in. In precedence order:
|
package/docs/CODEX.md
CHANGED
|
@@ -83,6 +83,32 @@ codex-accounts --help # all account commands and options
|
|
|
83
83
|
claude-multiacc codex status # same status command via the npm wrapper
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
+
## MCP servers for every account
|
|
87
|
+
|
|
88
|
+
`codex-accounts mcp add|add-json|remove|list|apply|import-local` manages the pool's MCP
|
|
89
|
+
registry (`~/.codex-accounts/mcp-servers.json`); `add`/`remove` default to `--provider both`,
|
|
90
|
+
so the claude pool beside it gets the same change, and `mcp remove` retires the server in
|
|
91
|
+
every account (`--user-only` keeps a claude project-local copy). A stock `codex mcp add|remove`
|
|
92
|
+
run under the shim — or from inside a pooled codex session — is mirrored into the registry and
|
|
93
|
+
every account; on a replica pool the mirror lands in the machine-local overlay instead, so
|
|
94
|
+
make registry changes on the source. The registry holds Claude-style blocks; for codex each
|
|
95
|
+
becomes a `[mcp_servers.<name>]` table in every account's `config.toml`, and unrelated
|
|
96
|
+
tables, their comments and blank lines are left alone: `command`/`args` as is, literal `env`
|
|
97
|
+
values as an inline `env` table, a `KEY=${KEY}` reference as `env_vars = ["KEY"]` (codex
|
|
98
|
+
forwards a variable under its own name only and expands nothing, so `KEY=${OTHER}` and
|
|
99
|
+
`${VAR:-default}` cannot be expressed and are left out with a warning), `headers` on an HTTP
|
|
100
|
+
server as `http_headers` (literal) / `env_http_headers` (references), `Authorization: Bearer
|
|
101
|
+
${VAR}` as `bearer_token_env_var`, and, for a stdio server, `startup_timeout_sec = 60` unless
|
|
102
|
+
the block sets one (a cold `npx` download must not trip codex's 10 s default). Codex-only keys
|
|
103
|
+
codex itself wrote (`oauth`, `enabled_tools`, …) ride along in the registry block and never
|
|
104
|
+
reach `.claude.json`. SSE transports cannot be expressed and are skipped with a warning;
|
|
105
|
+
project scope is claude-only because Codex 0.156 reads no per-project MCP config. Python
|
|
106
|
+
3.11+ is found the same way as for `configure`. `CODEX_MULTIACC_MCP=0` stops the reconcile at
|
|
107
|
+
seed and launch and the mirror; the CLI keeps working. The codex registry syncs only to codex
|
|
108
|
+
sync targets — a runner Mac's local-only codex pool gets its servers from app-robot's runner
|
|
109
|
+
overlay (`mcp import-local --owner app-robot`) or a direct `codex-accounts mcp add
|
|
110
|
+
--provider codex …` there.
|
|
111
|
+
|
|
86
112
|
## Opt-in subagent concurrency policy
|
|
87
113
|
|
|
88
114
|
The addon does not choose delegation policy by default. To manage the concurrent
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/lib/common.sh
CHANGED
|
@@ -685,6 +685,23 @@ codex_share_state_index() { # $1 acct dir — seed time: whatever index names ex
|
|
|
685
685
|
# shared sessions/ symlink (=> `codex resume` finds every session) with the
|
|
686
686
|
# shared rollout index that tree needs, and a shared AGENTS.md symlink so
|
|
687
687
|
# global instructions apply under any account.
|
|
688
|
+
# MCP servers for EVERY account (lib/mcp_registry.py). Both clients keep MCP servers in
|
|
689
|
+
# the CONFIG DIR (`<dir>/.claude.json`, `<CODEX_HOME>/config.toml`), so under the pool
|
|
690
|
+
# there is one MCP configuration per account and a stock `claude mcp add` lands in ONE
|
|
691
|
+
# random one. The pool's registry (mcp-servers.json, synced) plus the machine-local
|
|
692
|
+
# overlay (mcp-servers.local.json, never synced) are reconciled into every account here,
|
|
693
|
+
# at seed time, and by the shims right before exec. Fail-open: a seed never dies on it.
|
|
694
|
+
seed_mcp_registry() { # $1 = acct dir
|
|
695
|
+
local d="$1" off
|
|
696
|
+
if [ "$MULTIACC_PROVIDER" = "codex" ]; then off="${CODEX_MULTIACC_MCP:-1}"; else off="${CLAUDE_MULTIACC_MCP:-1}"; fi
|
|
697
|
+
[ "$off" = "0" ] && return 0
|
|
698
|
+
[ -f "$ACC_ROOT/mcp-servers.json" ] || [ -f "$ACC_ROOT/mcp-servers.local.json" ] || return 0
|
|
699
|
+
[ -f "$LIB_DIR/mcp_registry.py" ] || return 0
|
|
700
|
+
"$PYBIN" "$LIB_DIR/mcp_registry.py" --root "$ACC_ROOT" --provider "$MULTIACC_PROVIDER" apply \
|
|
701
|
+
--account-dir "$d" --fail-open --quiet >/dev/null || true
|
|
702
|
+
return 0
|
|
703
|
+
}
|
|
704
|
+
|
|
688
705
|
seed_account_dir() { # $1 = acct dir
|
|
689
706
|
local d="$1"
|
|
690
707
|
mkdir -p "$d"
|
|
@@ -704,6 +721,7 @@ seed_account_dir() { # $1 = acct dir
|
|
|
704
721
|
ln -s "$HOME/.codex/AGENTS.md" "$d/AGENTS.md" 2>/dev/null || true
|
|
705
722
|
fi
|
|
706
723
|
codex_share_state_index "$d"
|
|
724
|
+
seed_mcp_registry "$d"
|
|
707
725
|
return 0
|
|
708
726
|
fi
|
|
709
727
|
if [ ! -f "$d/.claude.json" ] && [ -f "$HOME/.claude.json" ]; then
|
|
@@ -730,6 +748,7 @@ PYEOF
|
|
|
730
748
|
if [ ! -e "$d/projects" ] && [ -d "$HOME/.claude/projects" ]; then
|
|
731
749
|
ln -s "$HOME/.claude/projects" "$d/projects" 2>/dev/null || true
|
|
732
750
|
fi
|
|
751
|
+
seed_mcp_registry "$d"
|
|
733
752
|
}
|
|
734
753
|
|
|
735
754
|
# Short-lived mutation lock: serialize only the brief critical sections (id reservation,
|