@foxden-app/foxclaw 0.3.1 → 0.3.2

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
@@ -51,7 +51,6 @@ FoxClaw(狸爪)的目标很直接:让你用手机控制本机的 Codex,
51
51
  ```bash
52
52
  npm install -g @foxden-app/foxclaw
53
53
  foxclaw init
54
- $EDITOR ~/.foxclaw/.env
55
54
  foxclaw doctor
56
55
  foxclaw start
57
56
  ```
@@ -61,11 +60,12 @@ pnpm 用户:
61
60
  ```bash
62
61
  pnpm add -g @foxden-app/foxclaw
63
62
  foxclaw init
64
- $EDITOR ~/.foxclaw/.env
65
63
  foxclaw doctor
66
64
  foxclaw start
67
65
  ```
68
66
 
67
+ `foxclaw init` 会创建 `~/.foxclaw/.env`,并在终端里提示填写 Telegram bot token、Telegram 数字用户 ID 和默认工作目录。任何一项都可以直接回车跳过,之后再用 `$EDITOR ~/.foxclaw/.env` 手动修改。
68
+
69
69
  跑 `doctor` 或 `start` 之前先把 `.env` 填好。私聊模式最小配置:
70
70
 
71
71
  ```dotenv
@@ -165,26 +165,9 @@ foxclaw serve
165
165
 
166
166
  可通过 `STORE_PATH`、`LOCK_PATH`、`CODEX_APP_SERVER_STATE_PATH`、`CODEX_APP_SERVER_LOG_PATH` 覆盖。
167
167
 
168
- ## 从 telegram-codex-app-bridge 迁移
169
-
170
- FoxClaw 最初 fork 自 `Gan-Xing/telegram-codex-app-bridge`,继续以 MIT License 分发。
171
-
172
- 升级已有安装:
173
-
174
- ```bash
175
- systemctl --user disable --now telegram-codex-app-bridge.service 2>/dev/null || true
176
- test -e ~/.foxclaw || cp -a ~/.telegram-codex-app-bridge ~/.foxclaw
177
- foxclaw start
178
- ```
179
-
180
- macOS launchd 用户先卸载旧 plist:
181
-
182
- ```bash
183
- launchctl unload ~/Library/LaunchAgents/com.ganxing.telegram-codex-app-bridge.plist 2>/dev/null || true
184
- foxclaw start
185
- ```
168
+ ## 鸣谢
186
169
 
187
- 旧目录不会被自动读取。如果要保留已有的绑定、线程缓存、审批和状态数据,手动复制一次即可。
170
+ FoxClaw 最初基于 `Gan-Xing/telegram-codex-app-bridge` fork 演进而来,继续以 MIT License 分发。感谢原项目对 Telegram 与 Codex 本地桥接思路的探索。
188
171
 
189
172
  ## Telegram 设置
190
173
 
@@ -292,7 +275,7 @@ foxclaw weixin-login
292
275
 
293
276
  ## 故障排查
294
277
 
295
- `doctor` 报错、Telegram 没回复、服务日志看不懂、重启行为异常、迁移出问题——都看 [故障排查](./docs/zh/troubleshooting.md)。
278
+ `doctor` 报错、Telegram 没回复、服务日志看不懂、重启行为异常——都看 [故障排查](./docs/zh/troubleshooting.md)。
296
279
 
297
280
  ## 运维命令
298
281
 
package/README_EN.md CHANGED
@@ -51,7 +51,6 @@ The minimum install needs only a Telegram bot token, your numeric Telegram user
51
51
  ```bash
52
52
  npm install -g @foxden-app/foxclaw
53
53
  foxclaw init
54
- $EDITOR ~/.foxclaw/.env
55
54
  foxclaw doctor
56
55
  foxclaw start
57
56
  ```
@@ -61,12 +60,13 @@ pnpm users:
61
60
  ```bash
62
61
  pnpm add -g @foxden-app/foxclaw
63
62
  foxclaw init
64
- $EDITOR ~/.foxclaw/.env
65
63
  foxclaw doctor
66
64
  foxclaw start
67
65
  ```
68
66
 
69
- Edit `.env` before running `doctor` or `start`. Minimum private-chat config:
67
+ `foxclaw init` creates `~/.foxclaw/.env` and prompts for the Telegram bot token, your numeric Telegram user id, and the default workspace. Press Enter on any field to skip it and edit later with `$EDITOR ~/.foxclaw/.env`.
68
+
69
+ Fill `.env` before running `doctor` or `start`. Minimum private-chat config:
70
70
 
71
71
  ```dotenv
72
72
  TG_BOT_TOKEN=123456:telegram-token
@@ -165,26 +165,9 @@ Default runtime files are stored under `~/.foxclaw`:
165
165
 
166
166
  Override with `STORE_PATH`, `LOCK_PATH`, `CODEX_APP_SERVER_STATE_PATH`, and `CODEX_APP_SERVER_LOG_PATH`.
167
167
 
168
- ## Migrating From telegram-codex-app-bridge
169
-
170
- FoxClaw was originally forked from `Gan-Xing/telegram-codex-app-bridge` and remains distributed under the MIT License.
171
-
172
- When upgrading an existing local install:
173
-
174
- ```bash
175
- systemctl --user disable --now telegram-codex-app-bridge.service 2>/dev/null || true
176
- test -e ~/.foxclaw || cp -a ~/.telegram-codex-app-bridge ~/.foxclaw
177
- foxclaw start
178
- ```
179
-
180
- For launchd installs, unload the old plist if present:
181
-
182
- ```bash
183
- launchctl unload ~/Library/LaunchAgents/com.ganxing.telegram-codex-app-bridge.plist 2>/dev/null || true
184
- foxclaw start
185
- ```
168
+ ## Acknowledgements
186
169
 
187
- The old runtime directory is not read automatically. Copy it once if you want to keep existing bindings, cached thread lists, approvals, and status data.
170
+ FoxClaw originally evolved from a fork of `Gan-Xing/telegram-codex-app-bridge` and remains distributed under the MIT License. Thanks to that project for exploring the Telegram-to-local-Codex bridge pattern.
188
171
 
189
172
  ## Telegram Setup
190
173
 
@@ -292,7 +275,7 @@ This repo ships a Codex skill at [`skills/foxclaw`](./skills/foxclaw). Use it wh
292
275
 
293
276
  ## Troubleshooting
294
277
 
295
- See [Troubleshooting](./docs/troubleshooting.md) for `doctor` failures, Telegram no-reply cases, service logs, reboot behavior, and migration issues.
278
+ See [Troubleshooting](./docs/troubleshooting.md) for `doctor` failures, Telegram no-reply cases, service logs, and reboot behavior.
296
279
 
297
280
  ## Operations
298
281
 
package/dist/main.js CHANGED
@@ -2,6 +2,7 @@
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import process from 'node:process';
5
+ import { createInterface } from 'node:readline/promises';
5
6
  import { spawnSync } from 'node:child_process';
6
7
  import { fileURLToPath } from 'node:url';
7
8
  import { APP_HOME, DEFAULT_ENV_PATH, DEFAULT_LOG_PATH, DEFAULT_STATUS_PATH, loadConfig, loadEnv, } from './config.js';
@@ -13,7 +14,7 @@ const packageRoot = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
13
14
  const entryPoint = fileURLToPath(import.meta.url);
14
15
  async function main() {
15
16
  if (command === 'init') {
16
- initConfig();
17
+ await initConfig();
17
18
  return;
18
19
  }
19
20
  if (command === 'install-systemd') {
@@ -143,17 +144,177 @@ async function runServeCli() {
143
144
  throw error;
144
145
  }
145
146
  }
146
- function initConfig() {
147
+ async function initConfig() {
147
148
  const envPath = process.env.FOXCLAW_ENV?.trim() || DEFAULT_ENV_PATH;
148
149
  fs.mkdirSync(path.dirname(envPath), { recursive: true });
149
- if (fs.existsSync(envPath)) {
150
+ const existed = fs.existsSync(envPath);
151
+ if (existed) {
150
152
  console.log(`Config already exists: ${envPath}`);
153
+ }
154
+ else {
155
+ const examplePath = path.join(packageRoot, '.env.example');
156
+ fs.copyFileSync(examplePath, envPath);
157
+ console.log(`Created ${envPath}`);
158
+ }
159
+ if (!canPromptForInit()) {
160
+ console.log(`Edit it manually, then run: foxclaw doctor`);
151
161
  return;
152
162
  }
153
- const examplePath = path.join(packageRoot, '.env.example');
154
- fs.copyFileSync(examplePath, envPath);
155
- console.log(`Created ${envPath}`);
156
- console.log('Edit it, then run: foxclaw doctor');
163
+ await configureEnvInteractively(envPath, existed);
164
+ }
165
+ function canPromptForInit() {
166
+ return Boolean(process.stdin.isTTY && process.stdout.isTTY && !process.argv.includes('--no-input') && !process.argv.includes('--skip-prompts'));
167
+ }
168
+ async function configureEnvInteractively(envPath, existed) {
169
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
170
+ try {
171
+ if (existed) {
172
+ const updateExisting = (await rl.question('Update Telegram/workspace setup fields now? [y/N]: ')).trim().toLowerCase();
173
+ if (updateExisting !== 'y' && updateExisting !== 'yes') {
174
+ console.log(`Edit it manually, then run: foxclaw doctor`);
175
+ return;
176
+ }
177
+ }
178
+ else {
179
+ console.log('Interactive setup. Press Enter to skip any field and edit it later.');
180
+ }
181
+ const updates = {};
182
+ const skipped = [];
183
+ const warnings = [];
184
+ const token = sanitizeEnvInput(await rl.question('Telegram bot token (TG_BOT_TOKEN): '));
185
+ if (token) {
186
+ updates.TG_BOT_TOKEN = token;
187
+ if (!/^\d+:[A-Za-z0-9_-]+$/.test(token)) {
188
+ warnings.push('TG_BOT_TOKEN does not look like a standard Telegram bot token.');
189
+ }
190
+ }
191
+ else {
192
+ skipped.push('TG_BOT_TOKEN');
193
+ }
194
+ const userId = sanitizeEnvInput(await rl.question('Telegram numeric user ID (TG_ALLOWED_USER_ID): '));
195
+ if (userId) {
196
+ if (/^\d+$/.test(userId)) {
197
+ updates.TG_ALLOWED_USER_ID = userId;
198
+ }
199
+ else {
200
+ skipped.push('TG_ALLOWED_USER_ID');
201
+ warnings.push('TG_ALLOWED_USER_ID must be numeric; use the Id from @userinfobot, not @username.');
202
+ }
203
+ }
204
+ else {
205
+ skipped.push('TG_ALLOWED_USER_ID');
206
+ }
207
+ const cwdDefault = defaultInitCwd();
208
+ const cwdPrompt = cwdDefault
209
+ ? `Default Codex workspace (DEFAULT_CWD) [${cwdDefault}]: `
210
+ : 'Default Codex workspace (DEFAULT_CWD): ';
211
+ const cwdAnswer = sanitizeEnvInput(await rl.question(cwdPrompt));
212
+ const cwd = cwdAnswer ? normalizeUserPath(cwdAnswer) : cwdDefault;
213
+ if (cwd) {
214
+ updates.DEFAULT_CWD = cwd;
215
+ warnings.push(...validateDefaultCwd(cwd));
216
+ }
217
+ else {
218
+ skipped.push('DEFAULT_CWD');
219
+ }
220
+ const codexBin = resolveCommand('codex');
221
+ if (codexBin) {
222
+ updates.CODEX_CLI_BIN = codexBin;
223
+ }
224
+ const updatedKeys = Object.keys(updates);
225
+ if (updatedKeys.length > 0) {
226
+ writeEnvUpdates(envPath, updates);
227
+ console.log(`Saved ${updatedKeys.join(', ')} to ${envPath}`);
228
+ }
229
+ else {
230
+ console.log('No setup fields changed.');
231
+ }
232
+ for (const warning of warnings) {
233
+ console.log(`[WARN] ${warning}`);
234
+ }
235
+ if (skipped.length > 0) {
236
+ console.log(`Skipped ${skipped.join(', ')}. Edit later: ${editorCommand(envPath)}`);
237
+ }
238
+ console.log('Next: foxclaw doctor');
239
+ }
240
+ finally {
241
+ rl.close();
242
+ }
243
+ }
244
+ function sanitizeEnvInput(value) {
245
+ return value.replace(/[\r\n]/g, '').trim();
246
+ }
247
+ function defaultInitCwd() {
248
+ const cwd = path.resolve(process.cwd());
249
+ if (isUnsafeDefaultCwd(cwd))
250
+ return null;
251
+ try {
252
+ if (fs.statSync(cwd).isDirectory())
253
+ return cwd;
254
+ }
255
+ catch {
256
+ return null;
257
+ }
258
+ return null;
259
+ }
260
+ function normalizeUserPath(value) {
261
+ const expanded = value === '~' || value.startsWith('~/')
262
+ ? path.join(process.env.HOME || '', value.slice(2))
263
+ : value;
264
+ return path.resolve(expanded);
265
+ }
266
+ function validateDefaultCwd(cwd) {
267
+ const warnings = [];
268
+ if (!path.isAbsolute(cwd)) {
269
+ warnings.push('DEFAULT_CWD should be an absolute path.');
270
+ }
271
+ if (isUnsafeDefaultCwd(cwd)) {
272
+ warnings.push('DEFAULT_CWD points at a very broad directory; use a project/workspace folder for the first install.');
273
+ }
274
+ try {
275
+ if (!fs.statSync(cwd).isDirectory()) {
276
+ warnings.push('DEFAULT_CWD exists but is not a directory.');
277
+ }
278
+ }
279
+ catch {
280
+ warnings.push('DEFAULT_CWD does not exist yet; create it or edit the path before starting.');
281
+ }
282
+ return warnings;
283
+ }
284
+ function isUnsafeDefaultCwd(cwd) {
285
+ const resolved = path.resolve(cwd);
286
+ const home = process.env.HOME ? path.resolve(process.env.HOME) : '';
287
+ return resolved === path.parse(resolved).root || resolved === home || resolved === '/home' || resolved === '/Users';
288
+ }
289
+ function writeEnvUpdates(envPath, updates) {
290
+ let text = fs.readFileSync(envPath, 'utf8');
291
+ const newline = text.includes('\r\n') ? '\r\n' : '\n';
292
+ for (const [key, value] of Object.entries(updates)) {
293
+ const line = `${key}=${formatEnvValue(value)}`;
294
+ const pattern = new RegExp(`^${escapeRegExp(key)}=.*$`, 'm');
295
+ if (pattern.test(text)) {
296
+ text = text.replace(pattern, line);
297
+ }
298
+ else {
299
+ if (text && !text.endsWith('\n') && !text.endsWith('\r\n')) {
300
+ text += newline;
301
+ }
302
+ text += `${line}${newline}`;
303
+ }
304
+ }
305
+ fs.writeFileSync(envPath, text);
306
+ }
307
+ function formatEnvValue(value) {
308
+ const cleaned = value.replace(/[\r\n]/g, '').trim();
309
+ if (!/[\s#"\\]/.test(cleaned))
310
+ return cleaned;
311
+ return `"${cleaned.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
312
+ }
313
+ function escapeRegExp(value) {
314
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
315
+ }
316
+ function editorCommand(envPath) {
317
+ return `${process.env.EDITOR?.trim() || '$EDITOR'} ${envPath}`;
157
318
  }
158
319
  function startService(action) {
159
320
  if (!runDoctorChecks()) {
@@ -463,13 +624,18 @@ void main().catch((error) => {
463
624
  process.exit(1);
464
625
  });
465
626
  function hasCommand(commandName) {
627
+ return Boolean(resolveCommand(commandName));
628
+ }
629
+ function resolveCommand(commandName) {
466
630
  try {
467
631
  const which = process.platform === 'win32' ? 'where' : 'which';
468
- const result = spawnSync(which, [commandName], { stdio: 'ignore' });
469
- return result.status === 0;
632
+ const result = spawnSync(which, [commandName], { encoding: 'utf8' });
633
+ if (result.status !== 0)
634
+ return null;
635
+ return result.stdout.split(/\r?\n/).map(line => line.trim()).find(Boolean) ?? null;
470
636
  }
471
637
  catch {
472
- return false;
638
+ return null;
473
639
  }
474
640
  }
475
641
  function hasConfiguredCodexBin(binPath) {
@@ -38,7 +38,7 @@ TG_ALLOWED_USER_ID=<paste numeric Telegram user id here>
38
38
  DEFAULT_CWD=<paste absolute working directory here>
39
39
 
40
40
  Tasks:
41
- 1. Inspect the machine first. If a FoxClaw or old telegram-codex-app-bridge service already exists, report it before changing services.
41
+ 1. Inspect the machine first. If a FoxClaw service already exists, report it before changing services.
42
42
  2. Ensure Node.js 24+ is available. If not, install or activate Node 24 with nvm.
43
43
  3. Ensure the Codex CLI exists and is logged in. If login is required, stop and tell me exactly what I need to do.
44
44
  4. Install or update FoxClaw with npm install -g @foxden-app/foxclaw@latest.
@@ -48,33 +48,10 @@ Tasks:
48
48
  8. Ask me to send /help and /status to the Telegram bot.
49
49
  9. Verify the final state:
50
50
  - foxclaw.service is active/enabled on Linux
51
- - old telegram-codex-app-bridge.service is inactive/disabled if present
52
51
  - foxclaw status works
53
52
  10. Report the commands used, the final status, and the log command I should use if something stops working. Redact TG_BOT_TOKEN and never print the full token or full .env content.
54
53
  ```
55
54
 
56
- ## Migration Prompt For Old Installs
57
-
58
- Use this when the target computer is still running `telegram-codex-app-bridge`:
59
-
60
- ```text
61
- Migrate this machine from telegram-codex-app-bridge to FoxClaw.
62
-
63
- New package:
64
- @foxden-app/foxclaw
65
-
66
- Please:
67
- 1. Inspect the current install method, service file, and runtime directory before changing anything.
68
- 2. Stop and disable telegram-codex-app-bridge.service if it exists.
69
- 3. If ~/.foxclaw does not exist and ~/.telegram-codex-app-bridge exists, copy ~/.telegram-codex-app-bridge to ~/.foxclaw.
70
- 4. Install or update FoxClaw with npm install -g @foxden-app/foxclaw@latest.
71
- 5. Run foxclaw init if ~/.foxclaw/.env does not exist, then verify ~/.foxclaw/.env.
72
- 6. Run foxclaw doctor.
73
- 7. Install or restart the FoxClaw service with foxclaw start.
74
- 8. Verify foxclaw.service is active and telegram-codex-app-bridge.service is inactive/disabled.
75
- 9. Report final status and any blockers. Redact TG_BOT_TOKEN and never print the full token or full .env content.
76
- ```
77
-
78
55
  ## Safety Notes
79
56
 
80
57
  - Do not paste bot tokens into public issue trackers or public chat logs.
@@ -123,7 +123,7 @@ npm install -g @foxden-app/foxclaw
123
123
  foxclaw init
124
124
  ```
125
125
 
126
- This creates the config file at `~/.foxclaw/.env`.
126
+ This creates the config file at `~/.foxclaw/.env` and prompts for the Telegram bot token, your numeric Telegram user id, and the default workspace.
127
127
 
128
128
  If you prefer pnpm:
129
129
 
@@ -134,7 +134,7 @@ foxclaw init
134
134
 
135
135
  ## 7. Fill In `.env`
136
136
 
137
- Open `.env` in a simple editor:
137
+ If you filled the token, user id, and workspace during `foxclaw init`, go straight to the first check. If you skipped a field or want to change anything, open `.env` in a simple editor:
138
138
 
139
139
  ```bash
140
140
  nano ~/.foxclaw/.env
@@ -129,20 +129,14 @@ If FoxClaw is still running, it may consume the update before you inspect it.
129
129
 
130
130
  If Telegram reports conflicts or the same bot behaves strangely, two processes may be polling the same bot token.
131
131
 
132
- Check old and new services:
132
+ Check the service and any extra foreground processes:
133
133
 
134
134
  ```bash
135
135
  systemctl --user is-active foxclaw.service
136
- systemctl --user is-active telegram-codex-app-bridge.service 2>/dev/null || true
136
+ pgrep -af foxclaw
137
137
  ```
138
138
 
139
- Stop the old service:
140
-
141
- ```bash
142
- systemctl --user disable --now telegram-codex-app-bridge.service
143
- ```
144
-
145
- Then restart FoxClaw:
139
+ Stop the extra process or service, then restart FoxClaw:
146
140
 
147
141
  ```bash
148
142
  foxclaw restart
@@ -219,18 +213,3 @@ macOS launchd starts FoxClaw when you log in after running:
219
213
  ```bash
220
214
  foxclaw start
221
215
  ```
222
-
223
- ## Migrating From The Old Project Name
224
-
225
- If this machine still runs `telegram-codex-app-bridge`, migrate once:
226
-
227
- ```bash
228
- systemctl --user disable --now telegram-codex-app-bridge.service 2>/dev/null || true
229
- test -e ~/.foxclaw || cp -a ~/.telegram-codex-app-bridge ~/.foxclaw
230
- npm install -g @foxden-app/foxclaw@latest
231
- foxclaw init
232
- foxclaw doctor
233
- foxclaw start
234
- ```
235
-
236
- If `~/.foxclaw/.env` already exists, `foxclaw init` leaves it untouched.
@@ -100,7 +100,7 @@ Both install the same published npm package. Use one global package manager cons
100
100
 
101
101
  ### 1.6 Fill In The Config
102
102
 
103
- The default config file is `~/.foxclaw/.env`:
103
+ `foxclaw init` creates the default config file at `~/.foxclaw/.env` and prompts for the Telegram bot token, your numeric Telegram user id, and the default workspace. Press Enter on any field to skip it, then edit manually if needed:
104
104
 
105
105
  ```bash
106
106
  $EDITOR ~/.foxclaw/.env
@@ -37,7 +37,7 @@ TG_ALLOWED_USER_ID=<把 Telegram 数字用户 ID 粘贴在这里>
37
37
  DEFAULT_CWD=<把绝对工作目录粘贴在这里>
38
38
 
39
39
  任务:
40
- 1. 先检查机器环境。如果已经存在 FoxClaw 或旧的 telegram-codex-app-bridge 服务,先报告再改服务。
40
+ 1. 先检查机器环境。如果已经存在 FoxClaw 服务,先报告再改服务。
41
41
  2. 确保 Node.js 24+ 可用;如果没有,请用 nvm 安装或切到 Node 24。
42
42
  3. 确保 Codex CLI 存在并且已经登录。如果需要登录,停下来告诉我具体要执行什么。
43
43
  4. 用 npm install -g @foxden-app/foxclaw@latest 安装或升级 FoxClaw。
@@ -47,33 +47,10 @@ DEFAULT_CWD=<把绝对工作目录粘贴在这里>
47
47
  8. 让我在 Telegram bot 里发送 /help 和 /status。
48
48
  9. 验证最终状态:
49
49
  - Linux 上 foxclaw.service 处于 active/enabled
50
- - 如果存在旧 telegram-codex-app-bridge.service,它应当 inactive/disabled
51
50
  - foxclaw status 可以正常输出
52
51
  10. 汇报执行过的命令、最终状态和后续看日志的命令。请隐藏 TG_BOT_TOKEN,不要打印完整 token 或完整 .env。
53
52
  ```
54
53
 
55
- ## 旧项目迁移提示词
56
-
57
- 如果目标机器还在跑 `telegram-codex-app-bridge`,用这段:
58
-
59
- ```text
60
- 请把这台机器从 telegram-codex-app-bridge 迁移到 FoxClaw。
61
-
62
- 新发布包:
63
- @foxden-app/foxclaw
64
-
65
- 请执行:
66
- 1. 修改前先检查现有安装方式、服务文件和运行目录。
67
- 2. 如果存在 telegram-codex-app-bridge.service,停止并禁用它。
68
- 3. 如果 ~/.foxclaw 不存在而 ~/.telegram-codex-app-bridge 存在,把旧目录复制到 ~/.foxclaw。
69
- 4. 用 npm install -g @foxden-app/foxclaw@latest 安装或升级 FoxClaw。
70
- 5. 如果 ~/.foxclaw/.env 不存在,运行 foxclaw init;然后检查配置是否完整。
71
- 6. 运行 foxclaw doctor。
72
- 7. 用 foxclaw start 安装或重启 FoxClaw 服务。
73
- 8. 验证 foxclaw.service 正常运行,旧 telegram-codex-app-bridge.service 已停止或禁用。
74
- 9. 汇报最终状态和阻塞点。请隐藏 TG_BOT_TOKEN,不要打印完整 token 或完整 .env。
75
- ```
76
-
77
54
  ## 安全注意事项
78
55
 
79
56
  - 不要把 bot token 粘贴到公开 issue、公开聊天或代码仓库。
@@ -121,7 +121,7 @@ npm install -g @foxden-app/foxclaw
121
121
  foxclaw init
122
122
  ```
123
123
 
124
- 这会创建默认配置文件 `~/.foxclaw/.env`。
124
+ 这会创建默认配置文件 `~/.foxclaw/.env`,并提示你填写 Telegram bot token、Telegram 数字用户 ID 和默认工作目录。
125
125
 
126
126
  如果你用 pnpm:
127
127
 
@@ -132,7 +132,7 @@ foxclaw init
132
132
 
133
133
  ## 7. 填写 `.env`
134
134
 
135
- 用简单编辑器打开配置:
135
+ 如果刚才在 `foxclaw init` 里已经填好了 token、用户 ID 和工作目录,可以直接进入下一步检查。如果你选择了跳过,或者想改配置,用简单编辑器打开:
136
136
 
137
137
  ```bash
138
138
  nano ~/.foxclaw/.env
@@ -279,20 +279,11 @@ npm install -g @foxden-app/foxclaw@latest
279
279
  foxclaw start
280
280
  ```
281
281
 
282
- ## 从旧项目名迁移
282
+ 如果 `~/.foxclaw/.env` 已经存在,`foxclaw init` 会先询问是否更新 Telegram 和工作目录相关字段,其它配置保持不变。
283
283
 
284
- 如果这台机器仍在运行 `telegram-codex-app-bridge`,迁移一次即可:
284
+ ## 鸣谢
285
285
 
286
- ```bash
287
- systemctl --user disable --now telegram-codex-app-bridge.service 2>/dev/null || true
288
- test -e ~/.foxclaw || cp -a ~/.telegram-codex-app-bridge ~/.foxclaw
289
- npm install -g @foxden-app/foxclaw@latest
290
- foxclaw init
291
- foxclaw doctor
292
- foxclaw start
293
- ```
294
-
295
- 如果 `~/.foxclaw/.env` 已经存在,`foxclaw init` 不会覆盖它。
286
+ FoxClaw 最初基于 `Gan-Xing/telegram-codex-app-bridge` fork 演进而来。感谢原项目对 Telegram 与 Codex 本地桥接思路的探索。
296
287
 
297
288
  ## 下一步
298
289
 
@@ -130,20 +130,14 @@ CODEX_CLI_BIN=/absolute/path/to/codex
130
130
 
131
131
  如果 Telegram 报 conflict,或者同一个 bot 行为异常,通常是两个进程在轮询同一个 bot token。
132
132
 
133
- 检查新旧服务:
133
+ 检查服务和额外的前台进程:
134
134
 
135
135
  ```bash
136
136
  systemctl --user is-active foxclaw.service
137
- systemctl --user is-active telegram-codex-app-bridge.service 2>/dev/null || true
137
+ pgrep -af foxclaw
138
138
  ```
139
139
 
140
- 停掉旧服务:
141
-
142
- ```bash
143
- systemctl --user disable --now telegram-codex-app-bridge.service
144
- ```
145
-
146
- 然后重启 FoxClaw:
140
+ 停掉多余进程或服务后,重启 FoxClaw:
147
141
 
148
142
  ```bash
149
143
  foxclaw restart
@@ -100,7 +100,7 @@ foxclaw init
100
100
 
101
101
  ### 1.6 填写配置
102
102
 
103
- 默认配置文件是 `~/.foxclaw/.env`:
103
+ `foxclaw init` 会创建默认配置文件 `~/.foxclaw/.env`,并提示填写 Telegram bot token、Telegram 数字用户 ID 和默认工作目录。任何一项都可以直接回车跳过,之后再手动编辑:
104
104
 
105
105
  ```bash
106
106
  $EDITOR ~/.foxclaw/.env
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foxden-app/foxclaw",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Foxden local execution claw for controlling Codex from trusted chat interfaces.",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",