@wangxt0223/codex-switcher 0.4.0 → 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 +16 -0
- package/README.en.md +18 -14
- package/README.md +47 -23
- package/package.json +1 -1
- package/plugins/codex-switcher/.codex-plugin/plugin.json +1 -1
- package/plugins/codex-switcher/README.en.md +48 -44
- package/plugins/codex-switcher/README.md +48 -44
- package/plugins/codex-switcher/scripts/codex-switcher +115 -19
- package/plugins/codex-switcher/scripts/test-switcher.sh +17 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
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
|
+
|
|
12
|
+
## 0.4.1 - 2026-04-12
|
|
13
|
+
|
|
14
|
+
- Refined README wording for a more conversational background/auth mechanism explanation.
|
|
15
|
+
- Moved command reference from plugin docs to root README in table format.
|
|
16
|
+
- Standardized README title to `codex-switcher`.
|
|
17
|
+
- Removed legacy package-name migration notices from docs.
|
|
18
|
+
|
|
3
19
|
## 0.4.0 - 2026-04-12
|
|
4
20
|
|
|
5
21
|
- Changed npm package name to `@wangxt0223/codex-switcher` (CLI command remains `codex-sw`).
|
package/README.en.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# codex-
|
|
1
|
+
# codex-switcher
|
|
2
2
|
|
|
3
3
|
[中文](README.md) | English
|
|
4
4
|
|
|
5
|
-
`codex-
|
|
5
|
+
`codex-switcher` is a lightweight profile switcher for Codex CLI and Codex App.
|
|
6
6
|
It isolates accounts by running each profile in its own `CODEX_HOME` directory.
|
|
7
7
|
|
|
8
8
|
## Background
|
|
@@ -10,7 +10,7 @@ It isolates accounts by running each profile in its own `CODEX_HOME` directory.
|
|
|
10
10
|
I originally used Codex for personal work while my company account lived in Cursor, so there was no conflict.
|
|
11
11
|
After the company migrated from Cursor to Codex, my personal and company Codex accounts started conflicting on the same machine, and switching became unreliable.
|
|
12
12
|
|
|
13
|
-
After inspecting local behavior, I found Codex's local auth model is straightforward: if account-local data is isolated per directory, account switching becomes stable. Based on that, I built `codex-
|
|
13
|
+
After inspecting local behavior, I found Codex's local auth model is straightforward: if account-local data is isolated per directory, account switching becomes stable. Based on that, I built `codex-switcher` with Codex to manage, switch, and isolate all my Codex accounts.
|
|
14
14
|
|
|
15
15
|
## Codex Local Auth Model (Summary)
|
|
16
16
|
|
|
@@ -21,7 +21,7 @@ The following is based on observed local behavior and filesystem layout:
|
|
|
21
21
|
- Session/history/state data is also stored under the same `CODEX_HOME` (for example `history.jsonl`, `sessions/`, `state_*.sqlite`).
|
|
22
22
|
- So when multiple accounts share one `CODEX_HOME`, auth/session data can overwrite or contaminate each other.
|
|
23
23
|
|
|
24
|
-
`codex-
|
|
24
|
+
`codex-switcher` solves this by assigning each account its own `CODEX_HOME` (`~/.codex-profiles/<profile>`) and switching that directory for CLI/App operations.
|
|
25
25
|
|
|
26
26
|
## Install
|
|
27
27
|
|
|
@@ -29,28 +29,28 @@ The following is based on observed local behavior and filesystem layout:
|
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
31
|
npm i -g @wangxt0223/codex-switcher
|
|
32
|
-
codex-
|
|
32
|
+
codex-switcher check
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
### Option B: from source checkout
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
38
|
./scripts/install.sh
|
|
39
|
-
codex-
|
|
39
|
+
codex-switcher check
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
## Quick start
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
|
-
codex-
|
|
46
|
-
codex-
|
|
45
|
+
codex-switcher add work
|
|
46
|
+
codex-switcher add personal
|
|
47
47
|
|
|
48
|
-
codex-
|
|
49
|
-
codex-
|
|
50
|
-
codex-
|
|
48
|
+
codex-switcher use work --sync
|
|
49
|
+
codex-switcher login --sync
|
|
50
|
+
codex-switcher exec -- login status
|
|
51
51
|
|
|
52
|
-
codex-
|
|
53
|
-
codex-
|
|
52
|
+
codex-switcher switch personal --sync
|
|
53
|
+
codex-switcher app use personal
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
## Sync options
|
|
@@ -58,6 +58,10 @@ codex-sw 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
|
|
|
@@ -81,7 +85,7 @@ npm run release:npm
|
|
|
81
85
|
## Upgrade
|
|
82
86
|
|
|
83
87
|
```bash
|
|
84
|
-
codex-
|
|
88
|
+
codex-switcher upgrade
|
|
85
89
|
```
|
|
86
90
|
|
|
87
91
|
## Docs
|
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# codex-
|
|
1
|
+
# codex-switcher
|
|
2
2
|
|
|
3
3
|
中文 | [English](README.en.md)
|
|
4
4
|
|
|
5
|
-
`codex-
|
|
5
|
+
`codex-switcher` 是一个面向 Codex CLI 与 Codex App 的轻量账号切换工具。
|
|
6
6
|
它通过为每个 profile 使用独立的 `CODEX_HOME` 目录实现账号隔离。
|
|
7
7
|
|
|
8
8
|
## 项目背景
|
|
@@ -11,18 +11,14 @@
|
|
|
11
11
|
后来公司从 Cursor 切到 Codex 后,我就得在同一台电脑上同时用个人账号和公司账号,很快就遇到冲突:登录态会互相覆盖,切换也不顺手。
|
|
12
12
|
|
|
13
13
|
为了搞清楚原因,我看了下 Codex 的本地数据机制,发现思路其实很直接:只要把不同账号对应的本地目录隔离开,就能稳定切换。
|
|
14
|
-
基于这个思路,我用 Codex 写了 `codex-
|
|
14
|
+
基于这个思路,我用 Codex 写了 `codex-switcher`,专门用来管理、切换和隔离我所有的 Codex 账号,现在日常在个人/公司账号之间切换方便很多。
|
|
15
15
|
|
|
16
16
|
## Codex 本地认证机制(简述)
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
简单说就是:Codex 会把“账号登录态 + 会话历史 + 一些本地状态”都放在 `CODEX_HOME` 这个目录里(默认一般是 `~/.codex`)。
|
|
19
|
+
如果两个账号共用同一个目录,就很容易出现你登我下、我登你下,或者历史数据串在一起的问题。
|
|
19
20
|
|
|
20
|
-
-
|
|
21
|
-
- 账号认证状态主要保存在 `CODEX_HOME/auth.json`。
|
|
22
|
-
- 会话、历史、索引和状态等数据也会写在同一 `CODEX_HOME` 下(如 `history.jsonl`、`sessions/`、`state_*.sqlite` 等)。
|
|
23
|
-
- 因此当多个账号共享同一个 `CODEX_HOME` 时,最容易出现“登录态互相覆盖/污染”的问题。
|
|
24
|
-
|
|
25
|
-
`codex-sw` 的做法就是为每个账号分配独立 `CODEX_HOME`(`~/.codex-profiles/<profile>`),并在执行命令或启动 App 时切换到对应目录,从而实现账号隔离与可控切换。
|
|
21
|
+
`codex-switcher` 做的事情其实不复杂:给每个账号分一个独立目录(`~/.codex-profiles/<profile>`),然后在你执行命令或启动 App 时自动切到对应目录。这样每个账号的数据都各管各的,切换也就稳定了。
|
|
26
22
|
|
|
27
23
|
## 安装
|
|
28
24
|
|
|
@@ -30,28 +26,28 @@
|
|
|
30
26
|
|
|
31
27
|
```bash
|
|
32
28
|
npm i -g @wangxt0223/codex-switcher
|
|
33
|
-
codex-
|
|
29
|
+
codex-switcher check
|
|
34
30
|
```
|
|
35
31
|
|
|
36
32
|
### 方式 B:源码安装
|
|
37
33
|
|
|
38
34
|
```bash
|
|
39
35
|
./scripts/install.sh
|
|
40
|
-
codex-
|
|
36
|
+
codex-switcher check
|
|
41
37
|
```
|
|
42
38
|
|
|
43
39
|
## 快速开始
|
|
44
40
|
|
|
45
41
|
```bash
|
|
46
|
-
codex-
|
|
47
|
-
codex-
|
|
42
|
+
codex-switcher add work
|
|
43
|
+
codex-switcher add personal
|
|
48
44
|
|
|
49
|
-
codex-
|
|
50
|
-
codex-
|
|
51
|
-
codex-
|
|
45
|
+
codex-switcher use work --sync
|
|
46
|
+
codex-switcher login --sync
|
|
47
|
+
codex-switcher exec -- login status
|
|
52
48
|
|
|
53
|
-
codex-
|
|
54
|
-
codex-
|
|
49
|
+
codex-switcher switch personal --sync
|
|
50
|
+
codex-switcher app use personal
|
|
55
51
|
```
|
|
56
52
|
|
|
57
53
|
## 同步选项
|
|
@@ -59,12 +55,40 @@ codex-sw app use personal
|
|
|
59
55
|
- `login --sync`:将 `~/.codex` 同步到目标 profile(不包含 `auth.json`)。
|
|
60
56
|
- `use/switch --sync`:将当前 CLI profile 同步到目标 profile(不包含 `auth.json`)。
|
|
61
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)。
|
|
62
62
|
|
|
63
63
|
## 命令参考
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
命令默认用 `codex-switcher`,你也可以继续使用兼容别名 `codex-sw`。
|
|
66
|
+
|
|
67
|
+
| 分类 | 命令 | 说明 |
|
|
68
|
+
| --- | --- | --- |
|
|
69
|
+
| Profile 管理 | `codex-switcher add <profile>` | 新建 profile |
|
|
70
|
+
| Profile 管理 | `codex-switcher remove <profile> [--force]` | 删除 profile |
|
|
71
|
+
| Profile 管理 | `codex-switcher list` | 列出所有 profile |
|
|
72
|
+
| Profile 管理 | `codex-switcher current [cli\|app]` | 查看当前 CLI / App profile |
|
|
73
|
+
| Profile 管理 | `codex-switcher status` | 查看当前 profile 登录状态 |
|
|
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` 的等价命令 |
|
|
76
|
+
| 数据迁移 | `codex-switcher import-default <profile> [--with-auth] [--force]` | 从 `~/.codex` 导入数据到 profile |
|
|
77
|
+
| CLI 登录态 | `codex-switcher login [profile] [--sync\|--no-sync]` | 登录指定或当前 CLI profile |
|
|
78
|
+
| CLI 登录态 | `codex-switcher logout [profile]` | 登出指定或当前 CLI profile |
|
|
79
|
+
| CLI 登录态 | `codex-switcher exec -- <codex args...>` | 在当前 CLI profile 下执行 codex 命令 |
|
|
80
|
+
| CLI 登录态 | `codex-switcher env [profile]` | 输出指定 profile 的 `CODEX_HOME` |
|
|
81
|
+
| App 控制 | `codex-switcher app open [profile]` | 用指定 profile 启动 App |
|
|
82
|
+
| App 控制 | `codex-switcher app use <profile>` | 切换 App profile(等价于 open) |
|
|
83
|
+
| App 控制 | `codex-switcher app logout [profile]` | 登出 App profile |
|
|
84
|
+
| App 控制 | `codex-switcher app status` | 查看 App 运行状态 |
|
|
85
|
+
| App 控制 | `codex-switcher app stop` | 停止由工具启动的 App 进程 |
|
|
86
|
+
| App 控制 | `codex-switcher app current` | 查看当前 App profile |
|
|
87
|
+
| 系统维护 | `codex-switcher check` | 基础环境与状态检查 |
|
|
88
|
+
| 系统维护 | `codex-switcher doctor [--fix]` | 诊断并可选自动修复 |
|
|
89
|
+
| 系统维护 | `codex-switcher recover [--dry-run]` | 恢复损坏的 current 指针 |
|
|
90
|
+
| 系统维护 | `codex-switcher init [--shell zsh\|bash] [--dry-run]` | 初始化 PATH 与快捷命令 |
|
|
91
|
+
| 系统维护 | `codex-switcher upgrade [--dry-run]` | 升级到最新版本 |
|
|
68
92
|
|
|
69
93
|
## 开发
|
|
70
94
|
|
|
@@ -82,7 +106,7 @@ npm run release:npm
|
|
|
82
106
|
## 升级
|
|
83
107
|
|
|
84
108
|
```bash
|
|
85
|
-
codex-
|
|
109
|
+
codex-switcher upgrade
|
|
86
110
|
```
|
|
87
111
|
|
|
88
112
|
## 文档
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# codex-
|
|
1
|
+
# codex-switcher
|
|
2
2
|
|
|
3
3
|
[中文](README.md) | English
|
|
4
4
|
|
|
@@ -14,45 +14,45 @@ Profile-based account switcher for Codex CLI and Codex App.
|
|
|
14
14
|
## Commands
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
codex-
|
|
18
|
-
codex-
|
|
19
|
-
codex-
|
|
20
|
-
codex-
|
|
21
|
-
codex-
|
|
22
|
-
codex-
|
|
23
|
-
codex-
|
|
24
|
-
codex-
|
|
25
|
-
|
|
26
|
-
codex-
|
|
27
|
-
codex-
|
|
28
|
-
codex-
|
|
29
|
-
codex-
|
|
30
|
-
|
|
31
|
-
codex-
|
|
32
|
-
codex-
|
|
33
|
-
codex-
|
|
34
|
-
codex-
|
|
35
|
-
codex-
|
|
36
|
-
|
|
37
|
-
codex-
|
|
38
|
-
codex-
|
|
39
|
-
codex-
|
|
40
|
-
codex-
|
|
41
|
-
codex-
|
|
17
|
+
codex-switcher add <profile>
|
|
18
|
+
codex-switcher remove <profile> [--force]
|
|
19
|
+
codex-switcher list
|
|
20
|
+
codex-switcher import-default <profile> [--with-auth] [--force]
|
|
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
|
+
codex-switcher current [cli|app]
|
|
24
|
+
codex-switcher status
|
|
25
|
+
|
|
26
|
+
codex-switcher exec -- <codex args...>
|
|
27
|
+
codex-switcher login [profile] [--sync|--no-sync]
|
|
28
|
+
codex-switcher logout [profile]
|
|
29
|
+
codex-switcher env [profile]
|
|
30
|
+
|
|
31
|
+
codex-switcher app open [profile]
|
|
32
|
+
codex-switcher app use <profile>
|
|
33
|
+
codex-switcher app logout [profile]
|
|
34
|
+
codex-switcher app status
|
|
35
|
+
codex-switcher app stop
|
|
36
|
+
|
|
37
|
+
codex-switcher init [--shell zsh|bash]
|
|
38
|
+
codex-switcher upgrade [--dry-run]
|
|
39
|
+
codex-switcher recover
|
|
40
|
+
codex-switcher check
|
|
41
|
+
codex-switcher doctor [--fix]
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
## Typical flow
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
|
-
codex-
|
|
48
|
-
codex-
|
|
47
|
+
codex-switcher add work
|
|
48
|
+
codex-switcher add personal
|
|
49
49
|
|
|
50
|
-
codex-
|
|
51
|
-
codex-
|
|
52
|
-
codex-
|
|
50
|
+
codex-switcher use work --sync
|
|
51
|
+
codex-switcher login --sync
|
|
52
|
+
codex-switcher exec -- login status
|
|
53
53
|
|
|
54
|
-
codex-
|
|
55
|
-
codex-
|
|
54
|
+
codex-switcher switch personal --sync
|
|
55
|
+
codex-switcher app use personal
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
## Migrate Existing App/CLI Data
|
|
@@ -60,14 +60,14 @@ codex-sw app use personal
|
|
|
60
60
|
If your existing data is in `~/.codex`, import it into a profile first:
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
|
-
codex-
|
|
63
|
+
codex-switcher import-default work
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
This copies records/projects/history but excludes `auth.json` by default.
|
|
67
67
|
If you want to carry login state too:
|
|
68
68
|
|
|
69
69
|
```bash
|
|
70
|
-
codex-
|
|
70
|
+
codex-switcher import-default work --with-auth
|
|
71
71
|
```
|
|
72
72
|
|
|
73
73
|
## Sync Behavior
|
|
@@ -75,31 +75,35 @@ codex-sw 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
|
|
|
81
85
|
```bash
|
|
82
|
-
codex-
|
|
83
|
-
codex-
|
|
84
|
-
codex-
|
|
86
|
+
codex-switcher login work --sync
|
|
87
|
+
codex-switcher switch personal --sync
|
|
88
|
+
codex-switcher use work --no-sync
|
|
85
89
|
```
|
|
86
90
|
|
|
87
91
|
## Upgrade
|
|
88
92
|
|
|
89
93
|
```bash
|
|
90
|
-
codex-
|
|
94
|
+
codex-switcher upgrade
|
|
91
95
|
```
|
|
92
96
|
|
|
93
97
|
## Notes
|
|
94
98
|
|
|
95
99
|
- Codex App is single-instance on macOS; switching App profile requires restart.
|
|
96
|
-
- `codex-
|
|
97
|
-
- `codex-
|
|
100
|
+
- `codex-switcher app stop` only stops app instances started and tracked by `codex-switcher`.
|
|
101
|
+
- `codex-switcher app open/use <profile>` requires that profile already exists and is logged in.
|
|
98
102
|
- `--sync` uses overwrite strategy (not merge): source overwrites target for all files except `auth.json`.
|
|
99
|
-
- `codex-
|
|
103
|
+
- `codex-switcher status` exit codes:
|
|
100
104
|
- `0`: both current profiles logged in
|
|
101
105
|
- `1`: at least one current profile not logged in
|
|
102
|
-
- `2`: pointer/profile integrity issue (run `codex-
|
|
106
|
+
- `2`: pointer/profile integrity issue (run `codex-switcher recover`)
|
|
103
107
|
|
|
104
108
|
## Validation
|
|
105
109
|
|
|
@@ -109,4 +113,4 @@ codex-sw upgrade
|
|
|
109
113
|
|
|
110
114
|
## Compatibility command
|
|
111
115
|
|
|
112
|
-
`codex-
|
|
116
|
+
`codex-sw` is kept as a compatibility entrypoint and maps to the same implementation.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# codex-
|
|
1
|
+
# codex-switcher
|
|
2
2
|
|
|
3
3
|
中文 | [English](README.en.md)
|
|
4
4
|
|
|
@@ -14,45 +14,45 @@
|
|
|
14
14
|
## 命令
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
codex-
|
|
18
|
-
codex-
|
|
19
|
-
codex-
|
|
20
|
-
codex-
|
|
21
|
-
codex-
|
|
22
|
-
codex-
|
|
23
|
-
codex-
|
|
24
|
-
codex-
|
|
25
|
-
|
|
26
|
-
codex-
|
|
27
|
-
codex-
|
|
28
|
-
codex-
|
|
29
|
-
codex-
|
|
30
|
-
|
|
31
|
-
codex-
|
|
32
|
-
codex-
|
|
33
|
-
codex-
|
|
34
|
-
codex-
|
|
35
|
-
codex-
|
|
36
|
-
|
|
37
|
-
codex-
|
|
38
|
-
codex-
|
|
39
|
-
codex-
|
|
40
|
-
codex-
|
|
41
|
-
codex-
|
|
17
|
+
codex-switcher add <profile>
|
|
18
|
+
codex-switcher remove <profile> [--force]
|
|
19
|
+
codex-switcher list
|
|
20
|
+
codex-switcher import-default <profile> [--with-auth] [--force]
|
|
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
|
+
codex-switcher current [cli|app]
|
|
24
|
+
codex-switcher status
|
|
25
|
+
|
|
26
|
+
codex-switcher exec -- <codex args...>
|
|
27
|
+
codex-switcher login [profile] [--sync|--no-sync]
|
|
28
|
+
codex-switcher logout [profile]
|
|
29
|
+
codex-switcher env [profile]
|
|
30
|
+
|
|
31
|
+
codex-switcher app open [profile]
|
|
32
|
+
codex-switcher app use <profile>
|
|
33
|
+
codex-switcher app logout [profile]
|
|
34
|
+
codex-switcher app status
|
|
35
|
+
codex-switcher app stop
|
|
36
|
+
|
|
37
|
+
codex-switcher init [--shell zsh|bash]
|
|
38
|
+
codex-switcher upgrade [--dry-run]
|
|
39
|
+
codex-switcher recover
|
|
40
|
+
codex-switcher check
|
|
41
|
+
codex-switcher doctor [--fix]
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
## 典型流程
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
|
-
codex-
|
|
48
|
-
codex-
|
|
47
|
+
codex-switcher add work
|
|
48
|
+
codex-switcher add personal
|
|
49
49
|
|
|
50
|
-
codex-
|
|
51
|
-
codex-
|
|
52
|
-
codex-
|
|
50
|
+
codex-switcher use work --sync
|
|
51
|
+
codex-switcher login --sync
|
|
52
|
+
codex-switcher exec -- login status
|
|
53
53
|
|
|
54
|
-
codex-
|
|
55
|
-
codex-
|
|
54
|
+
codex-switcher switch personal --sync
|
|
55
|
+
codex-switcher app use personal
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
## 迁移已有数据
|
|
@@ -60,14 +60,14 @@ codex-sw app use personal
|
|
|
60
60
|
如果你原本在 `~/.codex` 下使用 Codex,可先导入到某个 profile:
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
|
-
codex-
|
|
63
|
+
codex-switcher import-default work
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
默认会迁移记录/项目等数据,但不包含 `auth.json`。
|
|
67
67
|
如需连登录态一起导入:
|
|
68
68
|
|
|
69
69
|
```bash
|
|
70
|
-
codex-
|
|
70
|
+
codex-switcher import-default work --with-auth
|
|
71
71
|
```
|
|
72
72
|
|
|
73
73
|
## 同步行为
|
|
@@ -75,31 +75,35 @@ codex-sw 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
|
|
|
81
85
|
```bash
|
|
82
|
-
codex-
|
|
83
|
-
codex-
|
|
84
|
-
codex-
|
|
86
|
+
codex-switcher login work --sync
|
|
87
|
+
codex-switcher switch personal --sync
|
|
88
|
+
codex-switcher use work --no-sync
|
|
85
89
|
```
|
|
86
90
|
|
|
87
91
|
## 升级
|
|
88
92
|
|
|
89
93
|
```bash
|
|
90
|
-
codex-
|
|
94
|
+
codex-switcher upgrade
|
|
91
95
|
```
|
|
92
96
|
|
|
93
97
|
## 说明
|
|
94
98
|
|
|
95
99
|
- macOS 下 Codex App 是单实例;切换 App profile 需要重启。
|
|
96
|
-
- `codex-
|
|
97
|
-
- `codex-
|
|
100
|
+
- `codex-switcher app stop` 仅停止由 `codex-switcher` 启动并跟踪的 App 进程。
|
|
101
|
+
- `codex-switcher app open/use <profile>` 要求该 profile 已存在且已登录。
|
|
98
102
|
- `--sync` 为覆盖策略(不是合并):源目录覆盖目标目录,`auth.json` 除外。
|
|
99
|
-
- `codex-
|
|
103
|
+
- `codex-switcher status` 返回码:
|
|
100
104
|
- `0`:当前 CLI/App profile 均已登录
|
|
101
105
|
- `1`:至少一个当前 profile 未登录
|
|
102
|
-
- `2`:指针或 profile 完整性异常(可执行 `codex-
|
|
106
|
+
- `2`:指针或 profile 完整性异常(可执行 `codex-switcher recover`)
|
|
103
107
|
|
|
104
108
|
## 验证
|
|
105
109
|
|
|
@@ -109,4 +113,4 @@ codex-sw upgrade
|
|
|
109
113
|
|
|
110
114
|
## 兼容命令
|
|
111
115
|
|
|
112
|
-
`codex-
|
|
116
|
+
`codex-sw` 作为兼容入口保留,行为与 `codex-switcher` 一致。
|
|
@@ -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
|
|
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
|
-
|
|
984
|
-
|
|
985
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
997
|
-
|
|
998
|
-
|
|
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
|
-
|
|
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
|
-
"$
|
|
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" ]]
|