@maestroai/cli 0.1.1 → 0.1.2

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.
@@ -1,9 +1,14 @@
1
+ import {
2
+ checkClaudeInstalled,
3
+ getClaudeInstallInstructions
4
+ } from "./chunk-A3PN4QCM.js";
5
+
1
6
  // src/index.ts
2
7
  import { Command } from "commander";
3
8
 
4
9
  // src/commands/init.ts
5
10
  import * as fs from "fs";
6
- import * as path2 from "path";
11
+ import * as path from "path";
7
12
  import * as readline from "readline";
8
13
  import chalk from "chalk";
9
14
  import figures from "figures";
@@ -15,72 +20,6 @@ import {
15
20
  resetTaskCounter,
16
21
  getDefaultSystemPrompt
17
22
  } from "@maestroai/core";
18
-
19
- // src/utils/claude-check.ts
20
- import { existsSync } from "fs";
21
- import { execSync } from "child_process";
22
- import path from "path";
23
- import os from "os";
24
- function checkClaudeInstalled() {
25
- try {
26
- const claudePath = execSync("command -v claude", { encoding: "utf-8" }).trim();
27
- if (!claudePath) {
28
- const homeDir = os.homedir();
29
- const commonPaths = [
30
- path.join(homeDir, ".local", "bin", "claude"),
31
- "/usr/local/bin/claude",
32
- path.join(homeDir, "bin", "claude")
33
- ];
34
- for (const checkPath of commonPaths) {
35
- if (existsSync(checkPath)) {
36
- try {
37
- const version2 = execSync("claude --version", { encoding: "utf-8" }).trim();
38
- return { installed: true, path: checkPath, version: version2 };
39
- } catch {
40
- return { installed: true, path: checkPath };
41
- }
42
- }
43
- }
44
- return {
45
- installed: false,
46
- error: "Claude CLI not found in PATH or common installation directories"
47
- };
48
- }
49
- let version;
50
- try {
51
- version = execSync("claude --version", { encoding: "utf-8" }).trim();
52
- } catch {
53
- }
54
- return { installed: true, path: claudePath, version };
55
- } catch (error) {
56
- return {
57
- installed: false,
58
- error: error instanceof Error ? error.message : "Unknown error"
59
- };
60
- }
61
- }
62
- function getClaudeInstallInstructions() {
63
- const platform = os.platform();
64
- if (platform === "darwin") {
65
- return `Install Claude CLI for macOS:
66
- npm install -g @anthropic-ai/claude-code
67
-
68
- Or using Homebrew:
69
- brew install anthropic/claude/claude-code`;
70
- }
71
- if (platform === "linux") {
72
- return `Install Claude CLI for Linux:
73
- npm install -g @anthropic-ai/claude-code`;
74
- }
75
- if (platform === "win32") {
76
- return `Install Claude CLI for Windows:
77
- npm install -g @anthropic-ai/claude-code`;
78
- }
79
- return `Install Claude CLI:
80
- npm install -g @anthropic-ai/claude-code`;
81
- }
82
-
83
- // src/commands/init.ts
84
23
  function ask(rl, question, defaultValue) {
85
24
  const suffix = defaultValue ? ` (${defaultValue})` : "";
86
25
  return new Promise((resolve5) => {
@@ -96,7 +35,7 @@ function detectExistingProject(dir) {
96
35
  hasExistingCode: false,
97
36
  configFiles: []
98
37
  };
99
- const pkgJsonPath = path2.resolve(dir, "package.json");
38
+ const pkgJsonPath = path.resolve(dir, "package.json");
100
39
  if (fs.existsSync(pkgJsonPath)) {
101
40
  result.hasExistingCode = true;
102
41
  result.configFiles.push("package.json");
@@ -118,26 +57,26 @@ function detectExistingProject(dir) {
118
57
  } catch {
119
58
  }
120
59
  }
121
- if (fs.existsSync(path2.resolve(dir, "tsconfig.json"))) {
60
+ if (fs.existsSync(path.resolve(dir, "tsconfig.json"))) {
122
61
  result.hasExistingCode = true;
123
62
  result.configFiles.push("tsconfig.json");
124
63
  }
125
- if (fs.existsSync(path2.resolve(dir, "pyproject.toml"))) {
64
+ if (fs.existsSync(path.resolve(dir, "pyproject.toml"))) {
126
65
  result.hasExistingCode = true;
127
66
  result.configFiles.push("pyproject.toml");
128
67
  result.type = "python";
129
68
  }
130
- if (fs.existsSync(path2.resolve(dir, "requirements.txt"))) {
69
+ if (fs.existsSync(path.resolve(dir, "requirements.txt"))) {
131
70
  result.hasExistingCode = true;
132
71
  result.configFiles.push("requirements.txt");
133
72
  if (result.type === "unknown") result.type = "python";
134
73
  }
135
- if (fs.existsSync(path2.resolve(dir, "go.mod"))) {
74
+ if (fs.existsSync(path.resolve(dir, "go.mod"))) {
136
75
  result.hasExistingCode = true;
137
76
  result.configFiles.push("go.mod");
138
77
  result.type = "go";
139
78
  }
140
- if (fs.existsSync(path2.resolve(dir, "Cargo.toml"))) {
79
+ if (fs.existsSync(path.resolve(dir, "Cargo.toml"))) {
141
80
  result.hasExistingCode = true;
142
81
  result.configFiles.push("Cargo.toml");
143
82
  result.type = "rust";
@@ -162,7 +101,29 @@ function plannedToTask(planned) {
162
101
  };
163
102
  }
164
103
  function registerInitCommand(program) {
165
- program.command("init").description("Initialize a new Maestro project").option("--no-plan", "skip automatic task planning (create empty todo.md)").option("--model <model>", "model to use for planning", "sonnet").option("-d, --dir <path>", "working directory for project context", ".").option("-i, --instructions <path>", "path to an instructions/requirements file for the planner").action(async (options) => {
104
+ program.command("init").description("Initialize a new Maestro project").option("--no-tui", "use basic stdin prompts instead of interactive terminal UI").option("--no-plan", "skip automatic task planning (create empty todo.md)").option("--model <model>", "model to use for planning", "sonnet").option("-d, --dir <path>", "working directory for project context", ".").option("-i, --instructions <path>", "path to an instructions/requirements file for the planner").action(async (options) => {
105
+ if (options.tui !== false) {
106
+ const { renderInitTUI } = await import("./src/tui/init/InitTUI.js");
107
+ const result = await renderInitTUI({
108
+ dir: options.dir,
109
+ instructions: options.instructions,
110
+ onExit: () => process.exit(0)
111
+ });
112
+ if (!result) {
113
+ process.exit(0);
114
+ }
115
+ await createProjectWithConfig({
116
+ projectName: result.projectName,
117
+ description: result.description,
118
+ devCount: result.devCount,
119
+ techStack: result.techStack,
120
+ targetDir: path.resolve(options.dir),
121
+ options,
122
+ instructionsContent: options.instructions ? fs.readFileSync(path.resolve(options.instructions), "utf-8").trim() : "",
123
+ detected: detectExistingProject(path.resolve(options.dir))
124
+ });
125
+ return;
126
+ }
166
127
  const rl = readline.createInterface({
167
128
  input: process.stdin,
168
129
  output: process.stdout
@@ -195,7 +156,7 @@ function registerInitCommand(program) {
195
156
  }
196
157
  console.log();
197
158
  }
198
- const targetDir = path2.resolve(options.dir);
159
+ const targetDir = path.resolve(options.dir);
199
160
  if (targetDir !== process.cwd()) {
200
161
  fs.mkdirSync(targetDir, { recursive: true });
201
162
  process.chdir(targetDir);
@@ -214,7 +175,7 @@ function registerInitCommand(program) {
214
175
  }
215
176
  let instructionsContent = "";
216
177
  if (options.instructions) {
217
- const instrPath = path2.resolve(options.instructions);
178
+ const instrPath = path.resolve(options.instructions);
218
179
  if (!fs.existsSync(instrPath)) {
219
180
  console.error(chalk.red(` ${figures.cross} Instructions file not found: ${instrPath}`));
220
181
  process.exit(1);
@@ -223,7 +184,7 @@ function registerInitCommand(program) {
223
184
  console.log(chalk.cyan(` ${figures.info} Loaded instructions from ${chalk.bold(options.instructions)} (${instructionsContent.split("\n").length} lines)`));
224
185
  console.log();
225
186
  }
226
- const projectName = await ask(rl, " Project name", path2.basename(targetDir));
187
+ const projectName = await ask(rl, " Project name", path.basename(targetDir));
227
188
  console.log();
228
189
  console.log(chalk.dim(" Describe what the agents should work on. This can be:"));
229
190
  console.log(chalk.dim(" - A new app to build from scratch"));
@@ -316,7 +277,7 @@ ${frontend ? ` frontend: "${frontend}"
316
277
  ` : ""}${database ? ` database: "${database}"
317
278
  ` : ""}${otherTech ? ` other: "${otherTech}"
318
279
  ` : ""}` : ""}`;
319
- const maestroYamlPath = path2.resolve("maestro.yaml");
280
+ const maestroYamlPath = path.resolve("maestro.yaml");
320
281
  if (fs.existsSync(maestroYamlPath)) {
321
282
  const overwrite = await ask(rl, ` ${chalk.yellow("maestro.yaml already exists. Overwrite? (y/n)")}`, "n");
322
283
  if (overwrite.toLowerCase() === "y") {
@@ -336,13 +297,13 @@ ${frontend ? ` frontend: "${frontend}"
336
297
  ".maestro/sessions"
337
298
  ];
338
299
  for (const dir of dirs) {
339
- const dirPath = path2.resolve(dir);
300
+ const dirPath = path.resolve(dir);
340
301
  if (!fs.existsSync(dirPath)) {
341
302
  fs.mkdirSync(dirPath, { recursive: true });
342
303
  console.log(` ${chalk.green(figures.tick)} Created ${chalk.bold(dir + "/")}`);
343
304
  }
344
305
  }
345
- const gitignorePath = path2.resolve(".maestro/.gitignore");
306
+ const gitignorePath = path.resolve(".maestro/.gitignore");
346
307
  if (!fs.existsSync(gitignorePath)) {
347
308
  fs.writeFileSync(gitignorePath, `logs/
348
309
  sessions/
@@ -357,7 +318,7 @@ stop
357
318
  database: database || void 0,
358
319
  other: otherTech || void 0
359
320
  } : void 0;
360
- const agentsDir = path2.resolve(".agents");
321
+ const agentsDir = path.resolve(".agents");
361
322
  if (!fs.existsSync(agentsDir)) {
362
323
  fs.mkdirSync(agentsDir, { recursive: true });
363
324
  console.log(` ${chalk.green(figures.tick)} Created ${chalk.bold(".agents/")}`);
@@ -365,7 +326,7 @@ stop
365
326
  const roles = ["orchestrator", "project-manager", "architect", "developer", "designer", "qa-engineer", "devops", "technical-writer", "code-reviewer"];
366
327
  let createdPromptCount = 0;
367
328
  for (const role of roles) {
368
- const promptPath = path2.resolve(agentsDir, `${role}.md`);
329
+ const promptPath = path.resolve(agentsDir, `${role}.md`);
369
330
  if (!fs.existsSync(promptPath)) {
370
331
  const prompt = getDefaultSystemPrompt({
371
332
  role,
@@ -390,7 +351,7 @@ stop
390
351
  if (createdPromptCount > 0) {
391
352
  console.log(` ${chalk.green(figures.tick)} Created ${createdPromptCount} agent prompt files in ${chalk.bold(".agents/")}`);
392
353
  }
393
- const todoPath = path2.resolve("todo.md");
354
+ const todoPath = path.resolve("todo.md");
394
355
  const hasExistingTodo = fs.existsSync(todoPath);
395
356
  let existingTasks = [];
396
357
  if (hasExistingTodo) {
@@ -571,10 +532,320 @@ function writeEmptyTodo(todoPath, projectName) {
571
532
  console.log(` ${chalk.green(figures.tick)} Created ${chalk.bold("todo.md")}`);
572
533
  }
573
534
  }
535
+ async function createProjectWithConfig(config) {
536
+ const { projectName, description, devCount, techStack, targetDir, options, instructionsContent, detected } = config;
537
+ if (targetDir !== process.cwd()) {
538
+ fs.mkdirSync(targetDir, { recursive: true });
539
+ process.chdir(targetDir);
540
+ }
541
+ console.log();
542
+ console.log(chalk.bold(" MAESTRO") + " - Project Initialization");
543
+ console.log();
544
+ if (detected.hasExistingCode) {
545
+ console.log(chalk.cyan(` ${figures.info} Existing ${detected.type} project detected`));
546
+ console.log(chalk.dim(` Found: ${detected.configFiles.join(", ")}`));
547
+ const detectedTech = Object.values(detected.techStack).filter(Boolean);
548
+ if (detectedTech.length > 0) {
549
+ console.log(chalk.dim(` Detected tech: ${detectedTech.join(", ")}`));
550
+ }
551
+ console.log();
552
+ }
553
+ const techParts = [];
554
+ if (techStack.frontend) techParts.push(`Frontend: ${techStack.frontend}`);
555
+ if (techStack.uiLibrary) techParts.push(`UI: ${techStack.uiLibrary}`);
556
+ if (techStack.backend) techParts.push(`Backend: ${techStack.backend}`);
557
+ if (techStack.database) techParts.push(`Database: ${techStack.database}`);
558
+ if (techStack.other) techParts.push(`Other: ${techStack.other}`);
559
+ const workingDirValue = ".";
560
+ const configDescription = description || (instructionsContent ? `See instructions file: ${options.instructions}` : "A Maestro-managed project");
561
+ const configContent = `# Maestro Project Configuration
562
+ name: "${projectName}"
563
+ description: "${configDescription}"
564
+ version: "1.0.0"
565
+
566
+ agents:
567
+ - role: orchestrator
568
+ count: 1
569
+
570
+ - role: project-manager
571
+ count: 1
572
+
573
+ - role: architect
574
+ count: 1
575
+
576
+ - role: developer
577
+ count: ${devCount}
578
+
579
+ - role: designer
580
+ count: 1
581
+
582
+ - role: qa-engineer
583
+ count: 1
584
+
585
+ - role: devops
586
+ count: 1
587
+
588
+ - role: technical-writer
589
+ count: 1
590
+
591
+ - role: code-reviewer
592
+ count: 1
593
+
594
+ settings:
595
+ workingDirectory: "${workingDirValue}"
596
+ todoFile: "todo.md"
597
+ messagesDirectory: ".maestro/messages"
598
+ logsDirectory: ".maestro/logs"
599
+ defaultModel: "claude-sonnet-4-20250514"
600
+ maxConcurrentAgents: 10
601
+ pollIntervalMs: 5000
602
+ maxTotalBudgetUsd: 50.00
603
+
604
+ # Claude CLI configuration
605
+ # NOTE: Agents run with skip-permissions. Process safety (no builds, no Docker,
606
+ # no servers) is enforced via system prompts in .agents/*.md. Edit those files
607
+ # to customise safety rules.
608
+ claudeCommand: claude
609
+ claudeArgs:
610
+ - "--dangerously-skip-permissions"
611
+
612
+ feedback:
613
+ interactionMode: supervised
614
+ requirePlanApproval: true
615
+ progressReportIntervalMs: 60000
616
+ milestonePercentages: [25, 50, 75, 100]
617
+ questionTimeoutMs: 300000
618
+ ${techParts.length > 0 ? `
619
+ techStack:
620
+ ${techStack.frontend ? ` frontend: "${techStack.frontend}"
621
+ ` : ""}${techStack.uiLibrary ? ` uiLibrary: "${techStack.uiLibrary}"
622
+ ` : ""}${techStack.backend ? ` backend: "${techStack.backend}"
623
+ ` : ""}${techStack.database ? ` database: "${techStack.database}"
624
+ ` : ""}${techStack.other ? ` other: "${techStack.other}"
625
+ ` : ""}` : ""}`;
626
+ const maestroYamlPath = path.resolve("maestro.yaml");
627
+ if (fs.existsSync(maestroYamlPath)) {
628
+ fs.writeFileSync(maestroYamlPath, configContent, "utf-8");
629
+ console.log(` ${chalk.green(figures.tick)} Updated ${chalk.bold("maestro.yaml")}`);
630
+ } else {
631
+ fs.writeFileSync(maestroYamlPath, configContent, "utf-8");
632
+ console.log(` ${chalk.green(figures.tick)} Created ${chalk.bold("maestro.yaml")}`);
633
+ }
634
+ const dirs = [
635
+ ".maestro",
636
+ ".maestro/messages",
637
+ ".maestro/logs",
638
+ ".maestro/sessions"
639
+ ];
640
+ for (const dir of dirs) {
641
+ const dirPath = path.resolve(dir);
642
+ if (!fs.existsSync(dirPath)) {
643
+ fs.mkdirSync(dirPath, { recursive: true });
644
+ console.log(` ${chalk.green(figures.tick)} Created ${chalk.bold(dir + "/")}`);
645
+ }
646
+ }
647
+ const gitignorePath = path.resolve(".maestro/.gitignore");
648
+ if (!fs.existsSync(gitignorePath)) {
649
+ fs.writeFileSync(gitignorePath, `logs/
650
+ sessions/
651
+ stop
652
+ `, "utf-8");
653
+ console.log(` ${chalk.green(figures.tick)} Created ${chalk.bold(".maestro/.gitignore")}`);
654
+ }
655
+ const agentsDir = path.resolve(".agents");
656
+ if (!fs.existsSync(agentsDir)) {
657
+ fs.mkdirSync(agentsDir, { recursive: true });
658
+ console.log(` ${chalk.green(figures.tick)} Created ${chalk.bold(".agents/")}`);
659
+ }
660
+ const roles = ["orchestrator", "project-manager", "architect", "developer", "designer", "qa-engineer", "devops", "technical-writer", "code-reviewer"];
661
+ let createdPromptCount = 0;
662
+ for (const role of roles) {
663
+ const promptPath = path.resolve(agentsDir, `${role}.md`);
664
+ if (!fs.existsSync(promptPath)) {
665
+ const prompt = getDefaultSystemPrompt({
666
+ role,
667
+ agentId: "{{agentId}}",
668
+ projectName: "{{projectName}}",
669
+ todoFilePath: "{{todoFilePath}}",
670
+ inboxPath: "{{inboxPath}}",
671
+ outboxPath: "{{outboxPath}}",
672
+ workingDirectory: "{{workingDirectory}}",
673
+ techStack: techParts.length > 0 ? techStack : void 0
674
+ });
675
+ const header = [
676
+ `<!-- Maestro Agent Prompt: ${role} -->`,
677
+ `<!-- Edit this file to customise the ${role} agent's behaviour. -->`,
678
+ `<!-- Delete this file to fall back to the built-in default prompt. -->`,
679
+ ""
680
+ ].join("\n");
681
+ fs.writeFileSync(promptPath, header + prompt + "\n", "utf-8");
682
+ createdPromptCount++;
683
+ }
684
+ }
685
+ if (createdPromptCount > 0) {
686
+ console.log(` ${chalk.green(figures.tick)} Created ${createdPromptCount} agent prompt files in ${chalk.bold(".agents/")}`);
687
+ }
688
+ const todoPath = path.resolve("todo.md");
689
+ const hasExistingTodo = fs.existsSync(todoPath);
690
+ let existingTasks = [];
691
+ if (hasExistingTodo) {
692
+ const parser = new TaskParser();
693
+ const existing = parser.parse(fs.readFileSync(todoPath, "utf-8"));
694
+ existingTasks = existing.tasks;
695
+ console.log(chalk.cyan(` ${figures.info} Found existing ${chalk.bold("todo.md")} with ${existingTasks.length} tasks`));
696
+ }
697
+ if (options.plan) {
698
+ console.log();
699
+ const planner = new Planner({
700
+ model: options.model,
701
+ workingDirectory: process.cwd(),
702
+ techStack: techParts.length > 0 ? techStack : void 0
703
+ });
704
+ let planGoal = description || `Set up and develop ${projectName}`;
705
+ if (instructionsContent) {
706
+ planGoal = instructionsContent;
707
+ if (description) {
708
+ planGoal = `${description}
709
+
710
+ --- Detailed Instructions ---
711
+ ${instructionsContent}`;
712
+ }
713
+ }
714
+ if (detected.hasExistingCode) {
715
+ planGoal += `
716
+
717
+ This is an existing ${detected.type} project. Found config files: ${detected.configFiles.join(", ")}.`;
718
+ planGoal += `
719
+ Build on the existing codebase rather than creating from scratch.`;
720
+ }
721
+ if (existingTasks.length > 0) {
722
+ planGoal += `
723
+
724
+ EXISTING TASKS (do NOT duplicate these \u2014 only create NEW tasks for work not already covered):`;
725
+ for (const t of existingTasks) {
726
+ planGoal += `
727
+ - [${t.status}] ${t.id}: ${t.title}`;
728
+ }
729
+ }
730
+ const spinnerFrames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
731
+ let spinnerIndex = 0;
732
+ let spinnerActive = true;
733
+ const spinnerInterval = setInterval(() => {
734
+ if (!spinnerActive) return;
735
+ const frame = chalk.cyan(spinnerFrames[spinnerIndex]);
736
+ process.stdout.write(`\r ${frame} ${chalk.dim("Planning tasks with Claude...")}`);
737
+ spinnerIndex = (spinnerIndex + 1) % spinnerFrames.length;
738
+ }, 80);
739
+ try {
740
+ const plannedTasks = await planner.decompose(planGoal);
741
+ spinnerActive = false;
742
+ clearInterval(spinnerInterval);
743
+ process.stdout.write("\r " + chalk.green(figures.tick) + " " + chalk.dim("Planning tasks with Claude... done") + "\n");
744
+ let maxExistingNum = 0;
745
+ for (const t of existingTasks) {
746
+ const match = t.id.match(/^T-(\d+)$/);
747
+ if (match) {
748
+ maxExistingNum = Math.max(maxExistingNum, parseInt(match[1], 10));
749
+ }
750
+ }
751
+ resetTaskCounter(maxExistingNum);
752
+ const titleToId = /* @__PURE__ */ new Map();
753
+ for (const t of existingTasks) {
754
+ titleToId.set(t.title, t.id);
755
+ }
756
+ const newTasks = [];
757
+ for (const planned of plannedTasks) {
758
+ const task = plannedToTask(planned);
759
+ task.dependencies = planned.dependencies.map((depTitle) => titleToId.get(depTitle)).filter((id) => id != null);
760
+ titleToId.set(planned.title, task.id);
761
+ newTasks.push(task);
762
+ }
763
+ const allTasks = [...existingTasks, ...newTasks];
764
+ const writer = new TaskWriter();
765
+ const todoContent = writer.write(projectName, allTasks);
766
+ fs.writeFileSync(todoPath, todoContent, "utf-8");
767
+ if (existingTasks.length > 0) {
768
+ console.log(
769
+ chalk.green(` ${figures.tick} Updated ${chalk.bold("todo.md")}: ${existingTasks.length} existing + ${newTasks.length} new tasks`)
770
+ );
771
+ } else {
772
+ console.log(
773
+ chalk.green(` ${figures.tick} Created ${chalk.bold("todo.md")} with ${newTasks.length} planned tasks`)
774
+ );
775
+ }
776
+ console.log();
777
+ if (newTasks.length > 0) {
778
+ if (existingTasks.length > 0) {
779
+ console.log(chalk.dim(" New tasks:"));
780
+ }
781
+ for (const task of newTasks) {
782
+ const priorityColor = task.priority === "critical" ? chalk.red : task.priority === "high" ? chalk.yellow : task.priority === "medium" ? chalk.cyan : chalk.dim;
783
+ console.log(
784
+ ` ${priorityColor(task.id)} ${task.title}`
785
+ );
786
+ }
787
+ }
788
+ } catch (err) {
789
+ spinnerActive = false;
790
+ clearInterval(spinnerInterval);
791
+ process.stdout.write("\r " + chalk.yellow(figures.warning) + " " + chalk.dim("Planning tasks with Claude... failed") + "\n");
792
+ console.log(
793
+ chalk.yellow(
794
+ ` ${figures.warning} Planning failed: ${err.message}`
795
+ )
796
+ );
797
+ if (!hasExistingTodo) {
798
+ writeEmptyTodo(todoPath, projectName);
799
+ }
800
+ }
801
+ } else if (!hasExistingTodo) {
802
+ writeEmptyTodo(todoPath, projectName);
803
+ }
804
+ console.log();
805
+ console.log(chalk.green(" Project initialized successfully!"));
806
+ console.log();
807
+ console.log(chalk.bold(" Process Safety"));
808
+ console.log();
809
+ console.log(chalk.dim(" Agents share your machine's CPU and memory. To keep things stable,"));
810
+ console.log(chalk.dim(" they follow built-in process safety rules:"));
811
+ console.log();
812
+ console.log(` ${chalk.green(figures.tick)} ${chalk.white("Agents will")}:`);
813
+ console.log(chalk.dim(" - Write production code, tests, configs, docs, and infrastructure files"));
814
+ console.log(chalk.dim(" - Run lightweight commands (linters, type-checks on single files)"));
815
+ console.log(chalk.dim(" - Run targeted test files (a single spec, not the full suite)"));
816
+ console.log(chalk.dim(" - Install individual packages (e.g. npm install <pkg>)"));
817
+ console.log();
818
+ console.log(` ${chalk.red(figures.cross)} ${chalk.white("Agents will not")}:`);
819
+ console.log(chalk.dim(" - Run builds (npm run build, cargo build, make, etc.)"));
820
+ console.log(chalk.dim(" - Run Docker commands (docker build, docker compose up, etc.)"));
821
+ console.log(chalk.dim(" - Start dev servers (npm run dev, npm start, flask run, etc.)"));
822
+ console.log(chalk.dim(" - Run full dependency installs (npm install with no args)"));
823
+ console.log(chalk.dim(" - Run full test suites (npm test, pytest with no args)"));
824
+ console.log();
825
+ console.log(` ${chalk.cyan(figures.info)} ${chalk.white("You handle")}:`);
826
+ console.log(chalk.dim(" - Building the project when agents finish writing code"));
827
+ console.log(chalk.dim(" - Running Docker and starting dev servers"));
828
+ console.log(chalk.dim(" - Running full test suites and CI pipelines"));
829
+ console.log(chalk.dim(" - Reviewing and approving agent plans (in supervised mode)"));
830
+ console.log();
831
+ console.log(chalk.dim(` Want full autonomy? Edit the process safety section in ${chalk.bold(".agents/*.md")}`));
832
+ console.log(chalk.dim(` to loosen or remove these restrictions per role.`));
833
+ console.log();
834
+ console.log(` Next steps:`);
835
+ console.log(` 1. Review ${chalk.bold("todo.md")} and edit tasks if needed`);
836
+ console.log(` 2. Edit ${chalk.bold("maestro.yaml")} to adjust agents and settings`);
837
+ console.log(` 3. Customize agent prompts in ${chalk.bold(".agents/")} (optional)`);
838
+ console.log(` 4. Run ${chalk.bold("maestro start")} to begin`);
839
+ if (instructionsContent) {
840
+ console.log();
841
+ console.log(chalk.dim(` Instructions from ${chalk.bold(options.instructions)} were used for task planning.`));
842
+ }
843
+ console.log();
844
+ }
574
845
 
575
846
  // src/commands/start.ts
576
847
  import * as fs3 from "fs";
577
- import * as path4 from "path";
848
+ import * as path3 from "path";
578
849
  import chalk2 from "chalk";
579
850
  import figures2 from "figures";
580
851
  import {
@@ -585,7 +856,7 @@ import {
585
856
 
586
857
  // src/logging/file-logger.ts
587
858
  import * as fs2 from "fs";
588
- import * as path3 from "path";
859
+ import * as path2 from "path";
589
860
  var FileLogger = class {
590
861
  logsDir;
591
862
  streams = /* @__PURE__ */ new Map();
@@ -641,7 +912,7 @@ var FileLogger = class {
641
912
  getOrCreateStream(agentId) {
642
913
  let stream = this.streams.get(agentId);
643
914
  if (!stream) {
644
- const logFile = path3.join(this.logsDir, `${agentId}.log`);
915
+ const logFile = path2.join(this.logsDir, `${agentId}.log`);
645
916
  stream = fs2.createWriteStream(logFile, { flags: "a" });
646
917
  this.streams.set(agentId, stream);
647
918
  }
@@ -672,7 +943,7 @@ function registerStartCommand(program) {
672
943
  program.command("start").description("Start the Maestro orchestrator").option("-c, --config <path>", "path to maestro.yaml", "./maestro.yaml").option("-d, --dir <path>", "working directory for project context", ".").option("--no-tui", "run without TUI (log to console)").option("-m, --mode <mode>", "interaction mode (unattended, supervised, interactive)", "supervised").option("-v, --verbose", "show detailed agent output including tool calls", false).action(async (options) => {
673
944
  if (options.dir && options.dir !== ".") {
674
945
  try {
675
- process.chdir(path4.resolve(options.dir));
946
+ process.chdir(path3.resolve(options.dir));
676
947
  console.log(chalk2.dim(` Working directory changed to: ${process.cwd()}`));
677
948
  } catch (err) {
678
949
  console.error(
@@ -681,7 +952,7 @@ function registerStartCommand(program) {
681
952
  process.exit(1);
682
953
  }
683
954
  }
684
- const configPath = path4.resolve(options.config);
955
+ const configPath = path3.resolve(options.config);
685
956
  if (!fs3.existsSync(configPath)) {
686
957
  console.error(
687
958
  chalk2.red(`${figures2.cross} Config file not found: ${configPath}`)
@@ -691,7 +962,7 @@ function registerStartCommand(program) {
691
962
  );
692
963
  process.exit(1);
693
964
  }
694
- const stopFilePath = path4.resolve(".maestro/stop");
965
+ const stopFilePath = path3.resolve(".maestro/stop");
695
966
  if (fs3.existsSync(stopFilePath)) {
696
967
  fs3.unlinkSync(stopFilePath);
697
968
  }
@@ -1019,7 +1290,7 @@ ${figures2.star} Milestone: ${milestone.name} - ${milestone.message}`));
1019
1290
 
1020
1291
  // src/commands/status.ts
1021
1292
  import * as fs4 from "fs";
1022
- import * as path5 from "path";
1293
+ import * as path4 from "path";
1023
1294
  import chalk3 from "chalk";
1024
1295
  import figures3 from "figures";
1025
1296
  function parseTodoFile(content) {
@@ -1079,9 +1350,9 @@ function parseTodoFile(content) {
1079
1350
  }
1080
1351
  function registerStatusCommand(program) {
1081
1352
  program.command("status").description("Show current project status").option("-c, --config <path>", "path to maestro.yaml", "./maestro.yaml").action(async (options) => {
1082
- const todoPath = path5.resolve("todo.md");
1083
- const stopFilePath = path5.resolve(".maestro/stop");
1084
- const isRunning = !fs4.existsSync(stopFilePath) && fs4.existsSync(path5.resolve(".maestro"));
1353
+ const todoPath = path4.resolve("todo.md");
1354
+ const stopFilePath = path4.resolve(".maestro/stop");
1355
+ const isRunning = !fs4.existsSync(stopFilePath) && fs4.existsSync(path4.resolve(".maestro"));
1085
1356
  console.log();
1086
1357
  console.log(chalk3.bold(" MAESTRO") + " - Project Status");
1087
1358
  console.log();
@@ -1125,13 +1396,13 @@ function registerStatusCommand(program) {
1125
1396
 
1126
1397
  // src/commands/stop.ts
1127
1398
  import * as fs5 from "fs";
1128
- import * as path6 from "path";
1399
+ import * as path5 from "path";
1129
1400
  import chalk4 from "chalk";
1130
1401
  import figures4 from "figures";
1131
1402
  function registerStopCommand(program) {
1132
1403
  program.command("stop").description("Stop the running Maestro orchestrator").action(async () => {
1133
- const maestroDir = path6.resolve(".maestro");
1134
- const stopFilePath = path6.resolve(".maestro/stop");
1404
+ const maestroDir = path5.resolve(".maestro");
1405
+ const stopFilePath = path5.resolve(".maestro/stop");
1135
1406
  if (!fs5.existsSync(maestroDir)) {
1136
1407
  console.error(
1137
1408
  chalk4.red(
@@ -1169,4 +1440,4 @@ function createProgram() {
1169
1440
  export {
1170
1441
  createProgram
1171
1442
  };
1172
- //# sourceMappingURL=chunk-5ZDNPLKN.js.map
1443
+ //# sourceMappingURL=chunk-RWLHK222.js.map