feat(cli): wmill init creates root .claude/launch.json for the picker

Adds a workspace-root .claude/launch.json so Claude Code can launch
`wmill dev` from the project root and land on the file picker (no
--path → picker mode). Per-flow and per-raw_app launch.json files are
already generated by the existing scans. Skipped (with a gray log) if
the file already exists, so the user's customizations are preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Guilhem Lemouel
2026-04-24 10:04:04 +02:00
co-authored by Claude Opus 4.7
parent 694f8c910b
commit 8f74dfed5c
+29 -1
View File
@@ -1,6 +1,6 @@
import { stat, writeFile, rm, readdir } from "node:fs/promises";
import { join } from "node:path";
import { writeFileSync, mkdirSync } from "node:fs";
import { writeFileSync, mkdirSync, existsSync } from "node:fs";
import { colors } from "@cliffy/ansi/colors";
import { Command } from "@cliffy/command";
import { Confirm } from "@cliffy/prompt/confirm";
@@ -274,6 +274,34 @@ async function initAction(opts: InitOptions) {
}
}
// Generate .claude/launch.json at the workspace root so Claude Code can launch
// `wmill dev` from there and land on the file picker (no --path → picker mode).
try {
const rootClaudeDir = join(".", ".claude");
const rootLaunchPath = join(rootClaudeDir, "launch.json");
if (existsSync(rootLaunchPath)) {
log.info(colors.gray(`Skipped ${rootLaunchPath} (already exists)`));
} else {
const rootLaunchJson = JSON.stringify({
version: "0.0.1",
configurations: [{
name: "windmill",
runtimeExecutable: "bash",
runtimeArgs: ["-c", "wmill dev --proxy-port ${PORT:-4000} --no-open"],
port: 4000,
autoPort: true,
}],
}, null, 2) + "\n";
mkdirSync(rootClaudeDir, { recursive: true });
writeFileSync(rootLaunchPath, rootLaunchJson, "utf-8");
log.info(colors.green(`Created ${rootLaunchPath}`));
}
} catch (error) {
log.warn(
`Could not create root .claude/launch.json: ${error instanceof Error ? error.message : error}`
);
}
// Generate .claude/launch.json for each flow folder
try {
const flowSuffix = nonDottedPaths ? "__flow" : ".flow";