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/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>com.claude-multiacc.limits</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>60</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>com.claude-multiacc.health</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>com.claude-multiacc.update</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>com.claude-multiacc.codex-limits</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>60</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>com.claude-multiacc.codex-health</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 60s (claude + codex) + weekly health checks + daily auto-update"
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
- { crontab -l 2>/dev/null | grep -v "$CRON_TAG" || true; } > "$tmp"
262
+ env="$(cron_env_prefix)"
263
+ { crontab -l 2>/dev/null | cron_strip_ours; } > "$tmp"
192
264
  {
193
- echo "* * * * * $REPO_DIR/bin/claude-accounts limits --quiet >/dev/null 2>&1 $CRON_TAG"
194
- echo "* * * * * $REPO_DIR/bin/codex-accounts limits --quiet >/dev/null 2>&1 $CRON_TAG"
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 60s (claude + codex) + weekly health checks + daily auto-update"
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 | grep -v "$CRON_TAG" || true; } > "$tmp"
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
- strip_block "$HOME/.zshenv"
216
- strip_block "$HOME/.zprofile"
217
- strip_block "$HOME/.zshrc"
218
- strip_block "$HOME/.bashrc"
219
- strip_block "$HOME/.bash_profile"
220
- strip_block "$HOME/.profile"
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
- [ -f "$PROFILED" ] && rm -f "$PROFILED"
226
- if [ -L /usr/local/bin/claude ] && [ "$(canon_path /usr/local/bin/claude)" = "$(canon_path "$REPO_DIR/bin/claude")" ]; then
227
- rm -f /usr/local/bin/claude
228
- echo " removed /usr/local/bin/claude shim symlink"
229
- fi
230
- if [ -L /usr/local/bin/codex ] && [ "$(canon_path /usr/local/bin/codex)" = "$(canon_path "$REPO_DIR/bin/codex")" ]; then
231
- rm -f /usr/local/bin/codex
232
- echo " removed /usr/local/bin/codex shim symlink"
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
- case "$root" in
239
- */.claude-accounts|*/.codex-accounts) rm -rf "$root"; echo " purged $root" ;;
240
- *) echo " refusing to purge unusual accounts root: $root" >&2 ;;
241
- esac
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
- echo " account pool: $ACC_ROOT (manifest ready)"
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
- touch "$HOME/.zshenv"
306
- append_block "$HOME/.zshenv"
307
- touch "$HOME/.zprofile"
308
- append_block "$HOME/.zprofile"
309
- touch "$HOME/.zshrc"
310
- append_block "$HOME/.zshrc"
311
- [ -f "$HOME/.bash_profile" ] && append_block "$HOME/.bash_profile"
312
- [ -f "$HOME/.bashrc" ] && append_block "$HOME/.bashrc"
313
- echo " PATH block: end of ~/.zshenv, ~/.zprofile, ~/.zshrc (+ bash rc files if present)"
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
- touch "$HOME/.bashrc"
317
- append_block "$HOME/.bashrc"
318
- if [ -w /etc/profile.d ] 2>/dev/null || [ "$(id -u)" = "0" ]; then
319
- {
320
- printf '%s\n' "$MARK_BEGIN"
321
- path_block_body
322
- printf '%s\n' "$MARK_END"
323
- } > "$PROFILED"
324
- echo " PATH block: ~/.bashrc + $PROFILED"
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