@wangxt0223/codex-switcher 0.4.1 → 0.5.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 CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.0 - 2026-04-12
4
+
5
+ - Added automatic Codex CLI launch behavior for `use/switch` in interactive shells (`--launch=auto`).
6
+ - Added explicit `--launch` / `--no-launch` controls for `use/switch`.
7
+ - Added support for `use/switch -- <codex args...>` to switch profile and run Codex command in one step.
8
+ - Improved non-interactive UX with explicit auto-launch skip hint.
9
+ - Added smoke-test coverage for launch/no-launch behavior and argument conflict handling.
10
+ - Updated Chinese/English docs to describe launch semantics and new command forms.
11
+
3
12
  ## 0.4.1 - 2026-04-12
4
13
 
5
14
  - Refined README wording for a more conversational background/auth mechanism explanation.
package/README.en.md CHANGED
@@ -58,6 +58,10 @@ codex-switcher app use personal
58
58
  - `login --sync`: sync `~/.codex` into the target profile (excluding `auth.json`).
59
59
  - `use/switch --sync`: sync current CLI profile into target profile (excluding `auth.json`).
60
60
  - `--no-sync`: keep strict isolation without data copy (default).
61
+ - `use/switch` defaults to `--launch=auto`: on an interactive terminal, `codex` starts automatically after switch.
62
+ - `use/switch --launch`: launch `codex` CLI immediately after switching.
63
+ - `use/switch --no-launch`: switch CLI pointer only, without launching `codex`.
64
+ - `use/switch -- <codex args...>`: run `codex` with args right after switch (implies launch).
61
65
 
62
66
  ## Command reference
63
67
 
package/README.md CHANGED
@@ -55,6 +55,10 @@ codex-switcher app use personal
55
55
  - `login --sync`:将 `~/.codex` 同步到目标 profile(不包含 `auth.json`)。
56
56
  - `use/switch --sync`:将当前 CLI profile 同步到目标 profile(不包含 `auth.json`)。
57
57
  - `--no-sync`:不进行数据同步(默认)。
58
+ - `use/switch` 默认 `--launch=auto`:交互终端中切换后会自动启动 `codex` CLI。
59
+ - `use/switch --launch`:切换后立即启动 `codex` CLI。
60
+ - `use/switch --no-launch`:仅切换当前 CLI profile,不启动 `codex` CLI。
61
+ - `use/switch -- <codex args...>`:切换后直接执行 `codex` 参数(隐式启用 launch)。
58
62
 
59
63
  ## 命令参考
60
64
 
@@ -67,8 +71,8 @@ codex-switcher app use personal
67
71
  | Profile 管理 | `codex-switcher list` | 列出所有 profile |
68
72
  | Profile 管理 | `codex-switcher current [cli\|app]` | 查看当前 CLI / App profile |
69
73
  | Profile 管理 | `codex-switcher status` | 查看当前 profile 登录状态 |
70
- | Profile 管理 | `codex-switcher use <profile> [--sync\|--no-sync]` | 切换当前 CLI profile |
71
- | Profile 管理 | `codex-switcher switch <profile> [--sync\|--no-sync]` | `use` 的等价命令 |
74
+ | Profile 管理 | `codex-switcher use <profile> [--sync\|--no-sync] [--launch\|--no-launch] [-- <codex args...>]` | 切换当前 CLI profile,可选立即启动 `codex` |
75
+ | Profile 管理 | `codex-switcher switch <profile> [--sync\|--no-sync] [--launch\|--no-launch] [-- <codex args...>]` | `use` 的等价命令 |
72
76
  | 数据迁移 | `codex-switcher import-default <profile> [--with-auth] [--force]` | 从 `~/.codex` 导入数据到 profile |
73
77
  | CLI 登录态 | `codex-switcher login [profile] [--sync\|--no-sync]` | 登录指定或当前 CLI profile |
74
78
  | CLI 登录态 | `codex-switcher logout [profile]` | 登出指定或当前 CLI profile |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wangxt0223/codex-switcher",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "Profile-based account switcher for Codex CLI and Codex App using isolated CODEX_HOME directories.",
5
5
  "license": "MIT",
6
6
  "author": "wangxt",
@@ -18,8 +18,8 @@ codex-switcher add <profile>
18
18
  codex-switcher remove <profile> [--force]
19
19
  codex-switcher list
20
20
  codex-switcher import-default <profile> [--with-auth] [--force]
21
- codex-switcher use <profile> [--sync|--no-sync]
22
- codex-switcher switch <profile> [--sync|--no-sync]
21
+ codex-switcher use <profile> [--sync|--no-sync] [--launch|--no-launch] [-- <codex args...>]
22
+ codex-switcher switch <profile> [--sync|--no-sync] [--launch|--no-launch] [-- <codex args...>]
23
23
  codex-switcher current [cli|app]
24
24
  codex-switcher status
25
25
 
@@ -75,6 +75,10 @@ codex-switcher import-default work --with-auth
75
75
  - `login --sync`: overwrite sync from default `~/.codex` to target profile, excluding `auth.json`.
76
76
  - `use/switch --sync`: overwrite sync from current CLI profile to target profile, excluding `auth.json`.
77
77
  - `--no-sync`: explicit no-sync mode (default behavior).
78
+ - `use/switch` defaults to `--launch=auto`: in interactive terminals, `codex` starts right after switching.
79
+ - `use/switch --launch`: launch `codex` CLI immediately after switching profile.
80
+ - `use/switch --no-launch`: switch pointer only without launching `codex`.
81
+ - `use/switch -- <codex args...>`: run `codex` with provided args after switch (implies launch).
78
82
 
79
83
  Examples:
80
84
 
@@ -18,8 +18,8 @@ codex-switcher add <profile>
18
18
  codex-switcher remove <profile> [--force]
19
19
  codex-switcher list
20
20
  codex-switcher import-default <profile> [--with-auth] [--force]
21
- codex-switcher use <profile> [--sync|--no-sync]
22
- codex-switcher switch <profile> [--sync|--no-sync]
21
+ codex-switcher use <profile> [--sync|--no-sync] [--launch|--no-launch] [-- <codex args...>]
22
+ codex-switcher switch <profile> [--sync|--no-sync] [--launch|--no-launch] [-- <codex args...>]
23
23
  codex-switcher current [cli|app]
24
24
  codex-switcher status
25
25
 
@@ -75,6 +75,10 @@ codex-switcher import-default work --with-auth
75
75
  - `login --sync`:从默认 `~/.codex` 覆盖同步到目标 profile,排除 `auth.json`。
76
76
  - `use/switch --sync`:从当前 CLI profile 覆盖同步到目标 profile,排除 `auth.json`。
77
77
  - `--no-sync`:显式关闭同步(默认行为)。
78
+ - `use/switch` 默认 `--launch=auto`:交互终端中切换后自动启动 `codex` CLI。
79
+ - `use/switch --launch`:切换后立即以目标 profile 启动 `codex` CLI。
80
+ - `use/switch --no-launch`:切换后只更新 profile 指针,不启动 `codex` CLI。
81
+ - `use/switch -- <codex args...>`:切换后执行指定 `codex` 参数(等价于隐式 `--launch`)。
78
82
 
79
83
  示例:
80
84
 
@@ -18,8 +18,8 @@ Usage:
18
18
  codex-sw remove <profile> [--force]
19
19
  codex-sw list
20
20
  codex-sw import-default <profile> [--with-auth] [--force]
21
- codex-sw use <profile> [--sync|--no-sync]
22
- codex-sw switch <profile> [--sync|--no-sync]
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
23
  codex-sw current [cli|app]
24
24
  codex-sw status
25
25
 
@@ -514,15 +514,53 @@ cmd_use() {
514
514
  ensure_profile "$profile"
515
515
  set_current cli "$profile"
516
516
  log_event INFO "cli_use profile=$profile sync=$sync_mode"
517
- echo "Switched CLI profile to: $profile"
518
- echo "Run in current shell if needed:"
519
- echo " export CODEX_HOME='$(profile_path "$profile")'"
520
517
  }
521
518
 
522
519
  cmd_switch() {
523
520
  cmd_use "$1" "${2:-false}"
524
521
  }
525
522
 
523
+ should_launch_codex() {
524
+ local mode="$1"
525
+ case "$mode" in
526
+ true)
527
+ return 0
528
+ ;;
529
+ false)
530
+ return 1
531
+ ;;
532
+ auto)
533
+ [[ -t 0 && -t 1 ]]
534
+ ;;
535
+ *)
536
+ return 1
537
+ ;;
538
+ esac
539
+ }
540
+
541
+ cmd_use_and_maybe_launch() {
542
+ local mode_cmd="$1"
543
+ local profile="$2"
544
+ local sync_mode="${3:-false}"
545
+ local launch_mode="${4:-auto}"
546
+ shift 4 || true
547
+
548
+ with_lock "$mode_cmd" "$profile" "$sync_mode"
549
+
550
+ echo "Switched CLI profile to: $profile"
551
+ if should_launch_codex "$launch_mode"; then
552
+ echo "Launching codex with profile: $profile"
553
+ CODEX_HOME="$(profile_path "$profile")" command codex "$@"
554
+ return
555
+ fi
556
+
557
+ if [[ "$launch_mode" == "auto" ]]; then
558
+ echo "Auto launch skipped (non-interactive shell). Use --launch to force start."
559
+ fi
560
+ echo "Run in current shell if needed:"
561
+ echo " export CODEX_HOME='$(profile_path "$profile")'"
562
+ }
563
+
526
564
  cmd_current() {
527
565
  local target="${1:-all}"
528
566
  case "$target" in
@@ -977,30 +1015,88 @@ main() {
977
1015
  with_lock cmd_import_default "$profile" "$with_auth" "$force"
978
1016
  ;;
979
1017
  use)
980
- [[ "$#" -ge 1 && "$#" -le 2 ]] || err "usage: $SCRIPT_NAME use <profile> [--sync|--no-sync]"
1018
+ [[ "$#" -ge 1 ]] || err "usage: $SCRIPT_NAME use <profile> [--sync|--no-sync] [--launch|--no-launch] [-- <codex args...>]"
981
1019
  local profile="$1"
1020
+ shift
982
1021
  local sync="false"
983
- if [[ "${2:-}" == "--sync" ]]; then
984
- sync="true"
985
- elif [[ "${2:-}" == "--no-sync" || -z "${2:-}" ]]; then
986
- :
1022
+ local launch="auto"
1023
+ local codex_args=()
1024
+ while [[ "$#" -gt 0 ]]; do
1025
+ case "$1" in
1026
+ --sync)
1027
+ sync="true"
1028
+ ;;
1029
+ --no-sync)
1030
+ sync="false"
1031
+ ;;
1032
+ --launch)
1033
+ launch="true"
1034
+ ;;
1035
+ --no-launch)
1036
+ launch="false"
1037
+ ;;
1038
+ --)
1039
+ shift
1040
+ codex_args=("$@")
1041
+ break
1042
+ ;;
1043
+ *)
1044
+ err "unknown option: $1"
1045
+ ;;
1046
+ esac
1047
+ shift
1048
+ done
1049
+ if [[ "${#codex_args[@]}" -gt 0 ]]; then
1050
+ [[ "$launch" != "false" ]] || err "cannot pass codex args with --no-launch"
1051
+ launch="true"
1052
+ fi
1053
+ if [[ "${#codex_args[@]}" -gt 0 ]]; then
1054
+ cmd_use_and_maybe_launch cmd_use "$profile" "$sync" "$launch" "${codex_args[@]}"
987
1055
  else
988
- err "unknown option: ${2:-}"
1056
+ cmd_use_and_maybe_launch cmd_use "$profile" "$sync" "$launch"
989
1057
  fi
990
- with_lock cmd_use "$profile" "$sync"
991
1058
  ;;
992
1059
  switch)
993
- [[ "$#" -ge 1 && "$#" -le 2 ]] || err "usage: $SCRIPT_NAME switch <profile> [--sync|--no-sync]"
1060
+ [[ "$#" -ge 1 ]] || err "usage: $SCRIPT_NAME switch <profile> [--sync|--no-sync] [--launch|--no-launch] [-- <codex args...>]"
994
1061
  local profile="$1"
1062
+ shift
995
1063
  local sync="false"
996
- if [[ "${2:-}" == "--sync" ]]; then
997
- sync="true"
998
- elif [[ "${2:-}" == "--no-sync" || -z "${2:-}" ]]; then
999
- :
1064
+ local launch="auto"
1065
+ local codex_args=()
1066
+ while [[ "$#" -gt 0 ]]; do
1067
+ case "$1" in
1068
+ --sync)
1069
+ sync="true"
1070
+ ;;
1071
+ --no-sync)
1072
+ sync="false"
1073
+ ;;
1074
+ --launch)
1075
+ launch="true"
1076
+ ;;
1077
+ --no-launch)
1078
+ launch="false"
1079
+ ;;
1080
+ --)
1081
+ shift
1082
+ codex_args=("$@")
1083
+ break
1084
+ ;;
1085
+ *)
1086
+ err "unknown option: $1"
1087
+ ;;
1088
+ esac
1089
+ shift
1090
+ done
1091
+ if [[ "${#codex_args[@]}" -gt 0 ]]; then
1092
+ [[ "$launch" != "false" ]] || err "cannot pass codex args with --no-launch"
1093
+ launch="true"
1094
+ fi
1095
+ if [[ "${#codex_args[@]}" -gt 0 ]]; then
1096
+ cmd_use_and_maybe_launch cmd_switch "$profile" "$sync" "$launch" "${codex_args[@]}"
1000
1097
  else
1001
- err "unknown option: ${2:-}"
1098
+ cmd_use_and_maybe_launch cmd_switch "$profile" "$sync" "$launch"
1002
1099
  fi
1003
- with_lock cmd_switch "$profile" "$sync"
1004
1100
  ;;
1005
1101
  current)
1006
1102
  [[ "$#" -le 1 ]] || err "usage: $SCRIPT_NAME current [cli|app]"
@@ -21,6 +21,7 @@ trap cleanup EXIT INT TERM
21
21
  cat > "$BIN/codex" <<'FAKE'
22
22
  #!/usr/bin/env bash
23
23
  set -euo pipefail
24
+ echo "${CODEX_HOME:-}|$*" >> "${CODEX_SWITCHER_TEST_CODEX_LOG:?}"
24
25
  if [[ "${1:-}" == "login" && "${2:-}" == "status" ]]; then
25
26
  if [[ -f "${CODEX_HOME}/auth.json" ]]; then
26
27
  echo "Logged in"
@@ -64,6 +65,8 @@ export CODEX_SWITCHER_APP_BIN="$BIN/fake-codex-app"
64
65
  export CODEX_SWITCHER_LOCK_WAIT_SECONDS=2
65
66
  export CODEX_SWITCHER_DEFAULT_HOME="$TMPBASE/default-home"
66
67
  export CODEX_SWITCHER_TEST_NPM_LOG="$TMPBASE/npm-args.log"
68
+ export CODEX_SWITCHER_TEST_CODEX_LOG="$TMPBASE/codex-args.log"
69
+ : > "$CODEX_SWITCHER_TEST_CODEX_LOG"
67
70
 
68
71
  mkdir -p "$CODEX_SWITCHER_DEFAULT_HOME/memories"
69
72
  echo '{"auth_mode":"chatgpt"}' > "$CODEX_SWITCHER_DEFAULT_HOME/auth.json"
@@ -79,9 +82,22 @@ grep -q "i -g @wangxt0223/codex-switcher@latest --registry https://registry.npmj
79
82
 
80
83
  "$SW" add work
81
84
  "$SW" add personal
82
- "$SW" use personal
85
+ codex_calls_before="$(wc -l < "$CODEX_SWITCHER_TEST_CODEX_LOG" 2>/dev/null || echo 0)"
86
+ "$SW" use personal --no-launch
87
+ codex_calls_after="$(wc -l < "$CODEX_SWITCHER_TEST_CODEX_LOG" 2>/dev/null || echo 0)"
88
+ [[ "$codex_calls_before" -eq "$codex_calls_after" ]]
83
89
  [[ "$("$SW" current cli)" == "personal" ]]
84
90
 
91
+ "$SW" use personal -- --version
92
+ grep -Fq "$PROFILES/personal|--version" "$CODEX_SWITCHER_TEST_CODEX_LOG"
93
+
94
+ set +e
95
+ "$SW" use personal --no-launch -- --version >/tmp/codex_sw_use_no_launch_conflict 2>&1
96
+ use_no_launch_conflict_rc=$?
97
+ set -e
98
+ [[ "$use_no_launch_conflict_rc" -ne 0 ]]
99
+ grep -q "cannot pass codex args with --no-launch" /tmp/codex_sw_use_no_launch_conflict
100
+
85
101
  "$SW" login personal
86
102
  "$SW" login sync-login --sync
87
103
  [[ -f "$PROFILES/sync-login/state_5.sqlite" ]]