@linzumi/cli 0.0.22-beta → 0.0.23-beta

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 (3) hide show
  1. package/README.md +3 -3
  2. package/dist/index.js +125 -31
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -117,9 +117,9 @@ Codex command.
117
117
  npx -y @linzumi/cli@latest signup --email alice@example.com --workspace-name "Alice's Linzumi" --agent-name BuildBot
118
118
  npx -y @linzumi/cli@latest claim --pending <pending_id> --code <XXXX-XXXX>
119
119
  npx -y @linzumi/cli@latest channel post <support_channel_id> "Hello @sean, starting this launch run."
120
- npx -y @linzumi/cli@latest hello
120
+ npx -y @linzumi/cli@latest thread new "Hello Linzumi confetti" --message "Preparing the Hello Linzumi demo. Next I will generate /tmp/hello_linzumi, start its hot-reload server bound to 0.0.0.0 on port 8787, and ask Linzumi Codex to add confetti when the page loads."
121
+ npx -y @linzumi/cli@latest init-hello-linzumi-demo-app --parent-dir /tmp --name hello_linzumi --host 0.0.0.0 --port 8787 --reset --json
121
122
  (cd /tmp/hello_linzumi && npm run dev > /tmp/hello_linzumi/dev.log 2>&1 &)
122
- npx -y @linzumi/cli@latest thread new "Hello Linzumi confetti" --message "Please add confetti when the page loads."
123
123
  npx -y @linzumi/cli@latest agent runner /tmp/hello_linzumi \
124
124
  --runner-id hello-linzumi-agent \
125
125
  --allowed-cwd /tmp/hello_linzumi \
@@ -261,7 +261,7 @@ intentionally. Every action is auditable from the thread.
261
261
  ## Pinning a version
262
262
 
263
263
  ```bash
264
- npm install -g @linzumi/cli@0.0.22-beta
264
+ npm install -g @linzumi/cli@0.0.23-beta
265
265
  linzumi --version
266
266
  ```
267
267
 
package/dist/index.js CHANGED
@@ -7773,48 +7773,92 @@ Launch target:
7773
7773
  }
7774
7774
 
7775
7775
  // src/helloLinzumiProject.ts
7776
- import { existsSync as existsSync7, mkdirSync as mkdirSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "node:fs";
7776
+ import { existsSync as existsSync7, mkdirSync as mkdirSync7, readFileSync as readFileSync6, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "node:fs";
7777
7777
  import { dirname as dirname7, join as join7, resolve as resolve5 } from "node:path";
7778
7778
  import { fileURLToPath } from "node:url";
7779
7779
  var defaultHelloLinzumiProjectDir = "/tmp/hello_linzumi";
7780
+ var defaultHelloLinzumiProjectName = "hello_linzumi";
7781
+ var defaultHelloLinzumiParentDir = "/tmp";
7782
+ var defaultHelloLinzumiPort = 8787;
7783
+ var defaultHelloLinzumiHost = "0.0.0.0";
7780
7784
  var markerFile = ".linzumi-demo-project";
7781
7785
  var moduleDir = dirname7(fileURLToPath(import.meta.url));
7782
7786
  var linzumiLogoSvg = readFileSync6(join7(moduleDir, "assets", "linzumi-logo.svg"), "utf8");
7783
- function createHelloLinzumiProject(rootPath = defaultHelloLinzumiProjectDir) {
7784
- const root = resolve5(rootPath);
7785
- assertWritableDemoRoot(root);
7787
+ function createHelloLinzumiProject(input = {}) {
7788
+ const options = typeof input === "string" ? { rootPath: input } : input;
7789
+ const root = resolveHelloProjectRoot(options);
7790
+ const port = options.port ?? defaultHelloLinzumiPort;
7791
+ const host = normalizeHost(options.host);
7792
+ assertTcpPort(port);
7793
+ assertWritableDemoRoot(root, options.reset === true);
7786
7794
  mkdirSync7(join7(root, "src"), { recursive: true });
7787
- for (const file of demoFiles()) {
7795
+ for (const file of demoFiles({ root, port, host })) {
7788
7796
  writeFileSync6(join7(root, file.path), file.content, "utf8");
7789
7797
  }
7790
7798
  return {
7791
7799
  root,
7792
- port: 8787,
7800
+ port,
7801
+ host,
7793
7802
  startCommand: "npm run dev",
7794
- previewUrl: "http://127.0.0.1:8787"
7803
+ previewUrl: `http://${host}:${port}`
7795
7804
  };
7796
7805
  }
7797
- function assertWritableDemoRoot(root) {
7806
+ function resolveHelloProjectRoot(options) {
7807
+ if (options.rootPath !== undefined && (options.parentDir !== undefined || options.name !== undefined)) {
7808
+ throw new Error("linzumi init-hello-linzumi-demo-app accepts either --dir or --parent-dir/--name, not both");
7809
+ }
7810
+ if (options.rootPath !== undefined) {
7811
+ return resolve5(options.rootPath);
7812
+ }
7813
+ const name = normalizeProjectName(options.name ?? defaultHelloLinzumiProjectName);
7814
+ return resolve5(options.parentDir ?? defaultHelloLinzumiParentDir, name);
7815
+ }
7816
+ function normalizeProjectName(value) {
7817
+ const name = value.trim();
7818
+ if (name === "" || name === "." || name === ".." || name.includes("/") || name.includes("\\")) {
7819
+ throw new Error("--name must be a single directory name");
7820
+ }
7821
+ return name;
7822
+ }
7823
+ function normalizeHost(value) {
7824
+ const host = value?.trim() ?? defaultHelloLinzumiHost;
7825
+ if (host === "") {
7826
+ throw new Error("--host must not be empty");
7827
+ }
7828
+ return host;
7829
+ }
7830
+ function assertTcpPort(port) {
7831
+ if (Number.isInteger(port) && port > 0 && port <= 65535) {
7832
+ return;
7833
+ }
7834
+ throw new Error("--port must be a TCP port from 1 to 65535");
7835
+ }
7836
+ function assertWritableDemoRoot(root, reset) {
7798
7837
  if (!existsSync7(root)) {
7799
7838
  return;
7800
7839
  }
7801
7840
  const markerPath = join7(root, markerFile);
7802
- if (existsSync7(markerPath) && readFileSync6(markerPath, "utf8").trim() === "hello-linzumi") {
7841
+ const isDemoRoot = existsSync7(markerPath) && readFileSync6(markerPath, "utf8").trim() === "hello-linzumi";
7842
+ if (isDemoRoot && reset) {
7843
+ rmSync2(root, { recursive: true, force: true });
7844
+ return;
7845
+ }
7846
+ if (isDemoRoot) {
7803
7847
  return;
7804
7848
  }
7805
- throw new Error(`${root} already exists and is not a Linzumi demo project; move it before rerunning linzumi hello`);
7849
+ throw new Error(`${root} already exists and is not a Linzumi demo project; move it before rerunning linzumi init-hello-linzumi-demo-app`);
7806
7850
  }
7807
- function demoFiles() {
7851
+ function demoFiles(options) {
7808
7852
  return [
7809
7853
  { path: markerFile, content: `hello-linzumi
7810
7854
  ` },
7811
7855
  { path: "package.json", content: packageJson },
7812
- { path: "server.mjs", content: serverSource },
7856
+ { path: "server.mjs", content: serverSource(options) },
7813
7857
  { path: "index.html", content: htmlSource },
7814
- { path: "src/main.js", content: mainSource },
7858
+ { path: "src/main.js", content: mainSource(options) },
7815
7859
  { path: "src/styles.css", content: cssSource },
7816
7860
  { path: "src/linzumi-logo.svg", content: linzumiLogoSvg },
7817
- { path: "README.md", content: readmeSource }
7861
+ { path: "README.md", content: readmeSource(options) }
7818
7862
  ];
7819
7863
  }
7820
7864
  var packageJson = `${JSON.stringify({
@@ -7828,12 +7872,13 @@ var packageJson = `${JSON.stringify({
7828
7872
  }
7829
7873
  }, null, 2)}
7830
7874
  `;
7831
- var serverSource = `import { createReadStream, existsSync, statSync, watch } from "node:fs";
7875
+ var serverSource = ({ host, port }) => `import { createReadStream, existsSync, statSync, watch } from "node:fs";
7832
7876
  import { extname, join, normalize } from "node:path";
7833
7877
  import { createServer } from "node:http";
7834
7878
 
7835
7879
  const root = process.cwd();
7836
- const port = Number(process.env.PORT ?? "8787");
7880
+ const port = Number(process.env.PORT ?? "${port}");
7881
+ const host = process.env.HOST ?? ${JSON.stringify(host)};
7837
7882
  const clients = new Set();
7838
7883
 
7839
7884
  const contentTypes = new Map([
@@ -7844,7 +7889,7 @@ const contentTypes = new Map([
7844
7889
  ]);
7845
7890
 
7846
7891
  const server = createServer((request, response) => {
7847
- const url = new URL(request.url ?? "/", "http://127.0.0.1");
7892
+ const url = new URL(request.url ?? "/", "http://0.0.0.0");
7848
7893
 
7849
7894
  if (url.pathname === "/events") {
7850
7895
  response.writeHead(200, {
@@ -7891,10 +7936,10 @@ for (const watchedPath of [join(root, "index.html"), join(root, "src")]) {
7891
7936
  });
7892
7937
  }
7893
7938
 
7894
- server.listen(port, "127.0.0.1", () => {
7939
+ server.listen(port, host, () => {
7895
7940
  const address = server.address();
7896
7941
  const actualPort = typeof address === "object" && address !== null ? address.port : port;
7897
- process.stdout.write(\`Hello Linzumi listening on http://127.0.0.1:\${actualPort}\\n\`);
7942
+ process.stdout.write(\`Hello Linzumi listening on http://\${host}:\${actualPort}\\n\`);
7898
7943
  });
7899
7944
  `;
7900
7945
  var htmlSource = `<!doctype html>
@@ -8180,7 +8225,9 @@ h1 {
8180
8225
  }
8181
8226
  }
8182
8227
  `;
8183
- var mainSource = `const prompts = [
8228
+ var mainSource = ({ root, host, port }) => `const projectLabel = ${JSON.stringify(`${root} · ${host}:${port}`)};
8229
+
8230
+ const prompts = [
8184
8231
  "Add a soft confetti burst when I click the heading.",
8185
8232
  "Make this a kanban board with three columns for my groceries.",
8186
8233
  "Add a guestbook so my team can sign in.",
@@ -8236,7 +8283,7 @@ document.querySelector("#app").innerHTML = \`
8236
8283
  </div>
8237
8284
 
8238
8285
  <div class="footer-note">
8239
- <code>/tmp/hello_linzumi · localhost:8787</code>
8286
+ <code>\${escape(projectLabel)}</code>
8240
8287
  <a href="https://linzumi.com" target="_blank" rel="noreferrer">linzumi.com →</a>
8241
8288
  </div>
8242
8289
  </div>
@@ -8261,10 +8308,10 @@ events.addEventListener("reload", () => {
8261
8308
  window.location.reload();
8262
8309
  });
8263
8310
  `;
8264
- var readmeSource = `# Linzumi launch demo
8311
+ var readmeSource = ({ host, port }) => `# Linzumi launch demo
8265
8312
 
8266
8313
  A tiny Node-only HTTP server with browser live reload, generated by
8267
- \`linzumi hello\`.
8314
+ \`linzumi init-hello-linzumi-demo-app\`.
8268
8315
 
8269
8316
  Run it:
8270
8317
 
@@ -8272,7 +8319,8 @@ Run it:
8272
8319
  npm run dev
8273
8320
  \`\`\`
8274
8321
 
8275
- Then open http://127.0.0.1:8787. The page reloads when \`index.html\` or files
8322
+ The app binds to \`${host}\` by default so Linzumi can reach it through the
8323
+ secure tunnel. Then open http://${host}:${port}. The page reloads when \`index.html\` or files
8276
8324
  under \`src/\` change.
8277
8325
 
8278
8326
  The bootstrap agent in your terminal has already opened the browser VS Code
@@ -8318,6 +8366,12 @@ var flagDefinitions = new Map([
8318
8366
  ]);
8319
8367
  var helloFlagDefinitions = new Map([
8320
8368
  ["dir", { kind: "value" }],
8369
+ ["parent-dir", { kind: "value" }],
8370
+ ["name", { kind: "value" }],
8371
+ ["port", { kind: "value" }],
8372
+ ["host", { kind: "value" }],
8373
+ ["reset", { kind: "boolean" }],
8374
+ ["json", { kind: "boolean" }],
8321
8375
  ["help", { kind: "boolean" }]
8322
8376
  ]);
8323
8377
  if (isMainModule()) {
@@ -8343,7 +8397,7 @@ async function main(args) {
8343
8397
  process.stdout.write(connectGuideText());
8344
8398
  return;
8345
8399
  case "version":
8346
- process.stdout.write(`linzumi 0.0.22-beta
8400
+ process.stdout.write(`linzumi 0.0.23-beta
8347
8401
  `);
8348
8402
  return;
8349
8403
  case "auth":
@@ -8393,6 +8447,7 @@ function parseCommand(args) {
8393
8447
  case "paths":
8394
8448
  return { command: "paths", args: rest };
8395
8449
  case "hello":
8450
+ case "init-hello-linzumi-demo-app":
8396
8451
  return { command: "hello", args: rest };
8397
8452
  case "agent":
8398
8453
  return rest[0] === "runner" ? { command: "agentRunner", args: rest.slice(1) } : { command: "agent", args: rest };
@@ -8422,12 +8477,32 @@ function runHelloCommand(args) {
8422
8477
  process.stdout.write(helloHelpText());
8423
8478
  return;
8424
8479
  }
8425
- const project = createHelloLinzumiProject(stringValue3(values, "dir") ?? defaultHelloLinzumiProjectDir);
8480
+ const project = createHelloLinzumiProject({
8481
+ rootPath: stringValue3(values, "dir"),
8482
+ parentDir: stringValue3(values, "parent-dir") === undefined ? undefined : resolveUserPath(required(values, "parent-dir")),
8483
+ name: stringValue3(values, "name"),
8484
+ port: tcpPortValue(values, "port"),
8485
+ host: stringValue3(values, "host"),
8486
+ reset: values.get("reset") === true
8487
+ });
8488
+ if (values.get("json") === true) {
8489
+ process.stdout.write(`${JSON.stringify({
8490
+ project_dir: project.root,
8491
+ dev_command: project.startCommand,
8492
+ preview_url: project.previewUrl,
8493
+ port: project.port,
8494
+ host: project.host
8495
+ })}
8496
+ `);
8497
+ return;
8498
+ }
8426
8499
  process.stdout.write(`project_dir: ${project.root}
8427
8500
  `);
8428
8501
  process.stdout.write(`dev_command: ${project.startCommand}
8429
8502
  `);
8430
8503
  process.stdout.write(`preview_url: ${project.previewUrl}
8504
+ `);
8505
+ process.stdout.write(`bind_host: ${project.host}
8431
8506
  `);
8432
8507
  }
8433
8508
  function runPathsCommand(args) {
@@ -8742,7 +8817,7 @@ async function parseRunnerArgs(args, deps = {
8742
8817
  process.exit(0);
8743
8818
  }
8744
8819
  if (values.get("version") === true) {
8745
- process.stdout.write(`linzumi 0.0.22-beta
8820
+ process.stdout.write(`linzumi 0.0.23-beta
8746
8821
  `);
8747
8822
  process.exit(0);
8748
8823
  }
@@ -8941,6 +9016,17 @@ function positiveIntegerValue(values, key) {
8941
9016
  }
8942
9017
  throw new Error(`--${key} must be a positive integer`);
8943
9018
  }
9019
+ function tcpPortValue(values, key) {
9020
+ const value = stringValue3(values, key);
9021
+ if (value === undefined) {
9022
+ return;
9023
+ }
9024
+ const parsed = Number(value);
9025
+ if (Number.isInteger(parsed) && parsed > 0 && parsed <= 65535) {
9026
+ return parsed;
9027
+ }
9028
+ throw new Error(`--${key} must be a TCP port from 1 to 65535`);
9029
+ }
8944
9030
  function helpText() {
8945
9031
  return `Linzumi local Codex runner
8946
9032
 
@@ -8952,7 +9038,7 @@ Usage:
8952
9038
  linzumi post <thread_id> <message>
8953
9039
  linzumi inbox <thread_id> --since-last
8954
9040
  linzumi done <thread_id> --message <message>
8955
- linzumi hello
9041
+ linzumi init-hello-linzumi-demo-app
8956
9042
  linzumi agent runner <folder> [options]
8957
9043
  linzumi start <folder> [options]
8958
9044
  linzumi paths list|add|remove [path]
@@ -8994,7 +9080,7 @@ Examples:
8994
9080
  linzumi thread new "Hello world" --message "Starting now. ETA 3m."
8995
9081
  linzumi post thr_abc123 "PR is open"
8996
9082
  linzumi done thr_abc123 --message "Done: https://github.com/example/repo/pull/1"
8997
- linzumi hello
9083
+ linzumi init-hello-linzumi-demo-app
8998
9084
  linzumi agent runner ~/code/my-app --runner-id launch-agent-runner
8999
9085
  linzumi start ~/
9000
9086
  linzumi start ~/code/my-app
@@ -9019,19 +9105,27 @@ function helloHelpText() {
9019
9105
  return `Linzumi Hello demo project
9020
9106
 
9021
9107
  Usage:
9022
- linzumi hello [--dir <path>]
9108
+ linzumi init-hello-linzumi-demo-app [--dir <path>]
9109
+ linzumi init-hello-linzumi-demo-app [--parent-dir <path> --name <dirname>]
9023
9110
 
9024
9111
  Creates a tiny Node-only "Hello Linzumi" app with browser live reload.
9025
9112
 
9026
9113
  Default:
9027
9114
  ${defaultHelloLinzumiProjectDir}
9115
+ host ${defaultHelloLinzumiHost}, port ${defaultHelloLinzumiPort}
9028
9116
 
9029
9117
  After creation:
9030
9118
  cd ${defaultHelloLinzumiProjectDir}
9031
9119
  npm run dev
9032
9120
 
9033
9121
  Options:
9034
- --dir <path> Override the project directory for tests or local experiments.
9122
+ --dir <path> Exact project directory.
9123
+ --parent-dir <path> Parent directory, default ${defaultHelloLinzumiParentDir}.
9124
+ --name <dirname> Project directory name with --parent-dir, default ${defaultHelloLinzumiProjectName}.
9125
+ --host <host> Bind host baked into the demo app, default ${defaultHelloLinzumiHost}.
9126
+ --port <port> Port baked into the demo app, default ${defaultHelloLinzumiPort}.
9127
+ --reset Recreate an existing marked Linzumi demo directory.
9128
+ --json Print machine-readable project details.
9035
9129
  `;
9036
9130
  }
9037
9131
  function pathsHelpText() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linzumi/cli",
3
- "version": "0.0.22-beta",
3
+ "version": "0.0.23-beta",
4
4
  "description": "Linzumi CLI — point a Codex agent at the real code on your laptop, with your team watching and steering from shared threads.",
5
5
  "type": "module",
6
6
  "bin": {