codex-to-im 0.1.2 → 0.1.6

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/README.md CHANGED
@@ -38,13 +38,13 @@ Windows host installation guide: [docs/install-windows.md](D:/codex/Claude-to-IM
38
38
  ### Prerequisites
39
39
 
40
40
  - Node.js 20+
41
- - If you use the `codex` or `auto` runtime, complete Codex authentication under the same Windows user
41
+ - If you use the `codex` or `auto` runtime, complete Codex authentication under the same OS user account
42
42
 
43
43
  `codex-to-im` now ships with the required `@openai/codex-sdk` / Codex CLI platform dependency, so you do not need to install a separate global Codex CLI just to run the bridge.
44
44
 
45
45
  You still need Codex credentials to be available for the current user. Any of these is sufficient:
46
46
 
47
- - a logged-in Codex Windows App
47
+ - a logged-in Codex Desktop App
48
48
  - an existing Codex CLI login state
49
49
  - `CTI_CODEX_API_KEY`, `CODEX_API_KEY`, or `OPENAI_API_KEY`
50
50
 
@@ -86,6 +86,15 @@ http://127.0.0.1:4781
86
86
 
87
87
  If that port is already occupied, the app automatically finds an available local port and prints the actual address to the terminal when starting.
88
88
 
89
+ By default, the web workbench only accepts local access.
90
+
91
+ If you want to open it from your phone or another device on the same LAN, enable `允许局域网访问 Web 控制台` in the `配置` page. When enabled:
92
+
93
+ - the workbench shows detected LAN URLs
94
+ - the workbench displays an access token
95
+ - LAN devices see a login page before they can view or modify settings
96
+ - you can also copy a ready-to-use login link that includes `?token=...`
97
+
89
98
  If you forget the current address, run:
90
99
 
91
100
  ```bash
@@ -114,10 +123,21 @@ codex-to-im stop
114
123
  6. Bind a Feishu or Weixin chat to the target thread
115
124
  7. Continue the same Codex thread from IM
116
125
 
117
- Useful command:
126
+ If LAN access is enabled, the easiest path is to copy the LAN login link from the local workbench and open it on your phone or another device on the same network.
118
127
 
119
- - `/history` shows the latest N messages of the current session
128
+ Useful commands:
129
+
130
+ - `/` / `/status` shows the current session
131
+ - `/h` / `/help` shows help
132
+ - `/t` / `/threads` lists recent desktop threads, and `/t 1` / `/thread 1` binds the first one
133
+ - `/n proj1` / `/new proj1` creates a new project session under the default workspace root
134
+ - `/m` / `/mode` shows or changes the current mode; options: `code` / `plan` / `ask`
135
+ - `/r` / `/reasoning` shows or changes the current reasoning effort; options: `1|2|3|4|5`
136
+ - `/his` / `/history` shows the summarized history, and `/his raw` / `/history raw` shows raw history
137
+ - `/t 0` / `/thread 0` enters a temporary draft thread that does not pollute the main work thread
138
+ - `1 / 2 / 3` or `/perm ...` handles permission prompts
120
139
  - N is configurable in the web workbench under the basic settings panel
140
+ - The workbench command guide shows both short commands and compatible original commands
121
141
 
122
142
  If you enable Feishu streaming response cards, the Feishu app must have the required permissions published first, at minimum:
123
143
 
@@ -139,6 +159,33 @@ If creating a new session fails with `Not inside a trusted directory`, either:
139
159
  - change the default working directory to a trusted Git repo, or
140
160
  - enable `Allow Codex outside trusted Git repos` in the basic settings and restart the bridge
141
161
 
162
+ The configuration page also includes Codex runtime controls:
163
+
164
+ - `Default workspace root`
165
+ - parent directory used for `/new proj1`
166
+ - falls back to `~/cx2im` when left empty, expanded for the current OS
167
+ - `Codex filesystem permission`
168
+ - `read-only`, `workspace-write`, or `danger-full-access`
169
+ - default: `workspace-write`
170
+ - `Codex reasoning effort`
171
+ - global default reasoning level
172
+ - can be overridden per IM session with `/reasoning`
173
+ - official runtime levels are `minimal`, `low`, `medium`, `high`, `xhigh`
174
+ - IM numeric aliases are `1=minimal`, `2=low`, `3=medium`, `4=high`, `5=xhigh`
175
+
176
+ If you are using `codex-to-im` on your own development machine for real coding work, the more aggressive recommended setup is:
177
+
178
+ - set `Codex filesystem permission` to `danger-full-access`
179
+ - set `Codex reasoning effort` to `xhigh`
180
+
181
+ This is closer to a full-power `code` workflow. It fits a controlled local project, but is not a good default for unknown repositories or higher-risk environments.
182
+
183
+ The channel pages also expose a “Use Markdown for command feedback” switch:
184
+ - enabled by default for Feishu
185
+ - disabled by default for WeChat
186
+ - only affects bridge-generated feedback such as `/h`, `/status`, and `/threads`
187
+ - does not affect raw Codex replies
188
+
142
189
  ## Update
143
190
 
144
191
  On Windows, `npm update -g codex-to-im` can fail with `EBUSY` if the background UI or bridge is still running from the global install directory.
package/README_CN.md CHANGED
@@ -38,13 +38,13 @@ Windows 主机安装说明见:[docs/install-windows.md](D:/codex/Claude-to-IM-
38
38
  ### 依赖
39
39
 
40
40
  - Node.js 20+
41
- - 如果使用 `codex` 或 `auto` 运行时:需要在同一 Windows 用户下完成 Codex 认证
41
+ - 如果使用 `codex` 或 `auto` 运行时:需要在同一系统用户下完成 Codex 认证
42
42
 
43
43
  `codex-to-im` 当前已经随包带上运行所需的 `@openai/codex-sdk` / Codex CLI 平台依赖,正常使用 bridge 时不要求你额外再全局安装一份 Codex CLI。
44
44
 
45
45
  但你仍然需要让 Codex 在当前用户下可用。推荐满足以下任一条件:
46
46
 
47
- - 已安装并登录过 Codex Windows App
47
+ - 已安装并登录过 Codex Desktop App
48
48
  - 已经有可用的 Codex CLI 登录态
49
49
  - 已配置 `CTI_CODEX_API_KEY`、`CODEX_API_KEY` 或 `OPENAI_API_KEY`
50
50
 
@@ -86,6 +86,15 @@ http://127.0.0.1:4781
86
86
 
87
87
  如果默认端口已被占用,应用会自动选择一个可用端口,并在启动时把实际地址打印到命令行。
88
88
 
89
+ 默认情况下,Web 工作台只允许本机访问。
90
+
91
+ 如果你需要在手机或同一局域网里的其他设备上打开配置页,可以在“配置”页里勾选“允许局域网访问 Web 控制台”。开启后:
92
+
93
+ - 工作台会显示当前可用的局域网地址
94
+ - 工作台会生成并展示一个访问 token
95
+ - 局域网设备访问时会先进入登录页,输入 token 后才能查看和修改配置
96
+ - 也可以直接复制页面里的局域网登录链接,链接里会附带 `?token=...`
97
+
89
98
  如果你忘了当前地址,可以执行:
90
99
 
91
100
  ```bash
@@ -114,10 +123,21 @@ codex-to-im stop
114
123
  6. 把飞书或微信聊天绑定到目标 thread
115
124
  7. 在 IM 中继续同一条 Codex 会话
116
125
 
126
+ 如果开启了局域网访问,推荐在本机工作台里复制局域网登录链接,再发给你的手机或局域网里的其他设备。
127
+
117
128
  常用命令补充:
118
129
 
119
- - `/history` 查看当前会话最近 N 条消息
130
+ - `/` / `/status` 查看当前会话
131
+ - `/h` / `/help` 查看帮助
132
+ - `/t` / `/threads` 查看最近桌面会话,`/t 1` / `/thread 1` 接管第 1 条
133
+ - `/n proj1` / `/new proj1` 在默认工作空间下新建项目会话
134
+ - `/m` / `/mode` 查看或切换模式,可选 `code` / `plan` / `ask`
135
+ - `/r` / `/reasoning` 查看或切换思考级别,可选 `1|2|3|4|5`
136
+ - `/his` / `/history` 查看整理后的历史摘要,`/his raw` / `/history raw` 查看原始记录
137
+ - `/t 0` / `/thread 0` 进入临时草稿线程,不污染正式工作会话
138
+ - `1 / 2 / 3` 或 `/perm ...` 处理权限
120
139
  - N 可在 Web 工作台的“基础配置”里调整
140
+ - Web 工作台的“命令说明”页会同时列出短命令和兼容原命令
121
141
 
122
142
  如果你启用了飞书流式响应卡片,需要先在飞书应用侧开通并发布相关权限,至少包括:
123
143
 
@@ -139,6 +159,32 @@ codex-to-im stop
139
159
  - 把默认工作目录改成一个你已经信任的 Git 仓库
140
160
  - 或在基础配置里打开“允许在未信任 Git 目录运行 Codex”,然后重启 Bridge
141
161
 
162
+ 当前配置页新增了几项和 Codex 运行行为直接相关的配置:
163
+
164
+ - `默认工作空间`
165
+ - 给 `/new proj1` 这类相对项目名提供父目录
166
+ - 留空时默认回退到 `~/cx2im`,并按当前系统展开为实际路径
167
+ - `Codex 文件系统权限`
168
+ - 可选 `read-only`、`workspace-write`、`danger-full-access`
169
+ - 默认 `workspace-write`
170
+ - `Codex 思考级别`
171
+ - 全局默认值,可在 IM 中用 `/reasoning` 对当前会话覆盖
172
+ - 官方仅有 5 个级别:`minimal`、`low`、`medium`、`high`、`xhigh`
173
+ - IM 中也支持数字别名:`1=minimal`、`2=low`、`3=medium`、`4=high`、`5=xhigh`
174
+
175
+ 如果你是在自己的本地开发机上长期用 `codex-to-im` 做实际编码,当前更激进的推荐配置是:
176
+
177
+ - `Codex 文件系统权限` 设为 `danger-full-access`
178
+ - `Codex 思考级别` 设为 `xhigh`
179
+
180
+ 这样更接近完整 `code` 模式下的开发体验。它适合你自己的受控项目目录,不适合直接照搬到陌生仓库或高风险环境。
181
+
182
+ 通道页还支持“命令反馈使用 Markdown”开关:
183
+ - 飞书默认开启
184
+ - 微信默认关闭
185
+ - 只影响 `/h`、`/status`、`/threads` 这类 bridge 自己生成的反馈
186
+ - 不影响 Codex 原始回复内容
187
+
142
188
  ## 更新
143
189
 
144
190
  Windows 上如果后台 UI 或 bridge 仍在运行,`npm update -g codex-to-im` 可能会因为安装目录被占用而报 `EBUSY`。
@@ -11,10 +11,15 @@ CTI_RUNTIME=codex
11
11
  CTI_ENABLED_CHANNELS=feishu
12
12
 
13
13
  # Default working directory for Codex / bridge sessions
14
- CTI_DEFAULT_WORKDIR=/path/to/your/project
15
-
16
- # Default model (optional inherits from runtime's own default if not set)
17
- # CTI_DEFAULT_MODEL=
14
+ CTI_DEFAULT_WORKDIR=/path/to/your/project
15
+
16
+ # Default workspace root for `/new proj1` style project creation.
17
+ # When unset, codex-to-im falls back to `~/cx2im`
18
+ # and expands it per OS (Windows/macOS/Linux).
19
+ # CTI_DEFAULT_WORKSPACE_ROOT=/path/to/your/workspace
20
+
21
+ # Default model (optional — inherits from runtime's own default if not set)
22
+ # CTI_DEFAULT_MODEL=
18
23
 
19
24
  # Default mode (code, plan, ask)
20
25
  CTI_DEFAULT_MODE=code
@@ -43,9 +48,22 @@ CTI_DEFAULT_MODE=code
43
48
  # Allow Codex to run when CTI_DEFAULT_WORKDIR is not inside a trusted Git repo.
44
49
  # This project defaults it to true so first-time setup works more smoothly.
45
50
  CTI_CODEX_SKIP_GIT_REPO_CHECK=true
46
-
47
- # ── Telegram ──
48
- CTI_TG_BOT_TOKEN=your-telegram-bot-token
51
+ # Default filesystem permission mode for Codex threads created by codex-to-im.
52
+ # Options: read-only | workspace-write | danger-full-access
53
+ CTI_CODEX_SANDBOX_MODE=workspace-write
54
+ # Default reasoning effort for Codex.
55
+ # Official SDK/runtime levels: minimal | low | medium | high | xhigh
56
+ # IM aliases also support: 1=minimal, 2=low, 3=medium, 4=high, 5=xhigh
57
+ CTI_CODEX_REASONING_EFFORT=medium
58
+
59
+ # ── Web 控制台访问 ──
60
+ # 默认仅允许本机访问本地工作台。开启后,局域网设备访问时需要先输入 token。
61
+ # 可以在 Web 工作台里直接勾选并自动生成 token。
62
+ # CTI_UI_ALLOW_LAN=false
63
+ # CTI_UI_ACCESS_TOKEN=your-random-access-token
64
+
65
+ # ── Telegram ──
66
+ CTI_TG_BOT_TOKEN=your-telegram-bot-token
49
67
  # Chat ID for authorization (at least one of CHAT_ID or ALLOWED_USERS is required)
50
68
  # Get it: send a message to the bot, then visit https://api.telegram.org/botYOUR_TOKEN/getUpdates
51
69
  CTI_TG_CHAT_ID=your-chat-id
@@ -70,6 +88,9 @@ CTI_TG_CHAT_ID=your-chat-id
70
88
  # Current Codex runtime note: thinking/progress can update live, but
71
89
  # assistant body text may still arrive only at completion.
72
90
  # CTI_FEISHU_STREAMING_ENABLED=true
91
+ # Use Markdown for bridge-generated command feedback such as /h or /status.
92
+ # Does not affect raw Codex replies.
93
+ # CTI_FEISHU_COMMAND_MARKDOWN_ENABLED=true
73
94
 
74
95
  # ── QQ ──
75
96
  # Required: obtain from https://q.qq.com/qqbot/openclaw
@@ -88,11 +109,14 @@ CTI_TG_CHAT_ID=your-chat-id
88
109
  # Optional protocol overrides (normally leave unset)
89
110
  # CTI_WEIXIN_BASE_URL=https://ilinkai.weixin.qq.com
90
111
  # CTI_WEIXIN_CDN_BASE_URL=https://novac2c.cdn.weixin.qq.com/c2c
91
- # Enable inbound media download/processing for image/file/video messages.
92
- # Voice messages do not use raw audio download/transcription here: the bridge
93
- # only accepts WeChat-provided speech-to-text text and otherwise returns an error.
94
- # (default false for safety in CLI setups)
95
- # CTI_WEIXIN_MEDIA_ENABLED=false
112
+ # Enable inbound media download/processing for image/file/video messages.
113
+ # Voice messages do not use raw audio download/transcription here: the bridge
114
+ # only accepts WeChat-provided speech-to-text text and otherwise returns an error.
115
+ # (default false for safety in CLI setups)
116
+ # CTI_WEIXIN_MEDIA_ENABLED=false
117
+ # Use Markdown for bridge-generated command feedback such as /h or /status.
118
+ # Does not affect raw Codex replies. Default is false for WeChat.
119
+ # CTI_WEIXIN_COMMAND_MARKDOWN_ENABLED=false
96
120
 
97
121
  # ── Permission ──
98
122
  # Auto-approve all tool permission requests without user confirmation.
package/dist/cli.mjs CHANGED
@@ -14,6 +14,7 @@ import os from "node:os";
14
14
  import path from "node:path";
15
15
  var LEGACY_CTI_HOME = path.join(os.homedir(), ".claude-to-im");
16
16
  var DEFAULT_CTI_HOME = path.join(os.homedir(), ".codex-to-im");
17
+ var DEFAULT_WORKSPACE_ROOT = path.join(os.homedir(), "cx2im");
17
18
  function resolveDefaultCtiHome() {
18
19
  if (fs.existsSync(DEFAULT_CTI_HOME)) return DEFAULT_CTI_HOME;
19
20
  if (fs.existsSync(LEGACY_CTI_HOME)) return LEGACY_CTI_HOME;
@@ -31,6 +32,7 @@ var bridgePidFile = path2.join(runtimeDir, "bridge.pid");
31
32
  var bridgeStatusFile = path2.join(runtimeDir, "status.json");
32
33
  var uiStatusFile = path2.join(runtimeDir, "ui-server.json");
33
34
  var uiPort = 4781;
35
+ var WINDOWS_HIDE = process.platform === "win32" ? { windowsHide: true } : {};
34
36
  function ensureDirs() {
35
37
  fs2.mkdirSync(runtimeDir, { recursive: true });
36
38
  fs2.mkdirSync(logsDir, { recursive: true });
@@ -125,7 +127,8 @@ async function stopBridge() {
125
127
  if (process.platform === "win32") {
126
128
  await new Promise((resolve) => {
127
129
  const killer = spawn("cmd", ["/c", "taskkill", "/PID", String(status.pid), "/T", "/F"], {
128
- stdio: "ignore"
130
+ stdio: "ignore",
131
+ ...WINDOWS_HIDE
129
132
  });
130
133
  killer.on("exit", () => resolve());
131
134
  killer.on("error", () => resolve());
@@ -161,7 +164,8 @@ async function ensureUiServerRunning() {
161
164
  ...process.env,
162
165
  CTI_HOME
163
166
  },
164
- stdio: ["ignore", stdoutFd, stderrFd]
167
+ stdio: ["ignore", stdoutFd, stderrFd],
168
+ ...WINDOWS_HIDE
165
169
  });
166
170
  child.unref();
167
171
  const status = await waitForUiServer();
@@ -180,7 +184,8 @@ async function stopUiServer() {
180
184
  if (process.platform === "win32") {
181
185
  await new Promise((resolve) => {
182
186
  const killer = spawn("cmd", ["/c", "taskkill", "/PID", String(status.pid), "/T", "/F"], {
183
- stdio: "ignore"
187
+ stdio: "ignore",
188
+ ...WINDOWS_HIDE
184
189
  });
185
190
  killer.on("exit", () => resolve());
186
191
  killer.on("error", () => resolve());
@@ -212,7 +217,7 @@ function writeUiServerStatus(status) {
212
217
  }
213
218
  function openBrowser(url) {
214
219
  if (process.platform === "win32") {
215
- const child2 = spawn("cmd", ["/c", "start", "", url], { detached: true, stdio: "ignore" });
220
+ const child2 = spawn("cmd", ["/c", "start", "", url], { detached: true, stdio: "ignore", ...WINDOWS_HIDE });
216
221
  child2.unref();
217
222
  return;
218
223
  }