@revealui/cli 0.3.2 → 0.4.0

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/cli.js CHANGED
@@ -1,20 +1,231 @@
1
1
  // src/cli.ts
2
- import { createLogger as createLogger11 } from "@revealui/setup/utils";
2
+ import { createLogger as createLogger12 } from "@revealui/setup/utils";
3
3
  import { Command } from "commander";
4
4
 
5
+ // src/commands/agent.ts
6
+ import { createInterface } from "readline";
7
+ import { createLogger } from "@revealui/setup/utils";
8
+ var logger = createLogger({ prefix: "agent" });
9
+ async function runAgentStatusCommand() {
10
+ const { available, provider, model, projectRoot } = await detectProvider();
11
+ logger.info(`Provider: ${provider}`);
12
+ logger.info(`Model: ${model}`);
13
+ logger.info(`Project root: ${projectRoot}`);
14
+ logger.info(`Available: ${available ? "yes" : "no"}`);
15
+ if (!available) {
16
+ logger.warn("No LLM provider detected. Start BitNet, Ollama, or set GROQ_API_KEY.");
17
+ }
18
+ }
19
+ async function runAgentHeadlessCommand(prompt) {
20
+ const deps = await loadProDeps();
21
+ if (!deps) return;
22
+ const { StreamingAgentRuntime, createLLMClientFromEnv, createCodingTools } = deps;
23
+ const projectRoot = process.cwd();
24
+ const tools = createCodingTools({ projectRoot });
25
+ const llmClient = createLLMClientFromEnv();
26
+ const agent = {
27
+ id: "revealui-coding-agent",
28
+ name: "RevealUI Coding Agent",
29
+ instructions: buildMinimalInstructions(),
30
+ tools,
31
+ config: {},
32
+ getContext: () => ({ projectRoot, workingDirectory: projectRoot })
33
+ };
34
+ const task = {
35
+ id: `task-${Date.now()}`,
36
+ type: "headless-prompt",
37
+ description: prompt
38
+ };
39
+ const runtime = new StreamingAgentRuntime({
40
+ maxIterations: 10,
41
+ timeout: 12e4
42
+ });
43
+ try {
44
+ for await (const chunk of runtime.streamTask(agent, task, llmClient)) {
45
+ switch (chunk.type) {
46
+ case "text":
47
+ if (chunk.content) process.stdout.write(chunk.content);
48
+ break;
49
+ case "tool_call_start":
50
+ if (chunk.toolCall) {
51
+ process.stderr.write(`
52
+ [tool] ${chunk.toolCall.name}
53
+ `);
54
+ }
55
+ break;
56
+ case "tool_call_result":
57
+ if (chunk.toolResult?.content) {
58
+ process.stderr.write(` \u2192 ${chunk.toolResult.content}
59
+ `);
60
+ }
61
+ break;
62
+ case "error":
63
+ process.stderr.write(`
64
+ [error] ${chunk.error}
65
+ `);
66
+ break;
67
+ case "done":
68
+ process.stdout.write("\n");
69
+ break;
70
+ }
71
+ }
72
+ } finally {
73
+ await runtime.cleanup();
74
+ }
75
+ }
76
+ async function runAgentReplCommand() {
77
+ const deps = await loadProDeps();
78
+ if (!deps) return;
79
+ const { StreamingAgentRuntime, createLLMClientFromEnv, createCodingTools } = deps;
80
+ const projectRoot = process.cwd();
81
+ const tools = createCodingTools({ projectRoot });
82
+ const llmClient = createLLMClientFromEnv();
83
+ const agent = {
84
+ id: "revealui-coding-agent",
85
+ name: "RevealUI Coding Agent",
86
+ instructions: buildMinimalInstructions(),
87
+ tools,
88
+ config: {},
89
+ getContext: () => ({ projectRoot, workingDirectory: projectRoot })
90
+ };
91
+ logger.info('RevealUI Agent (type "exit" or Ctrl+C to quit)');
92
+ const rl = createInterface({
93
+ input: process.stdin,
94
+ output: process.stdout,
95
+ prompt: "\n> "
96
+ });
97
+ rl.prompt();
98
+ rl.on("line", async (line) => {
99
+ const input = line.trim();
100
+ if (!input) {
101
+ rl.prompt();
102
+ return;
103
+ }
104
+ if (input === "exit" || input === "quit") {
105
+ rl.close();
106
+ return;
107
+ }
108
+ const task = {
109
+ id: `task-${Date.now()}`,
110
+ type: "repl-prompt",
111
+ description: input
112
+ };
113
+ const runtime = new StreamingAgentRuntime({
114
+ maxIterations: 10,
115
+ timeout: 12e4
116
+ });
117
+ try {
118
+ for await (const chunk of runtime.streamTask(agent, task, llmClient)) {
119
+ switch (chunk.type) {
120
+ case "text":
121
+ if (chunk.content) process.stdout.write(chunk.content);
122
+ break;
123
+ case "tool_call_start":
124
+ if (chunk.toolCall) {
125
+ process.stderr.write(`
126
+ [tool] ${chunk.toolCall.name}
127
+ `);
128
+ }
129
+ break;
130
+ case "tool_call_result":
131
+ if (chunk.toolResult?.content) {
132
+ process.stderr.write(` \u2192 ${chunk.toolResult.content}
133
+ `);
134
+ }
135
+ break;
136
+ case "error":
137
+ process.stderr.write(`
138
+ [error] ${chunk.error}
139
+ `);
140
+ break;
141
+ case "done":
142
+ break;
143
+ }
144
+ }
145
+ } catch (err) {
146
+ logger.error(err instanceof Error ? err.message : String(err));
147
+ } finally {
148
+ await runtime.cleanup();
149
+ }
150
+ rl.prompt();
151
+ });
152
+ rl.on("close", () => {
153
+ process.exit(0);
154
+ });
155
+ }
156
+ async function loadProDeps() {
157
+ const aiRuntimePath = "@revealui/ai/orchestration/streaming-runtime";
158
+ const aiClientPath = "@revealui/ai/llm/client";
159
+ const aiToolsPath = "@revealui/ai/tools/coding";
160
+ try {
161
+ const [runtimeMod, clientMod, toolsMod] = await Promise.all([
162
+ import(aiRuntimePath),
163
+ import(aiClientPath),
164
+ import(aiToolsPath)
165
+ ]);
166
+ return {
167
+ StreamingAgentRuntime: runtimeMod.StreamingAgentRuntime,
168
+ createLLMClientFromEnv: clientMod.createLLMClientFromEnv,
169
+ createCodingTools: toolsMod.createCodingTools
170
+ };
171
+ } catch {
172
+ logger.error(
173
+ "Pro packages not found. Install @revealui/ai to use the agent.\n npm install @revealui/ai"
174
+ );
175
+ return null;
176
+ }
177
+ }
178
+ async function detectProvider() {
179
+ const projectRoot = process.cwd();
180
+ if (process.env.BITNET_BASE_URL) {
181
+ try {
182
+ const res = await fetch(`${process.env.BITNET_BASE_URL}/v1/models`, {
183
+ signal: AbortSignal.timeout(2e3)
184
+ });
185
+ if (res.ok) {
186
+ return { available: true, provider: "bitnet", model: "bitnet-b1.58-2B-4T", projectRoot };
187
+ }
188
+ } catch {
189
+ }
190
+ }
191
+ const ollamaUrl = process.env.OLLAMA_BASE_URL ?? "http://localhost:11434";
192
+ try {
193
+ const res = await fetch(`${ollamaUrl}/api/tags`, {
194
+ signal: AbortSignal.timeout(2e3)
195
+ });
196
+ if (res.ok) {
197
+ return { available: true, provider: "ollama", model: "llama3.2:3b", projectRoot };
198
+ }
199
+ } catch {
200
+ }
201
+ if (process.env.GROQ_API_KEY) {
202
+ return { available: true, provider: "groq", model: "llama-3.3-70b-versatile", projectRoot };
203
+ }
204
+ return { available: false, provider: "none", model: "none", projectRoot };
205
+ }
206
+ function buildMinimalInstructions() {
207
+ return [
208
+ "You are the RevealUI coding agent. You help with software development tasks in this project.",
209
+ "Use the available tools to read, write, edit, search, and execute commands.",
210
+ "Always read files before modifying them. Prefer surgical edits over full rewrites.",
211
+ "Follow project conventions discovered via the project_context tool.",
212
+ "Be concise and direct. Show your work through tool usage, not verbose explanations."
213
+ ].join("\n");
214
+ }
215
+
5
216
  // src/commands/create-flow.ts
6
217
  import { readFileSync } from "fs";
7
218
  import { homedir } from "os";
8
219
  import { join } from "path";
9
- import { createLogger as createLogger6 } from "@revealui/setup/utils";
220
+ import { createLogger as createLogger7 } from "@revealui/setup/utils";
10
221
  import { importSPKI, jwtVerify } from "jose";
11
222
 
12
223
  // src/prompts/database.ts
13
224
  import inquirer from "inquirer";
14
225
 
15
226
  // src/validators/credentials.ts
16
- import { createLogger } from "@revealui/setup/utils";
17
- var logger = createLogger({ prefix: "Validator" });
227
+ import { createLogger as createLogger2 } from "@revealui/setup/utils";
228
+ var logger2 = createLogger2({ prefix: "Validator" });
18
229
  async function validateStripeKey(key) {
19
230
  if (!(key.startsWith("sk_test_") || key.startsWith("sk_live_"))) {
20
231
  return {
@@ -54,7 +265,7 @@ async function validateSupabaseUrl(url) {
54
265
  try {
55
266
  const parsed = new URL(url);
56
267
  if (!parsed.hostname.includes("supabase")) {
57
- logger.warn("URL does not appear to be a Supabase URL");
268
+ logger2.warn("URL does not appear to be a Supabase URL");
58
269
  }
59
270
  return { valid: true };
60
271
  } catch {
@@ -342,18 +553,18 @@ async function promptStorageConfig() {
342
553
  }
343
554
 
344
555
  // src/validators/node-version.ts
345
- import { createLogger as createLogger2 } from "@revealui/setup/utils";
346
- var logger2 = createLogger2({ prefix: "Setup" });
556
+ import { createLogger as createLogger3 } from "@revealui/setup/utils";
557
+ var logger3 = createLogger3({ prefix: "Setup" });
347
558
  var REQUIRED_NODE_VERSION = "24.13.0";
348
559
  function validateNodeVersion() {
349
560
  const currentVersion = process.version.slice(1);
350
561
  const [currentMajor, currentMinor] = currentVersion.split(".").map(Number);
351
562
  const [requiredMajor, requiredMinor] = REQUIRED_NODE_VERSION.split(".").map(Number);
352
563
  if (currentMajor < requiredMajor || currentMajor === requiredMajor && currentMinor < requiredMinor) {
353
- logger2.error(
564
+ logger3.error(
354
565
  `Node.js ${REQUIRED_NODE_VERSION} or higher is required. You have ${currentVersion}.`
355
566
  );
356
- logger2.info("Please upgrade Node.js: https://nodejs.org/");
567
+ logger3.info("Please upgrade Node.js: https://nodejs.org/");
357
568
  return false;
358
569
  }
359
570
  return true;
@@ -361,10 +572,11 @@ function validateNodeVersion() {
361
572
 
362
573
  // src/commands/create.ts
363
574
  import crypto from "crypto";
575
+ import { existsSync } from "fs";
364
576
  import fs5 from "fs/promises";
365
577
  import path5 from "path";
366
578
  import { fileURLToPath } from "url";
367
- import { createLogger as createLogger5 } from "@revealui/setup/utils";
579
+ import { createLogger as createLogger6 } from "@revealui/setup/utils";
368
580
  import ora2 from "ora";
369
581
 
370
582
  // src/generators/devbox.ts
@@ -562,70 +774,42 @@ Run the development server:
562
774
  pnpm dev
563
775
  \`\`\`
564
776
 
565
- Open [http://localhost:4000](http://localhost:4000) with your browser to access the CMS.
566
-
567
- The web application runs on [http://localhost:3000](http://localhost:3000).
777
+ Open [http://localhost:4000](http://localhost:4000) with your browser.
568
778
 
569
- ## Development Environments
779
+ ## Requirements
570
780
 
571
- ### Standard Setup
572
-
573
- Requirements:
574
781
  - Node.js 24.13.0 or higher
575
- - pnpm 10.28.2 or higher
576
- - PostgreSQL 16
577
-
578
- ### Dev Containers
579
-
580
- Open in VS Code and select "Reopen in Container", or use GitHub Codespaces.
581
-
582
- ### Devbox
583
-
584
- Install Devbox:
585
-
586
- \`\`\`bash
587
- curl -fsSL https://get.jetpack.io/devbox | bash
588
- \`\`\`
589
-
590
- Then start the Devbox shell:
591
-
592
- \`\`\`bash
593
- devbox shell
594
- pnpm dev
595
- \`\`\`
782
+ - pnpm 10 or higher
783
+ - PostgreSQL 16 (or use a hosted provider like [Neon](https://neon.tech))
596
784
 
597
785
  ## Project Structure
598
786
 
599
787
  \`\`\`
600
788
  ${projectConfig.projectName}/
601
- \u251C\u2500\u2500 apps/
602
- \u2502 \u251C\u2500\u2500 cms/ # CMS application
603
- \u2502 \u2514\u2500\u2500 web/ # Frontend application
604
- \u251C\u2500\u2500 packages/
605
- \u2502 \u251C\u2500\u2500 auth/ # Authentication
606
- \u2502 \u251C\u2500\u2500 db/ # Database
607
- \u2502 \u2514\u2500\u2500 ... # Other shared packages
608
- \u251C\u2500\u2500 .devcontainer/ # Dev Container configuration
609
- \u251C\u2500\u2500 devbox.json # Devbox configuration
610
- \u2514\u2500\u2500 .env.development.local # Environment variables
789
+ \u251C\u2500\u2500 src/
790
+ \u2502 \u251C\u2500\u2500 app/ # Next.js App Router pages
791
+ \u2502 \u251C\u2500\u2500 collections/ # RevealUI collection definitions
792
+ \u2502 \u2514\u2500\u2500 seed.ts # Database seed script
793
+ \u251C\u2500\u2500 revealui.config.ts # RevealUI configuration
794
+ \u251C\u2500\u2500 next.config.mjs # Next.js configuration
795
+ \u2514\u2500\u2500 .env.local # Environment variables (git-ignored)
611
796
  \`\`\`
612
797
 
613
798
  ## Available Scripts
614
799
 
615
- - \`pnpm dev\` - Start development servers
800
+ - \`pnpm dev\` - Start the development server
616
801
  - \`pnpm build\` - Build for production
617
802
  - \`pnpm test\` - Run tests
618
- - \`pnpm lint\` - Run linters
803
+ - \`pnpm lint\` - Lint with Biome
619
804
  - \`pnpm typecheck\` - Type check
620
- - \`pnpm db:init\` - Initialize database
805
+ - \`pnpm db:init\` - Initialize the database
621
806
  - \`pnpm db:migrate\` - Run migrations
622
- - \`pnpm db:seed\` - Seed database
807
+ - \`pnpm db:seed\` - Seed sample content
623
808
 
624
809
  ## Learn More
625
810
 
626
- - [RevealUI Documentation](https://github.com/your-org/RevealUI)
811
+ - [RevealUI Documentation](https://docs.revealui.com)
627
812
  - [Next.js Documentation](https://nextjs.org/docs)
628
- - [Hono Documentation](https://hono.dev)
629
813
 
630
814
  ## Template
631
815
 
@@ -639,10 +823,10 @@ MIT
639
823
  }
640
824
 
641
825
  // src/installers/dependencies.ts
642
- import { createLogger as createLogger3 } from "@revealui/setup/utils";
826
+ import { createLogger as createLogger4 } from "@revealui/setup/utils";
643
827
  import { execa } from "execa";
644
828
  import ora from "ora";
645
- var logger3 = createLogger3({ prefix: "Install" });
829
+ var logger4 = createLogger4({ prefix: "Install" });
646
830
  async function installDependencies(projectPath) {
647
831
  const spinner = ora("Installing dependencies with pnpm...").start();
648
832
  try {
@@ -653,7 +837,7 @@ async function installDependencies(projectPath) {
653
837
  spinner.succeed("Dependencies installed successfully");
654
838
  } catch (error) {
655
839
  spinner.fail("Failed to install dependencies");
656
- logger3.error('Please run "pnpm install" manually');
840
+ logger4.error('Please run "pnpm install" manually');
657
841
  throw error;
658
842
  }
659
843
  }
@@ -667,15 +851,15 @@ async function isPnpmInstalled() {
667
851
  }
668
852
 
669
853
  // src/utils/git.ts
670
- import { createLogger as createLogger4 } from "@revealui/setup/utils";
854
+ import { createLogger as createLogger5 } from "@revealui/setup/utils";
671
855
  import { execa as execa2 } from "execa";
672
- var logger4 = createLogger4({ prefix: "Git" });
856
+ var logger5 = createLogger5({ prefix: "Git" });
673
857
  async function initializeGitRepo(projectPath) {
674
858
  try {
675
859
  await execa2("git", ["init"], { cwd: projectPath });
676
- logger4.success("Initialized git repository");
860
+ logger5.success("Initialized git repository");
677
861
  } catch (error) {
678
- logger4.warn("Failed to initialize git repository");
862
+ logger5.warn("Failed to initialize git repository");
679
863
  throw error;
680
864
  }
681
865
  }
@@ -683,9 +867,9 @@ async function createInitialCommit(projectPath) {
683
867
  try {
684
868
  await execa2("git", ["add", "."], { cwd: projectPath });
685
869
  await execa2("git", ["commit", "-m", "Initial commit from @revealui/cli"], { cwd: projectPath });
686
- logger4.success("Created initial commit");
870
+ logger5.success("Created initial commit");
687
871
  } catch (error) {
688
- logger4.warn("Failed to create initial commit");
872
+ logger5.warn("Failed to create initial commit");
689
873
  throw error;
690
874
  }
691
875
  }
@@ -699,10 +883,10 @@ async function isGitInstalled() {
699
883
  }
700
884
 
701
885
  // src/commands/create.ts
702
- var logger5 = createLogger5({ prefix: "Create" });
886
+ var logger6 = createLogger6({ prefix: "Create" });
703
887
  var __filename2 = fileURLToPath(import.meta.url);
704
888
  var __dirname2 = path5.dirname(__filename2);
705
- var TEMPLATES_DIR = path5.resolve(__dirname2, "../templates");
889
+ var TEMPLATES_DIR = existsSync(path5.resolve(__dirname2, "../../templates")) ? path5.resolve(__dirname2, "../../templates") : path5.resolve(__dirname2, "../templates");
706
890
  function buildEnvLocal(cfg) {
707
891
  const lines = [
708
892
  "# Generated by @revealui/cli \u2014 fill in the remaining placeholders before running `pnpm dev`",
@@ -787,6 +971,47 @@ function resolveTemplateName(template) {
787
971
  };
788
972
  return map[template] ?? "starter";
789
973
  }
974
+ async function pullContentRules(projectPath) {
975
+ const baseUrl = process.env.REVEALUI_RULES_URL ?? "https://raw.githubusercontent.com/RevealUIStudio/editor-configs/main/harnesses";
976
+ const spinner = ora2("Pulling AI coding rules...").start();
977
+ try {
978
+ const manifestRes = await fetch(`${baseUrl}/manifest.json`, {
979
+ signal: AbortSignal.timeout(1e4)
980
+ });
981
+ if (!manifestRes.ok) {
982
+ spinner.info("AI rules not available \u2014 skipping");
983
+ return;
984
+ }
985
+ const manifest = await manifestRes.json();
986
+ const generatorId = "claude-code";
987
+ const ossDefs = manifest.definitions.filter((d) => d.tier === "oss");
988
+ let written = 0;
989
+ for (const def of ossDefs) {
990
+ const paths = def.generatorPaths[generatorId] ?? [];
991
+ for (const relPath of paths) {
992
+ try {
993
+ const fileRes = await fetch(`${baseUrl}/generators/${generatorId}/${relPath}`, {
994
+ signal: AbortSignal.timeout(5e3)
995
+ });
996
+ if (!fileRes.ok) continue;
997
+ const content = await fileRes.text();
998
+ const absolutePath = path5.join(projectPath, relPath);
999
+ await fs5.mkdir(path5.dirname(absolutePath), { recursive: true });
1000
+ await fs5.writeFile(absolutePath, content, "utf-8");
1001
+ written++;
1002
+ } catch {
1003
+ }
1004
+ }
1005
+ }
1006
+ if (written > 0) {
1007
+ spinner.succeed(`Pulled ${written} AI coding rules`);
1008
+ } else {
1009
+ spinner.info("No AI rules pulled");
1010
+ }
1011
+ } catch {
1012
+ spinner.info("AI rules not available \u2014 skipping");
1013
+ }
1014
+ }
790
1015
  async function createProject(cfg) {
791
1016
  const { project, skipGit = false, skipInstall = false } = cfg;
792
1017
  const { projectPath, projectName, template } = project;
@@ -813,42 +1038,43 @@ async function createProject(cfg) {
813
1038
  throw err;
814
1039
  }
815
1040
  await generateReadme(projectPath, project);
816
- logger5.success("README.md generated");
1041
+ logger6.success("README.md generated");
817
1042
  if (cfg.devenv.createDevContainer) {
818
1043
  await generateDevContainer(projectPath);
819
- logger5.success(".devcontainer/ generated");
1044
+ logger6.success(".devcontainer/ generated");
820
1045
  }
821
1046
  if (cfg.devenv.createDevbox) {
822
1047
  await generateDevbox(projectPath);
823
- logger5.success("devbox.json generated");
1048
+ logger6.success("devbox.json generated");
824
1049
  }
1050
+ await pullContentRules(projectPath);
825
1051
  if (!skipInstall) {
826
1052
  const pnpmOk = await isPnpmInstalled();
827
1053
  if (!pnpmOk) {
828
- logger5.warn(
1054
+ logger6.warn(
829
1055
  "pnpm not found \u2014 skipping dependency installation. Run `pnpm install` manually."
830
1056
  );
831
1057
  } else {
832
1058
  await installDependencies(projectPath);
833
1059
  }
834
1060
  } else {
835
- logger5.info("Skipping dependency installation (--skip-install)");
1061
+ logger6.info("Skipping dependency installation (--skip-install)");
836
1062
  }
837
1063
  if (!skipGit) {
838
1064
  const gitOk = await isGitInstalled();
839
1065
  if (!gitOk) {
840
- logger5.warn("git not found \u2014 skipping repository initialisation.");
1066
+ logger6.warn("git not found \u2014 skipping repository initialisation.");
841
1067
  } else {
842
1068
  await initializeGitRepo(projectPath);
843
1069
  await createInitialCommit(projectPath);
844
1070
  }
845
1071
  } else {
846
- logger5.info("Skipping git initialisation (--skip-git)");
1072
+ logger6.info("Skipping git initialisation (--skip-git)");
847
1073
  }
848
1074
  }
849
1075
 
850
1076
  // src/commands/create-flow.ts
851
- var logger6 = createLogger6({ prefix: "@revealui/cli" });
1077
+ var logger7 = createLogger7({ prefix: "@revealui/cli" });
852
1078
  var PRO_TEMPLATES = /* @__PURE__ */ new Set([]);
853
1079
  async function checkProLicense() {
854
1080
  let key = process.env.REVEALUI_LICENSE_KEY;
@@ -861,7 +1087,7 @@ async function checkProLicense() {
861
1087
  }
862
1088
  }
863
1089
  if (!key) return false;
864
- const publicKeyPem = process.env.REVEALUI_LICENSE_PUBLIC_KEY;
1090
+ const publicKeyPem = process.env.REVEALUI_LICENSE_PUBLIC_KEY?.replace(/\\n/g, "\n");
865
1091
  if (publicKeyPem) {
866
1092
  try {
867
1093
  const publicKey = await importSPKI(publicKeyPem, "RS256");
@@ -885,76 +1111,131 @@ async function checkProLicense() {
885
1111
  return false;
886
1112
  }
887
1113
  }
888
- async function runCreateFlow(projectName, options) {
889
- logger6.info("[1/8] Validating Node.js version...");
890
- if (!validateNodeVersion()) {
891
- process.exit(1);
892
- }
893
- logger6.success(`Node.js version: ${process.version}`);
894
- logger6.info("[2/8] Configure your project");
895
- const projectConfig = await promptProjectConfig(projectName, options.template, options.yes);
896
- logger6.success(`Project: ${projectConfig.projectName}`);
897
- logger6.success(`Template: ${projectConfig.template}`);
898
- if (PRO_TEMPLATES.has(projectConfig.template)) {
899
- if (!await checkProLicense()) {
900
- logger6.error(`The "${projectConfig.template}" template requires a RevealUI Pro license.`);
901
- logger6.info("Get Pro at https://revealui.com/pricing");
902
- logger6.info("Set your license key: export REVEALUI_LICENSE_KEY=<your-key>");
903
- process.exit(2);
904
- }
905
- logger6.success("Pro license verified");
906
- }
907
- const nonInteractive = options.yes === true;
908
- logger6.info("[3/8] Configure database");
909
- const databaseConfig = nonInteractive ? { provider: "skip" } : await promptDatabaseConfig();
910
- if (databaseConfig.provider !== "skip") {
911
- logger6.success(`Database: ${databaseConfig.provider}`);
1114
+ function printBanner() {
1115
+ logger7.divider();
1116
+ logger7.info(" RevealUI \u2014 B.O.S.S.");
1117
+ logger7.info(" Build your business, not your boilerplate.");
1118
+ logger7.divider();
1119
+ logger7.info("");
1120
+ }
1121
+ function printPostCreateSummary(projectName) {
1122
+ logger7.divider();
1123
+ logger7.success("Your RevealUI project is ready!");
1124
+ logger7.info("");
1125
+ logger7.info(" Quick start:");
1126
+ logger7.info(` cd ${projectName}`);
1127
+ logger7.info(" pnpm install");
1128
+ logger7.info(" pnpm dev");
1129
+ logger7.info("");
1130
+ logger7.info(" What was created:");
1131
+ logger7.info(` ./${projectName}/ \u2014 project root`);
1132
+ logger7.info(` ./${projectName}/.env.local \u2014 environment variables (edit before pnpm dev)`);
1133
+ logger7.info(` ./${projectName}/README.md \u2014 getting started guide`);
1134
+ logger7.info("");
1135
+ logger7.info(" Helpful links:");
1136
+ logger7.info(" Docs: https://docs.revealui.com");
1137
+ logger7.info(" GitHub: https://github.com/RevealUIStudio/revealui");
1138
+ logger7.info(" Support: support@revealui.com");
1139
+ logger7.divider();
1140
+ }
1141
+ function formatCreateError(err) {
1142
+ const message = err instanceof Error ? err.message : String(err);
1143
+ const code = err instanceof Error && "code" in err ? err.code : void 0;
1144
+ logger7.error("Project creation failed.");
1145
+ logger7.info("");
1146
+ if (code === "EACCES") {
1147
+ logger7.info(" Permission denied. Try:");
1148
+ logger7.info(" - Running from a directory you own");
1149
+ logger7.info(" - Checking folder permissions with `ls -la`");
1150
+ } else if (code === "ENOENT") {
1151
+ logger7.info(" A required file or directory was not found.");
1152
+ logger7.info(" - Check that you are in the correct directory");
1153
+ logger7.info(" - Try running `revealui doctor` to diagnose your environment");
1154
+ } else if (code === "ENOSPC") {
1155
+ logger7.info(" Disk full. Free up space and try again.");
1156
+ } else if (message.includes("fetch") || message.includes("ENOTFOUND") || message.includes("ETIMEDOUT")) {
1157
+ logger7.info(" Network error. Check your internet connection and try again.");
912
1158
  } else {
913
- logger6.info("Database configuration skipped");
1159
+ logger7.info(` ${message}`);
914
1160
  }
915
- logger6.info("[4/8] Configure storage");
916
- const storageConfig = nonInteractive ? { provider: "skip" } : await promptStorageConfig();
917
- if (storageConfig.provider !== "skip") {
918
- logger6.success(`Storage: ${storageConfig.provider}`);
919
- } else {
920
- logger6.info("Storage configuration skipped");
921
- }
922
- logger6.info("[5/8] Configure payments");
923
- const paymentConfig = nonInteractive ? { enabled: false } : await promptPaymentConfig();
924
- if (paymentConfig.enabled) {
925
- logger6.success("Stripe configured");
926
- } else {
927
- logger6.info("Payments disabled");
1161
+ logger7.info("");
1162
+ logger7.info(" Troubleshooting:");
1163
+ logger7.info(" revealui doctor \u2014 diagnose your environment");
1164
+ logger7.info(" https://docs.revealui.com/docs/TROUBLESHOOTING");
1165
+ logger7.info(" support@revealui.com \u2014 we are here to help");
1166
+ logger7.divider();
1167
+ }
1168
+ async function runCreateFlow(projectName, options) {
1169
+ printBanner();
1170
+ try {
1171
+ logger7.info("[1/8] Validating Node.js version...");
1172
+ if (!validateNodeVersion()) {
1173
+ process.exit(1);
1174
+ }
1175
+ logger7.success(`Node.js version: ${process.version}`);
1176
+ logger7.info("[2/8] Configure your project");
1177
+ const projectConfig = await promptProjectConfig(projectName, options.template, options.yes);
1178
+ logger7.success(`Project: ${projectConfig.projectName}`);
1179
+ logger7.success(`Template: ${projectConfig.template}`);
1180
+ if (PRO_TEMPLATES.has(projectConfig.template)) {
1181
+ if (!await checkProLicense()) {
1182
+ logger7.error(`The "${projectConfig.template}" template requires a RevealUI Pro license.`);
1183
+ logger7.info("Get Pro at https://revealui.com/pricing");
1184
+ logger7.info("Set your license key: export REVEALUI_LICENSE_KEY=<your-key>");
1185
+ process.exit(2);
1186
+ }
1187
+ logger7.success("Pro license verified");
1188
+ }
1189
+ const nonInteractive = options.yes === true;
1190
+ logger7.info("[3/8] Configure database");
1191
+ const databaseConfig = nonInteractive ? { provider: "skip" } : await promptDatabaseConfig();
1192
+ if (databaseConfig.provider !== "skip") {
1193
+ logger7.success(`Database: ${databaseConfig.provider}`);
1194
+ } else {
1195
+ logger7.info("Database configuration skipped");
1196
+ }
1197
+ logger7.info("[4/8] Configure storage");
1198
+ const storageConfig = nonInteractive ? { provider: "skip" } : await promptStorageConfig();
1199
+ if (storageConfig.provider !== "skip") {
1200
+ logger7.success(`Storage: ${storageConfig.provider}`);
1201
+ } else {
1202
+ logger7.info("Storage configuration skipped");
1203
+ }
1204
+ logger7.info("[5/8] Configure payments");
1205
+ const paymentConfig = nonInteractive ? { enabled: false } : await promptPaymentConfig();
1206
+ if (paymentConfig.enabled) {
1207
+ logger7.success("Stripe configured");
1208
+ } else {
1209
+ logger7.info("Payments disabled");
1210
+ }
1211
+ logger7.info("[6/8] Configure development environment");
1212
+ const devEnvConfig = nonInteractive ? { createDevContainer: false, createDevbox: false } : await promptDevEnvConfig();
1213
+ logger7.success(
1214
+ `Dev Container: ${devEnvConfig.createDevContainer ? "Yes" : "No"}, Devbox: ${devEnvConfig.createDevbox ? "Yes" : "No"}`
1215
+ );
1216
+ logger7.info("[7/8] Creating project...");
1217
+ await createProject({
1218
+ project: projectConfig,
1219
+ database: databaseConfig,
1220
+ storage: storageConfig,
1221
+ payment: paymentConfig,
1222
+ devenv: devEnvConfig,
1223
+ skipGit: options.skipGit,
1224
+ skipInstall: options.skipInstall
1225
+ });
1226
+ logger7.success("Project created successfully");
1227
+ logger7.info("[8/8] Done!");
1228
+ printPostCreateSummary(projectConfig.projectName);
1229
+ } catch (err) {
1230
+ formatCreateError(err);
1231
+ process.exit(1);
928
1232
  }
929
- logger6.info("[6/8] Configure development environment");
930
- const devEnvConfig = nonInteractive ? { createDevContainer: false, createDevbox: false } : await promptDevEnvConfig();
931
- logger6.success(
932
- `Dev Container: ${devEnvConfig.createDevContainer ? "Yes" : "No"}, Devbox: ${devEnvConfig.createDevbox ? "Yes" : "No"}`
933
- );
934
- logger6.info("[7/8] Creating project...");
935
- await createProject({
936
- project: projectConfig,
937
- database: databaseConfig,
938
- storage: storageConfig,
939
- payment: paymentConfig,
940
- devenv: devEnvConfig,
941
- skipGit: options.skipGit,
942
- skipInstall: options.skipInstall
943
- });
944
- logger6.success("Project created successfully");
945
- logger6.info("[8/8] Next steps");
946
- logger6.divider();
947
- logger6.info(`cd ${projectConfig.projectName}`);
948
- logger6.info("pnpm install");
949
- logger6.info("pnpm dev");
950
- logger6.divider();
951
- logger6.success(`Project ${projectConfig.projectName} created successfully`);
952
1233
  }
953
1234
 
954
1235
  // src/commands/db.ts
955
1236
  import fs8 from "fs/promises";
956
1237
  import path8 from "path";
957
- import { createLogger as createLogger7 } from "@revealui/setup/utils";
1238
+ import { createLogger as createLogger8 } from "@revealui/setup/utils";
958
1239
  import { execa as execa4 } from "execa";
959
1240
 
960
1241
  // src/utils/command.ts
@@ -1066,7 +1347,7 @@ function findWorkspaceRoot(startDir = process.cwd()) {
1066
1347
  }
1067
1348
 
1068
1349
  // src/commands/db.ts
1069
- var logger7 = createLogger7({ prefix: "DB" });
1350
+ var logger8 = createLogger8({ prefix: "DB" });
1070
1351
  function isPgCtlNotRunningError(error) {
1071
1352
  return typeof error === "object" && error !== null && "exitCode" in error && error.exitCode === 3;
1072
1353
  }
@@ -1127,7 +1408,7 @@ async function runDbInitCommand(options = {}) {
1127
1408
  }
1128
1409
  );
1129
1410
  await writeLocalDbConfigs(pgdata);
1130
- logger7.success(`PostgreSQL initialized at ${pgdata}`);
1411
+ logger8.success(`PostgreSQL initialized at ${pgdata}`);
1131
1412
  }
1132
1413
  async function runDbStartCommand() {
1133
1414
  const root = getWorkspaceRootOrThrow();
@@ -1166,7 +1447,7 @@ async function runDbStatusCommand() {
1166
1447
  });
1167
1448
  } catch (error) {
1168
1449
  if (isPgCtlNotRunningError(error)) {
1169
- logger7.warn(`PostgreSQL is not running (PGDATA: ${pgdata})`);
1450
+ logger8.warn(`PostgreSQL is not running (PGDATA: ${pgdata})`);
1170
1451
  return;
1171
1452
  }
1172
1453
  throw error;
@@ -1210,7 +1491,7 @@ async function runDbCleanupCommand(options = {}) {
1210
1491
  }
1211
1492
 
1212
1493
  // src/commands/dev.ts
1213
- import { createLogger as createLogger10 } from "@revealui/setup/utils";
1494
+ import { createLogger as createLogger11 } from "@revealui/setup/utils";
1214
1495
  import { execa as execa6 } from "execa";
1215
1496
 
1216
1497
  // src/runtime/doctor.ts
@@ -1346,8 +1627,8 @@ function writeDevConfig(config, startDir = process.cwd()) {
1346
1627
  }
1347
1628
 
1348
1629
  // src/commands/doctor.ts
1349
- import { createLogger as createLogger8 } from "@revealui/setup/utils";
1350
- var logger8 = createLogger8({ prefix: "Doctor" });
1630
+ import { createLogger as createLogger9 } from "@revealui/setup/utils";
1631
+ var logger9 = createLogger9({ prefix: "Doctor" });
1351
1632
  function getDoctorFixPlan(report) {
1352
1633
  const attempted = [];
1353
1634
  const skipped = [];
@@ -1405,7 +1686,7 @@ async function runDoctorCommand(options = {}) {
1405
1686
  `);
1406
1687
  if (options.fix) {
1407
1688
  if (fixPlan.attempted.length === 0) {
1408
- logger8.warn("No safe automatic fixes available");
1689
+ logger9.warn("No safe automatic fixes available");
1409
1690
  } else {
1410
1691
  await applyDoctorFixes(report);
1411
1692
  report = await gatherDoctorReport();
@@ -1414,7 +1695,7 @@ async function runDoctorCommand(options = {}) {
1414
1695
  }
1415
1696
  }
1416
1697
  if (report.checks.some((check) => !check.ok)) {
1417
- logger8.warn("Some checks failed");
1698
+ logger9.warn("Some checks failed");
1418
1699
  if (options.strict || options.json || process.env.CI) {
1419
1700
  process.exitCode = 1;
1420
1701
  }
@@ -1422,9 +1703,9 @@ async function runDoctorCommand(options = {}) {
1422
1703
  }
1423
1704
 
1424
1705
  // src/commands/shell.ts
1425
- import { createLogger as createLogger9 } from "@revealui/setup/utils";
1706
+ import { createLogger as createLogger10 } from "@revealui/setup/utils";
1426
1707
  import { execa as execa5 } from "execa";
1427
- var logger9 = createLogger9({ prefix: "Shell" });
1708
+ var logger10 = createLogger10({ prefix: "Shell" });
1428
1709
  async function runShellCommand(options = {}) {
1429
1710
  if (!(options.inside || process.env.IN_NIX_SHELL) && await commandExists("nix")) {
1430
1711
  const workspaceRoot = findWorkspaceRoot();
@@ -1469,12 +1750,12 @@ async function runShellCommand(options = {}) {
1469
1750
  }
1470
1751
  process.stdout.write(`${formatDoctorReport(freshReport)}
1471
1752
  `);
1472
- logger9.info("Use `revealui doctor --json` for machine-readable status.");
1753
+ logger10.info("Use `revealui doctor --json` for machine-readable status.");
1473
1754
  return false;
1474
1755
  }
1475
1756
 
1476
1757
  // src/commands/dev.ts
1477
- var logger10 = createLogger10({ prefix: "Dev" });
1758
+ var logger11 = createLogger11({ prefix: "Dev" });
1478
1759
  var DEV_PROFILES = {
1479
1760
  local: {},
1480
1761
  agent: {
@@ -1600,20 +1881,20 @@ async function runDevUpCommand(options = {}) {
1600
1881
  process.stdout.write(`${formatDevActions(plan)}
1601
1882
  `);
1602
1883
  if (plan.dryRun) {
1603
- logger10.info("Dry run only; no migrations or services were started.");
1884
+ logger11.info("Dry run only; no migrations or services were started.");
1604
1885
  return;
1605
1886
  }
1606
1887
  if (options.fix) {
1607
1888
  await runDoctorCommand({ fix: true });
1608
1889
  }
1609
1890
  await runDbMigrateCommand();
1610
- logger10.success("Database migration complete");
1891
+ logger11.success("Database migration complete");
1611
1892
  if (shouldIncludeMcp(resolved.include)) {
1612
1893
  const workspaceRoot = findWorkspaceRoot();
1613
1894
  if (!workspaceRoot) {
1614
1895
  throw new Error("RevealUI workspace root not found");
1615
1896
  }
1616
- logger10.info("Validating MCP setup");
1897
+ logger11.info("Validating MCP setup");
1617
1898
  await execa6("pnpm", ["setup:mcp"], {
1618
1899
  cwd: workspaceRoot,
1619
1900
  stdio: "inherit"
@@ -1624,7 +1905,7 @@ async function runDevUpCommand(options = {}) {
1624
1905
  if (!workspaceRoot) {
1625
1906
  throw new Error("RevealUI workspace root not found");
1626
1907
  }
1627
- logger10.info(`Starting dev script: ${resolved.script}`);
1908
+ logger11.info(`Starting dev script: ${resolved.script}`);
1628
1909
  await execa6("pnpm", [resolved.script], {
1629
1910
  cwd: workspaceRoot,
1630
1911
  stdio: "inherit"
@@ -1682,7 +1963,7 @@ async function runDevProfileSetCommand(profile) {
1682
1963
  );
1683
1964
  }
1684
1965
  const configPath = writeDevConfig({ defaultProfile: profile });
1685
- logger10.success(`Default dev profile set to "${profile}" in ${configPath}`);
1966
+ logger11.success(`Default dev profile set to "${profile}" in ${configPath}`);
1686
1967
  }
1687
1968
  async function runDevProfileShowCommand(options = {}) {
1688
1969
  const configuredProfile = getConfiguredProfile() ?? null;
@@ -1696,10 +1977,10 @@ async function runDevProfileShowCommand(options = {}) {
1696
1977
  }
1697
1978
 
1698
1979
  // src/cli.ts
1699
- var logger11 = createLogger11({ prefix: "CLI" });
1980
+ var logger12 = createLogger12({ prefix: "CLI" });
1700
1981
  function configureCreateCommand(command, legacyName) {
1701
1982
  command.description("Create a new RevealUI project").argument("[project-name]", "Name of the project").option("-t, --template <name>", "Template to use (basic-blog, e-commerce, portfolio)").option("--skip-git", "Skip git initialization", false).option("--skip-install", "Skip dependency installation", false).option("-y, --yes", "Skip all prompts and use defaults", false).action(async (projectName, options) => {
1702
- logger11.header(legacyName ? "Create RevealUI Project" : "RevealUI Create");
1983
+ logger12.header(legacyName ? "Create RevealUI Project" : "RevealUI Create");
1703
1984
  await runCreateFlow(projectName, options);
1704
1985
  });
1705
1986
  return command;
@@ -1711,6 +1992,17 @@ function createCli() {
1711
1992
  program.command("doctor").description("Check RevealUI workspace and developer environment health").option("--json", "Output machine-readable JSON", false).option("--fix", "Apply safe automatic fixes when possible", false).option("--strict", "Exit nonzero when checks fail", false).action(async (options) => {
1712
1993
  await runDoctorCommand(options);
1713
1994
  });
1995
+ const agent = program.command("agent").description("RevealUI coding agent (powered by local or cloud LLMs)");
1996
+ agent.option("-p, --prompt <text>", "Run a single prompt in headless mode").action(async (options) => {
1997
+ if (options.prompt) {
1998
+ await runAgentHeadlessCommand(options.prompt);
1999
+ } else {
2000
+ await runAgentReplCommand();
2001
+ }
2002
+ });
2003
+ agent.command("status").description("Show agent status: model, provider, project root").action(async () => {
2004
+ await runAgentStatusCommand();
2005
+ });
1714
2006
  const db = program.command("db").description("Manage the local RevealUI database");
1715
2007
  db.command("init").description("Initialize the local PostgreSQL data directory").option("--force", "Delete and recreate the local data directory", false).action(async (options) => {
1716
2008
  await runDbInitCommand(options);