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