@revealui/cli 0.3.3 → 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;
@@ -365,7 +576,7 @@ import { existsSync } from "fs";
365
576
  import fs5 from "fs/promises";
366
577
  import path5 from "path";
367
578
  import { fileURLToPath } from "url";
368
- import { createLogger as createLogger5 } from "@revealui/setup/utils";
579
+ import { createLogger as createLogger6 } from "@revealui/setup/utils";
369
580
  import ora2 from "ora";
370
581
 
371
582
  // src/generators/devbox.ts
@@ -563,70 +774,42 @@ Run the development server:
563
774
  pnpm dev
564
775
  \`\`\`
565
776
 
566
- Open [http://localhost:4000](http://localhost:4000) with your browser to access the CMS.
567
-
568
- The web application runs on [http://localhost:3000](http://localhost:3000).
777
+ Open [http://localhost:4000](http://localhost:4000) with your browser.
569
778
 
570
- ## Development Environments
779
+ ## Requirements
571
780
 
572
- ### Standard Setup
573
-
574
- Requirements:
575
781
  - Node.js 24.13.0 or higher
576
- - pnpm 10.28.2 or higher
577
- - PostgreSQL 16
578
-
579
- ### Dev Containers
580
-
581
- Open in VS Code and select "Reopen in Container", or use GitHub Codespaces.
582
-
583
- ### Devbox
584
-
585
- Install Devbox:
586
-
587
- \`\`\`bash
588
- curl -fsSL https://get.jetpack.io/devbox | bash
589
- \`\`\`
590
-
591
- Then start the Devbox shell:
592
-
593
- \`\`\`bash
594
- devbox shell
595
- pnpm dev
596
- \`\`\`
782
+ - pnpm 10 or higher
783
+ - PostgreSQL 16 (or use a hosted provider like [Neon](https://neon.tech))
597
784
 
598
785
  ## Project Structure
599
786
 
600
787
  \`\`\`
601
788
  ${projectConfig.projectName}/
602
- \u251C\u2500\u2500 apps/
603
- \u2502 \u251C\u2500\u2500 cms/ # CMS application
604
- \u2502 \u2514\u2500\u2500 web/ # Frontend application
605
- \u251C\u2500\u2500 packages/
606
- \u2502 \u251C\u2500\u2500 auth/ # Authentication
607
- \u2502 \u251C\u2500\u2500 db/ # Database
608
- \u2502 \u2514\u2500\u2500 ... # Other shared packages
609
- \u251C\u2500\u2500 .devcontainer/ # Dev Container configuration
610
- \u251C\u2500\u2500 devbox.json # Devbox configuration
611
- \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)
612
796
  \`\`\`
613
797
 
614
798
  ## Available Scripts
615
799
 
616
- - \`pnpm dev\` - Start development servers
800
+ - \`pnpm dev\` - Start the development server
617
801
  - \`pnpm build\` - Build for production
618
802
  - \`pnpm test\` - Run tests
619
- - \`pnpm lint\` - Run linters
803
+ - \`pnpm lint\` - Lint with Biome
620
804
  - \`pnpm typecheck\` - Type check
621
- - \`pnpm db:init\` - Initialize database
805
+ - \`pnpm db:init\` - Initialize the database
622
806
  - \`pnpm db:migrate\` - Run migrations
623
- - \`pnpm db:seed\` - Seed database
807
+ - \`pnpm db:seed\` - Seed sample content
624
808
 
625
809
  ## Learn More
626
810
 
627
- - [RevealUI Documentation](https://github.com/your-org/RevealUI)
811
+ - [RevealUI Documentation](https://docs.revealui.com)
628
812
  - [Next.js Documentation](https://nextjs.org/docs)
629
- - [Hono Documentation](https://hono.dev)
630
813
 
631
814
  ## Template
632
815
 
@@ -640,10 +823,10 @@ MIT
640
823
  }
641
824
 
642
825
  // src/installers/dependencies.ts
643
- import { createLogger as createLogger3 } from "@revealui/setup/utils";
826
+ import { createLogger as createLogger4 } from "@revealui/setup/utils";
644
827
  import { execa } from "execa";
645
828
  import ora from "ora";
646
- var logger3 = createLogger3({ prefix: "Install" });
829
+ var logger4 = createLogger4({ prefix: "Install" });
647
830
  async function installDependencies(projectPath) {
648
831
  const spinner = ora("Installing dependencies with pnpm...").start();
649
832
  try {
@@ -654,7 +837,7 @@ async function installDependencies(projectPath) {
654
837
  spinner.succeed("Dependencies installed successfully");
655
838
  } catch (error) {
656
839
  spinner.fail("Failed to install dependencies");
657
- logger3.error('Please run "pnpm install" manually');
840
+ logger4.error('Please run "pnpm install" manually');
658
841
  throw error;
659
842
  }
660
843
  }
@@ -668,15 +851,15 @@ async function isPnpmInstalled() {
668
851
  }
669
852
 
670
853
  // src/utils/git.ts
671
- import { createLogger as createLogger4 } from "@revealui/setup/utils";
854
+ import { createLogger as createLogger5 } from "@revealui/setup/utils";
672
855
  import { execa as execa2 } from "execa";
673
- var logger4 = createLogger4({ prefix: "Git" });
856
+ var logger5 = createLogger5({ prefix: "Git" });
674
857
  async function initializeGitRepo(projectPath) {
675
858
  try {
676
859
  await execa2("git", ["init"], { cwd: projectPath });
677
- logger4.success("Initialized git repository");
860
+ logger5.success("Initialized git repository");
678
861
  } catch (error) {
679
- logger4.warn("Failed to initialize git repository");
862
+ logger5.warn("Failed to initialize git repository");
680
863
  throw error;
681
864
  }
682
865
  }
@@ -684,9 +867,9 @@ async function createInitialCommit(projectPath) {
684
867
  try {
685
868
  await execa2("git", ["add", "."], { cwd: projectPath });
686
869
  await execa2("git", ["commit", "-m", "Initial commit from @revealui/cli"], { cwd: projectPath });
687
- logger4.success("Created initial commit");
870
+ logger5.success("Created initial commit");
688
871
  } catch (error) {
689
- logger4.warn("Failed to create initial commit");
872
+ logger5.warn("Failed to create initial commit");
690
873
  throw error;
691
874
  }
692
875
  }
@@ -700,7 +883,7 @@ async function isGitInstalled() {
700
883
  }
701
884
 
702
885
  // src/commands/create.ts
703
- var logger5 = createLogger5({ prefix: "Create" });
886
+ var logger6 = createLogger6({ prefix: "Create" });
704
887
  var __filename2 = fileURLToPath(import.meta.url);
705
888
  var __dirname2 = path5.dirname(__filename2);
706
889
  var TEMPLATES_DIR = existsSync(path5.resolve(__dirname2, "../../templates")) ? path5.resolve(__dirname2, "../../templates") : path5.resolve(__dirname2, "../templates");
@@ -788,6 +971,47 @@ function resolveTemplateName(template) {
788
971
  };
789
972
  return map[template] ?? "starter";
790
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
+ }
791
1015
  async function createProject(cfg) {
792
1016
  const { project, skipGit = false, skipInstall = false } = cfg;
793
1017
  const { projectPath, projectName, template } = project;
@@ -814,42 +1038,43 @@ async function createProject(cfg) {
814
1038
  throw err;
815
1039
  }
816
1040
  await generateReadme(projectPath, project);
817
- logger5.success("README.md generated");
1041
+ logger6.success("README.md generated");
818
1042
  if (cfg.devenv.createDevContainer) {
819
1043
  await generateDevContainer(projectPath);
820
- logger5.success(".devcontainer/ generated");
1044
+ logger6.success(".devcontainer/ generated");
821
1045
  }
822
1046
  if (cfg.devenv.createDevbox) {
823
1047
  await generateDevbox(projectPath);
824
- logger5.success("devbox.json generated");
1048
+ logger6.success("devbox.json generated");
825
1049
  }
1050
+ await pullContentRules(projectPath);
826
1051
  if (!skipInstall) {
827
1052
  const pnpmOk = await isPnpmInstalled();
828
1053
  if (!pnpmOk) {
829
- logger5.warn(
1054
+ logger6.warn(
830
1055
  "pnpm not found \u2014 skipping dependency installation. Run `pnpm install` manually."
831
1056
  );
832
1057
  } else {
833
1058
  await installDependencies(projectPath);
834
1059
  }
835
1060
  } else {
836
- logger5.info("Skipping dependency installation (--skip-install)");
1061
+ logger6.info("Skipping dependency installation (--skip-install)");
837
1062
  }
838
1063
  if (!skipGit) {
839
1064
  const gitOk = await isGitInstalled();
840
1065
  if (!gitOk) {
841
- logger5.warn("git not found \u2014 skipping repository initialisation.");
1066
+ logger6.warn("git not found \u2014 skipping repository initialisation.");
842
1067
  } else {
843
1068
  await initializeGitRepo(projectPath);
844
1069
  await createInitialCommit(projectPath);
845
1070
  }
846
1071
  } else {
847
- logger5.info("Skipping git initialisation (--skip-git)");
1072
+ logger6.info("Skipping git initialisation (--skip-git)");
848
1073
  }
849
1074
  }
850
1075
 
851
1076
  // src/commands/create-flow.ts
852
- var logger6 = createLogger6({ prefix: "@revealui/cli" });
1077
+ var logger7 = createLogger7({ prefix: "@revealui/cli" });
853
1078
  var PRO_TEMPLATES = /* @__PURE__ */ new Set([]);
854
1079
  async function checkProLicense() {
855
1080
  let key = process.env.REVEALUI_LICENSE_KEY;
@@ -862,7 +1087,7 @@ async function checkProLicense() {
862
1087
  }
863
1088
  }
864
1089
  if (!key) return false;
865
- const publicKeyPem = process.env.REVEALUI_LICENSE_PUBLIC_KEY;
1090
+ const publicKeyPem = process.env.REVEALUI_LICENSE_PUBLIC_KEY?.replace(/\\n/g, "\n");
866
1091
  if (publicKeyPem) {
867
1092
  try {
868
1093
  const publicKey = await importSPKI(publicKeyPem, "RS256");
@@ -886,76 +1111,131 @@ async function checkProLicense() {
886
1111
  return false;
887
1112
  }
888
1113
  }
889
- async function runCreateFlow(projectName, options) {
890
- logger6.info("[1/8] Validating Node.js version...");
891
- if (!validateNodeVersion()) {
892
- process.exit(1);
893
- }
894
- logger6.success(`Node.js version: ${process.version}`);
895
- logger6.info("[2/8] Configure your project");
896
- const projectConfig = await promptProjectConfig(projectName, options.template, options.yes);
897
- logger6.success(`Project: ${projectConfig.projectName}`);
898
- logger6.success(`Template: ${projectConfig.template}`);
899
- if (PRO_TEMPLATES.has(projectConfig.template)) {
900
- if (!await checkProLicense()) {
901
- logger6.error(`The "${projectConfig.template}" template requires a RevealUI Pro license.`);
902
- logger6.info("Get Pro at https://revealui.com/pricing");
903
- logger6.info("Set your license key: export REVEALUI_LICENSE_KEY=<your-key>");
904
- process.exit(2);
905
- }
906
- logger6.success("Pro license verified");
907
- }
908
- const nonInteractive = options.yes === true;
909
- logger6.info("[3/8] Configure database");
910
- const databaseConfig = nonInteractive ? { provider: "skip" } : await promptDatabaseConfig();
911
- if (databaseConfig.provider !== "skip") {
912
- 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.");
913
1158
  } else {
914
- logger6.info("Database configuration skipped");
1159
+ logger7.info(` ${message}`);
915
1160
  }
916
- logger6.info("[4/8] Configure storage");
917
- const storageConfig = nonInteractive ? { provider: "skip" } : await promptStorageConfig();
918
- if (storageConfig.provider !== "skip") {
919
- logger6.success(`Storage: ${storageConfig.provider}`);
920
- } else {
921
- logger6.info("Storage configuration skipped");
922
- }
923
- logger6.info("[5/8] Configure payments");
924
- const paymentConfig = nonInteractive ? { enabled: false } : await promptPaymentConfig();
925
- if (paymentConfig.enabled) {
926
- logger6.success("Stripe configured");
927
- } else {
928
- 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);
929
1232
  }
930
- logger6.info("[6/8] Configure development environment");
931
- const devEnvConfig = nonInteractive ? { createDevContainer: false, createDevbox: false } : await promptDevEnvConfig();
932
- logger6.success(
933
- `Dev Container: ${devEnvConfig.createDevContainer ? "Yes" : "No"}, Devbox: ${devEnvConfig.createDevbox ? "Yes" : "No"}`
934
- );
935
- logger6.info("[7/8] Creating project...");
936
- await createProject({
937
- project: projectConfig,
938
- database: databaseConfig,
939
- storage: storageConfig,
940
- payment: paymentConfig,
941
- devenv: devEnvConfig,
942
- skipGit: options.skipGit,
943
- skipInstall: options.skipInstall
944
- });
945
- logger6.success("Project created successfully");
946
- logger6.info("[8/8] Next steps");
947
- logger6.divider();
948
- logger6.info(`cd ${projectConfig.projectName}`);
949
- logger6.info("pnpm install");
950
- logger6.info("pnpm dev");
951
- logger6.divider();
952
- logger6.success(`Project ${projectConfig.projectName} created successfully`);
953
1233
  }
954
1234
 
955
1235
  // src/commands/db.ts
956
1236
  import fs8 from "fs/promises";
957
1237
  import path8 from "path";
958
- import { createLogger as createLogger7 } from "@revealui/setup/utils";
1238
+ import { createLogger as createLogger8 } from "@revealui/setup/utils";
959
1239
  import { execa as execa4 } from "execa";
960
1240
 
961
1241
  // src/utils/command.ts
@@ -1067,7 +1347,7 @@ function findWorkspaceRoot(startDir = process.cwd()) {
1067
1347
  }
1068
1348
 
1069
1349
  // src/commands/db.ts
1070
- var logger7 = createLogger7({ prefix: "DB" });
1350
+ var logger8 = createLogger8({ prefix: "DB" });
1071
1351
  function isPgCtlNotRunningError(error) {
1072
1352
  return typeof error === "object" && error !== null && "exitCode" in error && error.exitCode === 3;
1073
1353
  }
@@ -1128,7 +1408,7 @@ async function runDbInitCommand(options = {}) {
1128
1408
  }
1129
1409
  );
1130
1410
  await writeLocalDbConfigs(pgdata);
1131
- logger7.success(`PostgreSQL initialized at ${pgdata}`);
1411
+ logger8.success(`PostgreSQL initialized at ${pgdata}`);
1132
1412
  }
1133
1413
  async function runDbStartCommand() {
1134
1414
  const root = getWorkspaceRootOrThrow();
@@ -1167,7 +1447,7 @@ async function runDbStatusCommand() {
1167
1447
  });
1168
1448
  } catch (error) {
1169
1449
  if (isPgCtlNotRunningError(error)) {
1170
- logger7.warn(`PostgreSQL is not running (PGDATA: ${pgdata})`);
1450
+ logger8.warn(`PostgreSQL is not running (PGDATA: ${pgdata})`);
1171
1451
  return;
1172
1452
  }
1173
1453
  throw error;
@@ -1211,7 +1491,7 @@ async function runDbCleanupCommand(options = {}) {
1211
1491
  }
1212
1492
 
1213
1493
  // src/commands/dev.ts
1214
- import { createLogger as createLogger10 } from "@revealui/setup/utils";
1494
+ import { createLogger as createLogger11 } from "@revealui/setup/utils";
1215
1495
  import { execa as execa6 } from "execa";
1216
1496
 
1217
1497
  // src/runtime/doctor.ts
@@ -1347,8 +1627,8 @@ function writeDevConfig(config, startDir = process.cwd()) {
1347
1627
  }
1348
1628
 
1349
1629
  // src/commands/doctor.ts
1350
- import { createLogger as createLogger8 } from "@revealui/setup/utils";
1351
- var logger8 = createLogger8({ prefix: "Doctor" });
1630
+ import { createLogger as createLogger9 } from "@revealui/setup/utils";
1631
+ var logger9 = createLogger9({ prefix: "Doctor" });
1352
1632
  function getDoctorFixPlan(report) {
1353
1633
  const attempted = [];
1354
1634
  const skipped = [];
@@ -1406,7 +1686,7 @@ async function runDoctorCommand(options = {}) {
1406
1686
  `);
1407
1687
  if (options.fix) {
1408
1688
  if (fixPlan.attempted.length === 0) {
1409
- logger8.warn("No safe automatic fixes available");
1689
+ logger9.warn("No safe automatic fixes available");
1410
1690
  } else {
1411
1691
  await applyDoctorFixes(report);
1412
1692
  report = await gatherDoctorReport();
@@ -1415,7 +1695,7 @@ async function runDoctorCommand(options = {}) {
1415
1695
  }
1416
1696
  }
1417
1697
  if (report.checks.some((check) => !check.ok)) {
1418
- logger8.warn("Some checks failed");
1698
+ logger9.warn("Some checks failed");
1419
1699
  if (options.strict || options.json || process.env.CI) {
1420
1700
  process.exitCode = 1;
1421
1701
  }
@@ -1423,9 +1703,9 @@ async function runDoctorCommand(options = {}) {
1423
1703
  }
1424
1704
 
1425
1705
  // src/commands/shell.ts
1426
- import { createLogger as createLogger9 } from "@revealui/setup/utils";
1706
+ import { createLogger as createLogger10 } from "@revealui/setup/utils";
1427
1707
  import { execa as execa5 } from "execa";
1428
- var logger9 = createLogger9({ prefix: "Shell" });
1708
+ var logger10 = createLogger10({ prefix: "Shell" });
1429
1709
  async function runShellCommand(options = {}) {
1430
1710
  if (!(options.inside || process.env.IN_NIX_SHELL) && await commandExists("nix")) {
1431
1711
  const workspaceRoot = findWorkspaceRoot();
@@ -1470,12 +1750,12 @@ async function runShellCommand(options = {}) {
1470
1750
  }
1471
1751
  process.stdout.write(`${formatDoctorReport(freshReport)}
1472
1752
  `);
1473
- logger9.info("Use `revealui doctor --json` for machine-readable status.");
1753
+ logger10.info("Use `revealui doctor --json` for machine-readable status.");
1474
1754
  return false;
1475
1755
  }
1476
1756
 
1477
1757
  // src/commands/dev.ts
1478
- var logger10 = createLogger10({ prefix: "Dev" });
1758
+ var logger11 = createLogger11({ prefix: "Dev" });
1479
1759
  var DEV_PROFILES = {
1480
1760
  local: {},
1481
1761
  agent: {
@@ -1601,20 +1881,20 @@ async function runDevUpCommand(options = {}) {
1601
1881
  process.stdout.write(`${formatDevActions(plan)}
1602
1882
  `);
1603
1883
  if (plan.dryRun) {
1604
- logger10.info("Dry run only; no migrations or services were started.");
1884
+ logger11.info("Dry run only; no migrations or services were started.");
1605
1885
  return;
1606
1886
  }
1607
1887
  if (options.fix) {
1608
1888
  await runDoctorCommand({ fix: true });
1609
1889
  }
1610
1890
  await runDbMigrateCommand();
1611
- logger10.success("Database migration complete");
1891
+ logger11.success("Database migration complete");
1612
1892
  if (shouldIncludeMcp(resolved.include)) {
1613
1893
  const workspaceRoot = findWorkspaceRoot();
1614
1894
  if (!workspaceRoot) {
1615
1895
  throw new Error("RevealUI workspace root not found");
1616
1896
  }
1617
- logger10.info("Validating MCP setup");
1897
+ logger11.info("Validating MCP setup");
1618
1898
  await execa6("pnpm", ["setup:mcp"], {
1619
1899
  cwd: workspaceRoot,
1620
1900
  stdio: "inherit"
@@ -1625,7 +1905,7 @@ async function runDevUpCommand(options = {}) {
1625
1905
  if (!workspaceRoot) {
1626
1906
  throw new Error("RevealUI workspace root not found");
1627
1907
  }
1628
- logger10.info(`Starting dev script: ${resolved.script}`);
1908
+ logger11.info(`Starting dev script: ${resolved.script}`);
1629
1909
  await execa6("pnpm", [resolved.script], {
1630
1910
  cwd: workspaceRoot,
1631
1911
  stdio: "inherit"
@@ -1683,7 +1963,7 @@ async function runDevProfileSetCommand(profile) {
1683
1963
  );
1684
1964
  }
1685
1965
  const configPath = writeDevConfig({ defaultProfile: profile });
1686
- logger10.success(`Default dev profile set to "${profile}" in ${configPath}`);
1966
+ logger11.success(`Default dev profile set to "${profile}" in ${configPath}`);
1687
1967
  }
1688
1968
  async function runDevProfileShowCommand(options = {}) {
1689
1969
  const configuredProfile = getConfiguredProfile() ?? null;
@@ -1697,10 +1977,10 @@ async function runDevProfileShowCommand(options = {}) {
1697
1977
  }
1698
1978
 
1699
1979
  // src/cli.ts
1700
- var logger11 = createLogger11({ prefix: "CLI" });
1980
+ var logger12 = createLogger12({ prefix: "CLI" });
1701
1981
  function configureCreateCommand(command, legacyName) {
1702
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) => {
1703
- logger11.header(legacyName ? "Create RevealUI Project" : "RevealUI Create");
1983
+ logger12.header(legacyName ? "Create RevealUI Project" : "RevealUI Create");
1704
1984
  await runCreateFlow(projectName, options);
1705
1985
  });
1706
1986
  return command;
@@ -1712,6 +1992,17 @@ function createCli() {
1712
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) => {
1713
1993
  await runDoctorCommand(options);
1714
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
+ });
1715
2006
  const db = program.command("db").description("Manage the local RevealUI database");
1716
2007
  db.command("init").description("Initialize the local PostgreSQL data directory").option("--force", "Delete and recreate the local data directory", false).action(async (options) => {
1717
2008
  await runDbInitCommand(options);