@4xeoz/re-entry 0.2.17 → 0.2.19

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
@@ -19,7 +19,7 @@ Requirements: macOS, Node.js 24+, Codex installed and signed in, and an absolute
19
19
  Codex may read and write.
20
20
 
21
21
  ```sh
22
- npx --yes --package=@4xeoz/re-entry re-entry install
22
+ npx --yes @4xeoz/re-entry install
23
23
  ```
24
24
 
25
25
  `npx` runs a temporary copy, so it does not leave a permanent shell command behind. Install the
@@ -30,8 +30,8 @@ npm install --global @4xeoz/re-entry
30
30
  ```
31
31
 
32
32
  The package installs both `re-entry` and the older `reentry` spelling; `re-entry` is the documented
33
- command. If you keep using the temporary `npx` form, run later commands with the same executable
34
- prefix, for example `npx --yes --package=@4xeoz/re-entry re-entry status`.
33
+ command. If you keep using the temporary `npx` form, run later commands with the same short
34
+ executable prefix, for example `npx --yes @4xeoz/re-entry status`.
35
35
 
36
36
  The CLI defaults to the current Cloud Receiver v2 preview at
37
37
  `https://cloud-receiver-delta.vercel.app`. Override it with `--receiver` or
@@ -42,13 +42,14 @@ The interactive CLI first offers Desktop, the current folder, or a small folder
42
42
  with ↑/↓ and Enter. If you want to skip the picker, pass the workspace directly:
43
43
 
44
44
  ```sh
45
- npx --yes --package=@4xeoz/re-entry re-entry install \
45
+ npx --yes @4xeoz/re-entry install \
46
46
  --codex-cd /absolute/path/to/your/project
47
47
  ```
48
48
 
49
- The guided screen stays intentionally small: **Workspace → System check → Connect Re-entry**. It
50
- shows one executable next command when setup finishes; internal Connector IDs, credential paths, and
51
- log paths stay out of the normal success screen.
49
+ The guided screen stays intentionally small: **Workspace → System check → Connect Re-entry**. On
50
+ success it shows a compact copy-paste command catalog for status, activity, testing, account
51
+ lifecycle, and local diagnostics. Internal Connector IDs, credential paths, and log paths stay out
52
+ of the normal success screen.
52
53
 
53
54
  Run this from the Host project directory, your home directory, or another normal working
54
55
  directory—not from a checked-out `runtime/local-connector` package directory. npm can treat that
@@ -66,7 +67,7 @@ re-entry install \
66
67
  Use `--receiver` to select an accepted replacement Receiver, such as a local historical preview:
67
68
 
68
69
  ```sh
69
- npx --yes --package=@4xeoz/re-entry re-entry install \
70
+ npx --yes @4xeoz/re-entry install \
70
71
  --receiver http://127.0.0.1:43224 \
71
72
  --codex-cd /absolute/path/to/your/project
72
73
  ```
@@ -104,12 +105,12 @@ re-entry uninstall
104
105
  If you used the temporary `npx` invocation:
105
106
 
106
107
  ```sh
107
- npx --yes --package=@4xeoz/re-entry re-entry status
108
- npx --yes --package=@4xeoz/re-entry re-entry listen
109
- npx --yes --package=@4xeoz/re-entry re-entry --help
110
- npx --yes --package=@4xeoz/re-entry re-entry stop
111
- npx --yes --package=@4xeoz/re-entry re-entry disconnect
112
- npx --yes --package=@4xeoz/re-entry re-entry uninstall
108
+ npx --yes @4xeoz/re-entry status
109
+ npx --yes @4xeoz/re-entry listen
110
+ npx --yes @4xeoz/re-entry --help
111
+ npx --yes @4xeoz/re-entry stop
112
+ npx --yes @4xeoz/re-entry disconnect
113
+ npx --yes @4xeoz/re-entry uninstall
113
114
  ```
114
115
 
115
116
  The status view checks the local authorization, background job, Receiver reachability, Node, and
@@ -119,16 +120,16 @@ the already-running background Connector and displays new activity until you pre
119
120
  not start a competing second poller. Useful development commands are:
120
121
 
121
122
  ```sh
122
- npx --yes --package=@4xeoz/re-entry re-entry doctor --codex-cd /absolute/path/to/project
123
- npx --yes --package=@4xeoz/re-entry re-entry connect --receiver http://127.0.0.1:43224
124
- npx --yes --package=@4xeoz/re-entry re-entry claim-once --codex-cd /absolute/path/to/project
125
- npx --yes --package=@4xeoz/re-entry re-entry start --codex-cd /absolute/path/to/project
123
+ npx --yes @4xeoz/re-entry doctor --codex-cd /absolute/path/to/project
124
+ npx --yes @4xeoz/re-entry connect --receiver http://127.0.0.1:43224
125
+ npx --yes @4xeoz/re-entry claim-once --codex-cd /absolute/path/to/project
126
+ npx --yes @4xeoz/re-entry start --codex-cd /absolute/path/to/project
126
127
  ```
127
128
 
128
129
  Test the local Codex handoff without waiting for Cloud work:
129
130
 
130
131
  ```sh
131
- npx --yes --package=@4xeoz/re-entry re-entry test "Reply with: Re-entry is working."
132
+ npx --yes @4xeoz/re-entry test "Reply with: Re-entry is working."
132
133
  ```
133
134
 
134
135
  This starts one fresh local Codex process through the same adapter seam used by real deliveries. It
@@ -137,12 +138,16 @@ underlying direct `codex exec` command. It does not create a Grant, claim Receiv
137
138
  Desktop UI thread, browser, or WebMCP return path. If it times out, run the equivalent direct
138
139
  `codex exec` command to inspect Codex's own output; the test does not contact the Receiver.
139
140
 
141
+ The one-shot test allows up to one hour by default. Override it with
142
+ `--activation-timeout <milliseconds>` when needed. Background delivery keeps its separate
143
+ 60-second adapter bound.
144
+
140
145
  To pause or remove the local Connector:
141
146
 
142
147
  ```sh
143
- npx --yes --package=@4xeoz/re-entry re-entry stop
144
- npx --yes --package=@4xeoz/re-entry re-entry disconnect
145
- npx --yes --package=@4xeoz/re-entry re-entry uninstall
148
+ npx --yes @4xeoz/re-entry stop
149
+ npx --yes @4xeoz/re-entry disconnect
150
+ npx --yes @4xeoz/re-entry uninstall
146
151
  ```
147
152
 
148
153
  `stop` pauses the macOS background service and keeps the account connection. `uninstall` requires
@@ -174,10 +179,10 @@ Copy this prompt into a coding-agent task:
174
179
 
175
180
  ```text
176
181
  Install the Re-entry Local Connector on this Mac. First read the package README. Verify Node.js 24
177
- or newer and locate the Connector executable. Run `npx --yes --package=@4xeoz/re-entry re-entry install` with an absolute
182
+ or newer and locate the Connector executable. Run `npx --yes @4xeoz/re-entry install` with an absolute
178
183
  project directory. Let the human create or sign in to a Re-entry account, click Pair this Mac, and
179
184
  enter the code in the CLI; never copy browser cookies, organization keys, Connector tokens, or private keys
180
- into chat, logs, source files, or git. Finish by running `npx --yes --package=@4xeoz/re-entry re-entry status`
185
+ into chat, logs, source files, or git. Finish by running `npx --yes @4xeoz/re-entry status`
181
186
  and report the bounded results without claiming Browser/WebMCP or production deployment.
182
187
  ```
183
188
 
@@ -250,9 +255,9 @@ npm publish --access public
250
255
  NPM versions are immutable: if the target version has already been published, bump it before
251
256
  publishing with `npm version patch --no-git-tag-version`.
252
257
 
253
- After publishing, users run `npx --yes --package=@4xeoz/re-entry re-entry install`. The explicit
254
- `--package` form works across npm versions when the package is scoped; the executable itself is
255
- still named `re-entry`. The command uses the built-in preview Receiver unless `--receiver` or
258
+ After publishing, users run `npx --yes @4xeoz/re-entry install`. The executable itself is still
259
+ named `re-entry`; the short package form works with the scoped package. The command uses the
260
+ built-in preview Receiver unless `--receiver` or
256
261
  `REENTRY_RECEIVER_ORIGIN` overrides it.
257
262
 
258
263
  A temporary `npx` invocation does not add `re-entry` to your shell `PATH`. If you prefer the shorter
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@4xeoz/re-entry",
3
- "version": "0.2.17",
3
+ "version": "0.2.19",
4
4
  "type": "module",
5
5
  "description": "Outbound Local Connector process for Re-entry Core; uses the Cloud Receiver v2 preview by default with an explicit override for other accepted origins.",
6
6
  "publishConfig": {
@@ -10,6 +10,8 @@ import {
10
10
  } from "./codex-discovery.mjs";
11
11
 
12
12
  export const CODEX_EXEC_ADAPTER_ID = "codex_exec_local";
13
+ export const DEFAULT_CODEX_PROMPT_TIMEOUT_MS = 3_600_000;
14
+ export const MAX_CODEX_PROMPT_TIMEOUT_MS = 3_600_000;
13
15
 
14
16
  const OPTION_FIELDS = Object.freeze([
15
17
  "workingDirectory",
@@ -89,7 +91,10 @@ export async function runCodexPrompt(options) {
89
91
  ? discoverCodexExecutable()
90
92
  : requireReference(options.executable, "Codex executable");
91
93
  const prompt = requirePrompt(options.prompt);
92
- const timeoutMs = requireTimeout(options.commandTimeoutMs ?? 60_000);
94
+ const timeoutMs = requireTimeout(
95
+ options.commandTimeoutMs ?? DEFAULT_CODEX_PROMPT_TIMEOUT_MS,
96
+ MAX_CODEX_PROMPT_TIMEOUT_MS,
97
+ );
93
98
  const spawnCommand = options.spawnCommand ?? spawn;
94
99
  if (typeof spawnCommand !== "function") {
95
100
  throw new TypeError("Codex prompt spawnCommand must be a function");
@@ -216,11 +221,11 @@ function readClock(clock) {
216
221
  return new Date(value.getTime());
217
222
  }
218
223
 
219
- function requireTimeout(value) {
224
+ function requireTimeout(value, maximum = MAX_COMMAND_TIMEOUT_MS) {
220
225
  if (
221
226
  !Number.isSafeInteger(value) ||
222
227
  value < MIN_COMMAND_TIMEOUT_MS ||
223
- value > MAX_COMMAND_TIMEOUT_MS
228
+ value > maximum
224
229
  ) {
225
230
  throw new TypeError("Codex exec adapter commandTimeoutMs is invalid");
226
231
  }
package/src/main.mjs CHANGED
@@ -10,7 +10,12 @@ import process from "node:process";
10
10
 
11
11
  import { LocalConnectorClient } from "@webmcp-challenge/reentry-core/local-connector-client";
12
12
  import { followConnectorActivity } from "./activity-monitor.mjs";
13
- import { createCodexExecAdapter, runCodexPrompt } from "./codex-exec-adapter.mjs";
13
+ import {
14
+ createCodexExecAdapter,
15
+ DEFAULT_CODEX_PROMPT_TIMEOUT_MS,
16
+ MAX_CODEX_PROMPT_TIMEOUT_MS,
17
+ runCodexPrompt,
18
+ } from "./codex-exec-adapter.mjs";
14
19
  import {
15
20
  discoverCodexExecutable,
16
21
  requireSupportedNode,
@@ -44,7 +49,7 @@ const DEFAULT_MAX_CONSECUTIVE_ERRORS = 5;
44
49
  const DEFAULT_PAIRING_REQUEST_TIMEOUT_MS = 20_000;
45
50
  const CONNECTOR_VERSION = readConnectorVersion();
46
51
  // The npx form is executable even when this CLI was launched from a temporary npx cache.
47
- const TEMPORARY_CLI_COMMAND = "npx --yes --package=@4xeoz/re-entry re-entry";
52
+ const TEMPORARY_CLI_COMMAND = "npx --yes @4xeoz/re-entry";
48
53
 
49
54
  async function main() {
50
55
  let ui;
@@ -139,7 +144,7 @@ Usage:
139
144
  re-entry test "Reply with hello" Test Codex locally
140
145
 
141
146
  Invocation:
142
- Temporary npx: npx --yes --package=@4xeoz/re-entry re-entry <command>
147
+ Temporary npx: npx --yes @4xeoz/re-entry <command>
143
148
  Global install: npm install --global @4xeoz/re-entry, then re-entry <command>
144
149
 
145
150
  Commands:
@@ -160,6 +165,8 @@ Common options:
160
165
  --receiver <url> Accepted Receiver origin (overrides the preview default)
161
166
  --codex-cd <path> Workspace for Codex; interactive mode offers a folder picker if omitted
162
167
  --codex-binary <path> Explicit Codex executable
168
+ --activation-timeout <ms>
169
+ Codex limit; test defaults to 1 hour, background start to 60 seconds
163
170
  --json Machine-readable output
164
171
  --yes Confirm uninstall in a non-interactive script
165
172
  --help Show this help
@@ -178,6 +185,96 @@ function cliCommand(command) {
178
185
  return `${TEMPORARY_CLI_COMMAND} ${command}`;
179
186
  }
180
187
 
188
+ function showInstallGuide(ui, workingDirectory) {
189
+ const workspace = shellQuote(workingDirectory);
190
+ ui.commands("COPY-PASTE COMMANDS", [
191
+ {
192
+ label: "Connect / install",
193
+ command: cliCommand(`install --codex-cd ${workspace}`),
194
+ detail: "run after disconnecting to connect one account on this Mac",
195
+ },
196
+ {
197
+ label: "Check status",
198
+ command: cliCommand("status"),
199
+ detail: "account, Cloud, background service, Node.js, and Codex",
200
+ },
201
+ {
202
+ label: "Watch activity",
203
+ command: cliCommand("listen"),
204
+ detail: "follow live work; Ctrl+C closes this view",
205
+ },
206
+ {
207
+ label: "Test Codex",
208
+ command: cliCommand(`test "Reply exactly: Re-entry is working." --codex-cd ${workspace}`),
209
+ detail: "local smoke test; no Cloud work is claimed",
210
+ },
211
+ {
212
+ label: "Check readiness",
213
+ command: cliCommand(`doctor --codex-cd ${workspace}`),
214
+ detail: "verify Node.js, Codex, and the workspace",
215
+ },
216
+ {
217
+ label: "Start manually",
218
+ command: cliCommand(`start --codex-cd ${workspace}`),
219
+ detail: "foreground delivery loop for development",
220
+ },
221
+ {
222
+ label: "Check once",
223
+ command: cliCommand(`claim-once --codex-cd ${workspace}`),
224
+ detail: "one delivery check, then exit",
225
+ },
226
+ {
227
+ label: "Pause",
228
+ command: cliCommand("stop"),
229
+ detail: "stop background delivery; keep the account connected",
230
+ },
231
+ {
232
+ label: "Sign out",
233
+ command: cliCommand("disconnect"),
234
+ detail: "clear this Mac's saved account connection",
235
+ },
236
+ {
237
+ label: "Remove setup",
238
+ command: cliCommand("uninstall"),
239
+ detail: "remove the local service, credential, and logs",
240
+ },
241
+ {
242
+ label: "Show all help",
243
+ command: cliCommand("--help"),
244
+ detail: "all commands, options, and the legacy pairing command",
245
+ },
246
+ ]);
247
+ ui.info("Account", "one account connected on this Mac; disconnect before connecting another");
248
+ ui.info("Test timeout", "one-shot Codex tests wait up to 1 hour by default");
249
+ }
250
+
251
+ function showTestGuide(ui, workingDirectory, prompt) {
252
+ const workspace = shellQuote(workingDirectory);
253
+ ui.commands("COPY-PASTE COMMANDS", [
254
+ {
255
+ label: "Test again",
256
+ command: cliCommand(`test ${shellQuote(prompt)} --codex-cd ${workspace}`),
257
+ detail: "run another local Codex smoke test",
258
+ },
259
+ {
260
+ label: "Check readiness",
261
+ command: cliCommand(`doctor --codex-cd ${workspace}`),
262
+ detail: "verify Node.js, Codex, and the workspace",
263
+ },
264
+ {
265
+ label: "Show all help",
266
+ command: cliCommand("--help"),
267
+ detail: "all commands, options, and account lifecycle actions",
268
+ },
269
+ ]);
270
+ ui.info("Scope", "local Codex test only; no account or Cloud work was used");
271
+ ui.info("Test timeout", "one-shot Codex tests wait up to 1 hour by default");
272
+ }
273
+
274
+ function shellQuote(value) {
275
+ return `'${String(value).replaceAll("'", "'\\''")}'`;
276
+ }
277
+
181
278
  function readConnectorVersion() {
182
279
  const packageJson = JSON.parse(
183
280
  readFileSync(new URL("../package.json", import.meta.url), "utf8"),
@@ -523,16 +620,16 @@ async function testCodex(flags, positionals, ui) {
523
620
  prompt,
524
621
  stdio: ui.interactive ? "inherit" : ["ignore", "ignore", "ignore"],
525
622
  commandTimeoutMs: readBoundedNumber(
526
- flags["activation-timeout"] ?? 60_000,
623
+ flags["activation-timeout"] ?? DEFAULT_CODEX_PROMPT_TIMEOUT_MS,
527
624
  100,
528
- 60_000,
529
- "connector_activation_timeout_invalid",
625
+ MAX_CODEX_PROMPT_TIMEOUT_MS,
626
+ "connector_test_timeout_invalid",
530
627
  ),
531
628
  });
532
629
  if (ui.interactive) {
533
630
  ui.stopWait("Codex", "completed the local test");
534
631
  ui.complete("Test passed", "The same fresh-session process seam is ready for Re-entry work.");
535
- ui.next(cliCommand("listen"), "Watch the background Connector for approved work.");
632
+ showTestGuide(ui, readiness.workingDirectory, prompt);
536
633
  } else {
537
634
  process.stdout.write('{"event":"connector_codex_test_passed"}\n');
538
635
  }
@@ -653,7 +750,7 @@ async function install(flags, ui) {
653
750
  if (ui.interactive) {
654
751
  ui.stopWait("Background", "running at login");
655
752
  ui.complete("You're all set", "Re-entry is connected and waiting for approved work.");
656
- ui.next(cliCommand("listen"), "Watch live activity. Press Ctrl+C when you are done.");
753
+ showInstallGuide(ui, readiness.workingDirectory);
657
754
  } else {
658
755
  process.stdout.write(`${JSON.stringify({
659
756
  event: "connector_service_installed",
@@ -1133,6 +1230,7 @@ function errorHint(error) {
1133
1230
  connector_service_stop_failed: `check the Connector status and try \`${cliCommand("stop")}\` again`,
1134
1231
  connector_test_prompt_missing: `use \`${cliCommand('test "Reply with: Re-entry is working."')}\``,
1135
1232
  connector_test_prompt_invalid: "use one short, single-line prompt inside quotes",
1233
+ connector_test_timeout_invalid: "use a test timeout between 100 and 3600000 milliseconds",
1136
1234
  connector_activation_timeout_invalid: "use an activation timeout between 100 and 60000 milliseconds",
1137
1235
  };
1138
1236
  return hints[error?.code] ?? "check the command output and try again";
@@ -128,6 +128,28 @@ export function createTerminalUi(options = {}) {
128
128
  write();
129
129
  },
130
130
 
131
+ commands(title, entries) {
132
+ if (!interactive) return;
133
+ clearSpinnerLine();
134
+ const validEntries = Array.isArray(entries)
135
+ ? entries.filter((entry) => (
136
+ entry &&
137
+ typeof entry.label === "string" && entry.label.length > 0 &&
138
+ typeof entry.command === "string" && entry.command.length > 0
139
+ ))
140
+ : [];
141
+ if (validEntries.length === 0) return;
142
+ const labelWidth = Math.max(...validEntries.map((entry) => entry.label.length));
143
+ write();
144
+ if (title) write(` ${style(title, CYAN)}`);
145
+ for (const entry of validEntries) {
146
+ const label = entry.label.padEnd(labelWidth);
147
+ write(` ${style(label, BOLD)} ${style("$", CYAN)} ${style(entry.command, BOLD)}`);
148
+ if (entry.detail) write(` ${style(entry.detail, DIM)}`);
149
+ }
150
+ write();
151
+ },
152
+
131
153
  error(label, detail, hint) {
132
154
  if (!interactive) return;
133
155
  clearSpinnerLine();