@wangxt0223/codex-switcher 0.5.1 → 0.6.0
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/CHANGELOG.md +10 -0
- package/README.en.md +13 -15
- package/README.md +17 -42
- package/docs/macos-manual-checklist.md +8 -7
- package/docs/upgrade.md +1 -1
- package/package.json +4 -3
- package/plugins/codex-switcher/README.en.md +55 -82
- package/plugins/codex-switcher/README.md +53 -80
- package/plugins/codex-switcher/scripts/codex-switcher +1121 -409
- package/plugins/codex-switcher/scripts/profile-metrics.py +378 -0
- package/plugins/codex-switcher/scripts/test-switcher.sh +106 -108
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
set -euo pipefail
|
|
3
3
|
|
|
4
4
|
STATE_DIR="${CODEX_SWITCHER_STATE_DIR:-$HOME/.codex-switcher}"
|
|
5
|
-
|
|
5
|
+
ENVS_DIR="${CODEX_SWITCHER_ENVS_DIR:-$HOME/.codex-envs}"
|
|
6
|
+
ACCOUNTS_DIR="${CODEX_SWITCHER_ACCOUNTS_DIR:-$STATE_DIR/env-accounts}"
|
|
7
|
+
DEFAULT_HOME="${CODEX_SWITCHER_DEFAULT_HOME:-$HOME/.codex}"
|
|
8
|
+
DEFAULT_ENV_NAME="default"
|
|
9
|
+
DEFAULT_ACCOUNT_NAME="default"
|
|
10
|
+
|
|
6
11
|
APP_LOG="${CODEX_SWITCHER_APP_LOG:-$STATE_DIR/app.log}"
|
|
7
12
|
SWITCH_LOG="${CODEX_SWITCHER_SWITCH_LOG:-$STATE_DIR/switcher.log}"
|
|
8
13
|
APP_PID_FILE="$STATE_DIR/app.pid"
|
|
@@ -14,23 +19,37 @@ SCRIPT_NAME="${CODEX_SWITCHER_INVOKED_AS:-$(basename "$0")}"
|
|
|
14
19
|
usage() {
|
|
15
20
|
cat <<'USAGE'
|
|
16
21
|
Usage:
|
|
17
|
-
codex-sw
|
|
18
|
-
codex-sw
|
|
22
|
+
codex-sw env list
|
|
23
|
+
codex-sw env create <env> [--empty|--from-default|--from-env <src>]
|
|
24
|
+
codex-sw env use <env> [--target cli|app|both]
|
|
25
|
+
codex-sw env remove <env> [--force]
|
|
26
|
+
codex-sw env current [cli|app]
|
|
27
|
+
codex-sw env path [env]
|
|
28
|
+
|
|
29
|
+
codex-sw account list [--env <env>]
|
|
30
|
+
codex-sw account add <account> [--env <env>]
|
|
31
|
+
codex-sw account remove <account> [--env <env>] [--force]
|
|
32
|
+
codex-sw account login <account> [--env <env>] [--target cli|app|both] [--sync|--no-sync]
|
|
33
|
+
codex-sw account use <account> [--env <env>] [--target cli|app|both] [--sync|--no-sync]
|
|
34
|
+
codex-sw account logout [account] [--env <env>] [--target cli|app|both]
|
|
35
|
+
codex-sw account current [cli|app]
|
|
36
|
+
|
|
19
37
|
codex-sw list
|
|
20
|
-
codex-sw import-default <profile> [--with-auth] [--force]
|
|
21
|
-
codex-sw use <profile> [--sync|--no-sync] [--launch|--no-launch] [-- <codex args...>]
|
|
22
|
-
codex-sw switch <profile> [--sync|--no-sync] [--launch|--no-launch] [-- <codex args...>]
|
|
23
|
-
codex-sw current [cli|app]
|
|
24
38
|
codex-sw status
|
|
25
|
-
|
|
39
|
+
codex-sw current [cli|app]
|
|
26
40
|
codex-sw exec -- <codex args...>
|
|
27
|
-
codex-sw login [
|
|
28
|
-
codex-sw logout [
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
codex-sw
|
|
32
|
-
codex-sw
|
|
33
|
-
codex-sw
|
|
41
|
+
codex-sw login [account] [--sync|--no-sync]
|
|
42
|
+
codex-sw logout [account]
|
|
43
|
+
|
|
44
|
+
codex-sw use <account> [--sync|--no-sync] [--launch|--no-launch] [-- <codex args...>]
|
|
45
|
+
codex-sw switch <account> [--sync|--no-sync] [--launch|--no-launch] [-- <codex args...>]
|
|
46
|
+
codex-sw add <account>
|
|
47
|
+
codex-sw remove <account> [--force]
|
|
48
|
+
codex-sw import-default <env> [--with-auth] [--force]
|
|
49
|
+
|
|
50
|
+
codex-sw app open [account] [-- <app args...>]
|
|
51
|
+
codex-sw app use <account> [-- <app args...>]
|
|
52
|
+
codex-sw app logout [account]
|
|
34
53
|
codex-sw app status
|
|
35
54
|
codex-sw app stop
|
|
36
55
|
codex-sw app current
|
|
@@ -44,22 +63,11 @@ Usage:
|
|
|
44
63
|
Compatibility:
|
|
45
64
|
codex-switcher <same-commands>
|
|
46
65
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
Environment overrides:
|
|
54
|
-
CODEX_SWITCHER_STATE_DIR
|
|
55
|
-
CODEX_SWITCHER_PROFILES_DIR
|
|
56
|
-
CODEX_SWITCHER_APP_BIN
|
|
57
|
-
CODEX_SWITCHER_APP_LOG
|
|
58
|
-
CODEX_SWITCHER_SWITCH_LOG
|
|
59
|
-
CODEX_SWITCHER_LOCK_WAIT_SECONDS
|
|
60
|
-
CODEX_SWITCHER_DEFAULT_HOME
|
|
61
|
-
CODEX_SWITCHER_UPGRADE_REGISTRY
|
|
62
|
-
CODEX_SWITCHER_NPM_PACKAGE
|
|
66
|
+
Notes:
|
|
67
|
+
- Built-in env "default" always maps to ~/.codex (or CODEX_SWITCHER_DEFAULT_HOME).
|
|
68
|
+
- Same-env account switch only swaps auth.json and does not sync shared data.
|
|
69
|
+
- `list` prints: EMAIL / PLAN / 5H USAGE / WEEKLY USAGE / LAST ACTIVITY (+ env/account context).
|
|
70
|
+
- Usage metrics are API-first and automatically fallback to local sessions; source is shown as (api|local).
|
|
63
71
|
USAGE
|
|
64
72
|
}
|
|
65
73
|
|
|
@@ -104,8 +112,9 @@ log_event() {
|
|
|
104
112
|
}
|
|
105
113
|
|
|
106
114
|
ensure_dirs() {
|
|
107
|
-
mkdir -p "$STATE_DIR" "$
|
|
108
|
-
|
|
115
|
+
mkdir -p "$STATE_DIR" "$ENVS_DIR" "$ACCOUNTS_DIR"
|
|
116
|
+
mkdir -p "$DEFAULT_HOME"
|
|
117
|
+
chmod 700 "$STATE_DIR" "$ENVS_DIR" "$ACCOUNTS_DIR" "$DEFAULT_HOME" 2>/dev/null || true
|
|
109
118
|
}
|
|
110
119
|
|
|
111
120
|
perm_of() {
|
|
@@ -117,77 +126,100 @@ perm_of() {
|
|
|
117
126
|
fi
|
|
118
127
|
}
|
|
119
128
|
|
|
120
|
-
|
|
129
|
+
validate_name_noexit() {
|
|
121
130
|
local name="${1:-}"
|
|
122
131
|
[[ -n "$name" ]] || return 1
|
|
123
132
|
[[ "$name" =~ ^[A-Za-z0-9._-]+$ ]] || return 1
|
|
124
133
|
return 0
|
|
125
134
|
}
|
|
126
135
|
|
|
127
|
-
|
|
136
|
+
validate_env_name_noexit() {
|
|
128
137
|
local name="${1:-}"
|
|
129
|
-
|
|
138
|
+
[[ "$name" == "$DEFAULT_ENV_NAME" ]] && return 0
|
|
139
|
+
validate_name_noexit "$name"
|
|
130
140
|
}
|
|
131
141
|
|
|
132
|
-
|
|
133
|
-
local
|
|
134
|
-
|
|
135
|
-
|
|
142
|
+
validate_env_name() {
|
|
143
|
+
local name="${1:-}"
|
|
144
|
+
validate_env_name_noexit "$name" || err "invalid env '$name' (allowed: A-Z a-z 0-9 . _ -, plus reserved: default)"
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
validate_account_name() {
|
|
148
|
+
local name="${1:-}"
|
|
149
|
+
validate_name_noexit "$name" || err "invalid account '$name' (allowed: A-Z a-z 0-9 . _ -)"
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
env_root_path() {
|
|
153
|
+
local env="$1"
|
|
154
|
+
echo "$ENVS_DIR/$env"
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
env_home_path() {
|
|
158
|
+
local env="$1"
|
|
159
|
+
if [[ "$env" == "$DEFAULT_ENV_NAME" ]]; then
|
|
160
|
+
echo "$DEFAULT_HOME"
|
|
136
161
|
else
|
|
137
|
-
echo "
|
|
162
|
+
echo "$ENVS_DIR/$env/home"
|
|
138
163
|
fi
|
|
139
164
|
}
|
|
140
165
|
|
|
141
|
-
|
|
142
|
-
local
|
|
143
|
-
|
|
166
|
+
account_dir_path() {
|
|
167
|
+
local env="$1"
|
|
168
|
+
local account="$2"
|
|
169
|
+
echo "$ACCOUNTS_DIR/$env/$account"
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
account_auth_path() {
|
|
173
|
+
local env="$1"
|
|
174
|
+
local account="$2"
|
|
175
|
+
echo "$(account_dir_path "$env" "$account")/auth.json"
|
|
144
176
|
}
|
|
145
177
|
|
|
146
|
-
|
|
147
|
-
local
|
|
148
|
-
|
|
149
|
-
p="$(profile_path "$name")"
|
|
150
|
-
mkdir -p "$p"
|
|
151
|
-
chmod 700 "$p" 2>/dev/null || true
|
|
178
|
+
current_env_file() {
|
|
179
|
+
local target="$1"
|
|
180
|
+
echo "$STATE_DIR/current_${target}_env"
|
|
152
181
|
}
|
|
153
182
|
|
|
154
|
-
|
|
155
|
-
local
|
|
156
|
-
|
|
157
|
-
p="$(profile_path "$name")"
|
|
158
|
-
[[ -d "$p" ]] || err "profile '$name' not found. run: $SCRIPT_NAME add $name"
|
|
183
|
+
current_account_file() {
|
|
184
|
+
local target="$1"
|
|
185
|
+
echo "$STATE_DIR/current_${target}_account"
|
|
159
186
|
}
|
|
160
187
|
|
|
161
|
-
|
|
188
|
+
set_current_env() {
|
|
162
189
|
local target="$1"
|
|
163
|
-
|
|
190
|
+
local env="$2"
|
|
191
|
+
local file tmp
|
|
192
|
+
file="$(current_env_file "$target")"
|
|
193
|
+
tmp="${file}.tmp"
|
|
194
|
+
printf '%s\n' "$env" > "$tmp"
|
|
195
|
+
chmod 600 "$tmp" 2>/dev/null || true
|
|
196
|
+
mv "$tmp" "$file"
|
|
164
197
|
}
|
|
165
198
|
|
|
166
|
-
|
|
199
|
+
set_current_account() {
|
|
167
200
|
local target="$1"
|
|
168
|
-
local
|
|
201
|
+
local account="$2"
|
|
169
202
|
local file tmp
|
|
170
|
-
file="$(
|
|
203
|
+
file="$(current_account_file "$target")"
|
|
171
204
|
tmp="${file}.tmp"
|
|
172
|
-
printf '%s\n' "$
|
|
205
|
+
printf '%s\n' "$account" > "$tmp"
|
|
173
206
|
chmod 600 "$tmp" 2>/dev/null || true
|
|
174
207
|
mv "$tmp" "$file"
|
|
175
208
|
}
|
|
176
209
|
|
|
177
|
-
|
|
210
|
+
read_current_env() {
|
|
178
211
|
local target="$1"
|
|
179
|
-
local file value
|
|
180
|
-
file="$(
|
|
181
|
-
default="$(default_profile_for "$target")"
|
|
212
|
+
local file value
|
|
213
|
+
file="$(current_env_file "$target")"
|
|
182
214
|
|
|
183
215
|
if [[ ! -f "$file" ]]; then
|
|
184
|
-
echo "$
|
|
216
|
+
echo "$DEFAULT_ENV_NAME"
|
|
185
217
|
return 1
|
|
186
218
|
fi
|
|
187
219
|
|
|
188
220
|
value="$(head -n 1 "$file" | tr -d '\r' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
|
|
189
|
-
if !
|
|
190
|
-
echo "$
|
|
221
|
+
if ! validate_env_name_noexit "$value"; then
|
|
222
|
+
echo "$DEFAULT_ENV_NAME"
|
|
191
223
|
return 2
|
|
192
224
|
fi
|
|
193
225
|
|
|
@@ -195,32 +227,170 @@ read_current() {
|
|
|
195
227
|
return 0
|
|
196
228
|
}
|
|
197
229
|
|
|
198
|
-
|
|
199
|
-
local
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
230
|
+
read_current_account() {
|
|
231
|
+
local target="$1"
|
|
232
|
+
local file value
|
|
233
|
+
file="$(current_account_file "$target")"
|
|
234
|
+
|
|
235
|
+
if [[ ! -f "$file" ]]; then
|
|
236
|
+
echo "$DEFAULT_ACCOUNT_NAME"
|
|
237
|
+
return 1
|
|
238
|
+
fi
|
|
239
|
+
|
|
240
|
+
value="$(head -n 1 "$file" | tr -d '\r' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
|
|
241
|
+
if ! validate_name_noexit "$value"; then
|
|
242
|
+
echo "$DEFAULT_ACCOUNT_NAME"
|
|
243
|
+
return 2
|
|
244
|
+
fi
|
|
245
|
+
|
|
246
|
+
echo "$value"
|
|
247
|
+
return 0
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
ensure_env_home() {
|
|
251
|
+
local env="$1"
|
|
252
|
+
local home
|
|
253
|
+
validate_env_name "$env"
|
|
254
|
+
home="$(env_home_path "$env")"
|
|
255
|
+
mkdir -p "$home"
|
|
256
|
+
if [[ "$env" != "$DEFAULT_ENV_NAME" ]]; then
|
|
257
|
+
mkdir -p "$(env_root_path "$env")"
|
|
258
|
+
fi
|
|
259
|
+
chmod 700 "$home" 2>/dev/null || true
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
env_exists() {
|
|
263
|
+
local env="$1"
|
|
264
|
+
if [[ "$env" == "$DEFAULT_ENV_NAME" ]]; then
|
|
265
|
+
return 0
|
|
266
|
+
fi
|
|
267
|
+
[[ -d "$(env_home_path "$env")" ]]
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
require_env_exists() {
|
|
271
|
+
local env="$1"
|
|
272
|
+
validate_env_name "$env"
|
|
273
|
+
if [[ "$env" == "$DEFAULT_ENV_NAME" ]]; then
|
|
274
|
+
ensure_env_home "$env"
|
|
203
275
|
return 0
|
|
204
276
|
fi
|
|
277
|
+
[[ -d "$(env_home_path "$env")" ]] || err "env '$env' not found. run: $SCRIPT_NAME env create $env"
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
ensure_account_slot() {
|
|
281
|
+
local env="$1"
|
|
282
|
+
local account="$2"
|
|
283
|
+
validate_env_name "$env"
|
|
284
|
+
validate_account_name "$account"
|
|
285
|
+
mkdir -p "$(account_dir_path "$env" "$account")"
|
|
286
|
+
chmod 700 "$(account_dir_path "$env" "$account")" 2>/dev/null || true
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
account_has_auth() {
|
|
290
|
+
local env="$1"
|
|
291
|
+
local account="$2"
|
|
292
|
+
local auth_file home_auth
|
|
293
|
+
auth_file="$(account_auth_path "$env" "$account")"
|
|
294
|
+
if [[ -f "$auth_file" ]]; then
|
|
295
|
+
return 0
|
|
296
|
+
fi
|
|
297
|
+
if [[ "$account" == "$DEFAULT_ACCOUNT_NAME" ]]; then
|
|
298
|
+
home_auth="$(env_home_path "$env")/auth.json"
|
|
299
|
+
[[ -f "$home_auth" ]] && return 0
|
|
300
|
+
fi
|
|
205
301
|
return 1
|
|
206
302
|
}
|
|
207
303
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
304
|
+
list_env_names() {
|
|
305
|
+
echo "$DEFAULT_ENV_NAME"
|
|
306
|
+
if [[ -d "$ENVS_DIR" ]]; then
|
|
307
|
+
find "$ENVS_DIR" -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | sort | while IFS= read -r env; do
|
|
308
|
+
validate_env_name_noexit "$env" || continue
|
|
309
|
+
[[ "$env" == "$DEFAULT_ENV_NAME" ]] && continue
|
|
310
|
+
[[ -d "$(env_home_path "$env")" ]] || continue
|
|
311
|
+
echo "$env"
|
|
312
|
+
done
|
|
213
313
|
fi
|
|
314
|
+
}
|
|
214
315
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
316
|
+
list_accounts_for_env() {
|
|
317
|
+
local env="$1"
|
|
318
|
+
local dir auth_file any
|
|
319
|
+
dir="$ACCOUNTS_DIR/$env"
|
|
320
|
+
any=0
|
|
321
|
+
|
|
322
|
+
if [[ -d "$dir" ]]; then
|
|
323
|
+
while IFS= read -r account; do
|
|
324
|
+
validate_name_noexit "$account" || continue
|
|
325
|
+
auth_file="$(account_auth_path "$env" "$account")"
|
|
326
|
+
if [[ -f "$auth_file" ]]; then
|
|
327
|
+
any=1
|
|
328
|
+
echo "$account"
|
|
329
|
+
fi
|
|
330
|
+
done < <(find "$dir" -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | sort)
|
|
218
331
|
fi
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
332
|
+
|
|
333
|
+
if [[ "$any" -eq 0 ]] && [[ "$env" == "$DEFAULT_ENV_NAME" ]] && [[ -f "$(env_home_path "$env")/auth.json" ]]; then
|
|
334
|
+
echo "$DEFAULT_ACCOUNT_NAME"
|
|
222
335
|
fi
|
|
223
|
-
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
copy_auth_file() {
|
|
339
|
+
local src="$1"
|
|
340
|
+
local dst="$2"
|
|
341
|
+
local tmp
|
|
342
|
+
tmp="${dst}.tmp"
|
|
343
|
+
cp "$src" "$tmp"
|
|
344
|
+
chmod 600 "$tmp" 2>/dev/null || true
|
|
345
|
+
mv "$tmp" "$dst"
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
save_env_auth_to_account() {
|
|
349
|
+
local env="$1"
|
|
350
|
+
local account="$2"
|
|
351
|
+
local home_auth dst
|
|
352
|
+
home_auth="$(env_home_path "$env")/auth.json"
|
|
353
|
+
[[ -f "$home_auth" ]] || return 1
|
|
354
|
+
ensure_account_slot "$env" "$account"
|
|
355
|
+
dst="$(account_auth_path "$env" "$account")"
|
|
356
|
+
copy_auth_file "$home_auth" "$dst"
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
clear_env_auth() {
|
|
360
|
+
local env="$1"
|
|
361
|
+
rm -f -- "$(env_home_path "$env")/auth.json"
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
install_account_auth_to_env() {
|
|
365
|
+
local env="$1"
|
|
366
|
+
local account="$2"
|
|
367
|
+
local src dst
|
|
368
|
+
src="$(account_auth_path "$env" "$account")"
|
|
369
|
+
dst="$(env_home_path "$env")/auth.json"
|
|
370
|
+
if [[ -f "$src" ]]; then
|
|
371
|
+
copy_auth_file "$src" "$dst"
|
|
372
|
+
return 0
|
|
373
|
+
fi
|
|
374
|
+
if [[ "$account" == "$DEFAULT_ACCOUNT_NAME" ]] && [[ -f "$dst" ]]; then
|
|
375
|
+
return 0
|
|
376
|
+
fi
|
|
377
|
+
rm -f -- "$dst"
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
sync_overwrite_excluding_auth() {
|
|
381
|
+
local src="$1"
|
|
382
|
+
local dst="$2"
|
|
383
|
+
|
|
384
|
+
[[ -d "$src" ]] || err "sync source not found: $src"
|
|
385
|
+
mkdir -p "$dst"
|
|
386
|
+
|
|
387
|
+
if command -v rsync >/dev/null 2>&1; then
|
|
388
|
+
rsync -a --checksum --delete --exclude 'auth.json' "$src/" "$dst/"
|
|
389
|
+
else
|
|
390
|
+
find "$dst" -mindepth 1 -maxdepth 1 ! -name 'auth.json' -exec rm -rf -- {} + 2>/dev/null || true
|
|
391
|
+
(cd "$src" && tar cf - --exclude ./auth.json .) | (cd "$dst" && tar xpf -)
|
|
392
|
+
fi
|
|
393
|
+
chmod 700 "$dst" 2>/dev/null || true
|
|
224
394
|
}
|
|
225
395
|
|
|
226
396
|
acquire_lock() {
|
|
@@ -271,24 +441,60 @@ with_lock() {
|
|
|
271
441
|
trap - EXIT INT TERM
|
|
272
442
|
}
|
|
273
443
|
|
|
274
|
-
|
|
275
|
-
local
|
|
444
|
+
with_targets() {
|
|
445
|
+
local target="$1"
|
|
446
|
+
shift
|
|
447
|
+
local fn="$1"
|
|
276
448
|
shift
|
|
277
|
-
|
|
278
|
-
|
|
449
|
+
case "$target" in
|
|
450
|
+
cli|app)
|
|
451
|
+
"$fn" "$target" "$@"
|
|
452
|
+
;;
|
|
453
|
+
both)
|
|
454
|
+
"$fn" cli "$@"
|
|
455
|
+
"$fn" app "$@"
|
|
456
|
+
;;
|
|
457
|
+
*)
|
|
458
|
+
err "invalid target '$target' (use cli|app|both)"
|
|
459
|
+
;;
|
|
460
|
+
esac
|
|
279
461
|
}
|
|
280
462
|
|
|
281
|
-
|
|
282
|
-
local
|
|
283
|
-
local
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
463
|
+
target_home_path() {
|
|
464
|
+
local target="$1"
|
|
465
|
+
local env
|
|
466
|
+
env="$(read_current_env "$target" || true)"
|
|
467
|
+
env_home_path "$env"
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
ensure_target_auth_installed() {
|
|
471
|
+
local target="$1"
|
|
472
|
+
local env account
|
|
473
|
+
env="$(read_current_env "$target" || true)"
|
|
474
|
+
account="$(read_current_account "$target" || true)"
|
|
475
|
+
ensure_env_home "$env"
|
|
476
|
+
if account_has_auth "$env" "$account"; then
|
|
477
|
+
install_account_auth_to_env "$env" "$account"
|
|
478
|
+
else
|
|
479
|
+
clear_env_auth "$env"
|
|
288
480
|
fi
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
run_codex_for_target() {
|
|
484
|
+
local target="$1"
|
|
485
|
+
shift
|
|
486
|
+
ensure_target_auth_installed "$target"
|
|
487
|
+
CODEX_HOME="$(target_home_path "$target")" command codex "$@"
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
login_state_for_target() {
|
|
491
|
+
local target="$1"
|
|
492
|
+
local rc home
|
|
493
|
+
ensure_target_auth_installed "$target"
|
|
494
|
+
home="$(target_home_path "$target")"
|
|
289
495
|
|
|
290
496
|
rc=0
|
|
291
|
-
CODEX_HOME="$
|
|
497
|
+
CODEX_HOME="$home" command codex login status >/dev/null 2>&1 || rc=$?
|
|
292
498
|
if [[ "$rc" -eq 0 ]]; then
|
|
293
499
|
echo "logged-in"
|
|
294
500
|
else
|
|
@@ -296,6 +502,24 @@ login_state_for_profile() {
|
|
|
296
502
|
fi
|
|
297
503
|
}
|
|
298
504
|
|
|
505
|
+
resolve_app_bin() {
|
|
506
|
+
if [[ -n "${CODEX_SWITCHER_APP_BIN:-}" ]]; then
|
|
507
|
+
[[ -x "$CODEX_SWITCHER_APP_BIN" ]] || err "CODEX_SWITCHER_APP_BIN is not executable: $CODEX_SWITCHER_APP_BIN"
|
|
508
|
+
echo "$CODEX_SWITCHER_APP_BIN"
|
|
509
|
+
return
|
|
510
|
+
fi
|
|
511
|
+
|
|
512
|
+
if [[ -x "/Applications/Codex.app/Contents/MacOS/Codex" ]]; then
|
|
513
|
+
echo "/Applications/Codex.app/Contents/MacOS/Codex"
|
|
514
|
+
return
|
|
515
|
+
fi
|
|
516
|
+
if [[ -x "$HOME/Applications/Codex.app/Contents/MacOS/Codex" ]]; then
|
|
517
|
+
echo "$HOME/Applications/Codex.app/Contents/MacOS/Codex"
|
|
518
|
+
return
|
|
519
|
+
fi
|
|
520
|
+
err "Codex.app binary not found. set CODEX_SWITCHER_APP_BIN manually"
|
|
521
|
+
}
|
|
522
|
+
|
|
299
523
|
kill_tree() {
|
|
300
524
|
local pid="$1"
|
|
301
525
|
local child
|
|
@@ -342,194 +566,461 @@ app_stop_managed() {
|
|
|
342
566
|
echo "Stopped managed app process"
|
|
343
567
|
}
|
|
344
568
|
|
|
345
|
-
|
|
346
|
-
local
|
|
347
|
-
|
|
348
|
-
|
|
569
|
+
metrics_script_path() {
|
|
570
|
+
local script_dir
|
|
571
|
+
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
572
|
+
echo "$script_dir/profile-metrics.py"
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
collect_profile_metrics_tsv() {
|
|
576
|
+
local account="$1"
|
|
577
|
+
local auth_file="$2"
|
|
578
|
+
local data_path="$3"
|
|
579
|
+
local script_path
|
|
580
|
+
script_path="$(metrics_script_path)"
|
|
581
|
+
[[ -f "$script_path" ]] || return 1
|
|
582
|
+
python3 "$script_path" --account-name "$account" --auth-file "$auth_file" --data-path "$data_path" 2>/dev/null
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
cmd_env_list() {
|
|
586
|
+
local cli_env app_env env marks
|
|
587
|
+
cli_env="$(read_current_env cli || true)"
|
|
588
|
+
app_env="$(read_current_env app || true)"
|
|
589
|
+
list_env_names | sort -u | while IFS= read -r env; do
|
|
590
|
+
marks=""
|
|
591
|
+
[[ "$env" == "$cli_env" ]] && marks="${marks} [cli-current]"
|
|
592
|
+
[[ "$env" == "$app_env" ]] && marks="${marks} [app-current]"
|
|
593
|
+
echo "- $env$marks"
|
|
594
|
+
done
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
cmd_env_create() {
|
|
598
|
+
local env="$1"
|
|
599
|
+
local mode="$2"
|
|
600
|
+
local src_env="${3:-}"
|
|
601
|
+
local home src
|
|
602
|
+
|
|
603
|
+
validate_env_name "$env"
|
|
604
|
+
[[ "$env" != "$DEFAULT_ENV_NAME" ]] || err "cannot create reserved env '$DEFAULT_ENV_NAME'"
|
|
605
|
+
if env_exists "$env"; then
|
|
606
|
+
err "env '$env' already exists"
|
|
349
607
|
fi
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
608
|
+
|
|
609
|
+
home="$(env_home_path "$env")"
|
|
610
|
+
mkdir -p "$home"
|
|
611
|
+
chmod 700 "$home" 2>/dev/null || true
|
|
612
|
+
|
|
613
|
+
case "$mode" in
|
|
614
|
+
empty)
|
|
615
|
+
:
|
|
616
|
+
;;
|
|
617
|
+
from-default)
|
|
618
|
+
sync_overwrite_excluding_auth "$DEFAULT_HOME" "$home"
|
|
619
|
+
;;
|
|
620
|
+
from-env)
|
|
621
|
+
validate_env_name "$src_env"
|
|
622
|
+
require_env_exists "$src_env"
|
|
623
|
+
src="$(env_home_path "$src_env")"
|
|
624
|
+
sync_overwrite_excluding_auth "$src" "$home"
|
|
356
625
|
;;
|
|
357
626
|
*)
|
|
358
|
-
|
|
359
|
-
return 1
|
|
627
|
+
err "unknown env create mode: $mode"
|
|
360
628
|
;;
|
|
361
629
|
esac
|
|
630
|
+
|
|
631
|
+
log_event INFO "env_create env=$env mode=$mode src=$src_env"
|
|
632
|
+
echo "Created env: $env"
|
|
362
633
|
}
|
|
363
634
|
|
|
364
|
-
|
|
365
|
-
local
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
635
|
+
_cmd_env_use_target() {
|
|
636
|
+
local target="$1"
|
|
637
|
+
local env="$2"
|
|
638
|
+
local account
|
|
639
|
+
|
|
640
|
+
account="$(read_current_account "$target" || true)"
|
|
641
|
+
set_current_env "$target" "$env"
|
|
642
|
+
if account_has_auth "$env" "$account"; then
|
|
643
|
+
set_current_account "$target" "$account"
|
|
644
|
+
install_account_auth_to_env "$env" "$account"
|
|
645
|
+
else
|
|
646
|
+
set_current_account "$target" "$DEFAULT_ACCOUNT_NAME"
|
|
647
|
+
if account_has_auth "$env" "$DEFAULT_ACCOUNT_NAME"; then
|
|
648
|
+
install_account_auth_to_env "$env" "$DEFAULT_ACCOUNT_NAME"
|
|
649
|
+
else
|
|
650
|
+
clear_env_auth "$env"
|
|
651
|
+
fi
|
|
652
|
+
fi
|
|
370
653
|
}
|
|
371
654
|
|
|
372
|
-
|
|
373
|
-
local
|
|
374
|
-
local
|
|
375
|
-
|
|
655
|
+
cmd_env_use() {
|
|
656
|
+
local env="$1"
|
|
657
|
+
local target="$2"
|
|
658
|
+
|
|
659
|
+
require_env_exists "$env"
|
|
660
|
+
with_targets "$target" _cmd_env_use_target "$env"
|
|
661
|
+
log_event INFO "env_use env=$env target=$target"
|
|
662
|
+
echo "Switched $target env to: $env"
|
|
663
|
+
}
|
|
376
664
|
|
|
377
|
-
|
|
378
|
-
|
|
665
|
+
cmd_env_remove() {
|
|
666
|
+
local env="$1"
|
|
667
|
+
local force="$2"
|
|
668
|
+
local cli_env app_env
|
|
379
669
|
|
|
380
|
-
|
|
381
|
-
|
|
670
|
+
validate_env_name "$env"
|
|
671
|
+
[[ "$env" != "$DEFAULT_ENV_NAME" ]] || err "cannot remove reserved env '$DEFAULT_ENV_NAME'"
|
|
672
|
+
env_exists "$env" || err "env '$env' not found"
|
|
382
673
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
fi
|
|
386
|
-
if [[ "$profile" == "$app_cur" && "$force" != "true" ]]; then
|
|
387
|
-
err "profile '$profile' is current App profile; use --force to remove"
|
|
388
|
-
fi
|
|
674
|
+
cli_env="$(read_current_env cli || true)"
|
|
675
|
+
app_env="$(read_current_env app || true)"
|
|
389
676
|
|
|
390
|
-
if [[ "$force" != "true" ]]; then
|
|
391
|
-
|
|
677
|
+
if [[ "$env" == "$cli_env" && "$force" != "true" ]]; then
|
|
678
|
+
err "env '$env' is current CLI env; use --force to remove"
|
|
679
|
+
fi
|
|
680
|
+
if [[ "$env" == "$app_env" && "$force" != "true" ]]; then
|
|
681
|
+
err "env '$env' is current App env; use --force to remove"
|
|
392
682
|
fi
|
|
393
683
|
|
|
394
|
-
if [[ "$
|
|
684
|
+
if [[ "$env" == "$app_env" ]]; then
|
|
395
685
|
app_stop_managed >/dev/null
|
|
396
|
-
|
|
686
|
+
set_current_env app "$DEFAULT_ENV_NAME"
|
|
687
|
+
set_current_account app "$DEFAULT_ACCOUNT_NAME"
|
|
688
|
+
ensure_target_auth_installed app
|
|
397
689
|
fi
|
|
398
|
-
if [[ "$
|
|
399
|
-
|
|
690
|
+
if [[ "$env" == "$cli_env" ]]; then
|
|
691
|
+
set_current_env cli "$DEFAULT_ENV_NAME"
|
|
692
|
+
set_current_account cli "$DEFAULT_ACCOUNT_NAME"
|
|
693
|
+
ensure_target_auth_installed cli
|
|
400
694
|
fi
|
|
401
695
|
|
|
402
|
-
rm -rf -- "$(
|
|
403
|
-
log_event INFO "
|
|
404
|
-
echo "Removed
|
|
696
|
+
rm -rf -- "$(env_root_path "$env")" "$ACCOUNTS_DIR/$env"
|
|
697
|
+
log_event INFO "env_remove env=$env force=$force"
|
|
698
|
+
echo "Removed env: $env"
|
|
405
699
|
}
|
|
406
700
|
|
|
407
|
-
|
|
408
|
-
local
|
|
409
|
-
|
|
410
|
-
|
|
701
|
+
cmd_env_current() {
|
|
702
|
+
local target="${1:-all}"
|
|
703
|
+
case "$target" in
|
|
704
|
+
cli)
|
|
705
|
+
read_current_env cli || true
|
|
706
|
+
;;
|
|
707
|
+
app)
|
|
708
|
+
read_current_env app || true
|
|
709
|
+
;;
|
|
710
|
+
all)
|
|
711
|
+
echo "cli: $(read_current_env cli || true)"
|
|
712
|
+
echo "app: $(read_current_env app || true)"
|
|
713
|
+
;;
|
|
714
|
+
*)
|
|
715
|
+
err "invalid target '$target' (use cli|app)"
|
|
716
|
+
;;
|
|
717
|
+
esac
|
|
718
|
+
}
|
|
411
719
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
720
|
+
cmd_env_path() {
|
|
721
|
+
local env="${1:-$(read_current_env cli || true)}"
|
|
722
|
+
validate_env_name "$env"
|
|
723
|
+
require_env_exists "$env"
|
|
724
|
+
echo "export CODEX_HOME='$(env_home_path "$env")'"
|
|
725
|
+
}
|
|
416
726
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
727
|
+
cmd_account_add() {
|
|
728
|
+
local account="$1"
|
|
729
|
+
local env="$2"
|
|
730
|
+
validate_account_name "$account"
|
|
731
|
+
require_env_exists "$env"
|
|
732
|
+
ensure_account_slot "$env" "$account"
|
|
733
|
+
log_event INFO "account_add env=$env account=$account"
|
|
734
|
+
echo "Added account slot: $env/$account"
|
|
424
735
|
}
|
|
425
736
|
|
|
426
|
-
|
|
427
|
-
local
|
|
428
|
-
local
|
|
737
|
+
cmd_account_remove() {
|
|
738
|
+
local account="$1"
|
|
739
|
+
local env="$2"
|
|
429
740
|
local force="$3"
|
|
430
|
-
local
|
|
741
|
+
local cli_env app_env cli_account app_account
|
|
431
742
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
[[ -d "$src" ]] || err "default codex home not found: $src"
|
|
435
|
-
ensure_profile "$profile"
|
|
436
|
-
dst="$(profile_path "$profile")"
|
|
743
|
+
validate_account_name "$account"
|
|
744
|
+
validate_env_name "$env"
|
|
437
745
|
|
|
438
|
-
if [[ "$
|
|
439
|
-
|
|
440
|
-
else
|
|
441
|
-
if find "$dst" -mindepth 1 -maxdepth 1 | grep -q .; then
|
|
442
|
-
err "profile '$profile' is not empty. use --force to overwrite"
|
|
443
|
-
fi
|
|
746
|
+
if [[ ! -d "$(account_dir_path "$env" "$account")" ]] && ! account_has_auth "$env" "$account"; then
|
|
747
|
+
err "account '$account' not found in env '$env'"
|
|
444
748
|
fi
|
|
445
749
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
(cd "$src" && tar cf - --exclude ./auth.json .) | (cd "$dst" && tar xpf -)
|
|
457
|
-
fi
|
|
750
|
+
cli_env="$(read_current_env cli || true)"
|
|
751
|
+
app_env="$(read_current_env app || true)"
|
|
752
|
+
cli_account="$(read_current_account cli || true)"
|
|
753
|
+
app_account="$(read_current_account app || true)"
|
|
754
|
+
|
|
755
|
+
if [[ "$env" == "$cli_env" && "$account" == "$cli_account" && "$force" != "true" ]]; then
|
|
756
|
+
err "account '$account' is current CLI account in env '$env'; use --force to remove"
|
|
757
|
+
fi
|
|
758
|
+
if [[ "$env" == "$app_env" && "$account" == "$app_account" && "$force" != "true" ]]; then
|
|
759
|
+
err "account '$account' is current App account in env '$env'; use --force to remove"
|
|
458
760
|
fi
|
|
459
761
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
762
|
+
rm -rf -- "$(account_dir_path "$env" "$account")"
|
|
763
|
+
if [[ "$account" == "$DEFAULT_ACCOUNT_NAME" ]]; then
|
|
764
|
+
rm -f -- "$(env_home_path "$env")/auth.json"
|
|
765
|
+
fi
|
|
766
|
+
|
|
767
|
+
if [[ "$env" == "$cli_env" && "$account" == "$cli_account" ]]; then
|
|
768
|
+
set_current_account cli "$DEFAULT_ACCOUNT_NAME"
|
|
769
|
+
ensure_target_auth_installed cli
|
|
465
770
|
fi
|
|
771
|
+
if [[ "$env" == "$app_env" && "$account" == "$app_account" ]]; then
|
|
772
|
+
set_current_account app "$DEFAULT_ACCOUNT_NAME"
|
|
773
|
+
ensure_target_auth_installed app
|
|
774
|
+
fi
|
|
775
|
+
|
|
776
|
+
log_event INFO "account_remove env=$env account=$account force=$force"
|
|
777
|
+
echo "Removed account slot: $env/$account"
|
|
466
778
|
}
|
|
467
779
|
|
|
468
|
-
|
|
469
|
-
local
|
|
470
|
-
local
|
|
780
|
+
cmd_account_list() {
|
|
781
|
+
local env="$1"
|
|
782
|
+
local cli_env app_env cli_account app_account found account marks
|
|
783
|
+
require_env_exists "$env"
|
|
471
784
|
|
|
472
|
-
|
|
473
|
-
|
|
785
|
+
cli_env="$(read_current_env cli || true)"
|
|
786
|
+
app_env="$(read_current_env app || true)"
|
|
787
|
+
cli_account="$(read_current_account cli || true)"
|
|
788
|
+
app_account="$(read_current_account app || true)"
|
|
789
|
+
found=0
|
|
474
790
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
791
|
+
while IFS= read -r account; do
|
|
792
|
+
found=1
|
|
793
|
+
marks=""
|
|
794
|
+
[[ "$env" == "$cli_env" && "$account" == "$cli_account" ]] && marks="${marks} [cli-current]"
|
|
795
|
+
[[ "$env" == "$app_env" && "$account" == "$app_account" ]] && marks="${marks} [app-current]"
|
|
796
|
+
echo "- $account$marks"
|
|
797
|
+
done < <(list_accounts_for_env "$env")
|
|
798
|
+
|
|
799
|
+
if [[ "$found" -eq 0 ]]; then
|
|
800
|
+
echo "No accounts in env '$env'. Use: $SCRIPT_NAME account login <account> --env $env"
|
|
480
801
|
fi
|
|
481
|
-
chmod 700 "$dst" 2>/dev/null || true
|
|
482
802
|
}
|
|
483
803
|
|
|
484
|
-
|
|
485
|
-
local
|
|
486
|
-
local
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
log_event INFO "sync_default profile=$profile src=$src"
|
|
493
|
-
echo "Synced default data to profile: $profile (auth.json excluded)"
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
sync_profile_to_profile() {
|
|
497
|
-
local from_profile="$1"
|
|
498
|
-
local to_profile="$2"
|
|
499
|
-
local src dst
|
|
804
|
+
_cmd_account_set_target() {
|
|
805
|
+
local target="$1"
|
|
806
|
+
local env="$2"
|
|
807
|
+
local account="$3"
|
|
808
|
+
set_current_env "$target" "$env"
|
|
809
|
+
set_current_account "$target" "$account"
|
|
810
|
+
install_account_auth_to_env "$env" "$account"
|
|
811
|
+
}
|
|
500
812
|
|
|
501
|
-
|
|
502
|
-
|
|
813
|
+
cmd_account_login() {
|
|
814
|
+
local account="$1"
|
|
815
|
+
local env="$2"
|
|
816
|
+
local target="$3"
|
|
817
|
+
local sync_mode="$4"
|
|
818
|
+
local home
|
|
819
|
+
|
|
820
|
+
validate_account_name "$account"
|
|
821
|
+
require_env_exists "$env"
|
|
822
|
+
ensure_env_home "$env"
|
|
823
|
+
home="$(env_home_path "$env")"
|
|
824
|
+
|
|
825
|
+
if [[ "$sync_mode" == "true" && "$env" != "$DEFAULT_ENV_NAME" ]]; then
|
|
826
|
+
sync_overwrite_excluding_auth "$DEFAULT_HOME" "$home"
|
|
503
827
|
fi
|
|
504
828
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
log_event INFO "
|
|
511
|
-
echo "
|
|
829
|
+
CODEX_HOME="$home" command codex login
|
|
830
|
+
save_env_auth_to_account "$env" "$account" || err "login did not produce auth.json in $home"
|
|
831
|
+
|
|
832
|
+
with_targets "$target" _cmd_account_set_target "$env" "$account"
|
|
833
|
+
|
|
834
|
+
log_event INFO "account_login env=$env account=$account target=$target sync=$sync_mode"
|
|
835
|
+
echo "Logged in account: $env/$account"
|
|
512
836
|
}
|
|
513
837
|
|
|
514
|
-
|
|
515
|
-
local
|
|
516
|
-
local
|
|
517
|
-
local
|
|
518
|
-
|
|
838
|
+
cmd_account_use() {
|
|
839
|
+
local account="$1"
|
|
840
|
+
local env="$2"
|
|
841
|
+
local target="$3"
|
|
842
|
+
local sync_mode="$4"
|
|
843
|
+
|
|
844
|
+
validate_account_name "$account"
|
|
845
|
+
require_env_exists "$env"
|
|
846
|
+
account_has_auth "$env" "$account" || err "account '$account' in env '$env' has no auth.json. run: $SCRIPT_NAME account login $account --env $env"
|
|
519
847
|
|
|
520
848
|
if [[ "$sync_mode" == "true" ]]; then
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
849
|
+
warn "same-env account switch only replaces auth.json; --sync is ignored"
|
|
850
|
+
fi
|
|
851
|
+
|
|
852
|
+
with_targets "$target" _cmd_account_set_target "$env" "$account"
|
|
853
|
+
log_event INFO "account_use env=$env account=$account target=$target"
|
|
854
|
+
echo "Switched $target account to: $env/$account"
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
cmd_account_logout() {
|
|
858
|
+
local account="$1"
|
|
859
|
+
local env="$2"
|
|
860
|
+
local target="$3"
|
|
861
|
+
local cli_env app_env cli_account app_account
|
|
862
|
+
|
|
863
|
+
validate_env_name "$env"
|
|
864
|
+
if [[ -z "$account" ]]; then
|
|
865
|
+
if [[ "$target" == "both" ]]; then
|
|
866
|
+
account="$(read_current_account cli || true)"
|
|
867
|
+
else
|
|
868
|
+
account="$(read_current_account "$target" || true)"
|
|
869
|
+
fi
|
|
870
|
+
fi
|
|
871
|
+
validate_account_name "$account"
|
|
872
|
+
require_env_exists "$env"
|
|
873
|
+
|
|
874
|
+
rm -f -- "$(account_auth_path "$env" "$account")"
|
|
875
|
+
|
|
876
|
+
cli_env="$(read_current_env cli || true)"
|
|
877
|
+
app_env="$(read_current_env app || true)"
|
|
878
|
+
cli_account="$(read_current_account cli || true)"
|
|
879
|
+
app_account="$(read_current_account app || true)"
|
|
880
|
+
|
|
881
|
+
if [[ "$env" == "$cli_env" && "$account" == "$cli_account" ]]; then
|
|
882
|
+
set_current_account cli "$DEFAULT_ACCOUNT_NAME"
|
|
883
|
+
ensure_target_auth_installed cli
|
|
884
|
+
fi
|
|
885
|
+
if [[ "$env" == "$app_env" && "$account" == "$app_account" ]]; then
|
|
886
|
+
set_current_account app "$DEFAULT_ACCOUNT_NAME"
|
|
887
|
+
ensure_target_auth_installed app
|
|
524
888
|
fi
|
|
525
889
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
890
|
+
if [[ "$account" == "$DEFAULT_ACCOUNT_NAME" ]]; then
|
|
891
|
+
rm -f -- "$(env_home_path "$env")/auth.json"
|
|
892
|
+
fi
|
|
893
|
+
|
|
894
|
+
log_event INFO "account_logout env=$env account=$account target=$target"
|
|
895
|
+
echo "Logged out account: $env/$account"
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
cmd_account_current() {
|
|
899
|
+
local target="${1:-all}"
|
|
900
|
+
case "$target" in
|
|
901
|
+
cli)
|
|
902
|
+
echo "$(read_current_env cli || true)/$(read_current_account cli || true)"
|
|
903
|
+
;;
|
|
904
|
+
app)
|
|
905
|
+
echo "$(read_current_env app || true)/$(read_current_account app || true)"
|
|
906
|
+
;;
|
|
907
|
+
all)
|
|
908
|
+
echo "cli: $(read_current_env cli || true)/$(read_current_account cli || true)"
|
|
909
|
+
echo "app: $(read_current_env app || true)/$(read_current_account app || true)"
|
|
910
|
+
;;
|
|
911
|
+
*)
|
|
912
|
+
err "invalid target '$target' (use cli|app)"
|
|
913
|
+
;;
|
|
914
|
+
esac
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
cmd_list() {
|
|
918
|
+
local cli_env app_env cli_account app_account
|
|
919
|
+
local env account marks auth_file home metrics
|
|
920
|
+
local email plan usage_5h usage_weekly last_activity source
|
|
921
|
+
|
|
922
|
+
cli_env="$(read_current_env cli || true)"
|
|
923
|
+
app_env="$(read_current_env app || true)"
|
|
924
|
+
cli_account="$(read_current_account cli || true)"
|
|
925
|
+
app_account="$(read_current_account app || true)"
|
|
926
|
+
|
|
927
|
+
printf '%-12s %-30s %-44s %-10s %-16s %-18s %s\n' "ENV" "ACCOUNT" "EMAIL" "PLAN" "5H USAGE" "WEEKLY USAGE" "LAST ACTIVITY"
|
|
928
|
+
while IFS= read -r env; do
|
|
929
|
+
home="$(env_home_path "$env")"
|
|
930
|
+
ensure_env_home "$env"
|
|
931
|
+
local found=0
|
|
932
|
+
while IFS= read -r account; do
|
|
933
|
+
found=1
|
|
934
|
+
marks=""
|
|
935
|
+
[[ "$env" == "$cli_env" && "$account" == "$cli_account" ]] && marks="${marks} [cli-current]"
|
|
936
|
+
[[ "$env" == "$app_env" && "$account" == "$app_account" ]] && marks="${marks} [app-current]"
|
|
937
|
+
auth_file="$(account_auth_path "$env" "$account")"
|
|
938
|
+
[[ -f "$auth_file" ]] || auth_file="$home/auth.json"
|
|
939
|
+
|
|
940
|
+
metrics="$(collect_profile_metrics_tsv "$account" "$auth_file" "$home" || true)"
|
|
941
|
+
if [[ -n "$metrics" ]]; then
|
|
942
|
+
IFS=$'\t' read -r email plan usage_5h usage_weekly last_activity source <<< "$metrics"
|
|
943
|
+
fi
|
|
944
|
+
email="${email:-($account)-}"
|
|
945
|
+
plan="${plan:-unknown}"
|
|
946
|
+
usage_5h="${usage_5h:--}"
|
|
947
|
+
usage_weekly="${usage_weekly:--}"
|
|
948
|
+
last_activity="${last_activity:--}"
|
|
949
|
+
source="${source:-local}"
|
|
950
|
+
[[ "$source" == "api" || "$source" == "local" ]] || source="local"
|
|
951
|
+
last_activity="${last_activity} (${source})"
|
|
952
|
+
|
|
953
|
+
printf '%-12s %-30s %-44s %-10s %-16s %-18s %s\n' "$env" "$account$marks" "$email" "$plan" "$usage_5h" "$usage_weekly" "$last_activity"
|
|
954
|
+
done < <(list_accounts_for_env "$env")
|
|
955
|
+
|
|
956
|
+
if [[ "$found" -eq 0 ]]; then
|
|
957
|
+
metrics="$(collect_profile_metrics_tsv "-" "$home/auth.json" "$home" || true)"
|
|
958
|
+
if [[ -n "$metrics" ]]; then
|
|
959
|
+
IFS=$'\t' read -r email plan usage_5h usage_weekly last_activity source <<< "$metrics"
|
|
960
|
+
fi
|
|
961
|
+
email="${email:--}"
|
|
962
|
+
plan="${plan:-unknown}"
|
|
963
|
+
usage_5h="${usage_5h:--}"
|
|
964
|
+
usage_weekly="${usage_weekly:--}"
|
|
965
|
+
last_activity="${last_activity:--}"
|
|
966
|
+
source="${source:-local}"
|
|
967
|
+
[[ "$source" == "api" || "$source" == "local" ]] || source="local"
|
|
968
|
+
last_activity="${last_activity} (${source})"
|
|
969
|
+
printf '%-12s %-30s %-44s %-10s %-16s %-18s %s\n' "$env" "-" "$email" "$plan" "$usage_5h" "$usage_weekly" "$last_activity"
|
|
970
|
+
fi
|
|
971
|
+
done < <(list_env_names | sort -u)
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
cmd_add() {
|
|
975
|
+
local account="$1"
|
|
976
|
+
local env
|
|
977
|
+
env="$(read_current_env cli || true)"
|
|
978
|
+
cmd_account_add "$account" "$env"
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
cmd_remove() {
|
|
982
|
+
local account="$1"
|
|
983
|
+
local force="$2"
|
|
984
|
+
local env
|
|
985
|
+
env="$(read_current_env cli || true)"
|
|
986
|
+
cmd_account_remove "$account" "$env" "$force"
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
cmd_import_default() {
|
|
990
|
+
local env="$1"
|
|
991
|
+
local with_auth="$2"
|
|
992
|
+
local force="$3"
|
|
993
|
+
|
|
994
|
+
validate_env_name "$env"
|
|
995
|
+
[[ "$env" != "$DEFAULT_ENV_NAME" ]] || err "cannot import into reserved env '$DEFAULT_ENV_NAME'"
|
|
996
|
+
|
|
997
|
+
if env_exists "$env"; then
|
|
998
|
+
if [[ "$force" != "true" ]]; then
|
|
999
|
+
err "env '$env' already exists. use --force to overwrite"
|
|
1000
|
+
fi
|
|
1001
|
+
rm -rf -- "$(env_root_path "$env")" "$ACCOUNTS_DIR/$env"
|
|
1002
|
+
fi
|
|
1003
|
+
|
|
1004
|
+
cmd_env_create "$env" "from-default" ""
|
|
1005
|
+
if [[ "$with_auth" == "true" && -f "$DEFAULT_HOME/auth.json" ]]; then
|
|
1006
|
+
ensure_account_slot "$env" "$DEFAULT_ACCOUNT_NAME"
|
|
1007
|
+
copy_auth_file "$DEFAULT_HOME/auth.json" "$(account_auth_path "$env" "$DEFAULT_ACCOUNT_NAME")"
|
|
1008
|
+
fi
|
|
1009
|
+
|
|
1010
|
+
log_event INFO "import_default_as_env env=$env with_auth=$with_auth force=$force"
|
|
1011
|
+
echo "Imported default data to env: $env"
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
cmd_use_compat() {
|
|
1015
|
+
local account="$1"
|
|
1016
|
+
local sync_mode="${2:-false}"
|
|
1017
|
+
local env
|
|
1018
|
+
env="$(read_current_env cli || true)"
|
|
1019
|
+
cmd_account_use "$account" "$env" "cli" "$sync_mode"
|
|
529
1020
|
}
|
|
530
1021
|
|
|
531
|
-
|
|
532
|
-
|
|
1022
|
+
cmd_switch_compat() {
|
|
1023
|
+
cmd_use_compat "$1" "${2:-false}"
|
|
533
1024
|
}
|
|
534
1025
|
|
|
535
1026
|
should_launch_codex() {
|
|
@@ -552,17 +1043,17 @@ should_launch_codex() {
|
|
|
552
1043
|
|
|
553
1044
|
cmd_use_and_maybe_launch() {
|
|
554
1045
|
local mode_cmd="$1"
|
|
555
|
-
local
|
|
1046
|
+
local account="$2"
|
|
556
1047
|
local sync_mode="${3:-false}"
|
|
557
1048
|
local launch_mode="${4:-auto}"
|
|
558
1049
|
shift 4 || true
|
|
559
1050
|
|
|
560
|
-
with_lock "$mode_cmd" "$
|
|
1051
|
+
with_lock "$mode_cmd" "$account" "$sync_mode"
|
|
561
1052
|
|
|
562
|
-
echo "Switched CLI
|
|
1053
|
+
echo "Switched CLI account to: $(read_current_env cli || true)/$(read_current_account cli || true)"
|
|
563
1054
|
if should_launch_codex "$launch_mode"; then
|
|
564
|
-
echo "Launching codex with
|
|
565
|
-
|
|
1055
|
+
echo "Launching codex with env/account: $(read_current_env cli || true)/$(read_current_account cli || true)"
|
|
1056
|
+
run_codex_for_target cli "$@"
|
|
566
1057
|
return
|
|
567
1058
|
fi
|
|
568
1059
|
|
|
@@ -570,21 +1061,21 @@ cmd_use_and_maybe_launch() {
|
|
|
570
1061
|
echo "Auto launch skipped (non-interactive shell). Use --launch to force start."
|
|
571
1062
|
fi
|
|
572
1063
|
echo "Run in current shell if needed:"
|
|
573
|
-
echo " export CODEX_HOME='$(
|
|
1064
|
+
echo " export CODEX_HOME='$(target_home_path cli)'"
|
|
574
1065
|
}
|
|
575
1066
|
|
|
576
1067
|
cmd_current() {
|
|
577
1068
|
local target="${1:-all}"
|
|
578
1069
|
case "$target" in
|
|
579
1070
|
cli)
|
|
580
|
-
|
|
1071
|
+
echo "$(read_current_env cli || true)/$(read_current_account cli || true)"
|
|
581
1072
|
;;
|
|
582
1073
|
app)
|
|
583
|
-
|
|
1074
|
+
echo "$(read_current_env app || true)/$(read_current_account app || true)"
|
|
584
1075
|
;;
|
|
585
1076
|
all)
|
|
586
|
-
echo "cli: $(
|
|
587
|
-
echo "app: $(
|
|
1077
|
+
echo "cli: $(read_current_env cli || true)/$(read_current_account cli || true)"
|
|
1078
|
+
echo "app: $(read_current_env app || true)/$(read_current_account app || true)"
|
|
588
1079
|
;;
|
|
589
1080
|
*)
|
|
590
1081
|
err "invalid target '$target' (use cli|app)"
|
|
@@ -593,31 +1084,31 @@ cmd_current() {
|
|
|
593
1084
|
}
|
|
594
1085
|
|
|
595
1086
|
cmd_status() {
|
|
596
|
-
local
|
|
597
|
-
local cli_ptr_state app_ptr_state
|
|
598
|
-
local cli_state app_state
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
1087
|
+
local cli_env app_env cli_account app_account
|
|
1088
|
+
local cli_ptr_state app_ptr_state cli_acc_state app_acc_state
|
|
1089
|
+
local cli_state app_state exit_code
|
|
1090
|
+
|
|
1091
|
+
cli_env="$(read_current_env cli)" || cli_ptr_state=$?
|
|
1092
|
+
app_env="$(read_current_env app)" || app_ptr_state=$?
|
|
1093
|
+
cli_account="$(read_current_account cli)" || cli_acc_state=$?
|
|
1094
|
+
app_account="$(read_current_account app)" || app_acc_state=$?
|
|
603
1095
|
cli_ptr_state="${cli_ptr_state:-0}"
|
|
604
1096
|
app_ptr_state="${app_ptr_state:-0}"
|
|
1097
|
+
cli_acc_state="${cli_acc_state:-0}"
|
|
1098
|
+
app_acc_state="${app_acc_state:-0}"
|
|
605
1099
|
|
|
606
|
-
cli_state="$(
|
|
607
|
-
app_state="$(
|
|
1100
|
+
cli_state="$(login_state_for_target cli)"
|
|
1101
|
+
app_state="$(login_state_for_target app)"
|
|
608
1102
|
|
|
609
|
-
echo "cli_current: $
|
|
610
|
-
echo "app_current: $
|
|
611
|
-
echo "cli($
|
|
612
|
-
echo "app($
|
|
1103
|
+
echo "cli_current: $cli_env/$cli_account"
|
|
1104
|
+
echo "app_current: $app_env/$app_account"
|
|
1105
|
+
echo "cli($cli_env/$cli_account): $cli_state"
|
|
1106
|
+
echo "app($app_env/$app_account): $app_state"
|
|
613
1107
|
|
|
614
1108
|
exit_code=0
|
|
615
|
-
if [[ "$cli_ptr_state" -eq 2 || "$app_ptr_state" -eq 2 ]]; then
|
|
1109
|
+
if [[ "$cli_ptr_state" -eq 2 || "$app_ptr_state" -eq 2 || "$cli_acc_state" -eq 2 || "$app_acc_state" -eq 2 ]]; then
|
|
616
1110
|
echo "hint: pointer file corrupted, run: $SCRIPT_NAME recover" >&2
|
|
617
1111
|
exit_code=2
|
|
618
|
-
elif [[ "$cli_state" == "missing-profile" || "$app_state" == "missing-profile" ]]; then
|
|
619
|
-
echo "hint: missing profile directory, run: $SCRIPT_NAME recover" >&2
|
|
620
|
-
exit_code=2
|
|
621
1112
|
elif [[ "$cli_state" != "logged-in" || "$app_state" != "logged-in" ]]; then
|
|
622
1113
|
exit_code=1
|
|
623
1114
|
fi
|
|
@@ -631,85 +1122,76 @@ cmd_exec() {
|
|
|
631
1122
|
shift
|
|
632
1123
|
fi
|
|
633
1124
|
[[ "$#" -gt 0 ]] || err "missing codex args after --"
|
|
634
|
-
|
|
635
|
-
local profile
|
|
636
|
-
profile="$(read_current cli || true)"
|
|
637
|
-
ensure_profile "$profile"
|
|
638
|
-
CODEX_HOME="$(profile_path "$profile")" command codex "$@"
|
|
1125
|
+
run_codex_for_target cli "$@"
|
|
639
1126
|
}
|
|
640
1127
|
|
|
641
1128
|
cmd_login() {
|
|
642
|
-
local
|
|
1129
|
+
local account="${1:-$(read_current_account cli || true)}"
|
|
643
1130
|
local sync_mode="${2:-false}"
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
sync_default_to_profile "$profile"
|
|
648
|
-
fi
|
|
649
|
-
log_event INFO "cli_login profile=$profile sync=$sync_mode"
|
|
650
|
-
run_codex_for_profile "$profile" login
|
|
1131
|
+
local env
|
|
1132
|
+
env="$(read_current_env cli || true)"
|
|
1133
|
+
cmd_account_login "$account" "$env" "cli" "$sync_mode"
|
|
651
1134
|
}
|
|
652
1135
|
|
|
653
1136
|
cmd_logout() {
|
|
654
|
-
local
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
run_codex_for_profile "$profile" logout
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
cmd_env() {
|
|
662
|
-
local profile="${1:-$(read_current cli || true)}"
|
|
663
|
-
validate_profile_name "$profile"
|
|
664
|
-
ensure_profile "$profile"
|
|
665
|
-
echo "export CODEX_HOME='$(profile_path "$profile")'"
|
|
1137
|
+
local account="${1:-}"
|
|
1138
|
+
local env
|
|
1139
|
+
env="$(read_current_env cli || true)"
|
|
1140
|
+
cmd_account_logout "$account" "$env" "cli"
|
|
666
1141
|
}
|
|
667
1142
|
|
|
668
1143
|
cmd_app_open() {
|
|
669
|
-
local
|
|
670
|
-
shift
|
|
671
|
-
local app_bin pid login_state
|
|
1144
|
+
local account="${1:-}"
|
|
1145
|
+
shift || true
|
|
1146
|
+
local env app_bin pid login_state use_account
|
|
1147
|
+
|
|
1148
|
+
env="$(read_current_env app || true)"
|
|
1149
|
+
use_account="${account:-$(read_current_account app || true)}"
|
|
1150
|
+
validate_account_name "$use_account"
|
|
1151
|
+
require_env_exists "$env"
|
|
1152
|
+
account_has_auth "$env" "$use_account" || err "account '$use_account' not logged in under env '$env'. run: $SCRIPT_NAME account login $use_account --env $env --target app"
|
|
1153
|
+
|
|
1154
|
+
set_current_env app "$env"
|
|
1155
|
+
set_current_account app "$use_account"
|
|
1156
|
+
ensure_target_auth_installed app
|
|
672
1157
|
|
|
673
|
-
|
|
674
|
-
require_profile_exists "$profile"
|
|
675
|
-
login_state="$(login_state_for_profile "$profile")"
|
|
1158
|
+
login_state="$(login_state_for_target app)"
|
|
676
1159
|
if [[ "$login_state" != "logged-in" ]]; then
|
|
677
|
-
err "
|
|
1160
|
+
err "account '$use_account' in env '$env' is not logged in"
|
|
678
1161
|
fi
|
|
679
1162
|
app_bin="$(resolve_app_bin)"
|
|
680
1163
|
|
|
681
1164
|
app_stop_managed >/dev/null
|
|
682
1165
|
|
|
683
1166
|
mkdir -p "$(dirname "$APP_LOG")"
|
|
684
|
-
nohup env CODEX_HOME="$(
|
|
1167
|
+
nohup env CODEX_HOME="$(target_home_path app)" CODEX_SWITCHER_MANAGED=1 CODEX_SWITCHER_ENV="$env" CODEX_SWITCHER_ACCOUNT="$use_account" "$app_bin" "$@" >>"$APP_LOG" 2>&1 &
|
|
685
1168
|
pid="$!"
|
|
686
1169
|
printf '%s\n' "$pid" > "$APP_PID_FILE"
|
|
687
1170
|
chmod 600 "$APP_PID_FILE" 2>/dev/null || true
|
|
688
1171
|
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
echo "Opened Codex App with profile: $profile"
|
|
1172
|
+
log_event INFO "app_open env=$env account=$use_account pid=$pid args=$*"
|
|
1173
|
+
echo "Opened Codex App with: $env/$use_account"
|
|
692
1174
|
echo "App log: $APP_LOG"
|
|
693
1175
|
}
|
|
694
1176
|
|
|
695
1177
|
cmd_app_use() {
|
|
696
|
-
local
|
|
697
|
-
shift
|
|
698
|
-
cmd_app_open "$
|
|
1178
|
+
local account="$1"
|
|
1179
|
+
shift || true
|
|
1180
|
+
cmd_app_open "$account" "$@"
|
|
699
1181
|
}
|
|
700
1182
|
|
|
701
1183
|
cmd_app_logout() {
|
|
702
|
-
local
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
run_codex_for_profile "$profile" logout
|
|
1184
|
+
local account="${1:-}"
|
|
1185
|
+
local env
|
|
1186
|
+
env="$(read_current_env app || true)"
|
|
1187
|
+
cmd_account_logout "$account" "$env" "app"
|
|
707
1188
|
}
|
|
708
1189
|
|
|
709
1190
|
cmd_app_status() {
|
|
710
|
-
local
|
|
711
|
-
|
|
712
|
-
|
|
1191
|
+
local env account
|
|
1192
|
+
env="$(read_current_env app || true)"
|
|
1193
|
+
account="$(read_current_account app || true)"
|
|
1194
|
+
echo "app_current: $env/$account"
|
|
713
1195
|
if app_is_running; then
|
|
714
1196
|
echo "app_process: running(pid=$(cat "$APP_PID_FILE"))"
|
|
715
1197
|
return 0
|
|
@@ -813,44 +1295,34 @@ cmd_upgrade() {
|
|
|
813
1295
|
|
|
814
1296
|
cmd_recover() {
|
|
815
1297
|
local dry_run="${1:-false}"
|
|
816
|
-
local
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
ensure_profile "$cli_profile"
|
|
1298
|
+
local target env account
|
|
1299
|
+
|
|
1300
|
+
for target in cli app; do
|
|
1301
|
+
env="$(read_current_env "$target" || true)"
|
|
1302
|
+
account="$(read_current_account "$target" || true)"
|
|
1303
|
+
validate_env_name_noexit "$env" || env="$DEFAULT_ENV_NAME"
|
|
1304
|
+
if [[ "$env" != "$DEFAULT_ENV_NAME" ]] && [[ ! -d "$(env_home_path "$env")" ]]; then
|
|
1305
|
+
env="$DEFAULT_ENV_NAME"
|
|
1306
|
+
fi
|
|
1307
|
+
validate_name_noexit "$account" || account="$DEFAULT_ACCOUNT_NAME"
|
|
1308
|
+
if ! account_has_auth "$env" "$account"; then
|
|
1309
|
+
account="$DEFAULT_ACCOUNT_NAME"
|
|
829
1310
|
fi
|
|
830
|
-
cli_ptr_state=3
|
|
831
|
-
fi
|
|
832
1311
|
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
app_profile="$first"
|
|
838
|
-
else
|
|
839
|
-
app_profile="$(default_profile_for app)"
|
|
840
|
-
ensure_profile "$app_profile"
|
|
1312
|
+
if [[ "$dry_run" != "true" ]]; then
|
|
1313
|
+
set_current_env "$target" "$env"
|
|
1314
|
+
set_current_account "$target" "$account"
|
|
1315
|
+
ensure_target_auth_installed "$target"
|
|
841
1316
|
fi
|
|
842
|
-
|
|
843
|
-
|
|
1317
|
+
|
|
1318
|
+
echo "recover($target): $env/$account"
|
|
1319
|
+
done
|
|
844
1320
|
|
|
845
1321
|
if [[ "$dry_run" == "true" ]]; then
|
|
846
|
-
echo "recover(dry-run): cli=$cli_profile app=$app_profile"
|
|
847
1322
|
return 0
|
|
848
1323
|
fi
|
|
849
1324
|
|
|
850
|
-
|
|
851
|
-
set_current app "$app_profile"
|
|
852
|
-
log_event INFO "recover cli=$cli_profile app=$app_profile"
|
|
853
|
-
echo "Recovered pointers: cli=$cli_profile app=$app_profile"
|
|
1325
|
+
log_event INFO "recover cli=$(read_current_env cli || true)/$(read_current_account cli || true) app=$(read_current_env app || true)/$(read_current_account app || true)"
|
|
854
1326
|
}
|
|
855
1327
|
|
|
856
1328
|
scan_logs_for_secrets() {
|
|
@@ -869,17 +1341,27 @@ scan_logs_for_secrets() {
|
|
|
869
1341
|
cmd_check() {
|
|
870
1342
|
command -v codex >/dev/null 2>&1 || err "codex command not found in PATH"
|
|
871
1343
|
resolve_app_bin >/dev/null
|
|
872
|
-
|
|
873
1344
|
ensure_dirs
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
1345
|
+
|
|
1346
|
+
local pstate=0
|
|
1347
|
+
read_current_env cli >/dev/null || pstate=$?
|
|
1348
|
+
if [[ "$pstate" -eq 2 ]]; then
|
|
1349
|
+
err "current_cli_env pointer corrupted; run: $SCRIPT_NAME recover"
|
|
1350
|
+
fi
|
|
1351
|
+
pstate=0
|
|
1352
|
+
read_current_env app >/dev/null || pstate=$?
|
|
1353
|
+
if [[ "$pstate" -eq 2 ]]; then
|
|
1354
|
+
err "current_app_env pointer corrupted; run: $SCRIPT_NAME recover"
|
|
1355
|
+
fi
|
|
1356
|
+
pstate=0
|
|
1357
|
+
read_current_account cli >/dev/null || pstate=$?
|
|
1358
|
+
if [[ "$pstate" -eq 2 ]]; then
|
|
1359
|
+
err "current_cli_account pointer corrupted; run: $SCRIPT_NAME recover"
|
|
878
1360
|
fi
|
|
879
1361
|
pstate=0
|
|
880
|
-
|
|
1362
|
+
read_current_account app >/dev/null || pstate=$?
|
|
881
1363
|
if [[ "$pstate" -eq 2 ]]; then
|
|
882
|
-
err "
|
|
1364
|
+
err "current_app_account pointer corrupted; run: $SCRIPT_NAME recover"
|
|
883
1365
|
fi
|
|
884
1366
|
|
|
885
1367
|
if ! scan_logs_for_secrets; then
|
|
@@ -893,16 +1375,19 @@ cmd_check() {
|
|
|
893
1375
|
cmd_doctor() {
|
|
894
1376
|
local fix="${1:-false}"
|
|
895
1377
|
local issues=0
|
|
896
|
-
local state_perm
|
|
1378
|
+
local state_perm envs_perm accounts_perm
|
|
897
1379
|
|
|
898
1380
|
ensure_dirs
|
|
899
1381
|
state_perm="$(perm_of "$STATE_DIR")"
|
|
900
|
-
|
|
1382
|
+
envs_perm="$(perm_of "$ENVS_DIR")"
|
|
1383
|
+
accounts_perm="$(perm_of "$ACCOUNTS_DIR")"
|
|
901
1384
|
|
|
902
1385
|
echo "state_dir: $STATE_DIR (perm=$state_perm)"
|
|
903
|
-
echo "
|
|
904
|
-
echo "
|
|
905
|
-
echo "
|
|
1386
|
+
echo "envs_dir: $ENVS_DIR (perm=$envs_perm)"
|
|
1387
|
+
echo "accounts_dir: $ACCOUNTS_DIR (perm=$accounts_perm)"
|
|
1388
|
+
echo "default_home: $DEFAULT_HOME (perm=$(perm_of "$DEFAULT_HOME"))"
|
|
1389
|
+
echo "cli_current: $(read_current_env cli || true)/$(read_current_account cli || true)"
|
|
1390
|
+
echo "app_current: $(read_current_env app || true)/$(read_current_account app || true)"
|
|
906
1391
|
|
|
907
1392
|
if ! command -v codex >/dev/null 2>&1; then
|
|
908
1393
|
echo "- codex in PATH: missing"
|
|
@@ -918,20 +1403,9 @@ cmd_doctor() {
|
|
|
918
1403
|
issues=1
|
|
919
1404
|
fi
|
|
920
1405
|
|
|
921
|
-
if [[ "$state_perm" != "700" ]]; then
|
|
922
|
-
echo "- state dir permission not 700"
|
|
923
|
-
issues=1
|
|
924
|
-
if [[ "$fix" == "true" ]]; then
|
|
925
|
-
chmod 700 "$STATE_DIR" || true
|
|
926
|
-
fi
|
|
927
|
-
fi
|
|
928
|
-
|
|
929
|
-
if [[ "$profiles_perm" != "700" ]]; then
|
|
930
|
-
echo "- profiles dir permission not 700"
|
|
1406
|
+
if [[ "$state_perm" != "700" || "$envs_perm" != "700" || "$accounts_perm" != "700" ]]; then
|
|
931
1407
|
issues=1
|
|
932
|
-
|
|
933
|
-
chmod 700 "$PROFILES_DIR" || true
|
|
934
|
-
fi
|
|
1408
|
+
echo "- directory permissions are not strict 700"
|
|
935
1409
|
fi
|
|
936
1410
|
|
|
937
1411
|
if ! scan_logs_for_secrets; then
|
|
@@ -940,23 +1414,9 @@ cmd_doctor() {
|
|
|
940
1414
|
echo "- redaction check: ok"
|
|
941
1415
|
fi
|
|
942
1416
|
|
|
943
|
-
local pstate=0
|
|
944
|
-
read_current cli >/dev/null || pstate=$?
|
|
945
|
-
if [[ "$pstate" -eq 2 ]]; then
|
|
946
|
-
echo "- current_cli pointer corrupted"
|
|
947
|
-
issues=1
|
|
948
|
-
fi
|
|
949
|
-
pstate=0
|
|
950
|
-
read_current app >/dev/null || pstate=$?
|
|
951
|
-
if [[ "$pstate" -eq 2 ]]; then
|
|
952
|
-
echo "- current_app pointer corrupted"
|
|
953
|
-
issues=1
|
|
954
|
-
fi
|
|
955
|
-
|
|
956
1417
|
if [[ "$fix" == "true" ]]; then
|
|
1418
|
+
chmod 700 "$STATE_DIR" "$ENVS_DIR" "$ACCOUNTS_DIR" "$DEFAULT_HOME" 2>/dev/null || true
|
|
957
1419
|
with_lock cmd_recover false
|
|
958
|
-
chmod 700 "$STATE_DIR" "$PROFILES_DIR" 2>/dev/null || true
|
|
959
|
-
find "$PROFILES_DIR" -mindepth 1 -maxdepth 1 -type d -exec chmod 700 {} \; 2>/dev/null || true
|
|
960
1420
|
issues=0
|
|
961
1421
|
if ! scan_logs_for_secrets; then
|
|
962
1422
|
issues=1
|
|
@@ -987,12 +1447,265 @@ main() {
|
|
|
987
1447
|
shift || true
|
|
988
1448
|
|
|
989
1449
|
case "$cmd" in
|
|
1450
|
+
env)
|
|
1451
|
+
local sub="${1:-}"
|
|
1452
|
+
if [[ -z "$sub" ]]; then
|
|
1453
|
+
usage
|
|
1454
|
+
exit 1
|
|
1455
|
+
fi
|
|
1456
|
+
shift || true
|
|
1457
|
+
case "$sub" in
|
|
1458
|
+
list)
|
|
1459
|
+
[[ "$#" -eq 0 ]] || err "usage: $SCRIPT_NAME env list"
|
|
1460
|
+
cmd_env_list
|
|
1461
|
+
;;
|
|
1462
|
+
create)
|
|
1463
|
+
[[ "$#" -ge 1 ]] || err "usage: $SCRIPT_NAME env create <env> [--empty|--from-default|--from-env <src>]"
|
|
1464
|
+
local env="$1"
|
|
1465
|
+
shift
|
|
1466
|
+
local mode="from-default"
|
|
1467
|
+
local src_env=""
|
|
1468
|
+
while [[ "$#" -gt 0 ]]; do
|
|
1469
|
+
case "$1" in
|
|
1470
|
+
--empty)
|
|
1471
|
+
mode="empty"
|
|
1472
|
+
;;
|
|
1473
|
+
--from-default)
|
|
1474
|
+
mode="from-default"
|
|
1475
|
+
;;
|
|
1476
|
+
--from-env)
|
|
1477
|
+
shift
|
|
1478
|
+
[[ "$#" -gt 0 ]] || err "missing source env after --from-env"
|
|
1479
|
+
mode="from-env"
|
|
1480
|
+
src_env="$1"
|
|
1481
|
+
;;
|
|
1482
|
+
*)
|
|
1483
|
+
err "unknown option: $1"
|
|
1484
|
+
;;
|
|
1485
|
+
esac
|
|
1486
|
+
shift
|
|
1487
|
+
done
|
|
1488
|
+
with_lock cmd_env_create "$env" "$mode" "$src_env"
|
|
1489
|
+
;;
|
|
1490
|
+
use)
|
|
1491
|
+
[[ "$#" -ge 1 ]] || err "usage: $SCRIPT_NAME env use <env> [--target cli|app|both]"
|
|
1492
|
+
local env="$1"
|
|
1493
|
+
shift
|
|
1494
|
+
local target="cli"
|
|
1495
|
+
while [[ "$#" -gt 0 ]]; do
|
|
1496
|
+
case "$1" in
|
|
1497
|
+
--target)
|
|
1498
|
+
shift
|
|
1499
|
+
[[ "$#" -gt 0 ]] || err "missing value after --target"
|
|
1500
|
+
target="$1"
|
|
1501
|
+
;;
|
|
1502
|
+
*)
|
|
1503
|
+
err "unknown option: $1"
|
|
1504
|
+
;;
|
|
1505
|
+
esac
|
|
1506
|
+
shift
|
|
1507
|
+
done
|
|
1508
|
+
with_lock cmd_env_use "$env" "$target"
|
|
1509
|
+
;;
|
|
1510
|
+
remove)
|
|
1511
|
+
[[ "$#" -ge 1 && "$#" -le 2 ]] || err "usage: $SCRIPT_NAME env remove <env> [--force]"
|
|
1512
|
+
local env="$1"
|
|
1513
|
+
local force="false"
|
|
1514
|
+
if [[ "${2:-}" == "--force" ]]; then
|
|
1515
|
+
force="true"
|
|
1516
|
+
elif [[ -n "${2:-}" ]]; then
|
|
1517
|
+
err "unknown option: ${2:-}"
|
|
1518
|
+
fi
|
|
1519
|
+
with_lock cmd_env_remove "$env" "$force"
|
|
1520
|
+
;;
|
|
1521
|
+
current)
|
|
1522
|
+
[[ "$#" -le 1 ]] || err "usage: $SCRIPT_NAME env current [cli|app]"
|
|
1523
|
+
cmd_env_current "${1:-all}"
|
|
1524
|
+
;;
|
|
1525
|
+
path)
|
|
1526
|
+
[[ "$#" -le 1 ]] || err "usage: $SCRIPT_NAME env path [env]"
|
|
1527
|
+
cmd_env_path "${1:-}"
|
|
1528
|
+
;;
|
|
1529
|
+
*)
|
|
1530
|
+
err "unknown env subcommand: $sub"
|
|
1531
|
+
;;
|
|
1532
|
+
esac
|
|
1533
|
+
;;
|
|
1534
|
+
account)
|
|
1535
|
+
local sub="${1:-}"
|
|
1536
|
+
[[ -n "$sub" ]] || err "usage: $SCRIPT_NAME account <list|add|remove|login|use|logout|current> ..."
|
|
1537
|
+
shift || true
|
|
1538
|
+
case "$sub" in
|
|
1539
|
+
list)
|
|
1540
|
+
local env="$(read_current_env cli || true)"
|
|
1541
|
+
while [[ "$#" -gt 0 ]]; do
|
|
1542
|
+
case "$1" in
|
|
1543
|
+
--env)
|
|
1544
|
+
shift
|
|
1545
|
+
[[ "$#" -gt 0 ]] || err "missing env after --env"
|
|
1546
|
+
env="$1"
|
|
1547
|
+
;;
|
|
1548
|
+
*)
|
|
1549
|
+
err "unknown option: $1"
|
|
1550
|
+
;;
|
|
1551
|
+
esac
|
|
1552
|
+
shift
|
|
1553
|
+
done
|
|
1554
|
+
cmd_account_list "$env"
|
|
1555
|
+
;;
|
|
1556
|
+
add)
|
|
1557
|
+
[[ "$#" -ge 1 ]] || err "usage: $SCRIPT_NAME account add <account> [--env <env>]"
|
|
1558
|
+
local account="$1"
|
|
1559
|
+
shift
|
|
1560
|
+
local env="$(read_current_env cli || true)"
|
|
1561
|
+
while [[ "$#" -gt 0 ]]; do
|
|
1562
|
+
case "$1" in
|
|
1563
|
+
--env)
|
|
1564
|
+
shift
|
|
1565
|
+
[[ "$#" -gt 0 ]] || err "missing env after --env"
|
|
1566
|
+
env="$1"
|
|
1567
|
+
;;
|
|
1568
|
+
*)
|
|
1569
|
+
err "unknown option: $1"
|
|
1570
|
+
;;
|
|
1571
|
+
esac
|
|
1572
|
+
shift
|
|
1573
|
+
done
|
|
1574
|
+
with_lock cmd_account_add "$account" "$env"
|
|
1575
|
+
;;
|
|
1576
|
+
remove)
|
|
1577
|
+
[[ "$#" -ge 1 ]] || err "usage: $SCRIPT_NAME account remove <account> [--env <env>] [--force]"
|
|
1578
|
+
local account="$1"
|
|
1579
|
+
shift
|
|
1580
|
+
local env="$(read_current_env cli || true)"
|
|
1581
|
+
local force="false"
|
|
1582
|
+
while [[ "$#" -gt 0 ]]; do
|
|
1583
|
+
case "$1" in
|
|
1584
|
+
--env)
|
|
1585
|
+
shift
|
|
1586
|
+
[[ "$#" -gt 0 ]] || err "missing env after --env"
|
|
1587
|
+
env="$1"
|
|
1588
|
+
;;
|
|
1589
|
+
--force)
|
|
1590
|
+
force="true"
|
|
1591
|
+
;;
|
|
1592
|
+
*)
|
|
1593
|
+
err "unknown option: $1"
|
|
1594
|
+
;;
|
|
1595
|
+
esac
|
|
1596
|
+
shift
|
|
1597
|
+
done
|
|
1598
|
+
with_lock cmd_account_remove "$account" "$env" "$force"
|
|
1599
|
+
;;
|
|
1600
|
+
login)
|
|
1601
|
+
[[ "$#" -ge 1 ]] || err "usage: $SCRIPT_NAME account login <account> [--env <env>] [--target cli|app|both] [--sync|--no-sync]"
|
|
1602
|
+
local account="$1"
|
|
1603
|
+
shift
|
|
1604
|
+
local env="$(read_current_env cli || true)"
|
|
1605
|
+
local target="cli"
|
|
1606
|
+
local sync_mode="false"
|
|
1607
|
+
while [[ "$#" -gt 0 ]]; do
|
|
1608
|
+
case "$1" in
|
|
1609
|
+
--env)
|
|
1610
|
+
shift
|
|
1611
|
+
[[ "$#" -gt 0 ]] || err "missing env after --env"
|
|
1612
|
+
env="$1"
|
|
1613
|
+
;;
|
|
1614
|
+
--target)
|
|
1615
|
+
shift
|
|
1616
|
+
[[ "$#" -gt 0 ]] || err "missing target after --target"
|
|
1617
|
+
target="$1"
|
|
1618
|
+
;;
|
|
1619
|
+
--sync)
|
|
1620
|
+
sync_mode="true"
|
|
1621
|
+
;;
|
|
1622
|
+
--no-sync)
|
|
1623
|
+
sync_mode="false"
|
|
1624
|
+
;;
|
|
1625
|
+
*)
|
|
1626
|
+
err "unknown option: $1"
|
|
1627
|
+
;;
|
|
1628
|
+
esac
|
|
1629
|
+
shift
|
|
1630
|
+
done
|
|
1631
|
+
with_lock cmd_account_login "$account" "$env" "$target" "$sync_mode"
|
|
1632
|
+
;;
|
|
1633
|
+
use)
|
|
1634
|
+
[[ "$#" -ge 1 ]] || err "usage: $SCRIPT_NAME account use <account> [--env <env>] [--target cli|app|both] [--sync|--no-sync]"
|
|
1635
|
+
local account="$1"
|
|
1636
|
+
shift
|
|
1637
|
+
local env="$(read_current_env cli || true)"
|
|
1638
|
+
local target="cli"
|
|
1639
|
+
local sync_mode="false"
|
|
1640
|
+
while [[ "$#" -gt 0 ]]; do
|
|
1641
|
+
case "$1" in
|
|
1642
|
+
--env)
|
|
1643
|
+
shift
|
|
1644
|
+
[[ "$#" -gt 0 ]] || err "missing env after --env"
|
|
1645
|
+
env="$1"
|
|
1646
|
+
;;
|
|
1647
|
+
--target)
|
|
1648
|
+
shift
|
|
1649
|
+
[[ "$#" -gt 0 ]] || err "missing target after --target"
|
|
1650
|
+
target="$1"
|
|
1651
|
+
;;
|
|
1652
|
+
--sync)
|
|
1653
|
+
sync_mode="true"
|
|
1654
|
+
;;
|
|
1655
|
+
--no-sync)
|
|
1656
|
+
sync_mode="false"
|
|
1657
|
+
;;
|
|
1658
|
+
*)
|
|
1659
|
+
err "unknown option: $1"
|
|
1660
|
+
;;
|
|
1661
|
+
esac
|
|
1662
|
+
shift
|
|
1663
|
+
done
|
|
1664
|
+
with_lock cmd_account_use "$account" "$env" "$target" "$sync_mode"
|
|
1665
|
+
;;
|
|
1666
|
+
logout)
|
|
1667
|
+
local account=""
|
|
1668
|
+
local env="$(read_current_env cli || true)"
|
|
1669
|
+
local target="cli"
|
|
1670
|
+
if [[ "$#" -gt 0 && "${1:-}" != --* ]]; then
|
|
1671
|
+
account="$1"
|
|
1672
|
+
shift
|
|
1673
|
+
fi
|
|
1674
|
+
while [[ "$#" -gt 0 ]]; do
|
|
1675
|
+
case "$1" in
|
|
1676
|
+
--env)
|
|
1677
|
+
shift
|
|
1678
|
+
[[ "$#" -gt 0 ]] || err "missing env after --env"
|
|
1679
|
+
env="$1"
|
|
1680
|
+
;;
|
|
1681
|
+
--target)
|
|
1682
|
+
shift
|
|
1683
|
+
[[ "$#" -gt 0 ]] || err "missing target after --target"
|
|
1684
|
+
target="$1"
|
|
1685
|
+
;;
|
|
1686
|
+
*)
|
|
1687
|
+
err "unknown option: $1"
|
|
1688
|
+
;;
|
|
1689
|
+
esac
|
|
1690
|
+
shift
|
|
1691
|
+
done
|
|
1692
|
+
with_lock cmd_account_logout "$account" "$env" "$target"
|
|
1693
|
+
;;
|
|
1694
|
+
current)
|
|
1695
|
+
[[ "$#" -le 1 ]] || err "usage: $SCRIPT_NAME account current [cli|app]"
|
|
1696
|
+
cmd_account_current "${1:-all}"
|
|
1697
|
+
;;
|
|
1698
|
+
*)
|
|
1699
|
+
err "unknown account subcommand: $sub"
|
|
1700
|
+
;;
|
|
1701
|
+
esac
|
|
1702
|
+
;;
|
|
990
1703
|
add)
|
|
991
|
-
[[ "$#" -eq 1 ]] || err "usage: $SCRIPT_NAME add <
|
|
1704
|
+
[[ "$#" -eq 1 ]] || err "usage: $SCRIPT_NAME add <account>"
|
|
992
1705
|
with_lock cmd_add "$1"
|
|
993
1706
|
;;
|
|
994
1707
|
remove)
|
|
995
|
-
[[ "$#" -ge 1 && "$#" -le 2 ]] || err "usage: $SCRIPT_NAME remove <
|
|
1708
|
+
[[ "$#" -ge 1 && "$#" -le 2 ]] || err "usage: $SCRIPT_NAME remove <account> [--force]"
|
|
996
1709
|
local force="false"
|
|
997
1710
|
if [[ "${2:-}" == "--force" ]]; then
|
|
998
1711
|
force="true"
|
|
@@ -1006,8 +1719,8 @@ main() {
|
|
|
1006
1719
|
cmd_list
|
|
1007
1720
|
;;
|
|
1008
1721
|
import-default)
|
|
1009
|
-
[[ "$#" -ge 1 ]] || err "usage: $SCRIPT_NAME import-default <
|
|
1010
|
-
local
|
|
1722
|
+
[[ "$#" -ge 1 ]] || err "usage: $SCRIPT_NAME import-default <env> [--with-auth] [--force]"
|
|
1723
|
+
local env="$1"
|
|
1011
1724
|
local with_auth="false"
|
|
1012
1725
|
local force="false"
|
|
1013
1726
|
shift
|
|
@@ -1025,11 +1738,11 @@ main() {
|
|
|
1025
1738
|
esac
|
|
1026
1739
|
shift
|
|
1027
1740
|
done
|
|
1028
|
-
with_lock cmd_import_default "$
|
|
1741
|
+
with_lock cmd_import_default "$env" "$with_auth" "$force"
|
|
1029
1742
|
;;
|
|
1030
1743
|
use)
|
|
1031
|
-
[[ "$#" -ge 1 ]] || err "usage: $SCRIPT_NAME use <
|
|
1032
|
-
local
|
|
1744
|
+
[[ "$#" -ge 1 ]] || err "usage: $SCRIPT_NAME use <account> [--sync|--no-sync] [--launch|--no-launch] [-- <codex args...>]"
|
|
1745
|
+
local account="$1"
|
|
1033
1746
|
shift
|
|
1034
1747
|
local sync="false"
|
|
1035
1748
|
local launch="auto"
|
|
@@ -1064,14 +1777,14 @@ main() {
|
|
|
1064
1777
|
launch="true"
|
|
1065
1778
|
fi
|
|
1066
1779
|
if [[ "${#codex_args[@]}" -gt 0 ]]; then
|
|
1067
|
-
cmd_use_and_maybe_launch
|
|
1780
|
+
cmd_use_and_maybe_launch cmd_use_compat "$account" "$sync" "$launch" "${codex_args[@]}"
|
|
1068
1781
|
else
|
|
1069
|
-
cmd_use_and_maybe_launch
|
|
1782
|
+
cmd_use_and_maybe_launch cmd_use_compat "$account" "$sync" "$launch"
|
|
1070
1783
|
fi
|
|
1071
1784
|
;;
|
|
1072
1785
|
switch)
|
|
1073
|
-
[[ "$#" -ge 1 ]] || err "usage: $SCRIPT_NAME switch <
|
|
1074
|
-
local
|
|
1786
|
+
[[ "$#" -ge 1 ]] || err "usage: $SCRIPT_NAME switch <account> [--sync|--no-sync] [--launch|--no-launch] [-- <codex args...>]"
|
|
1787
|
+
local account="$1"
|
|
1075
1788
|
shift
|
|
1076
1789
|
local sync="false"
|
|
1077
1790
|
local launch="auto"
|
|
@@ -1106,9 +1819,9 @@ main() {
|
|
|
1106
1819
|
launch="true"
|
|
1107
1820
|
fi
|
|
1108
1821
|
if [[ "${#codex_args[@]}" -gt 0 ]]; then
|
|
1109
|
-
cmd_use_and_maybe_launch
|
|
1822
|
+
cmd_use_and_maybe_launch cmd_switch_compat "$account" "$sync" "$launch" "${codex_args[@]}"
|
|
1110
1823
|
else
|
|
1111
|
-
cmd_use_and_maybe_launch
|
|
1824
|
+
cmd_use_and_maybe_launch cmd_switch_compat "$account" "$sync" "$launch"
|
|
1112
1825
|
fi
|
|
1113
1826
|
;;
|
|
1114
1827
|
current)
|
|
@@ -1123,8 +1836,8 @@ main() {
|
|
|
1123
1836
|
cmd_exec "$@"
|
|
1124
1837
|
;;
|
|
1125
1838
|
login)
|
|
1126
|
-
[[ "$#" -le 2 ]] || err "usage: $SCRIPT_NAME login [
|
|
1127
|
-
local
|
|
1839
|
+
[[ "$#" -le 2 ]] || err "usage: $SCRIPT_NAME login [account] [--sync|--no-sync]"
|
|
1840
|
+
local account=""
|
|
1128
1841
|
local sync="false"
|
|
1129
1842
|
local arg
|
|
1130
1843
|
for arg in "$@"; do
|
|
@@ -1136,44 +1849,43 @@ main() {
|
|
|
1136
1849
|
sync="false"
|
|
1137
1850
|
;;
|
|
1138
1851
|
*)
|
|
1139
|
-
if [[ -z "$
|
|
1140
|
-
|
|
1852
|
+
if [[ -z "$account" ]]; then
|
|
1853
|
+
account="$arg"
|
|
1141
1854
|
else
|
|
1142
1855
|
err "unknown option: $arg"
|
|
1143
1856
|
fi
|
|
1144
1857
|
;;
|
|
1145
1858
|
esac
|
|
1146
1859
|
done
|
|
1147
|
-
with_lock cmd_login "${
|
|
1860
|
+
with_lock cmd_login "${account:-}" "$sync"
|
|
1148
1861
|
;;
|
|
1149
1862
|
logout)
|
|
1150
|
-
[[ "$#" -le 1 ]] || err "usage: $SCRIPT_NAME logout [
|
|
1863
|
+
[[ "$#" -le 1 ]] || err "usage: $SCRIPT_NAME logout [account]"
|
|
1151
1864
|
with_lock cmd_logout "${1:-}"
|
|
1152
1865
|
;;
|
|
1153
|
-
env)
|
|
1154
|
-
[[ "$#" -le 1 ]] || err "usage: $SCRIPT_NAME env [profile]"
|
|
1155
|
-
cmd_env "${1:-}"
|
|
1156
|
-
;;
|
|
1157
1866
|
app)
|
|
1158
1867
|
local sub="${1:-}"
|
|
1159
1868
|
[[ -n "$sub" ]] || err "usage: $SCRIPT_NAME app <open|use|logout|status|stop|current> ..."
|
|
1160
1869
|
shift || true
|
|
1161
1870
|
case "$sub" in
|
|
1162
1871
|
open)
|
|
1163
|
-
local
|
|
1164
|
-
if [[ "$#" -gt 0 ]]; then
|
|
1872
|
+
local account=""
|
|
1873
|
+
if [[ "$#" -gt 0 && "${1:-}" != "--" ]]; then
|
|
1874
|
+
account="$1"
|
|
1875
|
+
shift
|
|
1876
|
+
fi
|
|
1165
1877
|
if [[ "${1:-}" == "--" ]]; then shift; fi
|
|
1166
|
-
with_lock cmd_app_open "$
|
|
1878
|
+
with_lock cmd_app_open "$account" "$@"
|
|
1167
1879
|
;;
|
|
1168
1880
|
use)
|
|
1169
|
-
[[ "$#" -ge 1 ]] || err "usage: $SCRIPT_NAME app use <
|
|
1170
|
-
local
|
|
1881
|
+
[[ "$#" -ge 1 ]] || err "usage: $SCRIPT_NAME app use <account> [-- <app args...>]"
|
|
1882
|
+
local account="$1"
|
|
1171
1883
|
shift
|
|
1172
1884
|
if [[ "${1:-}" == "--" ]]; then shift; fi
|
|
1173
|
-
with_lock cmd_app_use "$
|
|
1885
|
+
with_lock cmd_app_use "$account" "$@"
|
|
1174
1886
|
;;
|
|
1175
1887
|
logout)
|
|
1176
|
-
[[ "$#" -le 1 ]] || err "usage: $SCRIPT_NAME app logout [
|
|
1888
|
+
[[ "$#" -le 1 ]] || err "usage: $SCRIPT_NAME app logout [account]"
|
|
1177
1889
|
with_lock cmd_app_logout "${1:-}"
|
|
1178
1890
|
;;
|
|
1179
1891
|
status)
|
|
@@ -1186,7 +1898,7 @@ main() {
|
|
|
1186
1898
|
;;
|
|
1187
1899
|
current)
|
|
1188
1900
|
[[ "$#" -eq 0 ]] || err "usage: $SCRIPT_NAME app current"
|
|
1189
|
-
|
|
1901
|
+
echo "$(read_current_env app || true)/$(read_current_account app || true)"
|
|
1190
1902
|
;;
|
|
1191
1903
|
*)
|
|
1192
1904
|
err "unknown app subcommand: $sub"
|