Lines 1-42javascript
2// The public `loom` CLI — a small MANAGEMENT CLI over the single-process daemon (which serves the
3// prebuilt web viewport from its own loopback origin — Releases v1 Part 1).
5// loom start the daemon in the FOREGROUND + open the browser (backward-compatible:
6// byte-identical to the original bare `loom`; same as `loom start`)
7// loom start [-d] start the daemon. --detach/-d backgrounds it + writes a PID file
8// loom stop gracefully stop a running (detached) daemon + clean the PID file
9// loom status report running/stopped + version + URL + PID (exit non-zero if not running)
10// loom restart stop, then start (honors --detach/--port/--no-open)
11// loom open open the browser to a running daemon
12// loom update [--channel stable|beta]
13// upgrade in place (npm i -g loomctl@<dist-tag>) + restart the daemon
15// This file is shipped at <pkg>/bin/loom.mjs and the daemon at <pkg>/dist/index.js — the assembled npm
16// package layout (see scripts/build-npm-package.mjs). It is NOT meant to run from the monorepo source
17// tree (there is no <repo-root>/dist); use `pnpm daemon` for dev.
18import { pathToFileURL, fileURLToPath } from "node:url";
19import path from "node:path";
20import os from "node:os";
21import fs from "node:fs";
22import http from "node:http";
23import { spawn, spawnSync } from "node:child_process";
24import { CHANNELS, isValidChannel, installSpecFor, readChannel, writeChannel } from "./update-config.mjs";
26// UV_THREADPOOL_SIZE (task dea6728e, defense-in-depth): the default libuv pool is only 4 threads, so a
27// small handful of wedged fs ops could starve fs/dns/crypto process-wide. `startDetached`/`loom service`
28// spawn a FRESH node process for the daemon, where setting this on that child's env reliably works.
29// `startForeground` instead runs the daemon IN-PROCESS (the OS-service path: `loom start --no-open`) via
30// a dynamic import — by the time that import runs, this process's own ESM module loading has likely
31// already touched the threadpool, so this assignment is BEST-EFFORT for that path only, never a
32// guarantee (libuv reads the env var once, lazily, on first threadpool use — there is no in-process way
33// to resize it after the fact). Never overrides an operator's own explicit setting.
34if (!process.env.UV_THREADPOOL_SIZE) process.env.UV_THREADPOOL_SIZE = "16";
35
HighSame File Env Network Execution
A single source file combines environment access, network access, and code or shell execution; review context before blocking.
bin/loom.mjsView on unpkg · L21 36const here = path.dirname(fileURLToPath(import.meta.url));
37const pkgRoot = path.resolve(here, ".."); // the installed `loom` package root (holds the umbrella package.json)
38const DEFAULT_PORT = 4317;
39const SUBCOMMANDS = new Set(["start", "stop", "status", "restart", "open", "service", "update"]);
40const SERVICE_ACTIONS = new Set(["install", "uninstall", "status"]);
42function readVersion() {