clawdex-mobile 5.1.3-internal.0 → 5.1.3-internal.10
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 +23 -48
- package/docs/setup-and-operations.md +31 -92
- package/docs/troubleshooting.md +4 -56
- package/package.json +9 -4
- package/scripts/setup-secure-dev.sh +14 -78
- package/scripts/setup-wizard.sh +108 -75
- package/scripts/start-bridge-secure.js +9 -191
- package/services/rust-bridge/Cargo.lock +126 -107
- package/services/rust-bridge/Cargo.toml +1 -1
- package/services/rust-bridge/src/main.rs +2410 -266
- package/services/rust-bridge/src/services/git.rs +260 -6
- package/vendor/bridge-binaries/darwin-arm64/codex-rust-bridge +0 -0
- package/vendor/bridge-binaries/darwin-x64/codex-rust-bridge +0 -0
- package/vendor/bridge-binaries/linux-arm64/codex-rust-bridge +0 -0
- package/vendor/bridge-binaries/linux-armv7l/codex-rust-bridge +0 -0
- package/vendor/bridge-binaries/linux-x64/codex-rust-bridge +0 -0
- package/vendor/bridge-binaries/win32-x64/codex-rust-bridge.exe +0 -0
- package/scripts/codespaces-bootstrap.js +0 -231
package/README.md
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
<img src="https://raw.githubusercontent.com/Mohit-Patil/clawdex-mobile/main/screenshots/social/clawdex-social-poster-1200x675.png" alt="Clawdex social banner" width="100%" />
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
|
-
Run Codex or OpenCode from your phone. `clawdex-mobile` ships the bridge CLI plus bundled Rust bridge binaries for supported hosts, and the mobile app pairs to that bridge over Tailscale
|
|
7
|
+
Run Codex or OpenCode from your phone. `clawdex-mobile` ships the bridge CLI plus bundled Rust bridge binaries for supported hosts, and the mobile app pairs to that bridge over Tailscale or local LAN.
|
|
8
8
|
|
|
9
|
-
This project is for trusted/private networking by default.
|
|
9
|
+
This project is for trusted/private networking by default. Keep the bridge on a private network, leave bridge auth enabled, and do not expose it directly to the public internet.
|
|
10
10
|
|
|
11
11
|
## What You Get
|
|
12
12
|
|
|
@@ -25,6 +25,7 @@ Before you start:
|
|
|
25
25
|
- `git`
|
|
26
26
|
- `codex` in `PATH` for the default Codex flow
|
|
27
27
|
- `opencode` in `PATH` if you want the OpenCode flow
|
|
28
|
+
- `cursor-app-server` in `PATH` if you want the Cursor SDK flow
|
|
28
29
|
|
|
29
30
|
Install the mobile app:
|
|
30
31
|
|
|
@@ -52,62 +53,24 @@ clawdex init
|
|
|
52
53
|
clawdex stop
|
|
53
54
|
```
|
|
54
55
|
|
|
55
|
-
##
|
|
56
|
+
## Extra Harness Setup
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
From a repo checkout inside Codespaces:
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
npm run setup:wizard
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Pick `GitHub Codespaces` as the network mode. The setup flow writes forwarded HTTPS bridge URLs into `.env.secure`, and bridge startup will try to mark both bridge ports public automatically.
|
|
66
|
-
|
|
67
|
-
Notes:
|
|
68
|
-
|
|
69
|
-
- The mobile app should pair to the printed `https://<codespace>-8787.app.github.dev` URL, not `127.0.0.1`.
|
|
70
|
-
- Browser preview uses a second forwarded port (`8788` by default), so both ports need public visibility.
|
|
71
|
-
- GitHub resets public forwarded ports back to private when a codespace restarts. Restarting the bridge reruns the visibility step.
|
|
72
|
-
- If automatic visibility setup fails, run `gh codespace ports visibility 8787:public 8788:public`.
|
|
73
|
-
- If the mobile app is built with `EXPO_PUBLIC_GITHUB_CLIENT_ID`, users can now tap `Use GitHub Codespaces` in onboarding/settings, sign in with GitHub, pick a Codespace, and connect without manually copying the bridge token.
|
|
74
|
-
- The app can also create a new repo-backed Codespace directly. It prefers `<signed-in-user>/<EXPO_PUBLIC_GITHUB_CODESPACES_REPO_NAME>` first. If that repo does not exist, it automatically forks `EXPO_PUBLIC_GITHUB_CODESPACES_SOURCE_OWNER/<EXPO_PUBLIC_GITHUB_CODESPACES_REPO_NAME>` into the signed-in user account, then creates the Codespace there.
|
|
75
|
-
|
|
76
|
-
This repo now also includes a Codespaces bootstrap flow. On Codespace start/resume, `.devcontainer/devcontainer.json` runs:
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
npm run codespaces:bootstrap
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
During initial Codespace creation, the devcontainer also runs:
|
|
83
|
-
|
|
84
|
-
```bash
|
|
85
|
-
npm run codespaces:bootstrap -- --prepare-only
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
That pre-installs Codex and prebuilds the Rust bridge binary so the later startup path is faster. The normal bootstrap command rewrites `.env.secure` for Codespaces with `codex` as the only enabled engine and starts the bridge in the background. You can rerun either command manually any time.
|
|
89
|
-
|
|
90
|
-
The published npm package now includes that bootstrap script too, so a minimal Codespaces template repo can install `clawdex-mobile@latest` in `postCreateCommand` and call the packaged bootstrap without vendoring bridge source into the template itself.
|
|
91
|
-
|
|
92
|
-
In Codespaces mode, the bootstrap also enables bridge-side GitHub bearer auth for the current `CODESPACE_NAME`, so the mobile app can authenticate with the same GitHub OAuth token it used to discover and start the Codespace.
|
|
93
|
-
|
|
94
|
-
## OpenCode Setup
|
|
95
|
-
|
|
96
|
-
OpenCode is supported directly from the CLI now.
|
|
58
|
+
OpenCode and Cursor can run beside Codex from the same bridge.
|
|
97
59
|
|
|
98
60
|
```bash
|
|
99
61
|
npm install -g opencode-ai
|
|
62
|
+
npm install -g @clawdex/cursor-app-server
|
|
100
63
|
npm install -g clawdex-mobile@latest
|
|
101
|
-
clawdex init --engines codex,opencode
|
|
64
|
+
clawdex init --engines codex,opencode,cursor
|
|
102
65
|
```
|
|
103
66
|
|
|
104
|
-
That writes `BRIDGE_ENABLED_ENGINES=codex,opencode` to `.env.secure`, so the mobile app can control
|
|
67
|
+
That writes `BRIDGE_ENABLED_ENGINES=codex,opencode,cursor` to `.env.secure`, so the mobile app can control the selected harnesses from one bridge. When Cursor is selected, `clawdex init` asks for the Cursor API key and saves it in `.env.secure`.
|
|
105
68
|
|
|
106
69
|
Notes:
|
|
107
70
|
|
|
108
71
|
- `clawdex init` without flags now lets you multi-select harnesses in the wizard with Space, then Enter to continue.
|
|
109
|
-
- Use `clawdex init --engine codex` or `clawdex init --engine
|
|
110
|
-
-
|
|
72
|
+
- Use `clawdex init --engine codex`, `clawdex init --engine opencode`, or `clawdex init --engine cursor` if you want a single-harness setup.
|
|
73
|
+
- For non-interactive host automation, set `CURSOR_API_KEY` before running setup. `CURSOR_MODEL` is optional; the app model picker sends the model for normal chats.
|
|
111
74
|
|
|
112
75
|
## Monorepo Development
|
|
113
76
|
|
|
@@ -119,6 +82,16 @@ npm run setup:wizard
|
|
|
119
82
|
npm run mobile
|
|
120
83
|
```
|
|
121
84
|
|
|
85
|
+
For one-step restarts that switch the bridge network mode, reuse the existing token, start the
|
|
86
|
+
bridge in the background, and then launch Expo:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npm run stack:lan
|
|
90
|
+
npm run stack:tailscale
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`stack:lan` is the local network path, so it also covers the same-device LAN/VLAN case.
|
|
94
|
+
|
|
122
95
|
For an OpenCode-first repo checkout:
|
|
123
96
|
|
|
124
97
|
```bash
|
|
@@ -129,13 +102,15 @@ Use `npm run setup:wizard -- --no-start` if you only want to write config.
|
|
|
129
102
|
|
|
130
103
|
## Main Commands
|
|
131
104
|
|
|
132
|
-
- `clawdex init [--engine codex|opencode] [--engines codex,opencode] [--no-start]`
|
|
105
|
+
- `clawdex init [--engine codex|opencode|cursor] [--engines codex,opencode,cursor] [--no-start]`
|
|
133
106
|
- `clawdex stop`
|
|
134
107
|
- `clawdex upgrade` / `clawdex update`
|
|
135
108
|
- `clawdex version`
|
|
136
109
|
- `npm run setup:wizard`
|
|
137
110
|
- `npm run secure:bridge`
|
|
138
111
|
- `npm run mobile`
|
|
112
|
+
- `npm run stack:lan`
|
|
113
|
+
- `npm run stack:tailscale`
|
|
139
114
|
- `npm run ios`
|
|
140
115
|
- `npm run android`
|
|
141
116
|
- `npm run stop:services`
|
|
@@ -6,21 +6,23 @@ This guide is the detailed companion to the top-level `README.md`.
|
|
|
6
6
|
|
|
7
7
|
The setup wizard now lets you choose which harnesses the phone should control.
|
|
8
8
|
|
|
9
|
-
If you want
|
|
9
|
+
If you want Codex, OpenCode, and Cursor:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
clawdex init --engines codex,opencode
|
|
12
|
+
clawdex init --engines codex,opencode,cursor
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
From a source checkout, the equivalent command is:
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
npm run setup:wizard -- --engines codex,opencode
|
|
18
|
+
npm run setup:wizard -- --engines codex,opencode,cursor
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
That writes `BRIDGE_ENABLED_ENGINES=codex,opencode` into `.env.secure`, so the bridge starts
|
|
21
|
+
That writes `BRIDGE_ENABLED_ENGINES=codex,opencode,cursor` into `.env.secure`, so the bridge starts the selected backends and the mobile app can control them from one UI. When Cursor is selected, `clawdex init` asks for the Cursor API key and saves it in `.env.secure`.
|
|
22
22
|
|
|
23
|
-
If you want only one harness, use `--engine codex
|
|
23
|
+
If you want only one harness, use `--engine codex`, `--engine opencode`, or `--engine cursor`.
|
|
24
|
+
|
|
25
|
+
Cursor usage limits are not exposed by Cursor's public API today. The app shows key status, key metadata, runtime state, and models from Cursor; plan or weekly usage details remain in Cursor.
|
|
24
26
|
|
|
25
27
|
## Onboarding Output Cues
|
|
26
28
|
|
|
@@ -37,75 +39,6 @@ Published npm releases bundle prebuilt bridge binaries for `darwin-arm64`, `darw
|
|
|
37
39
|
|
|
38
40
|
Published CLI installs are bridge-only. They do not include the Expo workspace or mobile app source files.
|
|
39
41
|
|
|
40
|
-
## GitHub Codespaces Setup
|
|
41
|
-
|
|
42
|
-
Codespaces can replace a user-managed always-on machine for development and lightweight remote use.
|
|
43
|
-
|
|
44
|
-
From a repo checkout inside an active codespace:
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
npm run setup:wizard
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Choose `GitHub Codespaces` for the bridge network mode.
|
|
51
|
-
|
|
52
|
-
What that does:
|
|
53
|
-
|
|
54
|
-
- binds the bridge locally inside the codespace
|
|
55
|
-
- writes `BRIDGE_CONNECT_URL` and `BRIDGE_PREVIEW_CONNECT_URL` using the codespace forwarded HTTPS domain
|
|
56
|
-
- enables bridge-side GitHub bearer auth for the current codespace
|
|
57
|
-
- starts the bridge normally
|
|
58
|
-
- attempts to mark the bridge port and browser-preview port public on each startup
|
|
59
|
-
|
|
60
|
-
Important constraints:
|
|
61
|
-
|
|
62
|
-
- Pair the mobile app to the printed `https://<codespace>-8787.app.github.dev` URL, not `127.0.0.1`
|
|
63
|
-
- Browser preview uses the preview port (`8788` by default), so that forwarded port must also be public
|
|
64
|
-
- GitHub resets public forwarded ports back to private whenever the codespace restarts
|
|
65
|
-
- Keep bridge auth enabled and use Codespaces only for repos you trust, because public forwarded ports are internet-reachable
|
|
66
|
-
- If the mobile app build sets `EXPO_PUBLIC_GITHUB_CLIENT_ID`, onboarding/settings can now sign in with GitHub, start the Codespace, and connect directly with the same OAuth token instead of copying `BRIDGE_AUTH_TOKEN`
|
|
67
|
-
- The same in-app GitHub flow can create a new Codespace. It prefers `<signed-in-user>/<EXPO_PUBLIC_GITHUB_CODESPACES_REPO_NAME>`. If that repo does not exist yet, Clawdex automatically forks `EXPO_PUBLIC_GITHUB_CODESPACES_SOURCE_OWNER/<EXPO_PUBLIC_GITHUB_CODESPACES_REPO_NAME>` into the signed-in user account and creates the Codespace from that fork
|
|
68
|
-
|
|
69
|
-
Manual recovery if port visibility does not update automatically:
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
gh codespace ports visibility 8787:public 8788:public
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### Codespaces Bootstrap
|
|
76
|
-
|
|
77
|
-
The repo devcontainer now includes:
|
|
78
|
-
|
|
79
|
-
- `postCreateCommand`: `npm install --include=dev && npm run codespaces:bootstrap -- --prepare-only`
|
|
80
|
-
- `postStartCommand`: `npm run codespaces:bootstrap`
|
|
81
|
-
|
|
82
|
-
`npm run codespaces:bootstrap` does the following:
|
|
83
|
-
|
|
84
|
-
- installs the Codex CLI via `npm install -g @openai/codex` if it is missing
|
|
85
|
-
- in `--prepare-only` mode, prebuilds the Rust bridge binary without starting it
|
|
86
|
-
- rewrites `.env.secure` for `BRIDGE_NETWORK_MODE=codespaces` with `BRIDGE_ACTIVE_ENGINE=codex`, `BRIDGE_ENABLED_ENGINES=codex`, and `BRIDGE_GITHUB_CODESPACES_AUTH=true`
|
|
87
|
-
- starts the bridge in the background unless you set `CLAWDEX_CODESPACES_SKIP_START=true` or pass `--no-start`
|
|
88
|
-
|
|
89
|
-
That means the first Codespace create now front-loads the expensive bridge compile during `postCreateCommand`, so the later `postStartCommand` can usually start the bridge much faster.
|
|
90
|
-
|
|
91
|
-
The same bootstrap script is included in the published `clawdex-mobile` npm package. That lets the `clawdex-codespace` template stay minimal: it can install `clawdex-mobile@latest` globally in the devcontainer and invoke the packaged bootstrap against the current workspace instead of copying `scripts/*` and `services/rust-bridge/*` into the template repo.
|
|
92
|
-
|
|
93
|
-
Manual examples:
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
npm run codespaces:bootstrap -- --prepare-only
|
|
97
|
-
npm run codespaces:bootstrap
|
|
98
|
-
npm run codespaces:bootstrap -- --no-start
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
Minimal template equivalent:
|
|
102
|
-
|
|
103
|
-
```bash
|
|
104
|
-
npm install -g clawdex-mobile@latest @openai/codex
|
|
105
|
-
CLAWDEX_WORKSPACE_ROOT="$PWD" node "$(npm root -g)/clawdex-mobile/scripts/codespaces-bootstrap.js" --prepare-only
|
|
106
|
-
CLAWDEX_WORKSPACE_ROOT="$PWD" node "$(npm root -g)/clawdex-mobile/scripts/codespaces-bootstrap.js"
|
|
107
|
-
```
|
|
108
|
-
|
|
109
42
|
## Manual Secure Setup (No Wizard)
|
|
110
43
|
|
|
111
44
|
### 1) Install dependencies
|
|
@@ -120,10 +53,10 @@ npm install
|
|
|
120
53
|
npm run secure:setup
|
|
121
54
|
```
|
|
122
55
|
|
|
123
|
-
To generate
|
|
56
|
+
To generate multi-harness config instead:
|
|
124
57
|
|
|
125
58
|
```bash
|
|
126
|
-
BRIDGE_ENABLED_ENGINES=codex,opencode npm run secure:setup
|
|
59
|
+
BRIDGE_ENABLED_ENGINES=codex,opencode,cursor npm run secure:setup
|
|
127
60
|
```
|
|
128
61
|
|
|
129
62
|
Creates/updates:
|
|
@@ -137,17 +70,17 @@ Creates/updates:
|
|
|
137
70
|
npm run secure:bridge
|
|
138
71
|
```
|
|
139
72
|
|
|
140
|
-
If you want a one-off
|
|
73
|
+
If you want a one-off multi-harness launch without rewriting `.env.secure`:
|
|
141
74
|
|
|
142
75
|
```bash
|
|
143
|
-
BRIDGE_ENABLED_ENGINES=codex,opencode npm run secure:bridge
|
|
76
|
+
BRIDGE_ENABLED_ENGINES=codex,opencode,cursor npm run secure:bridge
|
|
144
77
|
```
|
|
145
78
|
|
|
146
|
-
When
|
|
79
|
+
When multiple harnesses are selected, the bridge starts each backend and merges chat lists while still routing each thread by engine.
|
|
147
80
|
|
|
148
81
|
### 4) Pair from the mobile app
|
|
149
82
|
|
|
150
|
-
Open the installed mobile app on your phone, then scan the bridge QR. If needed, enter the bridge URL manually (for example `http://100.x.y.z:8787
|
|
83
|
+
Open the installed mobile app on your phone, then scan the bridge QR. If needed, enter the bridge URL manually (for example `http://100.x.y.z:8787` or `http://192.168.x.y:8787`). The chosen bridge URL is stored on-device and can be changed later in Settings.
|
|
151
84
|
|
|
152
85
|
### In-app Bridge Maintenance
|
|
153
86
|
|
|
@@ -174,6 +107,18 @@ npm run mobile
|
|
|
174
107
|
|
|
175
108
|
`npm run mobile` uses `scripts/start-expo.sh`, which sets `REACT_NATIVE_PACKAGER_HOSTNAME` from your secure config so QR resolution is predictable.
|
|
176
109
|
|
|
110
|
+
If you want one command that switches the bridge between LAN/VLAN and Tailscale, preserves your
|
|
111
|
+
existing bridge token and enabled harnesses, restarts the bridge in the background, and then opens
|
|
112
|
+
Expo:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
npm run stack:lan
|
|
116
|
+
npm run stack:tailscale
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Both wrappers call `scripts/start-mobile-stack.sh`. Pass `--expo ios` or `--expo android` if you
|
|
120
|
+
want the same flow but to open a native Expo run command instead of the default `mobile` mode.
|
|
121
|
+
|
|
177
122
|
## Advanced Knobs
|
|
178
123
|
|
|
179
124
|
Optional environment variables:
|
|
@@ -242,7 +187,7 @@ npm run teardown -- --yes
|
|
|
242
187
|
|
|
243
188
|
| Variable | Purpose |
|
|
244
189
|
|---|---|
|
|
245
|
-
| `BRIDGE_NETWORK_MODE` | bridge connectivity mode (`tailscale
|
|
190
|
+
| `BRIDGE_NETWORK_MODE` | bridge connectivity mode (`tailscale` or `local`) |
|
|
246
191
|
| `BRIDGE_HOST` | bind host for rust bridge |
|
|
247
192
|
| `BRIDGE_PORT` | bridge port (default `8787`) |
|
|
248
193
|
| `BRIDGE_PREVIEW_PORT` | browser preview port for proxied localhost web apps (default `BRIDGE_PORT + 1`) |
|
|
@@ -250,13 +195,13 @@ npm run teardown -- --yes
|
|
|
250
195
|
| `BRIDGE_PREVIEW_CONNECT_URL` | externally reachable browser preview base URL |
|
|
251
196
|
| `BRIDGE_AUTH_TOKEN` | required auth token |
|
|
252
197
|
| `BRIDGE_ALLOW_QUERY_TOKEN_AUTH` | query-token auth fallback |
|
|
253
|
-
| `BRIDGE_GITHUB_CODESPACES_AUTH` | accept GitHub bearer tokens for the current codespace |
|
|
254
|
-
| `BRIDGE_GITHUB_CODESPACE_NAME` | codespace name used when validating GitHub bearer tokens |
|
|
255
|
-
| `BRIDGE_GITHUB_API_URL` | GitHub REST API base URL for Codespaces auth checks |
|
|
256
198
|
| `CODEX_CLI_BIN` | codex executable |
|
|
257
199
|
| `BRIDGE_ACTIVE_ENGINE` | internal preferred routing backend used when multiple harnesses are enabled |
|
|
258
|
-
| `BRIDGE_ENABLED_ENGINES` | selected harnesses to expose (`codex`, `opencode`, or
|
|
200
|
+
| `BRIDGE_ENABLED_ENGINES` | selected harnesses to expose (`codex`, `opencode`, `cursor`, or a comma-separated mix) |
|
|
259
201
|
| `OPENCODE_CLI_BIN` | opencode executable for dual-engine startup |
|
|
202
|
+
| `CURSOR_APP_SERVER_BIN` | Cursor app-server executable, usually `cursor-app-server` |
|
|
203
|
+
| `CURSOR_API_KEY` | Cursor API key used by the Cursor SDK harness; collected by `clawdex init` when Cursor is selected |
|
|
204
|
+
| `CURSOR_MODEL` | optional Cursor model id for non-interactive host defaults; normal mobile chats send the selected model |
|
|
260
205
|
| `BRIDGE_OPENCODE_HOST` | loopback host for spawned opencode server |
|
|
261
206
|
| `BRIDGE_OPENCODE_PORT` | loopback port for spawned opencode server |
|
|
262
207
|
| `BRIDGE_OPENCODE_SERVER_USERNAME` | basic-auth username passed to opencode server |
|
|
@@ -269,11 +214,6 @@ npm run teardown -- --yes
|
|
|
269
214
|
| Variable | Purpose |
|
|
270
215
|
|---|---|
|
|
271
216
|
| `EXPO_PUBLIC_HOST_BRIDGE_TOKEN` | token used by local mobile dev builds |
|
|
272
|
-
| `EXPO_PUBLIC_GITHUB_CLIENT_ID` | GitHub OAuth app client ID for in-app Codespaces sign-in |
|
|
273
|
-
| `EXPO_PUBLIC_GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN` | forwarded port domain used to derive Codespaces bridge URLs (`app.github.dev` by default) |
|
|
274
|
-
| `EXPO_PUBLIC_GITHUB_CODESPACES_REPO_NAME` | repository name to sort matching Codespaces first in the in-app picker |
|
|
275
|
-
| `EXPO_PUBLIC_GITHUB_CODESPACES_SOURCE_OWNER` | template/source repository owner used for automatic forking when the signed-in user does not have a same-name repo |
|
|
276
|
-
| `EXPO_PUBLIC_GITHUB_CODESPACES_REPO_REF` | optional git ref/branch used when creating a new Codespace |
|
|
277
217
|
| `EXPO_PUBLIC_ALLOW_QUERY_TOKEN_AUTH` | query-token behavior for WebSocket auth fallback |
|
|
278
218
|
| `EXPO_PUBLIC_ALLOW_INSECURE_REMOTE_BRIDGE` | suppress insecure-HTTP warning |
|
|
279
219
|
| `EXPO_PUBLIC_PRIVACY_POLICY_URL` | in-app Privacy link |
|
|
@@ -294,8 +234,7 @@ If you enable the optional tip jar:
|
|
|
294
234
|
## Production Readiness Checklist
|
|
295
235
|
|
|
296
236
|
- Keep bridge network-private only by default (Tailscale/private LAN/VPN + host firewall)
|
|
297
|
-
-
|
|
298
|
-
- Require bridge auth of some kind (`BRIDGE_AUTH_TOKEN` or GitHub Codespaces auth)
|
|
237
|
+
- Require bridge auth with `BRIDGE_AUTH_TOKEN`
|
|
299
238
|
- Keep `BRIDGE_ALLOW_QUERY_TOKEN_AUTH=true` only on private networks (required for Android WS auth fallback)
|
|
300
239
|
- Do not set `BRIDGE_ALLOW_INSECURE_NO_AUTH=true` outside local debugging
|
|
301
240
|
- Scope `BRIDGE_WORKDIR` to minimal required root
|
package/docs/troubleshooting.md
CHANGED
|
@@ -34,75 +34,24 @@ npm run stop:services
|
|
|
34
34
|
## Bridge auth errors (`401`, invalid token)
|
|
35
35
|
|
|
36
36
|
- For the shipped mobile app, rescan the bridge QR or update the stored token in Settings.
|
|
37
|
-
- For GitHub-auth Codespaces profiles, reopen `GitHub Codespaces` in the app and sign in with GitHub again if the OAuth token was revoked or expired.
|
|
38
37
|
- For a local dev build, also ensure `BRIDGE_AUTH_TOKEN` in `.env.secure` matches `EXPO_PUBLIC_HOST_BRIDGE_TOKEN` in `apps/mobile/.env`.
|
|
39
38
|
- Restart the bridge after token changes.
|
|
40
39
|
- On secure-launcher installs, `Settings > Bridge Maintenance > Restart bridge safely` can do that from the phone.
|
|
41
40
|
- If an in-app bridge update fails, inspect `.bridge-updater.log` and `.bridge-update-status.json` in the bridge install root.
|
|
42
41
|
|
|
43
|
-
## GitHub Codespaces bridge URL does not connect
|
|
44
|
-
|
|
45
|
-
- Pair to the printed forwarded HTTPS URL such as `https://<codespace>-8787.app.github.dev`, not `127.0.0.1`.
|
|
46
|
-
- Public forwarded ports reset back to private when the codespace restarts.
|
|
47
|
-
- Restart the bridge or rerun `npm run codespaces:bootstrap` to rerun the automatic visibility step.
|
|
48
|
-
- If needed, set both ports public manually:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
gh codespace ports visibility 8787:public 8788:public
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
- If `gh` is unavailable in the codespace, use the Codespaces `Ports` panel and change both forwarded ports to `Public`.
|
|
55
|
-
- Keep bridge auth enabled. Public forwarded ports without bridge auth are not a safe setup.
|
|
56
|
-
- If GitHub direct sign-in is not showing in the app, confirm the build includes `EXPO_PUBLIC_GITHUB_CLIENT_ID`.
|
|
57
|
-
- If in-app Codespace creation forks or targets the wrong repo, check `EXPO_PUBLIC_GITHUB_CODESPACES_REPO_NAME`, `EXPO_PUBLIC_GITHUB_CODESPACES_SOURCE_OWNER`, and `EXPO_PUBLIC_GITHUB_CODESPACES_REPO_REF` in the mobile build env.
|
|
58
|
-
|
|
59
|
-
## GitHub Codespaces bootstrap did not start the bridge
|
|
60
|
-
|
|
61
|
-
- Check the post-start command output in the Codespace terminal or rerun it manually:
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
npm run codespaces:bootstrap -- --prepare-only
|
|
65
|
-
npm run codespaces:bootstrap
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
- On the minimal `clawdex-codespace` template, rerun the packaged bootstrap instead:
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
CLAWDEX_WORKSPACE_ROOT="$PWD" node "$(npm root -g)/clawdex-mobile/scripts/codespaces-bootstrap.js" --prepare-only
|
|
72
|
-
CLAWDEX_WORKSPACE_ROOT="$PWD" node "$(npm root -g)/clawdex-mobile/scripts/codespaces-bootstrap.js"
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
- The Codespaces bootstrap only prepares the `codex` engine. It will try to install Codex automatically with `npm install -g @openai/codex`.
|
|
76
|
-
- `--prepare-only` installs Codex if needed and prebuilds the Rust bridge binary without starting the bridge.
|
|
77
|
-
- The bootstrap also enables `BRIDGE_GITHUB_CODESPACES_AUTH=true` so GitHub bearer tokens can connect directly to the bridge.
|
|
78
|
-
- If that install fails, fix npm/global package permissions in the codespace and rerun the bootstrap.
|
|
79
|
-
- Bridge startup logs and runtime state live in the Codespace repo root:
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
tail -n 200 .bridge.log
|
|
83
|
-
ls -la .bridge.pid .bridge.log .env.secure
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
- To only rewrite `.env.secure` without starting the bridge:
|
|
87
|
-
|
|
88
|
-
```bash
|
|
89
|
-
npm run codespaces:bootstrap -- --no-start
|
|
90
|
-
```
|
|
91
|
-
|
|
92
42
|
## Voice transcription says no credentials were found
|
|
93
43
|
|
|
94
|
-
- The bridge can transcribe with
|
|
95
|
-
-
|
|
96
|
-
- If you still see the error after logging in, restart the bridge once so it reloads the persisted auth cache:
|
|
44
|
+
- The bridge can transcribe with `OPENAI_API_KEY`, `BRIDGE_CHATGPT_ACCESS_TOKEN`, a legacy bridge token cache, or the Codex-managed ChatGPT token in `$CODEX_HOME/auth.json`.
|
|
45
|
+
- If Codex login just completed, restart the bridge once so it reloads the Codex auth home:
|
|
97
46
|
|
|
98
47
|
```bash
|
|
99
48
|
npm run secure:bridge
|
|
100
49
|
```
|
|
101
50
|
|
|
102
|
-
- You can inspect whether
|
|
51
|
+
- You can inspect whether Codex saved auth:
|
|
103
52
|
|
|
104
53
|
```bash
|
|
105
|
-
ls -la
|
|
54
|
+
ls -la "${CODEX_HOME:-$HOME/.codex}/auth.json"
|
|
106
55
|
```
|
|
107
56
|
|
|
108
57
|
## Local browser preview does not open
|
|
@@ -115,7 +64,6 @@ ls -la .clawdex-chatgpt-auth.json
|
|
|
115
64
|
- By default the preview server binds to `BRIDGE_PORT + 1`.
|
|
116
65
|
- Restart the bridge after changing `BRIDGE_PREVIEW_PORT`.
|
|
117
66
|
- If the page shell loads but live reload does not, verify the target dev server is still serving its WebSocket/HMR endpoint locally.
|
|
118
|
-
- In GitHub Codespaces, the preview port (`8788` by default) must also be public or the Browser screen will fail even if the main bridge port works.
|
|
119
67
|
|
|
120
68
|
## Tailscale issues
|
|
121
69
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clawdex-mobile",
|
|
3
|
-
"version": "5.1.3-internal.
|
|
3
|
+
"version": "5.1.3-internal.10",
|
|
4
4
|
"description": "Private-network mobile bridge and CLI for Codex and OpenCode",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"codex",
|
|
@@ -34,7 +34,6 @@
|
|
|
34
34
|
"docs/troubleshooting.md",
|
|
35
35
|
"scripts/bridge-binary.js",
|
|
36
36
|
"scripts/bridge-self-update.js",
|
|
37
|
-
"scripts/codespaces-bootstrap.js",
|
|
38
37
|
"scripts/setup-secure-dev.sh",
|
|
39
38
|
"scripts/setup-wizard.sh",
|
|
40
39
|
"scripts/start-bridge-secure.js",
|
|
@@ -52,6 +51,13 @@
|
|
|
52
51
|
"mobile": "./scripts/start-expo.sh mobile",
|
|
53
52
|
"ios": "./scripts/start-expo.sh ios",
|
|
54
53
|
"android": "./scripts/start-expo.sh android",
|
|
54
|
+
"desktop:mac": "swift run --package-path apps/macos ClawdexDesktop",
|
|
55
|
+
"desktop:mac:build": "swift build --package-path apps/macos",
|
|
56
|
+
"desktop:mac:bundle": "./scripts/build-macos-desktop-app.sh",
|
|
57
|
+
"desktop:mac:sign": "./scripts/sign-macos-desktop-app.sh",
|
|
58
|
+
"desktop:mac:notarize": "./scripts/notarize-macos-desktop-app.sh",
|
|
59
|
+
"stack:lan": "./scripts/start-mobile-stack-lan.sh",
|
|
60
|
+
"stack:tailscale": "./scripts/start-mobile-stack-tailscale.sh",
|
|
55
61
|
"bridge": "BRIDGE_WORKDIR=$(pwd) npm run -w @codex/rust-bridge dev",
|
|
56
62
|
"bridge:package:stage-current": "node ./scripts/bridge-binary.js stage-current",
|
|
57
63
|
"setup:wizard": "./scripts/setup-wizard.sh",
|
|
@@ -59,13 +65,12 @@
|
|
|
59
65
|
"secure:setup": "./scripts/setup-secure-dev.sh",
|
|
60
66
|
"secure:bridge": "node ./scripts/start-bridge-secure.js",
|
|
61
67
|
"secure:bridge:dev": "node ./scripts/start-bridge-secure.js --dev",
|
|
62
|
-
"codespaces:bootstrap": "node ./scripts/codespaces-bootstrap.js",
|
|
63
68
|
"bridge:ts": "BRIDGE_WORKDIR=$(pwd) npm run -w @codex/mac-bridge dev",
|
|
64
69
|
"version:sync": "node scripts/sync-versions.js",
|
|
65
70
|
"build": "npm run --workspaces build",
|
|
66
71
|
"typecheck": "npm run --workspaces typecheck",
|
|
67
72
|
"lint": "npm run --workspaces lint",
|
|
68
|
-
"test": "npm run test -w @codex/mac-bridge && npm run test -w apps/mobile && npm run test -w @codex/rust-bridge",
|
|
73
|
+
"test": "npm run test -w @codex/mac-bridge && npm run test -w apps/mobile && npm run test -w @codex/rust-bridge && npm run test -w @clawdex/cursor-app-server",
|
|
69
74
|
"teardown": "./scripts/teardown.sh"
|
|
70
75
|
}
|
|
71
76
|
}
|
|
@@ -13,6 +13,9 @@ MOBILE_ENV_EXAMPLE="$ROOT_DIR/apps/mobile/.env.example"
|
|
|
13
13
|
BRIDGE_ACTIVE_ENGINE="${BRIDGE_ACTIVE_ENGINE:-codex}"
|
|
14
14
|
BRIDGE_ENABLED_ENGINES="${BRIDGE_ENABLED_ENGINES:-$BRIDGE_ACTIVE_ENGINE}"
|
|
15
15
|
OPENCODE_CLI_BIN="${OPENCODE_CLI_BIN:-opencode}"
|
|
16
|
+
CURSOR_APP_SERVER_BIN="${CURSOR_APP_SERVER_BIN:-cursor-app-server}"
|
|
17
|
+
CURSOR_API_KEY="${CURSOR_API_KEY:-}"
|
|
18
|
+
CURSOR_MODEL="${CURSOR_MODEL:-}"
|
|
16
19
|
BRIDGE_CONNECT_URL=""
|
|
17
20
|
BRIDGE_PREVIEW_CONNECT_URL=""
|
|
18
21
|
|
|
@@ -109,51 +112,6 @@ is_non_loopback_ipv4() {
|
|
|
109
112
|
[[ "$ip" != 127.* ]]
|
|
110
113
|
}
|
|
111
114
|
|
|
112
|
-
normalize_base_url() {
|
|
113
|
-
local value="$1"
|
|
114
|
-
value="$(printf '%s' "$value" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
|
|
115
|
-
if [[ -z "$value" ]]; then
|
|
116
|
-
return 1
|
|
117
|
-
fi
|
|
118
|
-
|
|
119
|
-
case "$value" in
|
|
120
|
-
http://*|https://*)
|
|
121
|
-
;;
|
|
122
|
-
*)
|
|
123
|
-
return 1
|
|
124
|
-
;;
|
|
125
|
-
esac
|
|
126
|
-
|
|
127
|
-
printf '%s' "${value%/}"
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
resolve_codespaces_forwarded_url() {
|
|
131
|
-
local port="$1"
|
|
132
|
-
local override="$2"
|
|
133
|
-
local normalized_override=""
|
|
134
|
-
local codespace_name=""
|
|
135
|
-
local forwarding_domain=""
|
|
136
|
-
|
|
137
|
-
if [[ -n "$override" ]]; then
|
|
138
|
-
normalized_override="$(normalize_base_url "$override" || true)"
|
|
139
|
-
if [[ -z "$normalized_override" ]]; then
|
|
140
|
-
echo "error: invalid Codespaces URL override '$override'." >&2
|
|
141
|
-
return 1
|
|
142
|
-
fi
|
|
143
|
-
printf '%s' "$normalized_override"
|
|
144
|
-
return 0
|
|
145
|
-
fi
|
|
146
|
-
|
|
147
|
-
codespace_name="$(printf '%s' "${CODESPACE_NAME:-}" | tr -d '[:space:]')"
|
|
148
|
-
forwarding_domain="$(printf '%s' "${GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN:-}" | tr -d '[:space:]')"
|
|
149
|
-
if [[ -z "$codespace_name" ]] || [[ -z "$forwarding_domain" ]]; then
|
|
150
|
-
echo "error: GitHub Codespaces env vars are missing. Run this inside an active codespace or set BRIDGE_CONNECT_URL_OVERRIDE." >&2
|
|
151
|
-
return 1
|
|
152
|
-
fi
|
|
153
|
-
|
|
154
|
-
printf 'https://%s-%s.%s' "$codespace_name" "$port" "$forwarding_domain"
|
|
155
|
-
}
|
|
156
|
-
|
|
157
115
|
resolve_tailscale_ipv4() {
|
|
158
116
|
local ip
|
|
159
117
|
ip="$(tailscale ip -4 2>/dev/null | head -n1 | tr -d '[:space:]' || true)"
|
|
@@ -269,19 +227,19 @@ HOST_SOURCE=""
|
|
|
269
227
|
BRIDGE_NETWORK_MODE="${BRIDGE_NETWORK_MODE:-tailscale}"
|
|
270
228
|
|
|
271
229
|
case "$BRIDGE_NETWORK_MODE" in
|
|
272
|
-
tailscale|local
|
|
230
|
+
tailscale|local)
|
|
273
231
|
;;
|
|
274
232
|
*)
|
|
275
|
-
echo "error: BRIDGE_NETWORK_MODE must be 'tailscale'
|
|
233
|
+
echo "error: BRIDGE_NETWORK_MODE must be 'tailscale' or 'local'." >&2
|
|
276
234
|
exit 1
|
|
277
235
|
;;
|
|
278
236
|
esac
|
|
279
237
|
|
|
280
238
|
case "$BRIDGE_ACTIVE_ENGINE" in
|
|
281
|
-
codex|opencode)
|
|
239
|
+
codex|opencode|cursor)
|
|
282
240
|
;;
|
|
283
241
|
*)
|
|
284
|
-
echo "error: BRIDGE_ACTIVE_ENGINE must be 'codex' or '
|
|
242
|
+
echo "error: BRIDGE_ACTIVE_ENGINE must be 'codex', 'opencode', or 'cursor'." >&2
|
|
285
243
|
exit 1
|
|
286
244
|
;;
|
|
287
245
|
esac
|
|
@@ -301,7 +259,7 @@ validate_enabled_engines() {
|
|
|
301
259
|
continue
|
|
302
260
|
fi
|
|
303
261
|
case "$normalized" in
|
|
304
|
-
codex|opencode)
|
|
262
|
+
codex|opencode|cursor)
|
|
305
263
|
;;
|
|
306
264
|
*)
|
|
307
265
|
return 1
|
|
@@ -323,7 +281,7 @@ validate_enabled_engines() {
|
|
|
323
281
|
}
|
|
324
282
|
|
|
325
283
|
if ! validate_enabled_engines "$BRIDGE_ENABLED_ENGINES"; then
|
|
326
|
-
echo "error: BRIDGE_ENABLED_ENGINES must contain one or more of 'codex' and '
|
|
284
|
+
echo "error: BRIDGE_ENABLED_ENGINES must contain one or more of 'codex', 'opencode', and 'cursor'." >&2
|
|
327
285
|
exit 1
|
|
328
286
|
fi
|
|
329
287
|
|
|
@@ -342,9 +300,6 @@ else
|
|
|
342
300
|
ensure_tailscale_cli
|
|
343
301
|
BRIDGE_HOST="$(resolve_tailscale_ipv4)"
|
|
344
302
|
HOST_SOURCE="tailscale"
|
|
345
|
-
elif [[ "$BRIDGE_NETWORK_MODE" == "codespaces" ]]; then
|
|
346
|
-
BRIDGE_HOST="127.0.0.1"
|
|
347
|
-
HOST_SOURCE="codespaces"
|
|
348
303
|
else
|
|
349
304
|
BRIDGE_HOST="$(resolve_local_ipv4)"
|
|
350
305
|
HOST_SOURCE="local"
|
|
@@ -358,17 +313,8 @@ if [[ "$BRIDGE_PREVIEW_PORT" == "$BRIDGE_PORT" ]]; then
|
|
|
358
313
|
exit 1
|
|
359
314
|
fi
|
|
360
315
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
resolve_codespaces_forwarded_url "$BRIDGE_PORT" "${BRIDGE_CONNECT_URL_OVERRIDE:-}"
|
|
364
|
-
)"
|
|
365
|
-
BRIDGE_PREVIEW_CONNECT_URL="$(
|
|
366
|
-
resolve_codespaces_forwarded_url "$BRIDGE_PREVIEW_PORT" "${BRIDGE_PREVIEW_CONNECT_URL_OVERRIDE:-}"
|
|
367
|
-
)"
|
|
368
|
-
else
|
|
369
|
-
BRIDGE_CONNECT_URL="http://$BRIDGE_HOST:$BRIDGE_PORT"
|
|
370
|
-
BRIDGE_PREVIEW_CONNECT_URL="http://$BRIDGE_HOST:$BRIDGE_PREVIEW_PORT"
|
|
371
|
-
fi
|
|
316
|
+
BRIDGE_CONNECT_URL="http://$BRIDGE_HOST:$BRIDGE_PORT"
|
|
317
|
+
BRIDGE_PREVIEW_CONNECT_URL="http://$BRIDGE_HOST:$BRIDGE_PREVIEW_PORT"
|
|
372
318
|
|
|
373
319
|
EXISTING_TOKEN=""
|
|
374
320
|
if [[ -f "$SECURE_ENV_FILE" ]]; then
|
|
@@ -380,13 +326,6 @@ if [[ -z "$BRIDGE_TOKEN" ]]; then
|
|
|
380
326
|
BRIDGE_TOKEN="$(openssl rand -hex 24)"
|
|
381
327
|
fi
|
|
382
328
|
|
|
383
|
-
GITHUB_CODESPACES_AUTH_ENABLED="false"
|
|
384
|
-
GITHUB_CODESPACES_NAME=""
|
|
385
|
-
if [[ "$BRIDGE_NETWORK_MODE" == "codespaces" ]]; then
|
|
386
|
-
GITHUB_CODESPACES_AUTH_ENABLED="true"
|
|
387
|
-
GITHUB_CODESPACES_NAME="$(printf '%s' "${CODESPACE_NAME:-}" | tr -d '[:space:]')"
|
|
388
|
-
fi
|
|
389
|
-
|
|
390
329
|
cat > "$SECURE_ENV_FILE" <<EOT
|
|
391
330
|
BRIDGE_NETWORK_MODE=$BRIDGE_NETWORK_MODE
|
|
392
331
|
BRIDGE_HOST=$BRIDGE_HOST
|
|
@@ -396,13 +335,13 @@ BRIDGE_CONNECT_URL=$BRIDGE_CONNECT_URL
|
|
|
396
335
|
BRIDGE_PREVIEW_CONNECT_URL=$BRIDGE_PREVIEW_CONNECT_URL
|
|
397
336
|
BRIDGE_AUTH_TOKEN=$BRIDGE_TOKEN
|
|
398
337
|
BRIDGE_ALLOW_QUERY_TOKEN_AUTH=true
|
|
399
|
-
BRIDGE_GITHUB_CODESPACES_AUTH=$GITHUB_CODESPACES_AUTH_ENABLED
|
|
400
|
-
BRIDGE_GITHUB_CODESPACE_NAME=$GITHUB_CODESPACES_NAME
|
|
401
|
-
BRIDGE_GITHUB_API_URL=https://api.github.com
|
|
402
338
|
BRIDGE_ACTIVE_ENGINE=$BRIDGE_ACTIVE_ENGINE
|
|
403
339
|
BRIDGE_ENABLED_ENGINES=$BRIDGE_ENABLED_ENGINES
|
|
404
340
|
CODEX_CLI_BIN=codex
|
|
405
341
|
OPENCODE_CLI_BIN=$OPENCODE_CLI_BIN
|
|
342
|
+
CURSOR_APP_SERVER_BIN=$CURSOR_APP_SERVER_BIN
|
|
343
|
+
CURSOR_API_KEY=$CURSOR_API_KEY
|
|
344
|
+
CURSOR_MODEL=$CURSOR_MODEL
|
|
406
345
|
BRIDGE_WORKDIR=$ROOT_DIR
|
|
407
346
|
EOT
|
|
408
347
|
|
|
@@ -422,9 +361,6 @@ echo "Bridge network mode: $BRIDGE_NETWORK_MODE"
|
|
|
422
361
|
echo "Bridge host: $BRIDGE_HOST ($HOST_SOURCE)"
|
|
423
362
|
echo "Bridge port: $BRIDGE_PORT"
|
|
424
363
|
echo "Bridge connect URL: $BRIDGE_CONNECT_URL"
|
|
425
|
-
if [[ "$GITHUB_CODESPACES_AUTH_ENABLED" == "true" ]]; then
|
|
426
|
-
echo "GitHub Codespaces auth: enabled"
|
|
427
|
-
fi
|
|
428
364
|
echo "Harnesses: $BRIDGE_ENABLED_ENGINES"
|
|
429
365
|
echo "Token source: $SECURE_ENV_FILE"
|
|
430
366
|
if has_local_mobile_workspace; then
|