castle-web-cli 0.4.38 → 0.4.39

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/dist/index.js CHANGED
@@ -135,14 +135,6 @@ async function main() {
135
135
  case 'login':
136
136
  await login();
137
137
  break;
138
- case 'build-archives': {
139
- // Dev/publish tool: generate the prebuilt per-kit deck archives that
140
- // `init` extracts in published mode. Run after `npm run build -w cli`.
141
- const { buildKitArchives } = await import('./buildArchive.js');
142
- const only = getFlagValue('--kit');
143
- buildKitArchives(only ? [only] : undefined);
144
- break;
145
- }
146
138
  default:
147
139
  usage();
148
140
  }
package/dist/init.d.ts CHANGED
@@ -1,22 +1,4 @@
1
- export declare const PUBLISHED_SDK_VERSION = "0.4.4";
2
- export declare const KIT_COPY_EXCLUDE: Set<string>;
3
- export declare const ARCHIVE_NAME = "published-deck.tgz";
4
- export declare function getKitArchivePath(kit: string): string;
5
- export declare function copyKitSource(kitDir: string, dest: string, extraExclude?: Set<string>): void;
6
- export declare function rewriteKitPackageJson(pkg: {
7
- name?: string;
8
- dependencies?: Record<string, string>;
9
- scripts?: Record<string, string>;
10
- }, name: string, refs: ReturnType<typeof resolveScaffoldRefs>): void;
11
- declare function resolveScaffoldRefs(): {
12
- workspaceMode: boolean;
13
- sdkRef: string;
14
- cliCommand: string;
15
- cliDistAbs: string | null;
16
- sdkPathPosix: string | null;
17
- };
18
1
  export declare function init(dir: string, opts?: {
19
2
  kit?: string;
20
3
  serve?: boolean;
21
4
  }): Promise<void>;
22
- export {};
package/dist/init.js CHANGED
@@ -1,9 +1,9 @@
1
- import { execFileSync, execSync } from 'child_process';
2
- import * as fs from 'fs';
3
- import * as path from 'path';
4
- import { COMMON_INSTRUCTIONS } from './commonInstructions.js';
5
- import { getCliEntryPath, getKitsDir, getRepoRoot, getSdkPackagePath, toPosixPath } from './localPaths.js';
6
- import { serve } from './serve.js';
1
+ import { execSync } from "child_process";
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ import { COMMON_INSTRUCTIONS } from "./commonInstructions.js";
5
+ import { getCliEntryPath, getKitsDir, getRepoRoot, getSdkPackagePath, toPosixPath, } from "./localPaths.js";
6
+ import { serve } from "./serve.js";
7
7
  const INDEX_HTML = `<!DOCTYPE html>
8
8
  <html>
9
9
  <head>
@@ -31,66 +31,20 @@ card.appendChild(el);
31
31
  `;
32
32
  // Default kit copied by `init` when no --kit is given. `none`/`bare` skip the
33
33
  // kit and produce the minimal index.html + game.js stub above.
34
- const DEFAULT_KIT = 'basic-2d';
34
+ const DEFAULT_KIT = "basic-2d";
35
35
  // Registry version of castle-web-sdk to inject when scaffolding from a
36
36
  // globally-installed castle-web (not from inside the workspace). Bumped
37
37
  // alongside cli/sdk version bumps.
38
- export const PUBLISHED_SDK_VERSION = '0.4.4';
38
+ const PUBLISHED_SDK_VERSION = "0.4.4";
39
39
  // Never copied into a fresh deck: build/dependency junk, and castle.json (a
40
40
  // fresh deck has no deckId until its first save-deck).
41
- export const KIT_COPY_EXCLUDE = new Set(['node_modules', '.castle', 'dist', '.git', 'castle.json']);
42
- // A globally-installed castle-web ships one prebuilt, ready-to-serve archive
43
- // per kit (kit source + installed node_modules + published-mode package.json),
44
- // gzipped. `init` in published mode extracts it instead of cp + `npm install`.
45
- // Lives inside each bundled kit dir (cli/kits/<kit>/), generated by
46
- // `build-archives` (see buildArchive.ts). Workspace mode never uses it.
47
- export const ARCHIVE_NAME = 'published-deck.tgz';
48
- export function getKitArchivePath(kit) {
49
- return path.join(getKitsDir(), kit, ARCHIVE_NAME);
50
- }
51
- // Copy a framework kit into `dest`, dropping build/dependency junk + castle.json
52
- // (and any caller-supplied extra names, e.g. a stale archive). Shared by the
53
- // live scaffold and archive generation so the two stay in sync.
54
- export function copyKitSource(kitDir, dest, extraExclude) {
55
- fs.cpSync(kitDir, dest, {
56
- recursive: true,
57
- // Keep symlinks verbatim so the kit's AGENTS.md -> CLAUDE.md stays a link.
58
- verbatimSymlinks: true,
59
- filter: (src) => src === kitDir ||
60
- (!KIT_COPY_EXCLUDE.has(path.basename(src)) && !extraExclude?.has(path.basename(src))),
61
- });
62
- }
63
- // Rewrite a kit's package.json (in place) so the scaffolded deck references the
64
- // sdk + cli per the resolved mode. Workspace mode points at the local checkout
65
- // (file: sdk + node <abs cli dist>); published mode points at the registry sdk
66
- // + the `castle-web` binary. Shared by the live scaffold and archive generation.
67
- export function rewriteKitPackageJson(pkg, name, refs) {
68
- pkg.name = name;
69
- const { workspaceMode, sdkRef, cliDistAbs, sdkPathPosix } = refs;
70
- if (pkg.dependencies &&
71
- typeof pkg.dependencies['castle-web-sdk'] === 'string' &&
72
- pkg.dependencies['castle-web-sdk'].startsWith('file:')) {
73
- pkg.dependencies['castle-web-sdk'] = sdkRef;
74
- }
75
- if (!pkg.scripts)
76
- return;
77
- for (const k of Object.keys(pkg.scripts)) {
78
- if (typeof pkg.scripts[k] !== 'string')
79
- continue;
80
- if (workspaceMode) {
81
- pkg.scripts[k] = pkg.scripts[k]
82
- .replace(/\.\.\/\.\.\/cli\/dist/g, cliDistAbs)
83
- .replace(/\.\.\/\.\.\/sdk/g, sdkPathPosix);
84
- }
85
- else {
86
- // Globally-installed: route through the `castle-web` binary on PATH.
87
- pkg.scripts[k] = pkg.scripts[k]
88
- .replace(/node\s+\.\.\/\.\.\/cli\/dist\/index\.js/g, 'castle-web')
89
- .replace(/await import\((['"])\.\.\/\.\.\/cli\/dist\/bundle\.js\1\)/g, "await import('castle-web-cli/dist/bundle.js')")
90
- .replace(/\.\.\/\.\.\/sdk/g, '');
91
- }
92
- }
93
- }
41
+ const KIT_COPY_EXCLUDE = new Set([
42
+ "node_modules",
43
+ ".castle",
44
+ "dist",
45
+ ".git",
46
+ "castle.json",
47
+ ]);
94
48
  // Resolve how a scaffolded deck should reference the sdk + cli. Both the bare
95
49
  // and kit scaffold paths go through here so they stay in sync.
96
50
  // workspace mode (sdk/ sits next to cli/, i.e. running from a checkout):
@@ -104,11 +58,17 @@ function resolveScaffoldRefs() {
104
58
  // npm package and need the published refs + `castle-web` binary.
105
59
  const workspaceMode = fs.existsSync(sdkPath);
106
60
  const sdkPathPosix = workspaceMode ? toPosixPath(sdkPath) : null;
107
- const cliDistAbs = workspaceMode ? toPosixPath(path.dirname(getCliEntryPath())) : null;
61
+ const cliDistAbs = workspaceMode
62
+ ? toPosixPath(path.dirname(getCliEntryPath()))
63
+ : null;
108
64
  return {
109
65
  workspaceMode,
110
- sdkRef: workspaceMode ? `file:${sdkPathPosix}` : `^${PUBLISHED_SDK_VERSION}`,
111
- cliCommand: workspaceMode ? `node ${toPosixPath(getCliEntryPath())}` : 'castle-web',
66
+ sdkRef: workspaceMode
67
+ ? `file:${sdkPathPosix}`
68
+ : `^${PUBLISHED_SDK_VERSION}`,
69
+ cliCommand: workspaceMode
70
+ ? `node ${toPosixPath(getCliEntryPath())}`
71
+ : "castle-web",
112
72
  cliDistAbs,
113
73
  sdkPathPosix,
114
74
  };
@@ -118,9 +78,9 @@ function makeClaudeMd() {
118
78
  // castle-experimental-web checkout, but breaks when the scaffold lives
119
79
  // outside the repo (the relative path no longer resolves).
120
80
  const repoRoot = getRepoRoot();
121
- const upstream = path.join(repoRoot, 'CLAUDE.md');
81
+ const upstream = path.join(repoRoot, "CLAUDE.md");
122
82
  try {
123
- return fs.readFileSync(upstream, 'utf8').trimEnd() + '\n';
83
+ return fs.readFileSync(upstream, "utf8").trimEnd() + "\n";
124
84
  }
125
85
  catch {
126
86
  return `# Castle Experimental Web\n\nSee https://github.com/castle-xyz/castle-experimental-web for the agent guide.\n`;
@@ -130,13 +90,15 @@ function makeClaudeMd() {
130
90
  // the kit's (or bare) CLAUDE.md is written; the AGENTS.md symlink picks the
131
91
  // appended content up for free.
132
92
  function appendCommonInstructions(projectDir) {
133
- const claudePath = path.join(projectDir, 'CLAUDE.md');
134
- const existing = fs.existsSync(claudePath) ? fs.readFileSync(claudePath, 'utf8').trimEnd() + '\n\n' : '';
93
+ const claudePath = path.join(projectDir, "CLAUDE.md");
94
+ const existing = fs.existsSync(claudePath)
95
+ ? fs.readFileSync(claudePath, "utf8").trimEnd() + "\n\n"
96
+ : "";
135
97
  fs.writeFileSync(claudePath, existing + COMMON_INSTRUCTIONS);
136
98
  }
137
99
  function tryMakeAgentsSymlink(agentsPath) {
138
100
  try {
139
- fs.symlinkSync('CLAUDE.md', agentsPath);
101
+ fs.symlinkSync("CLAUDE.md", agentsPath);
140
102
  }
141
103
  catch {
142
104
  // symlink already exists / unsupported FS — non-fatal
@@ -147,79 +109,45 @@ function makePackageJson(projectDir) {
147
109
  return {
148
110
  name: path.basename(projectDir),
149
111
  private: true,
150
- type: 'module',
112
+ type: "module",
151
113
  scripts: {
152
114
  restart: `${cliCommand} restart .`,
153
115
  screenshot: `${cliCommand} screenshot .`,
154
- 'save-deck': `${cliCommand} save-deck .`,
116
+ "save-deck": `${cliCommand} save-deck .`,
155
117
  },
156
118
  dependencies: {
157
- 'castle-web-sdk': sdkRef,
119
+ "castle-web-sdk": sdkRef,
158
120
  },
159
121
  };
160
122
  }
161
123
  // Some coding agents read AGENTS.md by convention. Symlink so they get the
162
124
  // same guidance without a duplicate copy.
163
125
  function ensureAgentsSymlink(projectDir) {
164
- const agentsPath = path.join(projectDir, 'AGENTS.md');
126
+ const agentsPath = path.join(projectDir, "AGENTS.md");
165
127
  if (fs.lstatSync(agentsPath, { throwIfNoEntry: false }))
166
128
  return;
167
129
  // Don't create a dangling link — only symlink when CLAUDE.md is present.
168
- if (!fs.existsSync(path.join(projectDir, 'CLAUDE.md')))
130
+ if (!fs.existsSync(path.join(projectDir, "CLAUDE.md")))
169
131
  return;
170
132
  tryMakeAgentsSymlink(agentsPath);
171
133
  }
172
134
  // Bare scaffold: a plain code-only deck with no kit framework.
173
135
  function scaffoldBare(projectDir) {
174
136
  fs.mkdirSync(projectDir, { recursive: true });
175
- fs.writeFileSync(path.join(projectDir, 'index.html'), INDEX_HTML);
176
- fs.writeFileSync(path.join(projectDir, 'game.js'), GAME_JS);
177
- fs.writeFileSync(path.join(projectDir, 'CLAUDE.md'), makeClaudeMd());
137
+ fs.writeFileSync(path.join(projectDir, "index.html"), INDEX_HTML);
138
+ fs.writeFileSync(path.join(projectDir, "game.js"), GAME_JS);
139
+ fs.writeFileSync(path.join(projectDir, "CLAUDE.md"), makeClaudeMd());
178
140
  appendCommonInstructions(projectDir);
179
141
  ensureAgentsSymlink(projectDir);
180
- fs.writeFileSync(path.join(projectDir, 'package.json'), JSON.stringify(makePackageJson(projectDir), null, 2) + '\n');
181
- }
182
- // Finalize a deck whose files are already on disk (mirroring scaffoldFromKit's
183
- // tail): ensure a CLAUDE.md, append the cli-owned common guidance, and create
184
- // the AGENTS.md symlink. Used by both the cp path and the archive-extract path.
185
- function finalizeDeckDocs(projectDir) {
186
- // Every deck needs a CLAUDE.md so coding agents know how castle-web works.
187
- // Keep the kit's own if it ships one; otherwise generate from the upstream.
188
- const claudePath = path.join(projectDir, 'CLAUDE.md');
189
- if (!fs.existsSync(claudePath)) {
190
- fs.writeFileSync(claudePath, makeClaudeMd());
191
- }
192
- appendCommonInstructions(projectDir);
193
- ensureAgentsSymlink(projectDir);
194
- }
195
- // Published fast path: extract the prebuilt, ready-to-serve archive into the
196
- // deck dir (no cp, no `npm install`). The archive carries the kit source +
197
- // installed node_modules + a published-mode package.json with a generic name;
198
- // rename it to the deck dir, then run the shared doc finalization.
199
- function extractKitArchive(archivePath, projectDir) {
200
- fs.mkdirSync(projectDir, { recursive: true });
201
- execFileSync('tar', ['-xzf', archivePath, '-C', projectDir], { stdio: 'inherit' });
202
- const pkgPath = path.join(projectDir, 'package.json');
203
- if (fs.existsSync(pkgPath)) {
204
- try {
205
- const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
206
- pkg.name = path.basename(projectDir);
207
- fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
208
- }
209
- catch {
210
- // archived an unparseable package.json — leave it for the user to fix
211
- }
212
- }
213
- finalizeDeckDocs(projectDir);
142
+ fs.writeFileSync(path.join(projectDir, "package.json"), JSON.stringify(makePackageJson(projectDir), null, 2) + "\n");
214
143
  }
215
144
  // Copy a framework kit from kits/<kit>/ into the new deck dir, dropping
216
- // build/dependency junk and castle.json. Returns whether deps are already
217
- // installed (true only on the published archive-extract fast path).
145
+ // build/dependency junk and castle.json.
218
146
  function scaffoldFromKit(kit, projectDir) {
219
147
  const kitDir = path.join(getKitsDir(), kit);
220
148
  if (!fs.existsSync(kitDir) || !fs.statSync(kitDir).isDirectory()) {
221
149
  console.error(`Kit "${kit}" not found at ${kitDir}.`);
222
- console.error('Available kits:');
150
+ console.error("Available kits:");
223
151
  try {
224
152
  const kits = fs
225
153
  .readdirSync(getKitsDir())
@@ -228,43 +156,103 @@ function scaffoldFromKit(kit, projectDir) {
228
156
  for (const name of kits)
229
157
  console.error(` ${name}`);
230
158
  else
231
- console.error(' (none)');
159
+ console.error(" (none)");
232
160
  }
233
161
  catch {
234
- console.error(' (none — kits/ directory is missing)');
162
+ console.error(" (none — kits/ directory is missing)");
235
163
  }
236
- console.error('Or use `--kit none` for a bare code-only deck.');
164
+ console.error("Or use `--kit none` for a bare code-only deck.");
237
165
  process.exit(1);
238
166
  }
239
- // Published mode (globally-installed castle-web, no sibling sdk/) extracts a
240
- // prebuilt archive when one ships for this kit -- skipping cp + `npm install`.
241
- // Workspace mode always does the live cp so local sdk edits stay live.
242
- const refs = resolveScaffoldRefs();
243
- const archivePath = getKitArchivePath(kit);
244
- if (!refs.workspaceMode && fs.existsSync(archivePath)) {
245
- console.log('Extracting prebuilt deck (deps included)...');
246
- extractKitArchive(archivePath, projectDir);
247
- return { depsInstalled: true };
248
- }
249
- copyKitSource(kitDir, projectDir);
167
+ fs.cpSync(kitDir, projectDir, {
168
+ recursive: true,
169
+ // Keep symlinks verbatim so the kit's AGENTS.md -> CLAUDE.md stays a link.
170
+ verbatimSymlinks: true,
171
+ filter: (src) => src === kitDir || !KIT_COPY_EXCLUDE.has(path.basename(src)),
172
+ });
250
173
  // The kit's package.json carries the kit's name; rename it to the deck dir.
251
174
  // Kit-relative refs to `../../sdk` and `../../cli/dist` only resolve when the
252
175
  // deck lives at castle-experimental-web/decks/<name>/. Rewrite both to
253
176
  // absolute paths so the scaffolded deck works anywhere -- including under
254
177
  // /tmp where macOS's /tmp -> /private/tmp symlink breaks relative-path math.
255
- const pkgPath = path.join(projectDir, 'package.json');
178
+ const pkgPath = path.join(projectDir, "package.json");
256
179
  if (fs.existsSync(pkgPath)) {
257
180
  try {
258
- const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
259
- rewriteKitPackageJson(pkg, path.basename(projectDir), refs);
260
- fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
181
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
182
+ pkg.name = path.basename(projectDir);
183
+ // Local-dev paths (`file:../../sdk` / `node ../../cli/dist/index.js`) only
184
+ // work when the deck lives inside the castle-experimental-web workspace.
185
+ // For a deck scaffolded from a globally-installed castle-web, rewrite to
186
+ // the published packages instead. Same workspace-vs-published resolution
187
+ // the bare scaffold path uses.
188
+ const { workspaceMode, sdkRef, cliDistAbs, sdkPathPosix } = resolveScaffoldRefs();
189
+ if (pkg.dependencies &&
190
+ typeof pkg.dependencies["castle-web-sdk"] === "string" &&
191
+ pkg.dependencies["castle-web-sdk"].startsWith("file:")) {
192
+ pkg.dependencies["castle-web-sdk"] = sdkRef;
193
+ }
194
+ if (pkg.scripts) {
195
+ for (const k of Object.keys(pkg.scripts)) {
196
+ if (typeof pkg.scripts[k] !== "string")
197
+ continue;
198
+ if (workspaceMode) {
199
+ pkg.scripts[k] = pkg.scripts[k]
200
+ .replace(/\.\.\/\.\.\/cli\/dist/g, cliDistAbs)
201
+ .replace(/\.\.\/\.\.\/sdk/g, sdkPathPosix);
202
+ }
203
+ else {
204
+ // Globally-installed: route through the `castle-web` binary on PATH.
205
+ pkg.scripts[k] = pkg.scripts[k]
206
+ .replace(/node\s+\.\.\/\.\.\/cli\/dist\/index\.js/g, "castle-web")
207
+ .replace(/await import\((['"])\.\.\/\.\.\/cli\/dist\/bundle\.js\1\)/g, "await import('castle-web-cli/dist/bundle.js')")
208
+ .replace(/\.\.\/\.\.\/sdk/g, "");
209
+ }
210
+ }
211
+ }
212
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
261
213
  }
262
214
  catch {
263
215
  // kit shipped an unparseable package.json — leave it for the user to fix
264
216
  }
265
217
  }
266
- finalizeDeckDocs(projectDir);
267
- return { depsInstalled: false };
218
+ // Every deck needs a CLAUDE.md so coding agents know how castle-web works.
219
+ // Keep the kit's own if it ships one; otherwise generate from the upstream.
220
+ const claudePath = path.join(projectDir, "CLAUDE.md");
221
+ if (!fs.existsSync(claudePath)) {
222
+ fs.writeFileSync(claudePath, makeClaudeMd());
223
+ }
224
+ appendCommonInstructions(projectDir);
225
+ ensureAgentsSymlink(projectDir);
226
+ }
227
+ function hasPnpm() {
228
+ try {
229
+ execSync("pnpm --version", { stdio: "ignore" });
230
+ return true;
231
+ }
232
+ catch {
233
+ return false;
234
+ }
235
+ }
236
+ // Install the scaffolded deck's deps. Prefer pnpm -- in the e2b template a pnpm
237
+ // store is baked in, so `pnpm install` is near-instant (hardlinks from the
238
+ // store, no download). Fall back to npm when pnpm isn't on PATH (e.g. a local
239
+ // laptop that never installed it). --prefer-offline uses the store/cache first
240
+ // and only hits the network for anything missing.
241
+ function installDeps(projectDir) {
242
+ if (hasPnpm()) {
243
+ console.log("Installing deps (pnpm)...");
244
+ execSync("pnpm install --prefer-offline", {
245
+ cwd: projectDir,
246
+ stdio: "inherit",
247
+ });
248
+ }
249
+ else {
250
+ console.log("Installing deps (npm)...");
251
+ execSync("npm install --no-audit --no-fund --loglevel=error", {
252
+ cwd: projectDir,
253
+ stdio: "inherit",
254
+ });
255
+ }
268
256
  }
269
257
  export async function init(dir, opts = {}) {
270
258
  const projectDir = path.resolve(dir);
@@ -273,54 +261,44 @@ export async function init(dir, opts = {}) {
273
261
  process.exit(1);
274
262
  }
275
263
  const kit = opts.kit ?? DEFAULT_KIT;
276
- const bare = kit === 'none' || kit === 'bare';
277
- // depsInstalled is true only when the published archive fast-path ran, which
278
- // already ships node_modules -- so we can skip `npm install` below.
279
- let depsInstalled = false;
264
+ const bare = kit === "none" || kit === "bare";
280
265
  if (bare) {
281
266
  scaffoldBare(projectDir);
282
267
  }
283
268
  else {
284
- ({ depsInstalled } = scaffoldFromKit(kit, projectDir));
269
+ scaffoldFromKit(kit, projectDir);
270
+ }
271
+ console.log(`Created project in ${projectDir}/${bare ? "" : ` (from kit "${kit}")`}`);
272
+ // Always install deps so the deck is ready to serve/edit immediately. The
273
+ // serve step is what `--no-serve` skips (callers like the cloud launcher run
274
+ // their own serve), but they still want the deps in place.
275
+ console.log("");
276
+ let installed = false;
277
+ try {
278
+ installDeps(projectDir);
279
+ installed = true;
280
+ }
281
+ catch {
282
+ console.error("dependency install failed; re-run `pnpm install` (or `npm install`) in the deck.");
285
283
  }
286
- console.log(`Created project in ${projectDir}/${bare ? '' : ` (from kit "${kit}")`}`);
287
- // Auto-run npm install + serve so the page is up the moment the
288
- // agent / user starts editing. Pass --no-serve to skip.
289
284
  const autoServe = opts.serve !== false;
290
- if (autoServe) {
291
- console.log('');
292
- if (!depsInstalled) {
293
- console.log('Installing deps + serving (pass --no-serve to skip)...');
294
- try {
295
- execSync('npm install --no-audit --no-fund --loglevel=error', {
296
- cwd: projectDir,
297
- stdio: 'inherit',
298
- });
299
- }
300
- catch {
301
- console.error('npm install failed; skipping serve. Re-run yourself with `npm install && castle-web serve .` (& in your shell to background it).');
302
- return;
303
- }
304
- }
305
- else {
306
- console.log('Serving (deps prebuilt)...');
307
- }
285
+ if (autoServe && installed) {
308
286
  // Call serve() with detach so init returns once the server is up. serve()
309
287
  // handles the background spawn internally; init doesn't shell out.
310
288
  // Bind all interfaces by default so a tailnet / LAN browser can reach
311
289
  // the served page; users can override host on a subsequent serve call.
312
290
  // Open in the user's default browser unless we're clearly headless (SSH
313
291
  // session) or the user has opted out via CASTLE_WEB_CLI_NO_OPEN=1.
314
- const noOpen = process.env.CASTLE_WEB_CLI_NO_OPEN === '1' ||
292
+ const noOpen = process.env.CASTLE_WEB_CLI_NO_OPEN === "1" ||
315
293
  !!process.env.SSH_CONNECTION ||
316
294
  !!process.env.SSH_TTY;
317
- await serve(projectDir, { host: '0.0.0.0', detach: true, open: !noOpen });
295
+ await serve(projectDir, { host: "0.0.0.0", detach: true, open: !noOpen });
318
296
  return;
319
297
  }
320
- console.log('');
321
- console.log('Next steps:');
298
+ console.log("");
299
+ console.log("Next steps:");
322
300
  console.log(` cd ${dir}`);
323
- if (!depsInstalled)
324
- console.log(' npm install');
325
- console.log(' castle-web serve . # & in your shell to background it');
301
+ if (!installed)
302
+ console.log(" pnpm install # or: npm install");
303
+ console.log(" castle-web serve . # & in your shell to background it");
326
304
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "castle-web-cli",
3
- "version": "0.4.38",
3
+ "version": "0.4.39",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "castle-web": "./dist/index.js"
Binary file
Binary file