claude-multiacc 1.0.13 → 1.0.14
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 +249 -14
- package/bin/claude +402 -38
- package/bin/claude-accounts +141 -45
- package/bin/codex +254 -26
- package/bin/codex-accounts +157 -52
- package/install.sh +175 -69
- package/lib/common.sh +262 -2
- package/lib/credential.py +336 -0
- package/lib/report.py +355 -0
- package/package.json +1 -1
- package/tests/run-tests.sh +1053 -1
package/install.sh
CHANGED
|
@@ -4,41 +4,107 @@
|
|
|
4
4
|
# its install dir, or its update machinery.
|
|
5
5
|
#
|
|
6
6
|
# ./install.sh [--server user@host] install or update (data untouched)
|
|
7
|
+
# ./install.sh --no-server install with NO sync target (local-only pool:
|
|
8
|
+
# a panel/runner daemon distributes accounts)
|
|
9
|
+
# ./install.sh --instance NAME label this install's agents (default: derived
|
|
10
|
+
# from the pool root when it is not the default)
|
|
7
11
|
# ./install.sh --uninstall remove addon (keeps ~/.claude-accounts)
|
|
8
12
|
# ./install.sh --uninstall --purge-data remove addon + all account data
|
|
13
|
+
#
|
|
14
|
+
# INSTANCE-SCOPED POOLS: export CLAUDE_ACCOUNTS_ROOT / CODEX_ACCOUNTS_ROOT before
|
|
15
|
+
# running this and the whole install serves that pool — its LaunchAgents/cron entries
|
|
16
|
+
# get their own labels and carry the roots in their environment, so several app-robot
|
|
17
|
+
# instances on one machine never touch each other's accounts or agents.
|
|
9
18
|
set -u
|
|
10
19
|
|
|
11
20
|
REPO_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
|
12
21
|
# shellcheck source=lib/common.sh
|
|
13
22
|
. "$REPO_DIR/lib/common.sh"
|
|
14
23
|
# common.sh is sourced in claude mode (ACC_ROOT = the claude pool); the codex pool
|
|
15
|
-
# root is needed here too for uninstall/purge messaging.
|
|
16
|
-
CODEX_ACC_ROOT="${CODEX_ACCOUNTS_DIR:-$HOME/.codex-accounts}"
|
|
17
|
-
|
|
18
|
-
MARK_BEGIN="# >>> claude-multiacc >>>"
|
|
19
|
-
MARK_END="# <<< claude-multiacc <<<"
|
|
20
|
-
CRON_TAG="# claude-multiacc"
|
|
21
|
-
PLIST_LIMITS="$HOME/Library/LaunchAgents/com.claude-multiacc.limits.plist"
|
|
22
|
-
PLIST_HEALTH="$HOME/Library/LaunchAgents/com.claude-multiacc.health.plist"
|
|
23
|
-
PLIST_UPDATE="$HOME/Library/LaunchAgents/com.claude-multiacc.update.plist"
|
|
24
|
-
PLIST_CODEX_LIMITS="$HOME/Library/LaunchAgents/com.claude-multiacc.codex-limits.plist"
|
|
25
|
-
PLIST_CODEX_HEALTH="$HOME/Library/LaunchAgents/com.claude-multiacc.codex-health.plist"
|
|
26
|
-
PROFILED="/etc/profile.d/claude-multiacc.sh"
|
|
24
|
+
# root is needed here too for the codex agents and uninstall/purge messaging.
|
|
25
|
+
CODEX_ACC_ROOT="${CODEX_ACCOUNTS_ROOT:-${CODEX_ACCOUNTS_DIR:-$HOME/.codex-accounts}}"
|
|
27
26
|
|
|
28
27
|
UNINSTALL=0
|
|
29
28
|
PURGE=0
|
|
30
29
|
SERVER_OVERRIDE=""
|
|
31
30
|
NO_SCHEDULE=0
|
|
31
|
+
INSTANCE_OVERRIDE=""
|
|
32
32
|
while [ $# -gt 0 ]; do
|
|
33
33
|
case "$1" in
|
|
34
34
|
--uninstall) UNINSTALL=1; shift ;;
|
|
35
35
|
--purge-data) PURGE=1; shift ;;
|
|
36
36
|
--server) SERVER_OVERRIDE="${2:?--server requires a value}"; shift 2 ;;
|
|
37
|
+
--no-server) SERVER_OVERRIDE="none"; shift ;;
|
|
38
|
+
--instance) INSTANCE_OVERRIDE="${2:?--instance requires a name}"; shift 2 ;;
|
|
37
39
|
--no-schedule) NO_SCHEDULE=1; shift ;;
|
|
38
40
|
*) echo "unknown flag: $1" >&2; exit 1 ;;
|
|
39
41
|
esac
|
|
40
42
|
done
|
|
41
43
|
|
|
44
|
+
# ---- instance scoping -----------------------------------------------------------
|
|
45
|
+
# An install whose pool roots are the defaults keeps the historical labels and rc
|
|
46
|
+
# blocks byte-for-byte. Anything else is an INSTANCE: its agents get a suffix (two
|
|
47
|
+
# instances would otherwise overwrite each other's plists) and the shell rc block is
|
|
48
|
+
# left alone, because one interactive PATH cannot point at two pools at once.
|
|
49
|
+
default_pool_roots() {
|
|
50
|
+
[ "$ACC_ROOT" = "$HOME/.claude-accounts" ] && [ "$CODEX_ACC_ROOT" = "$HOME/.codex-accounts" ]
|
|
51
|
+
}
|
|
52
|
+
short_hash() { # stable 8-char digest of $1, on macOS and Linux alike
|
|
53
|
+
if command -v shasum >/dev/null 2>&1; then printf '%s' "$1" | shasum | cut -c1-8
|
|
54
|
+
elif command -v sha1sum >/dev/null 2>&1; then printf '%s' "$1" | sha1sum | cut -c1-8
|
|
55
|
+
else printf '%s' "$1" | cksum | tr -d ' ' | cut -c1-8; fi
|
|
56
|
+
}
|
|
57
|
+
if [ -n "$INSTANCE_OVERRIDE" ]; then
|
|
58
|
+
case "$INSTANCE_OVERRIDE" in
|
|
59
|
+
*[!A-Za-z0-9-]*) echo "--instance must be letters, digits and dashes: $INSTANCE_OVERRIDE" >&2; exit 1 ;;
|
|
60
|
+
esac
|
|
61
|
+
INSTANCE="$INSTANCE_OVERRIDE"
|
|
62
|
+
elif default_pool_roots; then
|
|
63
|
+
INSTANCE=""
|
|
64
|
+
else
|
|
65
|
+
INSTANCE="i$(short_hash "$ACC_ROOT")"
|
|
66
|
+
fi
|
|
67
|
+
# The roots are interpolated into plists and crontab lines; a quote or newline in one
|
|
68
|
+
# would break out of that context, so such a root is refused up front.
|
|
69
|
+
case "$ACC_ROOT$CODEX_ACC_ROOT" in
|
|
70
|
+
*["'\"<>&"]*|*"
|
|
71
|
+
"*) echo "pool root contains a character that cannot be scheduled safely: $ACC_ROOT / $CODEX_ACC_ROOT" >&2; exit 1 ;;
|
|
72
|
+
esac
|
|
73
|
+
|
|
74
|
+
LABEL="com.claude-multiacc${INSTANCE:+.$INSTANCE}"
|
|
75
|
+
MARK_BEGIN="# >>> claude-multiacc >>>"
|
|
76
|
+
MARK_END="# <<< claude-multiacc <<<"
|
|
77
|
+
CRON_TAG="# claude-multiacc${INSTANCE:+ $INSTANCE}"
|
|
78
|
+
PLIST_LIMITS="$HOME/Library/LaunchAgents/$LABEL.limits.plist"
|
|
79
|
+
PLIST_HEALTH="$HOME/Library/LaunchAgents/$LABEL.health.plist"
|
|
80
|
+
PLIST_UPDATE="$HOME/Library/LaunchAgents/$LABEL.update.plist"
|
|
81
|
+
PLIST_CODEX_LIMITS="$HOME/Library/LaunchAgents/$LABEL.codex-limits.plist"
|
|
82
|
+
PLIST_CODEX_HEALTH="$HOME/Library/LaunchAgents/$LABEL.codex-health.plist"
|
|
83
|
+
PROFILED="/etc/profile.d/claude-multiacc.sh"
|
|
84
|
+
|
|
85
|
+
# Pool roots (and any sync override) for a scheduled agent, so it refreshes THIS
|
|
86
|
+
# instance's pool. Empty for a default install — nothing changes there.
|
|
87
|
+
plist_env_block() {
|
|
88
|
+
[ -n "$INSTANCE" ] || return 0
|
|
89
|
+
printf ' <key>EnvironmentVariables</key><dict>\n'
|
|
90
|
+
printf ' <key>CLAUDE_ACCOUNTS_ROOT</key><string>%s</string>\n' "$ACC_ROOT"
|
|
91
|
+
printf ' <key>CODEX_ACCOUNTS_ROOT</key><string>%s</string>\n' "$CODEX_ACC_ROOT"
|
|
92
|
+
printf ' </dict>\n'
|
|
93
|
+
}
|
|
94
|
+
cron_env_prefix() {
|
|
95
|
+
[ -n "$INSTANCE" ] || return 0
|
|
96
|
+
printf "CLAUDE_ACCOUNTS_ROOT='%s' CODEX_ACCOUNTS_ROOT='%s' " "$ACC_ROOT" "$CODEX_ACC_ROOT"
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
is_pool_root() { # true when $1 is safe to delete as an account pool
|
|
100
|
+
case "$1" in
|
|
101
|
+
''|/|"$HOME") return 1 ;;
|
|
102
|
+
*/.claude-accounts|*/.codex-accounts) return 0 ;;
|
|
103
|
+
/*) [ -f "$1/accounts.json" ] ;;
|
|
104
|
+
*) return 1 ;;
|
|
105
|
+
esac
|
|
106
|
+
}
|
|
107
|
+
|
|
42
108
|
strip_block() { # remove our marked block from a file (portable, no sed -i)
|
|
43
109
|
local f="$1"
|
|
44
110
|
[ -f "$f" ] || return 0
|
|
@@ -78,13 +144,13 @@ mac_schedule_install() {
|
|
|
78
144
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
79
145
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
80
146
|
<plist version="1.0"><dict>
|
|
81
|
-
<key>Label</key><string
|
|
147
|
+
<key>Label</key><string>$LABEL.limits</string>
|
|
82
148
|
<key>ProgramArguments</key><array>
|
|
83
149
|
<string>$REPO_DIR/bin/claude-accounts</string>
|
|
84
150
|
<string>limits</string>
|
|
85
151
|
<string>--quiet</string>
|
|
86
152
|
</array>
|
|
87
|
-
<key>StartInterval</key><integer>
|
|
153
|
+
$(plist_env_block) <key>StartInterval</key><integer>300</integer>
|
|
88
154
|
<key>RunAtLoad</key><true/>
|
|
89
155
|
<key>StandardOutPath</key><string>/dev/null</string>
|
|
90
156
|
<key>StandardErrorPath</key><string>/dev/null</string>
|
|
@@ -94,12 +160,12 @@ EOF
|
|
|
94
160
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
95
161
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
96
162
|
<plist version="1.0"><dict>
|
|
97
|
-
<key>Label</key><string
|
|
163
|
+
<key>Label</key><string>$LABEL.health</string>
|
|
98
164
|
<key>ProgramArguments</key><array>
|
|
99
165
|
<string>$REPO_DIR/bin/claude-accounts</string>
|
|
100
166
|
<string>health</string>
|
|
101
167
|
</array>
|
|
102
|
-
<key>StartCalendarInterval</key><dict>
|
|
168
|
+
$(plist_env_block) <key>StartCalendarInterval</key><dict>
|
|
103
169
|
<key>Weekday</key><integer>1</integer>
|
|
104
170
|
<key>Hour</key><integer>9</integer>
|
|
105
171
|
<key>Minute</key><integer>17</integer>
|
|
@@ -113,13 +179,13 @@ EOF
|
|
|
113
179
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
114
180
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
115
181
|
<plist version="1.0"><dict>
|
|
116
|
-
<key>Label</key><string
|
|
182
|
+
<key>Label</key><string>$LABEL.update</string>
|
|
117
183
|
<key>ProgramArguments</key><array>
|
|
118
184
|
<string>$REPO_DIR/bin/claude-accounts</string>
|
|
119
185
|
<string>self-update</string>
|
|
120
186
|
<string>--quiet</string>
|
|
121
187
|
</array>
|
|
122
|
-
<key>StartCalendarInterval</key><dict>
|
|
188
|
+
$(plist_env_block) <key>StartCalendarInterval</key><dict>
|
|
123
189
|
<key>Hour</key><integer>4</integer>
|
|
124
190
|
<key>Minute</key><integer>7</integer>
|
|
125
191
|
</dict>
|
|
@@ -133,13 +199,13 @@ EOF
|
|
|
133
199
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
134
200
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
135
201
|
<plist version="1.0"><dict>
|
|
136
|
-
<key>Label</key><string
|
|
202
|
+
<key>Label</key><string>$LABEL.codex-limits</string>
|
|
137
203
|
<key>ProgramArguments</key><array>
|
|
138
204
|
<string>$REPO_DIR/bin/codex-accounts</string>
|
|
139
205
|
<string>limits</string>
|
|
140
206
|
<string>--quiet</string>
|
|
141
207
|
</array>
|
|
142
|
-
<key>StartInterval</key><integer>
|
|
208
|
+
$(plist_env_block) <key>StartInterval</key><integer>300</integer>
|
|
143
209
|
<key>RunAtLoad</key><true/>
|
|
144
210
|
<key>StandardOutPath</key><string>/dev/null</string>
|
|
145
211
|
<key>StandardErrorPath</key><string>/dev/null</string>
|
|
@@ -149,12 +215,12 @@ EOF
|
|
|
149
215
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
150
216
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
151
217
|
<plist version="1.0"><dict>
|
|
152
|
-
<key>Label</key><string
|
|
218
|
+
<key>Label</key><string>$LABEL.codex-health</string>
|
|
153
219
|
<key>ProgramArguments</key><array>
|
|
154
220
|
<string>$REPO_DIR/bin/codex-accounts</string>
|
|
155
221
|
<string>health</string>
|
|
156
222
|
</array>
|
|
157
|
-
<key>StartCalendarInterval</key><dict>
|
|
223
|
+
$(plist_env_block) <key>StartCalendarInterval</key><dict>
|
|
158
224
|
<key>Weekday</key><integer>1</integer>
|
|
159
225
|
<key>Hour</key><integer>9</integer>
|
|
160
226
|
<key>Minute</key><integer>37</integer>
|
|
@@ -173,7 +239,7 @@ EOF
|
|
|
173
239
|
launchctl load -w "$PLIST_CODEX_LIMITS" 2>/dev/null || true
|
|
174
240
|
launchctl load -w "$PLIST_CODEX_HEALTH" 2>/dev/null || true
|
|
175
241
|
[ "${CLAUDE_MULTIACC_AUTOUPDATE:-1}" = "1" ] && launchctl load -w "$PLIST_UPDATE" 2>/dev/null || true
|
|
176
|
-
echo " launchd: limits refresh every
|
|
242
|
+
echo " launchd: limits refresh every 5m (claude + codex) + weekly health checks + daily auto-update"
|
|
177
243
|
}
|
|
178
244
|
|
|
179
245
|
mac_schedule_remove() {
|
|
@@ -185,60 +251,80 @@ mac_schedule_remove() {
|
|
|
185
251
|
rm -f "$PLIST_LIMITS" "$PLIST_HEALTH" "$PLIST_UPDATE" "$PLIST_CODEX_LIMITS" "$PLIST_CODEX_HEALTH"
|
|
186
252
|
}
|
|
187
253
|
|
|
254
|
+
# Only THIS instance's lines are dropped: the tag is matched anchored to end of line,
|
|
255
|
+
# so a default install ("# claude-multiacc") never removes an instance's lines
|
|
256
|
+
# ("# claude-multiacc iXXXXXXXX") or the other way round.
|
|
257
|
+
cron_strip_ours() { grep -v -E "$CRON_TAG\$" || true; }
|
|
258
|
+
|
|
188
259
|
linux_schedule_install() {
|
|
189
|
-
local tmp
|
|
260
|
+
local tmp env
|
|
190
261
|
tmp="$(mktemp)"
|
|
191
|
-
|
|
262
|
+
env="$(cron_env_prefix)"
|
|
263
|
+
{ crontab -l 2>/dev/null | cron_strip_ours; } > "$tmp"
|
|
192
264
|
{
|
|
193
|
-
echo "
|
|
194
|
-
echo "
|
|
195
|
-
echo "17 9 * * 1 $REPO_DIR/bin/claude-accounts health >/dev/null 2>&1 $CRON_TAG"
|
|
196
|
-
echo "37 9 * * 1 $REPO_DIR/bin/codex-accounts health >/dev/null 2>&1 $CRON_TAG"
|
|
265
|
+
echo "*/5 * * * * $env$REPO_DIR/bin/claude-accounts limits --quiet >/dev/null 2>&1 $CRON_TAG"
|
|
266
|
+
echo "*/5 * * * * $env$REPO_DIR/bin/codex-accounts limits --quiet >/dev/null 2>&1 $CRON_TAG"
|
|
267
|
+
echo "17 9 * * 1 $env$REPO_DIR/bin/claude-accounts health >/dev/null 2>&1 $CRON_TAG"
|
|
268
|
+
echo "37 9 * * 1 $env$REPO_DIR/bin/codex-accounts health >/dev/null 2>&1 $CRON_TAG"
|
|
197
269
|
[ "${CLAUDE_MULTIACC_AUTOUPDATE:-1}" = "1" ] && \
|
|
198
|
-
echo "7 4 * * * $REPO_DIR/bin/claude-accounts self-update --quiet >/dev/null 2>&1 $CRON_TAG"
|
|
270
|
+
echo "7 4 * * * $env$REPO_DIR/bin/claude-accounts self-update --quiet >/dev/null 2>&1 $CRON_TAG"
|
|
199
271
|
} >> "$tmp"
|
|
200
272
|
crontab "$tmp"
|
|
201
273
|
rm -f "$tmp"
|
|
202
|
-
echo " cron: limits refresh every
|
|
274
|
+
echo " cron: limits refresh every 5m (claude + codex) + weekly health checks + daily auto-update"
|
|
203
275
|
}
|
|
204
276
|
|
|
205
277
|
linux_schedule_remove() {
|
|
206
278
|
local tmp
|
|
207
279
|
tmp="$(mktemp)"
|
|
208
|
-
{ crontab -l 2>/dev/null |
|
|
280
|
+
{ crontab -l 2>/dev/null | cron_strip_ours; } > "$tmp"
|
|
209
281
|
crontab "$tmp"
|
|
210
282
|
rm -f "$tmp"
|
|
211
283
|
}
|
|
212
284
|
|
|
213
285
|
do_uninstall() {
|
|
214
286
|
echo "claude-multiacc: uninstalling (restoring stock behavior)"
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
287
|
+
# An instance install never wrote a shell rc block, a /etc/profile.d file or the
|
|
288
|
+
# /usr/local/bin shims — those belong to the DEFAULT install and are shared with it.
|
|
289
|
+
# Removing them here would disable the operator's shim while only one instance was
|
|
290
|
+
# being uninstalled, so an instance removes exactly its own agents.
|
|
291
|
+
if [ -n "$INSTANCE" ]; then
|
|
292
|
+
echo " instance $INSTANCE: removing its agents only (PATH block and shims belong to the default install)"
|
|
293
|
+
else
|
|
294
|
+
strip_block "$HOME/.zshenv"
|
|
295
|
+
strip_block "$HOME/.zprofile"
|
|
296
|
+
strip_block "$HOME/.zshrc"
|
|
297
|
+
strip_block "$HOME/.bashrc"
|
|
298
|
+
strip_block "$HOME/.bash_profile"
|
|
299
|
+
strip_block "$HOME/.profile"
|
|
300
|
+
fi
|
|
221
301
|
if [ "$(machine_kind)" = "mac" ]; then
|
|
222
302
|
mac_schedule_remove
|
|
223
303
|
else
|
|
224
304
|
linux_schedule_remove
|
|
225
|
-
[ -
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
305
|
+
if [ -z "$INSTANCE" ]; then
|
|
306
|
+
[ -f "$PROFILED" ] && rm -f "$PROFILED"
|
|
307
|
+
if [ -L /usr/local/bin/claude ] && [ "$(canon_path /usr/local/bin/claude)" = "$(canon_path "$REPO_DIR/bin/claude")" ]; then
|
|
308
|
+
rm -f /usr/local/bin/claude
|
|
309
|
+
echo " removed /usr/local/bin/claude shim symlink"
|
|
310
|
+
fi
|
|
311
|
+
if [ -L /usr/local/bin/codex ] && [ "$(canon_path /usr/local/bin/codex)" = "$(canon_path "$REPO_DIR/bin/codex")" ]; then
|
|
312
|
+
rm -f /usr/local/bin/codex
|
|
313
|
+
echo " removed /usr/local/bin/codex shim symlink"
|
|
314
|
+
fi
|
|
233
315
|
fi
|
|
234
316
|
fi
|
|
235
317
|
local root
|
|
236
318
|
for root in "$ACC_ROOT" "$CODEX_ACC_ROOT"; do
|
|
237
319
|
if [ "$PURGE" = "1" ]; then
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
320
|
+
# Either the conventional location, or a directory that is provably a pool (it
|
|
321
|
+
# holds a manifest) — an instance root lives anywhere, so the manifest is what
|
|
322
|
+
# makes `rm -rf` safe. Anything else is left alone.
|
|
323
|
+
if is_pool_root "$root"; then
|
|
324
|
+
rm -rf "$root"; echo " purged $root"
|
|
325
|
+
else
|
|
326
|
+
echo " refusing to purge unusual accounts root: $root" >&2
|
|
327
|
+
fi
|
|
242
328
|
fi
|
|
243
329
|
done
|
|
244
330
|
if [ "$PURGE" != "1" ]; then
|
|
@@ -251,6 +337,9 @@ do_install() {
|
|
|
251
337
|
local kind
|
|
252
338
|
kind="$(machine_kind)"
|
|
253
339
|
echo "claude-multiacc: installing (mode: $kind, repo: $REPO_DIR)"
|
|
340
|
+
if [ -n "$INSTANCE" ]; then
|
|
341
|
+
echo " instance: $INSTANCE (agents labelled $LABEL.*, pools $ACC_ROOT + $CODEX_ACC_ROOT)"
|
|
342
|
+
fi
|
|
254
343
|
|
|
255
344
|
[ -x "$REPO_DIR/bin/claude" ] || chmod +x "$REPO_DIR/bin/claude" 2>/dev/null || true
|
|
256
345
|
[ -x "$REPO_DIR/bin/claude-accounts" ] || chmod +x "$REPO_DIR/bin/claude-accounts" 2>/dev/null || true
|
|
@@ -289,7 +378,11 @@ with open(sys.argv[1] + '.tmp', 'w') as f:
|
|
|
289
378
|
os.replace(sys.argv[1] + '.tmp', sys.argv[1])
|
|
290
379
|
PYEOF
|
|
291
380
|
fi
|
|
292
|
-
|
|
381
|
+
if sync_target_is_local "$(sync_target)"; then
|
|
382
|
+
echo " account pool: $ACC_ROOT (manifest ready; sync target: none — local-only)"
|
|
383
|
+
else
|
|
384
|
+
echo " account pool: $ACC_ROOT (manifest ready; sync target: $(sync_target))"
|
|
385
|
+
fi
|
|
293
386
|
# The codex pool gets its own skeleton + manifest (same schema, separate root).
|
|
294
387
|
if ! "$REPO_DIR/bin/codex-accounts" init-pool "${SERVER_OVERRIDE:-}" >/dev/null 2>&1; then
|
|
295
388
|
echo " WARNING: codex pool init failed (codex-accounts init-pool)" >&2
|
|
@@ -297,31 +390,44 @@ PYEOF
|
|
|
297
390
|
echo " codex account pool: $CODEX_ACC_ROOT (manifest ready)"
|
|
298
391
|
fi
|
|
299
392
|
|
|
393
|
+
# An INSTANCE install never rewrites the shell rc blocks: one interactive PATH
|
|
394
|
+
# cannot serve two pools, and clobbering the default install's block would point
|
|
395
|
+
# the operator's shell at an instance pool. Its agents (below) carry the roots
|
|
396
|
+
# instead, and the runner daemon invokes the shims by absolute path.
|
|
397
|
+
if [ -n "$INSTANCE" ]; then
|
|
398
|
+
echo " PATH block: skipped (instance install) — for a shell against this pool:"
|
|
399
|
+
echo " export CLAUDE_ACCOUNTS_ROOT='$ACC_ROOT' CODEX_ACCOUNTS_ROOT='$CODEX_ACC_ROOT'"
|
|
400
|
+
echo " export PATH=\"$REPO_DIR/bin:\$PATH\""
|
|
401
|
+
fi
|
|
300
402
|
if [ "$kind" = "mac" ]; then
|
|
301
403
|
# .zshenv covers non-interactive zsh; the .zshrc block must be LAST so it wins
|
|
302
404
|
# over ~/.local/bin re-prepends done earlier in .zshrc/.zprofile.
|
|
303
405
|
# zsh reads: .zshenv always; .zprofile for login; .zshrc for interactive.
|
|
304
406
|
# The block must end each file that later re-prepends ~/.local/bin.
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
407
|
+
if [ -z "$INSTANCE" ]; then
|
|
408
|
+
touch "$HOME/.zshenv"
|
|
409
|
+
append_block "$HOME/.zshenv"
|
|
410
|
+
touch "$HOME/.zprofile"
|
|
411
|
+
append_block "$HOME/.zprofile"
|
|
412
|
+
touch "$HOME/.zshrc"
|
|
413
|
+
append_block "$HOME/.zshrc"
|
|
414
|
+
[ -f "$HOME/.bash_profile" ] && append_block "$HOME/.bash_profile"
|
|
415
|
+
[ -f "$HOME/.bashrc" ] && append_block "$HOME/.bashrc"
|
|
416
|
+
echo " PATH block: end of ~/.zshenv, ~/.zprofile, ~/.zshrc (+ bash rc files if present)"
|
|
417
|
+
fi
|
|
314
418
|
[ "$NO_SCHEDULE" = "1" ] || mac_schedule_install
|
|
315
419
|
else
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
420
|
+
if [ -z "$INSTANCE" ]; then
|
|
421
|
+
touch "$HOME/.bashrc"
|
|
422
|
+
append_block "$HOME/.bashrc"
|
|
423
|
+
if [ -w /etc/profile.d ] 2>/dev/null || [ "$(id -u)" = "0" ]; then
|
|
424
|
+
{
|
|
425
|
+
printf '%s\n' "$MARK_BEGIN"
|
|
426
|
+
path_block_body
|
|
427
|
+
printf '%s\n' "$MARK_END"
|
|
428
|
+
} > "$PROFILED"
|
|
429
|
+
echo " PATH block: ~/.bashrc + $PROFILED"
|
|
430
|
+
fi
|
|
325
431
|
fi
|
|
326
432
|
if [ "$(id -u)" = "0" ]; then
|
|
327
433
|
if [ -e /usr/local/bin/claude ] && [ ! -L /usr/local/bin/claude ]; then
|