@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 +445 -154
- package/dist/cli.js.map +1 -1
- package/dist/index.js +445 -154
- package/dist/index.js.map +1 -1
- package/package.json +16 -8
- package/templates/basic-blog/next.config.mjs +1 -3
- package/templates/basic-blog/package.json +1 -1
- package/templates/e-commerce/next.config.mjs +1 -3
- package/templates/e-commerce/package.json +1 -1
- package/templates/portfolio/next.config.mjs +1 -3
- package/templates/portfolio/package.json +1 -1
- package/templates/starter/next.config.mjs +1 -3
- package/templates/starter/package.json +1 -1
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
348
|
-
var
|
|
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
|
-
|
|
566
|
+
logger3.error(
|
|
356
567
|
`Node.js ${REQUIRED_NODE_VERSION} or higher is required. You have ${currentVersion}.`
|
|
357
568
|
);
|
|
358
|
-
|
|
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
|
|
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
|
|
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
|
-
##
|
|
781
|
+
## Requirements
|
|
573
782
|
|
|
574
|
-
### Standard Setup
|
|
575
|
-
|
|
576
|
-
Requirements:
|
|
577
783
|
- Node.js 24.13.0 or higher
|
|
578
|
-
- pnpm 10
|
|
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
|
|
605
|
-
\u2502 \u251C\u2500\u2500
|
|
606
|
-
\u2502 \
|
|
607
|
-
\
|
|
608
|
-
\
|
|
609
|
-
\
|
|
610
|
-
\
|
|
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
|
|
802
|
+
- \`pnpm dev\` - Start the development server
|
|
619
803
|
- \`pnpm build\` - Build for production
|
|
620
804
|
- \`pnpm test\` - Run tests
|
|
621
|
-
- \`pnpm lint\` -
|
|
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
|
|
809
|
+
- \`pnpm db:seed\` - Seed sample content
|
|
626
810
|
|
|
627
811
|
## Learn More
|
|
628
812
|
|
|
629
|
-
- [RevealUI Documentation](https://
|
|
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
|
|
828
|
+
import { createLogger as createLogger4 } from "@revealui/setup/utils";
|
|
646
829
|
import { execa } from "execa";
|
|
647
830
|
import ora from "ora";
|
|
648
|
-
var
|
|
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
|
-
|
|
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
|
|
856
|
+
import { createLogger as createLogger5 } from "@revealui/setup/utils";
|
|
674
857
|
import { execa as execa2 } from "execa";
|
|
675
|
-
var
|
|
858
|
+
var logger5 = createLogger5({ prefix: "Git" });
|
|
676
859
|
async function initializeGitRepo(projectPath) {
|
|
677
860
|
try {
|
|
678
861
|
await execa2("git", ["init"], { cwd: projectPath });
|
|
679
|
-
|
|
862
|
+
logger5.success("Initialized git repository");
|
|
680
863
|
} catch (error) {
|
|
681
|
-
|
|
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
|
-
|
|
872
|
+
logger5.success("Created initial commit");
|
|
690
873
|
} catch (error) {
|
|
691
|
-
|
|
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
|
|
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
|
-
|
|
1043
|
+
logger6.success("README.md generated");
|
|
820
1044
|
if (cfg.devenv.createDevContainer) {
|
|
821
1045
|
await generateDevContainer(projectPath);
|
|
822
|
-
|
|
1046
|
+
logger6.success(".devcontainer/ generated");
|
|
823
1047
|
}
|
|
824
1048
|
if (cfg.devenv.createDevbox) {
|
|
825
1049
|
await generateDevbox(projectPath);
|
|
826
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1074
|
+
logger6.info("Skipping git initialisation (--skip-git)");
|
|
850
1075
|
}
|
|
851
1076
|
}
|
|
852
1077
|
|
|
853
1078
|
// src/commands/create-flow.ts
|
|
854
|
-
var
|
|
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
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
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
|
-
|
|
1161
|
+
logger7.info(` ${message}`);
|
|
917
1162
|
}
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
1353
|
-
var
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1708
|
+
import { createLogger as createLogger10 } from "@revealui/setup/utils";
|
|
1429
1709
|
import { execa as execa5 } from "execa";
|
|
1430
|
-
var
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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);
|