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