@foxden-app/foxclaw 0.2.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.
Files changed (126) hide show
  1. package/.env.example +36 -0
  2. package/LICENSE +22 -0
  3. package/README.md +244 -0
  4. package/README_EN.md +244 -0
  5. package/dist/channels/bridge_messaging_router.d.ts +27 -0
  6. package/dist/channels/bridge_messaging_router.js +85 -0
  7. package/dist/channels/telegram/telegram_channel_adapter.d.ts +12 -0
  8. package/dist/channels/telegram/telegram_channel_adapter.js +21 -0
  9. package/dist/channels/telegram/telegram_messaging_port.d.ts +25 -0
  10. package/dist/channels/telegram/telegram_messaging_port.js +51 -0
  11. package/dist/channels/weixin/account_store.d.ts +15 -0
  12. package/dist/channels/weixin/account_store.js +54 -0
  13. package/dist/channels/weixin/ilink/aes_ecb.d.ts +3 -0
  14. package/dist/channels/weixin/ilink/aes_ecb.js +12 -0
  15. package/dist/channels/weixin/ilink/api.d.ts +44 -0
  16. package/dist/channels/weixin/ilink/api.js +187 -0
  17. package/dist/channels/weixin/ilink/cdn_upload.d.ts +11 -0
  18. package/dist/channels/weixin/ilink/cdn_upload.js +60 -0
  19. package/dist/channels/weixin/ilink/cdn_url.d.ts +7 -0
  20. package/dist/channels/weixin/ilink/cdn_url.js +7 -0
  21. package/dist/channels/weixin/ilink/constants.d.ts +7 -0
  22. package/dist/channels/weixin/ilink/constants.js +27 -0
  23. package/dist/channels/weixin/ilink/context.d.ts +13 -0
  24. package/dist/channels/weixin/ilink/context.js +13 -0
  25. package/dist/channels/weixin/ilink/login_qr.d.ts +34 -0
  26. package/dist/channels/weixin/ilink/login_qr.js +233 -0
  27. package/dist/channels/weixin/ilink/media_image.d.ts +11 -0
  28. package/dist/channels/weixin/ilink/media_image.js +44 -0
  29. package/dist/channels/weixin/ilink/mime.d.ts +3 -0
  30. package/dist/channels/weixin/ilink/mime.js +36 -0
  31. package/dist/channels/weixin/ilink/pic_decrypt.d.ts +2 -0
  32. package/dist/channels/weixin/ilink/pic_decrypt.js +56 -0
  33. package/dist/channels/weixin/ilink/random.d.ts +2 -0
  34. package/dist/channels/weixin/ilink/random.js +7 -0
  35. package/dist/channels/weixin/ilink/redact.d.ts +4 -0
  36. package/dist/channels/weixin/ilink/redact.js +34 -0
  37. package/dist/channels/weixin/ilink/runtime_attach.d.ts +3 -0
  38. package/dist/channels/weixin/ilink/runtime_attach.js +13 -0
  39. package/dist/channels/weixin/ilink/send.d.ts +21 -0
  40. package/dist/channels/weixin/ilink/send.js +108 -0
  41. package/dist/channels/weixin/ilink/session_guard.d.ts +6 -0
  42. package/dist/channels/weixin/ilink/session_guard.js +39 -0
  43. package/dist/channels/weixin/ilink/types.d.ts +155 -0
  44. package/dist/channels/weixin/ilink/types.js +10 -0
  45. package/dist/channels/weixin/ilink/upload.d.ts +15 -0
  46. package/dist/channels/weixin/ilink/upload.js +75 -0
  47. package/dist/channels/weixin/sync_buf_store.d.ts +3 -0
  48. package/dist/channels/weixin/sync_buf_store.js +19 -0
  49. package/dist/channels/weixin/weixin_channel_adapter.d.ts +18 -0
  50. package/dist/channels/weixin/weixin_channel_adapter.js +273 -0
  51. package/dist/channels/weixin/weixin_messaging_port.d.ts +29 -0
  52. package/dist/channels/weixin/weixin_messaging_port.js +113 -0
  53. package/dist/codex_app/client.d.ts +176 -0
  54. package/dist/codex_app/client.js +1230 -0
  55. package/dist/codex_app/deeplink.d.ts +7 -0
  56. package/dist/codex_app/deeplink.js +29 -0
  57. package/dist/codex_app/local_usage.d.ts +16 -0
  58. package/dist/codex_app/local_usage.js +123 -0
  59. package/dist/config.d.ts +44 -0
  60. package/dist/config.js +131 -0
  61. package/dist/controller/access.d.ts +11 -0
  62. package/dist/controller/access.js +33 -0
  63. package/dist/controller/activity.d.ts +62 -0
  64. package/dist/controller/activity.js +330 -0
  65. package/dist/controller/commands.d.ts +6 -0
  66. package/dist/controller/commands.js +17 -0
  67. package/dist/controller/controller.d.ts +326 -0
  68. package/dist/controller/controller.js +7503 -0
  69. package/dist/controller/observer.d.ts +16 -0
  70. package/dist/controller/observer.js +98 -0
  71. package/dist/controller/presentation.d.ts +80 -0
  72. package/dist/controller/presentation.js +568 -0
  73. package/dist/controller/service_tier.d.ts +9 -0
  74. package/dist/controller/service_tier.js +32 -0
  75. package/dist/controller/session_observer.d.ts +22 -0
  76. package/dist/controller/session_observer.js +259 -0
  77. package/dist/controller/status.d.ts +10 -0
  78. package/dist/controller/status.js +28 -0
  79. package/dist/core/bridge_scope.d.ts +18 -0
  80. package/dist/core/bridge_scope.js +46 -0
  81. package/dist/core/channel_port.d.ts +15 -0
  82. package/dist/core/channel_port.js +1 -0
  83. package/dist/i18n.d.ts +1108 -0
  84. package/dist/i18n.js +1154 -0
  85. package/dist/lock.d.ts +7 -0
  86. package/dist/lock.js +80 -0
  87. package/dist/logger.d.ts +12 -0
  88. package/dist/logger.js +57 -0
  89. package/dist/main.d.ts +2 -0
  90. package/dist/main.js +236 -0
  91. package/dist/runtime.d.ts +3 -0
  92. package/dist/runtime.js +14 -0
  93. package/dist/store/database.d.ts +79 -0
  94. package/dist/store/database.js +489 -0
  95. package/dist/store/migrate_bridge_scope.d.ts +6 -0
  96. package/dist/store/migrate_bridge_scope.js +59 -0
  97. package/dist/telegram/addressing.d.ts +33 -0
  98. package/dist/telegram/addressing.js +57 -0
  99. package/dist/telegram/api.d.ts +14 -0
  100. package/dist/telegram/api.js +89 -0
  101. package/dist/telegram/gateway.d.ts +76 -0
  102. package/dist/telegram/gateway.js +383 -0
  103. package/dist/telegram/media.d.ts +34 -0
  104. package/dist/telegram/media.js +180 -0
  105. package/dist/telegram/rendering.d.ts +10 -0
  106. package/dist/telegram/rendering.js +21 -0
  107. package/dist/telegram/scope.d.ts +6 -0
  108. package/dist/telegram/scope.js +24 -0
  109. package/dist/telegram/text.d.ts +7 -0
  110. package/dist/telegram/text.js +47 -0
  111. package/dist/types.d.ts +343 -0
  112. package/dist/types.js +1 -0
  113. package/docs/agent-assisted-install.md +84 -0
  114. package/docs/install-for-beginners.md +287 -0
  115. package/docs/troubleshooting.md +239 -0
  116. package/package.json +62 -0
  117. package/scripts/doctor.sh +3 -0
  118. package/scripts/launchd/install.sh +54 -0
  119. package/scripts/status.sh +3 -0
  120. package/scripts/systemd/install.sh +83 -0
  121. package/scripts/systemd/uninstall.sh +15 -0
  122. package/skills/foxclaw/SKILL.md +167 -0
  123. package/skills/foxclaw/agents/openai.yaml +4 -0
  124. package/skills/foxclaw/references/telegram-setup.md +93 -0
  125. package/skills/foxclaw/scripts/bootstrap_host.py +350 -0
  126. package/skills/foxclaw/scripts/bootstrap_remote.py +67 -0
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
4
+ PLIST="$HOME/Library/LaunchAgents/app.foxden.foxclaw.plist"
5
+ NODE_BIN="$(command -v node)"
6
+ PATH_VALUE="$PATH"
7
+ HOME_VALUE="$HOME"
8
+ USER_VALUE="${USER:-}"
9
+ LOGNAME_VALUE="${LOGNAME:-$USER_VALUE}"
10
+ if [[ -z "$NODE_BIN" ]]; then
11
+ echo "node not found in PATH" >&2
12
+ exit 1
13
+ fi
14
+ mkdir -p "$HOME/Library/LaunchAgents" "$HOME/.foxclaw/logs"
15
+ cat > "$PLIST" <<PLIST
16
+ <?xml version="1.0" encoding="UTF-8"?>
17
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
18
+ <plist version="1.0">
19
+ <dict>
20
+ <key>Label</key>
21
+ <string>app.foxden.foxclaw</string>
22
+ <key>ProgramArguments</key>
23
+ <array>
24
+ <string>$NODE_BIN</string>
25
+ <string>$ROOT_DIR/dist/main.js</string>
26
+ <string>serve</string>
27
+ </array>
28
+ <key>WorkingDirectory</key>
29
+ <string>$ROOT_DIR</string>
30
+ <key>EnvironmentVariables</key>
31
+ <dict>
32
+ <key>PATH</key>
33
+ <string>$PATH_VALUE</string>
34
+ <key>HOME</key>
35
+ <string>$HOME_VALUE</string>
36
+ <key>USER</key>
37
+ <string>$USER_VALUE</string>
38
+ <key>LOGNAME</key>
39
+ <string>$LOGNAME_VALUE</string>
40
+ </dict>
41
+ <key>RunAtLoad</key>
42
+ <true/>
43
+ <key>KeepAlive</key>
44
+ <true/>
45
+ <key>StandardOutPath</key>
46
+ <string>$HOME/.foxclaw/logs/launchd.out.log</string>
47
+ <key>StandardErrorPath</key>
48
+ <string>$HOME/.foxclaw/logs/launchd.err.log</string>
49
+ </dict>
50
+ </plist>
51
+ PLIST
52
+ launchctl unload "$PLIST" >/dev/null 2>&1 || true
53
+ launchctl load "$PLIST"
54
+ echo "Installed $PLIST"
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ node dist/main.js status
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
4
+ UNIT_NAME="foxclaw.service"
5
+ USER_SYSTEMD_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user"
6
+ UNIT_PATH="$USER_SYSTEMD_DIR/$UNIT_NAME"
7
+ NODE_BIN="$(command -v node)"
8
+ # Do not embed full interactive $PATH: WSL often includes /mnt/c/Program Files/... which breaks
9
+ # systemd's unquoted Environment=PATH=... (spaces split the assignment). Use a small Linux PATH.
10
+ NODE_DIR="$(dirname "$NODE_BIN")"
11
+ PATH_VALUE="${NODE_DIR}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
12
+ if [[ -d "${HOME}/.local/bin" ]]; then
13
+ PATH_VALUE="${HOME}/.local/bin:${PATH_VALUE}"
14
+ fi
15
+ HOME_VALUE="${HOME:?}"
16
+ USER_VALUE="${USER:-}"
17
+ LOGNAME_VALUE="${LOGNAME:-$USER_VALUE}"
18
+
19
+ if [[ -z "$NODE_BIN" ]]; then
20
+ echo "node not found in PATH" >&2
21
+ exit 1
22
+ fi
23
+
24
+ if ! command -v systemctl >/dev/null 2>&1; then
25
+ echo "systemctl not found (need systemd)" >&2
26
+ exit 1
27
+ fi
28
+
29
+ NO_BUILD=0
30
+ NO_START=0
31
+ for arg in "$@"; do
32
+ case "$arg" in
33
+ --no-build) NO_BUILD=1 ;;
34
+ --no-start) NO_START=1 ;;
35
+ esac
36
+ done
37
+
38
+ if [[ "$NO_BUILD" -eq 0 ]]; then
39
+ (cd "$ROOT_DIR" && npm run build)
40
+ fi
41
+
42
+ mkdir -p "$USER_SYSTEMD_DIR" "$HOME/.foxclaw/logs"
43
+
44
+ cat >"$UNIT_PATH" <<UNIT
45
+ [Unit]
46
+ Description=FoxClaw local Codex execution bridge
47
+ Documentation=https://github.com/foxden-app/foxclaw
48
+ After=network-online.target
49
+ Wants=network-online.target
50
+ StartLimitIntervalSec=300
51
+ StartLimitBurst=5
52
+
53
+ [Service]
54
+ Type=simple
55
+ WorkingDirectory=$ROOT_DIR
56
+ Environment=HOME=$HOME_VALUE
57
+ Environment=USER=$USER_VALUE
58
+ Environment=LOGNAME=$LOGNAME_VALUE
59
+ Environment=PATH=$PATH_VALUE
60
+ ExecStart=$NODE_BIN dist/main.js serve
61
+ Restart=always
62
+ RestartSec=10
63
+ TimeoutStopSec=45
64
+ KillMode=process
65
+
66
+ [Install]
67
+ WantedBy=default.target
68
+ UNIT
69
+
70
+ systemctl --user daemon-reload
71
+ systemctl --user enable "$UNIT_NAME"
72
+ if [[ "$NO_START" -eq 0 ]]; then
73
+ systemctl --user restart "$UNIT_NAME" || systemctl --user start "$UNIT_NAME"
74
+ fi
75
+
76
+ echo "Installed $UNIT_PATH"
77
+ echo "Status: systemctl --user status $UNIT_NAME"
78
+ echo "Logs: journalctl --user -u $UNIT_NAME -f"
79
+ if [[ "$(loginctl show-user "$USER" -p Linger --value 2>/dev/null || true)" != "yes" ]]; then
80
+ echo ""
81
+ echo "Tip: for this service to start at boot without an interactive login, run once:"
82
+ echo " loginctl enable-linger $USER"
83
+ fi
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ UNIT_NAME="foxclaw.service"
4
+ USER_SYSTEMD_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user"
5
+ UNIT_PATH="$USER_SYSTEMD_DIR/$UNIT_NAME"
6
+
7
+ if ! command -v systemctl >/dev/null 2>&1; then
8
+ echo "systemctl not found" >&2
9
+ exit 1
10
+ fi
11
+
12
+ systemctl --user disable --now "$UNIT_NAME" 2>/dev/null || true
13
+ rm -f "$UNIT_PATH"
14
+ systemctl --user daemon-reload
15
+ echo "Removed $UNIT_PATH"
@@ -0,0 +1,167 @@
1
+ ---
2
+ name: foxclaw
3
+ description: Deploy, configure, and validate FoxClaw on macOS, locally or over SSH. Use when Codex needs to clone or update the FoxClaw repo, collect Telegram bot and chat/topic values, write `.env`, enable a launchd service, and guide the user through the first Telegram message test. Trigger on requests about trusted chat interfaces controlling local Codex, copying FoxClaw to another Mac, remote FoxClaw deployment, or turning this repo into an installable Codex skill.
4
+ ---
5
+
6
+ # FoxClaw
7
+
8
+ Deploy FoxClaw to a Mac with as little manual setup as possible. The bundled scripts install user-scoped Node.js and Codex CLI when missing, clone or update the FoxClaw repo, write `.env`, build the project, run doctor checks, and optionally install the launchd service.
9
+
10
+ This skill is not finished when the repo is merely installed. Treat a bridge setup as complete only after:
11
+
12
+ 1. the repo exists at the target path
13
+ 2. `.env` contains the correct Telegram values
14
+ 3. the bridge passes `doctor` and can report `status`
15
+ 4. the user has been told exactly where to send the first Telegram message
16
+ 5. the setup has been smoke-tested or clearly blocked by missing Telegram-side values
17
+
18
+ ## Mandatory Workflow
19
+
20
+ Follow this order every time:
21
+
22
+ 1. Decide whether this is a local Mac install or a remote Mac over SSH.
23
+ 2. Confirm where the bridge repo should live. If the repo is not already present, clone it or let bootstrap clone it.
24
+ 3. Decide the Telegram mode before writing `.env`:
25
+ - private chat only
26
+ - one allowed group
27
+ - one allowed topic inside one group
28
+ 4. Collect the Telegram values and filesystem paths listed below.
29
+ 5. Run the correct bootstrap script with explicit arguments.
30
+ 6. Run post-install validation.
31
+ 7. Tell the user to send a first Telegram message and explain exactly where to send it.
32
+ 8. If the bridge does not answer, inspect `status`, logs, and Telegram configuration instead of declaring success.
33
+
34
+ Do not stop after "install completed" if the user asked for a working bot.
35
+
36
+ ## Required Inputs
37
+
38
+ Collect these values before running bootstrap:
39
+
40
+ - `TG_BOT_TOKEN`
41
+ - `TG_ALLOWED_USER_ID`
42
+ - `DEFAULT_CWD`
43
+
44
+ Collect these values when group/topic mode is used:
45
+
46
+ - `TG_ALLOWED_CHAT_ID`
47
+ - `TG_ALLOWED_TOPIC_ID`
48
+
49
+ Collect these deployment values on every run:
50
+
51
+ - install directory
52
+ - SSH host when deploying remotely
53
+
54
+ Defaults:
55
+
56
+ - repo URL: `https://github.com/foxden-app/foxclaw.git`
57
+ - repo ref: `main`
58
+ - install directory: `~/foxclaw`
59
+ - `DEFAULT_APPROVAL_POLICY`: `on-request`
60
+ - `DEFAULT_SANDBOX_MODE`: `workspace-write`
61
+
62
+ Telegram behavior:
63
+
64
+ - private chat with `TG_ALLOWED_USER_ID` remains available even when `TG_ALLOWED_CHAT_ID` or `TG_ALLOWED_TOPIC_ID` is set
65
+ - `TG_ALLOWED_CHAT_ID` and `TG_ALLOWED_TOPIC_ID` choose the default group or topic scope; they do not disable private chat
66
+
67
+ If `TG_ALLOWED_CHAT_ID` or `TG_ALLOWED_TOPIC_ID` is missing, read [references/telegram-setup.md](./references/telegram-setup.md) and explicitly guide the user through collecting it.
68
+
69
+ ## Deployment Rules
70
+
71
+ 1. If the user is deploying to a second Mac, prefer one bot per device.
72
+ 2. If no unique bot token has been provided for the second Mac, bootstrap with `--no-start`.
73
+ 3. If group or topic mode is involved, read [references/telegram-setup.md](./references/telegram-setup.md) before continuing.
74
+ 4. Always explain to the user which values will be written into `.env` before starting bootstrap.
75
+ 5. After bootstrap, check `codex login status`. If authentication is missing, tell the user to run `codex login` or open `codex app` on that Mac.
76
+ 6. If the user only says "set it up" and has not given all required values, ask for the missing values directly instead of guessing Telegram IDs.
77
+ 7. If the user wants a fully usable setup, continue until first-message validation is done or clearly blocked by Telegram-side prerequisites.
78
+
79
+ ## What To Ask The User
80
+
81
+ Use short direct questions when values are missing. The minimum useful checklist is:
82
+
83
+ 1. Where should the repo live on the target Mac?
84
+ 2. Which directory should be the bridge's default working directory?
85
+ 3. What is the Telegram bot token?
86
+ 4. What is the Telegram numeric user id allowed to control the bridge?
87
+ 5. Are we using private chat only, a group, or a specific topic?
88
+ 6. If group/topic mode: what are the `TG_ALLOWED_CHAT_ID` and `TG_ALLOWED_TOPIC_ID` values?
89
+
90
+ If the user does not know the Telegram ids, point them to the exact `getUpdates` method in [references/telegram-setup.md](./references/telegram-setup.md).
91
+
92
+ ## Local Bootstrap
93
+
94
+ Run:
95
+
96
+ ```bash
97
+ python3 "$CODEX_HOME/skills/foxclaw/scripts/bootstrap_host.py" \
98
+ --tg-bot-token "<BOT_TOKEN>" \
99
+ --tg-allowed-user-id "<USER_ID>" \
100
+ --default-cwd "<ABSOLUTE_CWD>" \
101
+ --tg-allowed-chat-id "<CHAT_ID>" \
102
+ --tg-allowed-topic-id "<TOPIC_ID>" \
103
+ --default-sandbox-mode "workspace-write"
104
+ ```
105
+
106
+ Omit `--tg-allowed-chat-id` and `--tg-allowed-topic-id` when using private chat only.
107
+
108
+ Use `--no-start` when you only want the host prepared but do not want the bridge service to start yet.
109
+
110
+ When the repo is not already present on disk, this bootstrap path counts as the repo download step because it clones the bridge automatically.
111
+
112
+ ## Remote Bootstrap Over SSH
113
+
114
+ Run:
115
+
116
+ ```bash
117
+ python3 "$CODEX_HOME/skills/foxclaw/scripts/bootstrap_remote.py" \
118
+ --ssh-host "<USER@HOST>" \
119
+ --install-dir "<REMOTE_INSTALL_DIR>" \
120
+ --tg-bot-token "<BOT_TOKEN>" \
121
+ --tg-allowed-user-id "<USER_ID>" \
122
+ --default-cwd "<REMOTE_ABSOLUTE_CWD>" \
123
+ --tg-allowed-chat-id "<CHAT_ID>" \
124
+ --tg-allowed-topic-id "<TOPIC_ID>" \
125
+ --default-sandbox-mode "workspace-write"
126
+ ```
127
+
128
+ Use `--no-start` by default when preparing a second Mac before a unique bot token is ready.
129
+
130
+ ## Validation
131
+
132
+ After either bootstrap path:
133
+
134
+ 1. Run `node dist/main.js doctor` in the installed bridge repo.
135
+ 2. If launchd was installed, run `node dist/main.js status`.
136
+ 3. Check `codex login status`. If authentication is missing, stop and tell the user exactly how to log in.
137
+ 4. If the bridge is expected to answer in a Telegram group, confirm:
138
+ - `privacy mode` is disabled
139
+ - the bot is an admin in the group
140
+ - the configured `TG_ALLOWED_CHAT_ID` and `TG_ALLOWED_TOPIC_ID` match the target group/topic
141
+ 5. If group or topic mode is enabled, also verify that private chat still responds for the configured `TG_ALLOWED_USER_ID`.
142
+
143
+ ## First Telegram Message Check
144
+
145
+ Do this whenever the bridge has been started:
146
+
147
+ 1. Tell the user exactly where to send the first test message:
148
+ - private chat mode: send `/help` to the bot in private chat
149
+ - group mode: send `/help@botname` or `/help` in the configured default scope
150
+ - topic mode: send `/help` inside the configured topic, then send one plain-language message
151
+ 2. After the user sends that message, verify the bridge is listening:
152
+ - `node dist/main.js status`
153
+ - launchd or service log if there is no reply
154
+ 3. If the bot still does not answer, debug the Telegram side before changing the bridge:
155
+ - wrong bot token
156
+ - wrong user id
157
+ - wrong chat/topic ids
158
+ - privacy mode still on
159
+ - bot not admin in group
160
+
161
+ Do not describe the setup as "done" until this smoke test has either passed or been blocked by missing Telegram-side access.
162
+
163
+ ## Resources
164
+
165
+ - [references/telegram-setup.md](./references/telegram-setup.md): Telegram-side checklist and ID discovery
166
+ - `scripts/bootstrap_host.py`: install and configure the bridge on the current Mac
167
+ - `scripts/bootstrap_remote.py`: run the same bootstrap on another Mac over SSH
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "FoxClaw"
3
+ short_description: "Install, configure, and validate Telegram Codex bridges"
4
+ default_prompt: "Use $foxclaw to clone the FoxClaw repo, collect Telegram values, write .env, start the service, and verify it with a first Telegram message."
@@ -0,0 +1,93 @@
1
+ # Telegram Bridge Checklist
2
+
3
+ Use this checklist whenever the bridge is configured for a Telegram group or topic.
4
+
5
+ ## Mode Selection
6
+
7
+ Pick one mode before writing `.env`:
8
+
9
+ - private chat only
10
+ - one allowed group
11
+ - one allowed topic inside one allowed group
12
+
13
+ Rules:
14
+
15
+ - private chat remains available even when group/topic ids are configured
16
+ - if multiple bots share one group, prefer one topic per bot
17
+ - if a user only wants the bot in private chat, leave both `TG_ALLOWED_CHAT_ID` and `TG_ALLOWED_TOPIC_ID` empty
18
+
19
+ ## Required Values
20
+
21
+ - `TG_BOT_TOKEN`
22
+ - `TG_ALLOWED_USER_ID`
23
+ - `DEFAULT_CWD`
24
+
25
+ Optional values:
26
+
27
+ - `TG_ALLOWED_CHAT_ID`
28
+ - `TG_ALLOWED_TOPIC_ID`
29
+
30
+ Behavior:
31
+
32
+ - No `TG_ALLOWED_CHAT_ID`: private-chat mode
33
+ - `TG_ALLOWED_CHAT_ID` only: the whole group becomes the default scope
34
+ - `TG_ALLOWED_CHAT_ID` + `TG_ALLOWED_TOPIC_ID`: that topic becomes the default scope
35
+ - Private chat with `TG_ALLOWED_USER_ID` still works in every mode above
36
+
37
+ If multiple bots share one group, keep the same `TG_ALLOWED_CHAT_ID` and give each bot a different `TG_ALLOWED_TOPIC_ID`.
38
+
39
+ ## Path Guidance
40
+
41
+ Best practice:
42
+
43
+ - keep the FoxClaw repo in a stable path such as `~/foxclaw`
44
+ - point `DEFAULT_CWD` at a directory the user actually wants Codex to work inside, such as `~/workspace`, `~/Documents`, or `~/Dev`
45
+ - do not use an ambiguous or disposable path unless the user explicitly wants that
46
+
47
+ ## Group Requirements
48
+
49
+ Before testing natural-language chat in a group:
50
+
51
+ 1. Add the bot to the target group.
52
+ 2. Disable the bot's `privacy mode` in `@BotFather`.
53
+ 3. Promote the bot to administrator.
54
+ 4. If natural-language messages still do not arrive after the privacy change, remove the bot and add it back.
55
+
56
+ `/status@botname` can work even when normal group text still does not. Do not treat command success as proof that group natural-language mode is ready.
57
+
58
+ ## Finding Chat And Topic IDs
59
+
60
+ 1. Stop the bridge.
61
+ 2. Send a message in the target group or topic.
62
+ 3. Open `https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates`.
63
+ 4. Read:
64
+ - `message.chat.id` -> `TG_ALLOWED_CHAT_ID`
65
+ - `message.message_thread_id` -> `TG_ALLOWED_TOPIC_ID`
66
+
67
+ If the bridge is still polling, it may consume the update before you inspect it.
68
+
69
+ ## First Message Smoke Test
70
+
71
+ After the bridge is started:
72
+
73
+ 1. Private chat mode:
74
+ - send `/help` to the bot in private chat
75
+ - send one plain-language message such as `show /status`
76
+ 2. Group mode:
77
+ - send `/help` in the configured group or default topic
78
+ - if multiple bots are present, use `@botname`
79
+ 3. Topic mode:
80
+ - send `/help` inside the configured topic
81
+ - then send one plain-language message inside that same topic
82
+
83
+ If the bot does not answer:
84
+
85
+ 1. run `node dist/main.js status`
86
+ 2. inspect the bridge log
87
+ 3. re-check:
88
+ - bot token
89
+ - allowed user id
90
+ - chat id
91
+ - topic id
92
+ - privacy mode
93
+ - admin status