castle-web-cli 0.4.5 → 0.4.7

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
@@ -25,6 +25,9 @@ function getFlagValue(flag) {
25
25
  const idx = args.indexOf(flag);
26
26
  return idx >= 0 ? args[idx + 1] : undefined;
27
27
  }
28
+ function hasFlag(flag) {
29
+ return args.includes(flag);
30
+ }
28
31
  function readServeWsPort(dir) {
29
32
  try {
30
33
  const serveJson = JSON.parse(fs.readFileSync(path.join(path.resolve(dir), '.castle', 'serve.json'), 'utf-8'));
@@ -70,7 +73,7 @@ async function main() {
70
73
  process.exit(1);
71
74
  }
72
75
  const kit = getFlagValue('--kit');
73
- init(dir, { kit });
76
+ await init(dir, { kit, serve: !hasFlag('--no-serve') });
74
77
  break;
75
78
  }
76
79
  case 'serve': {
package/dist/init.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export declare function init(dir: string, opts?: {
2
2
  kit?: string;
3
- }): void;
3
+ serve?: boolean;
4
+ }): Promise<void>;
package/dist/init.js CHANGED
@@ -1,6 +1,8 @@
1
+ import { execSync } from 'child_process';
1
2
  import * as fs from 'fs';
2
3
  import * as path from 'path';
3
4
  import { getCliEntryPath, getKitsDir, getRepoRoot, getSdkPackagePath, toPosixPath } from './localPaths.js';
5
+ import { serve } from './serve.js';
4
6
  const INDEX_HTML = `<!DOCTYPE html>
5
7
  <html>
6
8
  <head>
@@ -187,7 +189,7 @@ function scaffoldFromKit(kit, projectDir) {
187
189
  }
188
190
  ensureAgentsSymlink(projectDir);
189
191
  }
190
- export function init(dir, opts = {}) {
192
+ export async function init(dir, opts = {}) {
191
193
  const projectDir = path.resolve(dir);
192
194
  if (fs.existsSync(projectDir) && fs.readdirSync(projectDir).length > 0) {
193
195
  console.error(`Directory "${dir}" is not empty.`);
@@ -202,10 +204,37 @@ export function init(dir, opts = {}) {
202
204
  scaffoldFromKit(kit, projectDir);
203
205
  }
204
206
  console.log(`Created project in ${projectDir}/${bare ? '' : ` (from kit "${kit}")`}`);
207
+ // Auto-run npm install + serve so the page is up the moment the
208
+ // agent / user starts editing. Pass --no-serve to skip.
209
+ const autoServe = opts.serve !== false;
210
+ if (autoServe) {
211
+ console.log('');
212
+ console.log('Installing deps + serving (pass --no-serve to skip)...');
213
+ try {
214
+ execSync('npm install --no-audit --no-fund --loglevel=error', {
215
+ cwd: projectDir,
216
+ stdio: 'inherit',
217
+ });
218
+ }
219
+ catch {
220
+ console.error('npm install failed; skipping serve. Re-run yourself with `npm install && castle-web serve .` (& in your shell to background it).');
221
+ return;
222
+ }
223
+ // Call serve() with detach so init returns once the server is up. serve()
224
+ // handles the background spawn internally; init doesn't shell out.
225
+ // Bind all interfaces by default so a tailnet / LAN browser can reach
226
+ // the served page; users can override host on a subsequent serve call.
227
+ // Open in the user's default browser unless we're clearly headless (SSH
228
+ // session) or the user has opted out via CASTLE_WEB_CLI_NO_OPEN=1.
229
+ const noOpen = process.env.CASTLE_WEB_CLI_NO_OPEN === '1' ||
230
+ !!process.env.SSH_CONNECTION ||
231
+ !!process.env.SSH_TTY;
232
+ await serve(projectDir, { host: '0.0.0.0', detach: true, open: !noOpen });
233
+ return;
234
+ }
205
235
  console.log('');
206
236
  console.log('Next steps:');
207
237
  console.log(` cd ${dir}`);
208
238
  console.log(' npm install');
209
- console.log(' npm run serve');
210
- console.log(' npm run save-deck');
239
+ console.log(' castle-web serve . # & in your shell to background it');
211
240
  }
package/dist/serve.js CHANGED
@@ -84,7 +84,10 @@ export async function serve(dir, options = {}) {
84
84
  console.error(`No index.html found in ${projectDir}`);
85
85
  process.exit(1);
86
86
  }
87
- if (options.detach) {
87
+ // --detach is kept for back-compat. Agent evals (and any harness running
88
+ // castle-web in a context that can't manage a foreground process) should
89
+ // prefer the CASTLE_WEB_CLI_DETACH=1 env var instead.
90
+ if (options.detach || process.env.CASTLE_WEB_CLI_DETACH === '1') {
88
91
  await serveDetached(projectDir, options);
89
92
  return;
90
93
  }
@@ -12,9 +12,10 @@ Write the smallest game that satisfies what the user asked for. No sound, partic
12
12
 
13
13
  ## Workflow
14
14
 
15
- 1. **Serve first.** `castle-web serve . --detach` immediately (unless a serve is already running -- check `.castle/serve.json`). This makes your work visible to the user from the start.
16
- 2. **Build incrementally.** Start with a minimal playable core (one mechanic, simplest scene), restart, verify, then add the next piece. Do NOT write the whole game in one shot. The user is watching the served page; demonstrate progress.
17
- 3. **After every edit:** `npm run restart` (no hot reload). The served page refreshes; keep showing results as you go.
15
+ The deck is already serving when you start (`castle-web init` set that up; see `.castle/serve.json` for the URL). The user is watching that page right now. Your job is to make it interesting incrementally:
16
+
17
+ 1. **Build incrementally.** Start with the smallest playable thing (one mechanic, one scene change), `npm run restart`, then add the next piece. Do NOT write the whole game in one shot.
18
+ 2. **After every edit:** `npm run restart` (no hot reload). The served page refreshes and the user sees the change.
18
19
 
19
20
  Card size is **500 wide × 700 tall** (origin top-left, +y is down).
20
21
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "castle-web-cli",
3
- "version": "0.4.5",
3
+ "version": "0.4.7",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "castle-web": "./dist/index.js"