remodex-windows-fix 1.0.2 → 1.0.3

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
@@ -1,183 +1,186 @@
1
- # remodex-windows-fix
2
-
3
- Windows-friendly mirror of `remodex` with a launcher fix for `codex app-server`.
4
-
5
- ## What Changed
6
-
7
- - Fixes Windows startup when `remodex up` tries to spawn `codex` and fails with `spawn codex ENOENT`.
8
- - Prefers `codex.cmd` or `codex.bat` on Windows and runs them with shell support.
9
- - Falls back to `codex.exe` when a wrapper script is not present.
10
- - Adds `REMODEX_CODEX_BIN` and `PHODEX_CODEX_BIN` overrides for explicit Codex binary selection.
11
- - Prevents immediate uncaught startup crashes by routing launcher failures through Remodex error handling.
12
-
13
- ## Why This Exists
14
-
15
- On Windows, `codex` is often installed through npm as a `.cmd` shim. A plain Node `spawn("codex", ["app-server"])` call can fail even when `codex` works in PowerShell. This fork resolves the executable explicitly before launching the bridge.
16
-
17
- ## Install
18
-
19
- Install from this GitHub repository:
20
-
21
- ```bash
22
- npm install -g github:needitem/remodex-windows-fix
23
- ```
24
-
25
- Global CLI command:
26
-
27
- ```bash
28
- remodex-windows-fix
29
- ```
30
-
31
- ## Usage
32
-
33
- Start the bridge:
34
-
35
- ```bash
36
- remodex-windows-fix up
37
- ```
38
-
39
- Resume the last active thread:
40
-
41
- ```bash
42
- remodex-windows-fix resume
43
- ```
44
-
45
- Watch rollout output:
46
-
47
- ```bash
48
- remodex-windows-fix watch [threadId]
49
- ```
50
-
51
- ## Windows Override
52
-
53
- If you want to force a specific Codex binary, set one of these environment variables before running `remodex up`:
54
-
55
- ```powershell
56
- $env:REMODEX_CODEX_BIN = "C:\Users\th072\AppData\Roaming\npm\codex.cmd"
57
- ```
58
-
59
- Legacy alias:
60
-
61
- ```powershell
62
- $env:PHODEX_CODEX_BIN = "C:\Users\th072\AppData\Roaming\npm\codex.cmd"
63
- ```
64
-
65
- ## Self-Hosted Relay
66
-
67
- This repository now includes the upstream-compatible relay code and a local runner.
68
-
69
- Start your own relay:
70
-
71
- ```bash
72
- npm run relay
73
- ```
74
-
75
- Or use the bundled binary directly:
76
-
77
- ```bash
78
- remodex-relay
79
- ```
80
-
81
- Optional relay host/port overrides:
82
-
83
- ```powershell
84
- $env:REMODEX_RELAY_HOST = "0.0.0.0"
85
- $env:REMODEX_RELAY_PORT = "9000"
86
- ```
87
-
88
- Point the bridge at your relay:
89
-
90
- ```powershell
91
- $env:REMODEX_RELAY = "ws://YOUR_HOST:9000/relay"
92
- remodex up
93
- ```
94
-
95
- For TLS/reverse-proxy setups, use the public `wss://YOUR_DOMAIN/relay` URL instead.
96
-
97
- Health endpoint:
98
-
99
- ```text
100
- GET /health
101
- ```
102
-
103
- ## Cloudflare Deploy
104
-
105
- This repository also includes a Cloudflare Workers relay implementation in [cloudflare/worker.mjs](cloudflare/worker.mjs) with Durable Objects configured in [wrangler.toml](wrangler.toml).
106
-
107
- GitHub itself still does not host persistent WebSocket servers, but Cloudflare Workers can deploy this relay directly from your GitHub repository without running anything locally.
108
-
109
- Import this repository in Cloudflare:
110
-
111
- 1. Open Cloudflare Workers & Pages.
112
- 2. Create or import a Worker from your GitHub repository.
113
- 3. Use the worker name `remodex-relay` so it matches [wrangler.toml](wrangler.toml).
114
- 4. Deploy the repository as-is.
115
- 5. After deploy, use the public Worker URL as the relay base:
116
-
117
- ```powershell
118
- $env:REMODEX_RELAY = "wss://YOUR-WORKER.YOUR-SUBDOMAIN.workers.dev/relay"
119
- remodex-windows-fix up
120
- ```
121
-
122
- Current deployed example for this repository:
123
-
124
- ```powershell
125
- $env:REMODEX_RELAY = "wss://remodex-relay.th07290828.workers.dev/relay"
126
- remodex-windows-fix up
127
- ```
128
-
129
- If you are using `cmd.exe` instead of PowerShell:
130
-
131
- ```cmd
132
- set REMODEX_RELAY=wss://remodex-relay.th07290828.workers.dev/relay
133
- remodex-windows-fix up
134
- ```
135
-
136
- Health check:
137
-
138
- ```text
139
- https://remodex-relay.th07290828.workers.dev/health
140
- ```
141
-
142
- Cloudflare health endpoint:
143
-
144
- ```text
145
- GET /health
146
- ```
147
-
148
- ## Alternative GitHub Deploy
149
-
150
- If you prefer a normal Node web service instead of Workers, this repository still includes the Render-compatible runner in [render.yaml](render.yaml).
151
-
152
- ```powershell
153
- $env:REMODEX_RELAY = "wss://YOUR-SERVICE.onrender.com/relay"
154
- remodex-windows-fix up
155
- ```
156
-
157
- ## Validation
158
-
159
- Typical local verification:
160
-
161
- ```bash
162
- codex --version
163
- codex app-server --help
164
- remodex-windows-fix up
165
- ```
166
-
167
- Expected Windows resolution after the fix:
168
-
169
- ```text
170
- C:\Users\th072\AppData\Roaming\npm\codex.cmd app-server
171
- ```
172
-
173
- ## Project Layout
174
-
175
- ```text
176
- bin/
177
- src/
178
- package.json
179
- ```
180
-
181
- ## Attribution
182
-
183
- This repository preserves the upstream Remodex package structure and credits the original package author in `package.json`. This fork adds a Windows launcher compatibility patch and accompanying documentation.
1
+ # remodex-windows-fix
2
+
3
+ Windows-friendly mirror of `remodex` with a launcher fix for `codex app-server`.
4
+
5
+ ## What Changed
6
+
7
+ - Fixes Windows startup when `remodex up` tries to spawn `codex` and fails with `spawn codex ENOENT`.
8
+ - Prefers `codex.cmd` or `codex.bat` on Windows and runs them with shell support.
9
+ - Falls back to `codex.exe` when a wrapper script is not present.
10
+ - Adds `REMODEX_CODEX_BIN` and `PHODEX_CODEX_BIN` overrides for explicit Codex binary selection.
11
+ - Prevents immediate uncaught startup crashes by routing launcher failures through Remodex error handling.
12
+
13
+ ## Why This Exists
14
+
15
+ On Windows, `codex` is often installed through npm as a `.cmd` shim. A plain Node `spawn("codex", ["app-server"])` call can fail even when `codex` works in PowerShell. This fork resolves the executable explicitly before launching the bridge.
16
+
17
+ ## Install
18
+
19
+ Install from npm:
20
+
21
+ ```bash
22
+ npm install -g remodex-windows-fix
23
+ ```
24
+
25
+ Global CLI command:
26
+
27
+ ```bash
28
+ remodex-windows-fix
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ Start the bridge:
34
+
35
+ ```bash
36
+ remodex-windows-fix up
37
+ ```
38
+
39
+ Resume the last active thread:
40
+
41
+ ```bash
42
+ remodex-windows-fix resume
43
+ ```
44
+
45
+ Watch rollout output:
46
+
47
+ ```bash
48
+ remodex-windows-fix watch [threadId]
49
+ ```
50
+
51
+ ## Windows Override
52
+
53
+ If you want to force a specific Codex binary, set one of these environment variables before running `remodex up`:
54
+
55
+ ```powershell
56
+ $env:REMODEX_CODEX_BIN = "C:\Users\th072\AppData\Roaming\npm\codex.cmd"
57
+ ```
58
+
59
+ Legacy alias:
60
+
61
+ ```powershell
62
+ $env:PHODEX_CODEX_BIN = "C:\Users\th072\AppData\Roaming\npm\codex.cmd"
63
+ ```
64
+
65
+ ## Self-Hosted Relay
66
+
67
+ This repository now includes the upstream-compatible relay code and a local runner.
68
+
69
+ Start your own relay:
70
+
71
+ ```bash
72
+ npm run relay
73
+ ```
74
+
75
+ Or use the bundled binary directly:
76
+
77
+ ```bash
78
+ remodex-relay
79
+ ```
80
+
81
+ Optional relay host/port overrides:
82
+
83
+ ```powershell
84
+ $env:REMODEX_RELAY_HOST = "0.0.0.0"
85
+ $env:REMODEX_RELAY_PORT = "9000"
86
+ ```
87
+
88
+ Point the bridge at your relay:
89
+
90
+ ```powershell
91
+ $env:REMODEX_RELAY = "ws://YOUR_HOST:9000/relay"
92
+ remodex-windows-fix up
93
+ ```
94
+
95
+ For TLS/reverse-proxy setups, use the public `wss://YOUR_DOMAIN/relay` URL instead.
96
+
97
+ Health endpoint:
98
+
99
+ ```text
100
+ GET /health
101
+ ```
102
+
103
+ ## Cloudflare Deploy
104
+
105
+ This repository also includes a Cloudflare Workers relay implementation in [cloudflare/worker.mjs](cloudflare/worker.mjs) with Durable Objects configured in [wrangler.toml](wrangler.toml).
106
+
107
+ GitHub itself still does not host persistent WebSocket servers, but Cloudflare Workers can deploy this relay directly from your GitHub repository without running anything locally.
108
+
109
+ Import this repository in Cloudflare:
110
+
111
+ 1. Open Cloudflare Workers & Pages.
112
+ 2. Create or import a Worker from your GitHub repository.
113
+ 3. Use the worker name `remodex-relay` so it matches [wrangler.toml](wrangler.toml).
114
+ 4. Deploy the repository as-is.
115
+ 5. After deploy, use the public Worker URL as the relay base:
116
+
117
+ ```powershell
118
+ $env:REMODEX_RELAY = "wss://YOUR-WORKER.YOUR-SUBDOMAIN.workers.dev/relay"
119
+ remodex-windows-fix up
120
+ ```
121
+
122
+ Current deployed example for this repository:
123
+
124
+ ```powershell
125
+ $env:REMODEX_RELAY = "wss://remodex-relay.th07290828.workers.dev/relay"
126
+ remodex-windows-fix up
127
+ ```
128
+
129
+ If you are using `cmd.exe` instead of PowerShell:
130
+
131
+ ```cmd
132
+ set REMODEX_RELAY=wss://remodex-relay.th07290828.workers.dev/relay
133
+ remodex-windows-fix up
134
+ ```
135
+
136
+ Health check:
137
+
138
+ ```text
139
+ https://remodex-relay.th07290828.workers.dev/health
140
+ ```
141
+
142
+ Cloudflare health endpoint:
143
+
144
+ ```text
145
+ GET /health
146
+ ```
147
+
148
+ ## Alternative GitHub Deploy
149
+
150
+ If you prefer a normal Node web service instead of Workers, this repository still includes the Render-compatible runner in [render.yaml](render.yaml).
151
+
152
+ ```powershell
153
+ $env:REMODEX_RELAY = "wss://YOUR-SERVICE.onrender.com/relay"
154
+ remodex-windows-fix up
155
+ ```
156
+
157
+ ## Validation
158
+
159
+ Typical local verification:
160
+
161
+ ```bash
162
+ codex --version
163
+ codex app-server --help
164
+ remodex-windows-fix up
165
+ ```
166
+
167
+ Expected Windows resolution after the fix:
168
+
169
+ ```text
170
+ C:\Users\th072\AppData\Roaming\npm\codex.cmd app-server
171
+ ```
172
+
173
+ ## Project Layout
174
+
175
+ ```text
176
+ bin/
177
+ cloudflare/
178
+ relay/
179
+ src/
180
+ wrangler.toml
181
+ package.json
182
+ ```
183
+
184
+ ## Attribution
185
+
186
+ This repository preserves the upstream Remodex package structure and credits the original package author in `package.json`. This fork adds a Windows launcher compatibility patch and accompanying documentation.
package/bin/phodex.js CHANGED
@@ -1,8 +1,8 @@
1
- #!/usr/bin/env node
2
- // FILE: phodex.js
3
- // Purpose: Backward-compatible wrapper that forwards legacy `phodex up` usage to `remodex up`.
4
- // Layer: CLI binary
5
- // Exports: none
6
- // Depends on: ./remodex
7
-
8
- require("./remodex");
1
+ #!/usr/bin/env node
2
+ // FILE: phodex.js
3
+ // Purpose: Backward-compatible wrapper that forwards legacy `phodex up` usage to `remodex up`.
4
+ // Layer: CLI binary
5
+ // Exports: none
6
+ // Depends on: ./remodex
7
+
8
+ require("./remodex");
@@ -1,19 +1,19 @@
1
- #!/usr/bin/env node
2
- // FILE: remodex-relay.js
3
- // Purpose: CLI entrypoint for running the bundled Remodex relay locally.
4
- // Layer: CLI binary
5
- // Exports: none
6
- // Depends on: ../src/relay-server
7
-
8
- const { startRelayServer } = require("../src/relay-server");
9
-
10
- if (process.argv.includes("--help") || process.argv.includes("-h")) {
11
- console.log("Usage: remodex-relay [port]");
12
- console.log("Environment: REMODEX_RELAY_HOST, REMODEX_RELAY_PORT");
13
- process.exit(0);
14
- }
15
-
16
- const portArg = process.argv[2];
17
- startRelayServer({
18
- port: portArg ? Number.parseInt(portArg, 10) : undefined,
19
- });
1
+ #!/usr/bin/env node
2
+ // FILE: remodex-relay.js
3
+ // Purpose: CLI entrypoint for running the bundled Remodex relay locally.
4
+ // Layer: CLI binary
5
+ // Exports: none
6
+ // Depends on: ../src/relay-server
7
+
8
+ const { startRelayServer } = require("../src/relay-server");
9
+
10
+ if (process.argv.includes("--help") || process.argv.includes("-h")) {
11
+ console.log("Usage: remodex-relay [port]");
12
+ console.log("Environment: REMODEX_RELAY_HOST, REMODEX_RELAY_PORT");
13
+ process.exit(0);
14
+ }
15
+
16
+ const portArg = process.argv[2];
17
+ startRelayServer({
18
+ port: portArg ? Number.parseInt(portArg, 10) : undefined,
19
+ });
package/bin/remodex.js CHANGED
@@ -1,44 +1,44 @@
1
- #!/usr/bin/env node
2
- // FILE: remodex.js
3
- // Purpose: CLI surface for starting the local Remodex bridge, reopening the latest active thread, and tailing its rollout file.
4
- // Layer: CLI binary
5
- // Exports: none
6
- // Depends on: ../src
7
-
8
- const { startBridge, openLastActiveThread, watchThreadRollout } = require("../src");
9
-
10
- const command = process.argv[2] || "up";
11
-
12
- if (command === "up") {
13
- startBridge();
14
- return;
15
- }
16
-
17
- if (command === "resume") {
18
- try {
19
- const state = openLastActiveThread();
20
- console.log(
21
- `[remodex] Opened last active thread: ${state.threadId} (${state.source || "unknown"})`
22
- );
23
- } catch (error) {
24
- console.error(`[remodex] ${(error && error.message) || "Failed to reopen the last thread."}`);
25
- process.exit(1);
26
- }
27
- return;
28
- }
29
-
30
- if (command === "watch") {
31
- try {
32
- watchThreadRollout(process.argv[3] || "");
33
- } catch (error) {
34
- console.error(`[remodex] ${(error && error.message) || "Failed to watch the thread rollout."}`);
35
- process.exit(1);
36
- }
37
- return;
38
- }
39
-
40
- if (command !== "up") {
41
- console.error(`Unknown command: ${command}`);
42
- console.error("Usage: remodex up | remodex resume | remodex watch [threadId]");
43
- process.exit(1);
44
- }
1
+ #!/usr/bin/env node
2
+ // FILE: remodex.js
3
+ // Purpose: CLI surface for starting the local Remodex bridge, reopening the latest active thread, and tailing its rollout file.
4
+ // Layer: CLI binary
5
+ // Exports: none
6
+ // Depends on: ../src
7
+
8
+ const { startBridge, openLastActiveThread, watchThreadRollout } = require("../src");
9
+
10
+ const command = process.argv[2] || "up";
11
+
12
+ if (command === "up") {
13
+ startBridge();
14
+ return;
15
+ }
16
+
17
+ if (command === "resume") {
18
+ try {
19
+ const state = openLastActiveThread();
20
+ console.log(
21
+ `[remodex] Opened last active thread: ${state.threadId} (${state.source || "unknown"})`
22
+ );
23
+ } catch (error) {
24
+ console.error(`[remodex] ${(error && error.message) || "Failed to reopen the last thread."}`);
25
+ process.exit(1);
26
+ }
27
+ return;
28
+ }
29
+
30
+ if (command === "watch") {
31
+ try {
32
+ watchThreadRollout(process.argv[3] || "");
33
+ } catch (error) {
34
+ console.error(`[remodex] ${(error && error.message) || "Failed to watch the thread rollout."}`);
35
+ process.exit(1);
36
+ }
37
+ return;
38
+ }
39
+
40
+ if (command !== "up") {
41
+ console.error(`Unknown command: ${command}`);
42
+ console.error("Usage: remodex up | remodex resume | remodex watch [threadId]");
43
+ process.exit(1);
44
+ }
@@ -1,16 +1,16 @@
1
- # Cloudflare Relay
2
-
3
- This folder contains a Cloudflare Workers + Durable Objects implementation of the Remodex relay protocol.
4
-
5
- It preserves the same session path and headers used by the bridge and iPhone client:
6
-
7
- - path: `/relay/{sessionId}`
8
- - required header: `x-role: mac` or `x-role: iphone`
9
- - close code `4000`: invalid session or role
10
- - close code `4001`: previous Mac connection replaced
11
- - close code `4002`: session unavailable / Mac disconnected
12
- - close code `4003`: previous iPhone connection replaced
13
-
14
- The public health endpoint is:
15
-
16
- - `GET /health`
1
+ # Cloudflare Relay
2
+
3
+ This folder contains a Cloudflare Workers + Durable Objects implementation of the Remodex relay protocol.
4
+
5
+ It preserves the same session path and headers used by the bridge and iPhone client:
6
+
7
+ - path: `/relay/{sessionId}`
8
+ - required header: `x-role: mac` or `x-role: iphone`
9
+ - close code `4000`: invalid session or role
10
+ - close code `4001`: previous Mac connection replaced
11
+ - close code `4002`: session unavailable / Mac disconnected
12
+ - close code `4003`: previous iPhone connection replaced
13
+
14
+ The public health endpoint is:
15
+
16
+ - `GET /health`
@@ -1,6 +1,5 @@
1
1
  import { DurableObject } from "cloudflare:workers";
2
2
 
3
- const MAX_HISTORY = 500;
4
3
  const CLOSE_CODE_INVALID_SESSION = 4000;
5
4
  const CLOSE_CODE_MAC_REPLACED = 4001;
6
5
  const CLOSE_CODE_SESSION_UNAVAILABLE = 4002;
@@ -36,19 +35,15 @@ export class SessionRelay extends DurableObject {
36
35
  this.env = env;
37
36
  this.mac = null;
38
37
  this.clients = new Set();
39
- this.history = [];
40
-
41
- this.ctx.blockConcurrencyWhile(async () => {
42
- this.history = (await this.ctx.storage.get("history")) || [];
43
- for (const socket of this.ctx.getWebSockets()) {
44
- const metadata = socket.deserializeAttachment() || {};
45
- if (metadata.role === "mac") {
46
- this.mac = socket;
47
- } else if (metadata.role === "iphone") {
48
- this.clients.add(socket);
49
- }
38
+
39
+ for (const socket of this.ctx.getWebSockets()) {
40
+ const metadata = socket.deserializeAttachment() || {};
41
+ if (metadata.role === "mac") {
42
+ this.mac = socket;
43
+ } else if (metadata.role === "iphone") {
44
+ this.clients.add(socket);
50
45
  }
51
- });
46
+ }
52
47
  }
53
48
 
54
49
  async fetch(request) {
@@ -104,10 +99,6 @@ export class SessionRelay extends DurableObject {
104
99
  }
105
100
  this.clients = new Set([serverSocket]);
106
101
  console.log(`[relay] iPhone connected -> session ${sessionId} (1 client)`);
107
-
108
- for (const msg of this.history) {
109
- this.safeSend(serverSocket, msg);
110
- }
111
102
  }
112
103
 
113
104
  return new Response(null, { status: 101, webSocket: clientSocket });
@@ -118,12 +109,6 @@ export class SessionRelay extends DurableObject {
118
109
  const text = normalizeMessage(message);
119
110
 
120
111
  if (metadata.role === "mac") {
121
- this.history.push(text);
122
- if (this.history.length > MAX_HISTORY) {
123
- this.history.shift();
124
- }
125
- await this.ctx.storage.put("history", this.history);
126
-
127
112
  for (const client of this.clients) {
128
113
  this.safeSend(client, text);
129
114
  }
@@ -158,11 +143,6 @@ export class SessionRelay extends DurableObject {
158
143
  } else if (metadata.role === "iphone") {
159
144
  this.clients.delete(socket);
160
145
  }
161
-
162
- if (!this.isSocketOpen(this.mac) && this.clients.size === 0) {
163
- this.history = [];
164
- await this.ctx.storage.deleteAll();
165
- }
166
146
  }
167
147
 
168
148
  isSocketOpen(socket) {