create-ai-scaffold 0.1.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 +467 -0
- package/package.json +52 -0
- package/src/index.ts +13 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
|
|
6
|
+
// src/commands/init.ts
|
|
7
|
+
import path3 from "path";
|
|
8
|
+
import { input, select, confirm } from "@inquirer/prompts";
|
|
9
|
+
|
|
10
|
+
// src/scaffolder/scaffold.ts
|
|
11
|
+
import path2 from "path";
|
|
12
|
+
|
|
13
|
+
// src/utils/fs.ts
|
|
14
|
+
import fs from "fs";
|
|
15
|
+
import path from "path";
|
|
16
|
+
function ensureDir(dirPath) {
|
|
17
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
18
|
+
}
|
|
19
|
+
function writeFileSafe(filePath, content) {
|
|
20
|
+
if (fs.existsSync(filePath)) {
|
|
21
|
+
return "skipped";
|
|
22
|
+
}
|
|
23
|
+
ensureDir(path.dirname(filePath));
|
|
24
|
+
fs.writeFileSync(filePath, content, "utf-8");
|
|
25
|
+
return "created";
|
|
26
|
+
}
|
|
27
|
+
var MERGE_HEADER = "# --- Added by create-ai-scaffold ---";
|
|
28
|
+
function mergeGitignore(filePath, newEntries) {
|
|
29
|
+
if (!fs.existsSync(filePath)) {
|
|
30
|
+
ensureDir(path.dirname(filePath));
|
|
31
|
+
fs.writeFileSync(filePath, newEntries.join("\n") + "\n", "utf-8");
|
|
32
|
+
return "created";
|
|
33
|
+
}
|
|
34
|
+
const existing = fs.readFileSync(filePath, "utf-8");
|
|
35
|
+
const existingLines = new Set(
|
|
36
|
+
existing.split("\n").map((l) => l.trim()).filter(Boolean)
|
|
37
|
+
);
|
|
38
|
+
const missing = newEntries.filter((entry) => !existingLines.has(entry.trim()));
|
|
39
|
+
if (missing.length === 0) {
|
|
40
|
+
return "skipped";
|
|
41
|
+
}
|
|
42
|
+
const append = `
|
|
43
|
+
${MERGE_HEADER}
|
|
44
|
+
${missing.join("\n")}
|
|
45
|
+
`;
|
|
46
|
+
fs.appendFileSync(filePath, append, "utf-8");
|
|
47
|
+
return "merged";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/scaffolder/templates/claude-md.ts
|
|
51
|
+
function claudeMd(_opts) {
|
|
52
|
+
return `# CLAUDE.md
|
|
53
|
+
|
|
54
|
+
This file is the entry point for Claude Code (claude.ai/code).
|
|
55
|
+
|
|
56
|
+
**All instructions live in \`.ai/assistant.md\`** \u2014 this file just points there.
|
|
57
|
+
|
|
58
|
+
Read \`.ai/assistant.md\` before starting any task.
|
|
59
|
+
`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// src/scaffolder/templates/agents-md.ts
|
|
63
|
+
function agentsMd(_opts) {
|
|
64
|
+
return `# AGENTS.md
|
|
65
|
+
|
|
66
|
+
This file is the entry point for Codex and other agent-based tools.
|
|
67
|
+
|
|
68
|
+
**All instructions live in \`.ai/assistant.md\`** \u2014 this file just points there.
|
|
69
|
+
|
|
70
|
+
Read \`.ai/assistant.md\` before starting any task.
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/scaffolder/templates/cursorrules.ts
|
|
75
|
+
function cursorrules(_opts) {
|
|
76
|
+
return `# .cursorrules
|
|
77
|
+
|
|
78
|
+
This file is the entry point for Cursor.
|
|
79
|
+
|
|
80
|
+
**All instructions live in \`.ai/assistant.md\`** \u2014 this file just points there.
|
|
81
|
+
|
|
82
|
+
Read \`.ai/assistant.md\` before starting any task.
|
|
83
|
+
`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/scaffolder/templates/windsurfrules.ts
|
|
87
|
+
function windsurfrules(_opts) {
|
|
88
|
+
return `# .windsurfrules
|
|
89
|
+
|
|
90
|
+
This file is the entry point for Windsurf.
|
|
91
|
+
|
|
92
|
+
**All instructions live in \`.ai/assistant.md\`** \u2014 this file just points there.
|
|
93
|
+
|
|
94
|
+
Read \`.ai/assistant.md\` before starting any task.
|
|
95
|
+
`;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// src/scaffolder/templates/assistant-md.ts
|
|
99
|
+
function assistantMd(opts) {
|
|
100
|
+
const { projectName, tier } = opts;
|
|
101
|
+
const header = `# AI Assistant Instructions \u2014 ${projectName}
|
|
102
|
+
|
|
103
|
+
## Getting Started
|
|
104
|
+
|
|
105
|
+
- Read this file before starting any task.
|
|
106
|
+
- Check \`.ai/buildplan.md\` for the current implementation plan.
|
|
107
|
+
- Check \`.ai/conventions.md\` for project conventions and patterns.
|
|
108
|
+
- Drop relevant context files in \`.ai/context/\` for reference.
|
|
109
|
+
`;
|
|
110
|
+
const workflow = `
|
|
111
|
+
## Workflow
|
|
112
|
+
|
|
113
|
+
1. **Read** the relevant plan section or issue before writing code.
|
|
114
|
+
2. **Implement** in small, focused commits.
|
|
115
|
+
3. **Test** your changes before marking work as done.
|
|
116
|
+
4. **Update** the buildplan when completing a step.
|
|
117
|
+
`;
|
|
118
|
+
const conventions = `
|
|
119
|
+
## Conventions Reference
|
|
120
|
+
|
|
121
|
+
See \`.ai/conventions.md\` for:
|
|
122
|
+
- Code style and formatting rules
|
|
123
|
+
- Naming conventions
|
|
124
|
+
- File organization patterns
|
|
125
|
+
`;
|
|
126
|
+
let tierSpecific = "";
|
|
127
|
+
if (tier === "team" || tier === "production") {
|
|
128
|
+
tierSpecific += `
|
|
129
|
+
## Architecture Decisions
|
|
130
|
+
|
|
131
|
+
Record significant decisions in \`.ai/decisions/\` using the ADR template.
|
|
132
|
+
When facing a non-trivial design choice, create a decision record before implementing.
|
|
133
|
+
`;
|
|
134
|
+
}
|
|
135
|
+
if (tier === "production") {
|
|
136
|
+
tierSpecific += `
|
|
137
|
+
## Quality Requirements
|
|
138
|
+
|
|
139
|
+
- **Tests**: All new features and bug fixes require tests.
|
|
140
|
+
- **Documentation**: Update relevant docs when changing public APIs.
|
|
141
|
+
- **Security**: Never commit secrets. Validate all external input.
|
|
142
|
+
- **Review**: All changes should be reviewed before merging.
|
|
143
|
+
`;
|
|
144
|
+
}
|
|
145
|
+
return header + workflow + conventions + tierSpecific;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// src/scaffolder/templates/buildplan-md.ts
|
|
149
|
+
function buildplanMd(opts) {
|
|
150
|
+
return `# Build Plan \u2014 ${opts.projectName}
|
|
151
|
+
|
|
152
|
+
<!-- This is your implementation roadmap. Break work into phases and steps. -->
|
|
153
|
+
<!-- AI assistants will read this to understand what to work on next. -->
|
|
154
|
+
|
|
155
|
+
## Phase 1 \u2014 MVP
|
|
156
|
+
|
|
157
|
+
<!-- Describe the minimum viable version of your project. -->
|
|
158
|
+
|
|
159
|
+
### Step 1: ...
|
|
160
|
+
|
|
161
|
+
<!-- What needs to happen first? -->
|
|
162
|
+
|
|
163
|
+
### Step 2: ...
|
|
164
|
+
|
|
165
|
+
<!-- What comes next? -->
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Phase 2 \u2014 Enhancements
|
|
170
|
+
|
|
171
|
+
<!-- What comes after the MVP? -->
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Notes
|
|
176
|
+
|
|
177
|
+
<!-- Any additional context, open questions, or constraints. -->
|
|
178
|
+
`;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// src/scaffolder/templates/conventions-md.ts
|
|
182
|
+
function conventionsMd(opts) {
|
|
183
|
+
const { tier } = opts;
|
|
184
|
+
if (tier === "solo") {
|
|
185
|
+
return `# Conventions
|
|
186
|
+
|
|
187
|
+
<!-- Define your project's conventions here so AI assistants follow them consistently. -->
|
|
188
|
+
|
|
189
|
+
## Code Style
|
|
190
|
+
|
|
191
|
+
<!-- e.g., "Use single quotes", "Prefer const over let", "Max line length: 100" -->
|
|
192
|
+
|
|
193
|
+
## File Organization
|
|
194
|
+
|
|
195
|
+
<!-- e.g., "Components in src/components/", "Tests next to source files" -->
|
|
196
|
+
|
|
197
|
+
## Naming
|
|
198
|
+
|
|
199
|
+
<!-- e.g., "camelCase for variables", "PascalCase for components" -->
|
|
200
|
+
`;
|
|
201
|
+
}
|
|
202
|
+
return `# Conventions
|
|
203
|
+
|
|
204
|
+
<!-- Define your project's conventions here so AI assistants follow them consistently. -->
|
|
205
|
+
|
|
206
|
+
## Code Style
|
|
207
|
+
|
|
208
|
+
<!-- e.g., "Use single quotes", "Prefer const over let", "Max line length: 100" -->
|
|
209
|
+
|
|
210
|
+
## File Organization
|
|
211
|
+
|
|
212
|
+
<!-- e.g., "Components in src/components/", "Tests next to source files" -->
|
|
213
|
+
|
|
214
|
+
## Naming
|
|
215
|
+
|
|
216
|
+
<!-- e.g., "camelCase for variables", "PascalCase for components", "kebab-case for files" -->
|
|
217
|
+
|
|
218
|
+
## Git & Branching
|
|
219
|
+
|
|
220
|
+
<!-- e.g., "Conventional commits", "Feature branches off main", "Squash merges" -->
|
|
221
|
+
|
|
222
|
+
## Testing
|
|
223
|
+
|
|
224
|
+
<!-- e.g., "Unit tests for all utils", "Integration tests for API routes" -->
|
|
225
|
+
|
|
226
|
+
## Dependencies
|
|
227
|
+
|
|
228
|
+
<!-- e.g., "Prefer stdlib over deps", "All deps must be MIT/Apache licensed" -->
|
|
229
|
+
|
|
230
|
+
## Documentation
|
|
231
|
+
|
|
232
|
+
<!-- e.g., "JSDoc for public APIs", "README per package" -->
|
|
233
|
+
`;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// src/scaffolder/templates/decision-template-md.ts
|
|
237
|
+
function decisionTemplateMd(_opts) {
|
|
238
|
+
return `# ADR-000: [Title]
|
|
239
|
+
|
|
240
|
+
## Status
|
|
241
|
+
|
|
242
|
+
<!-- Proposed | Accepted | Deprecated | Superseded by ADR-XXX -->
|
|
243
|
+
|
|
244
|
+
Proposed
|
|
245
|
+
|
|
246
|
+
## Context
|
|
247
|
+
|
|
248
|
+
<!-- What is the issue that we're seeing that motivates this decision? -->
|
|
249
|
+
|
|
250
|
+
## Decision
|
|
251
|
+
|
|
252
|
+
<!-- What is the change that we're proposing and/or doing? -->
|
|
253
|
+
|
|
254
|
+
## Consequences
|
|
255
|
+
|
|
256
|
+
<!-- What becomes easier or harder because of this change? -->
|
|
257
|
+
`;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// src/scaffolder/templates/context-readme-md.ts
|
|
261
|
+
function contextReadmeMd(_opts) {
|
|
262
|
+
return `# Context
|
|
263
|
+
|
|
264
|
+
Drop files here that you want AI assistants to reference during tasks.
|
|
265
|
+
|
|
266
|
+
## Examples
|
|
267
|
+
|
|
268
|
+
- API specs (OpenAPI/Swagger docs)
|
|
269
|
+
- Design documents or wireframes
|
|
270
|
+
- Architecture diagrams
|
|
271
|
+
- Relevant RFCs or technical specs
|
|
272
|
+
- Example code from other projects
|
|
273
|
+
|
|
274
|
+
## Tips
|
|
275
|
+
|
|
276
|
+
- Keep files focused \u2014 one topic per file.
|
|
277
|
+
- Use descriptive filenames (e.g., \`auth-api-spec.md\`, not \`notes.md\`).
|
|
278
|
+
- Remove files when they're no longer relevant.
|
|
279
|
+
- AI assistants won't read these automatically \u2014 reference them in your prompts.
|
|
280
|
+
`;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// src/scaffolder/templates/gitignore.ts
|
|
284
|
+
var GITIGNORE_ENTRIES = [
|
|
285
|
+
"node_modules/",
|
|
286
|
+
"dist/",
|
|
287
|
+
".env",
|
|
288
|
+
".env.*",
|
|
289
|
+
"!.env.example",
|
|
290
|
+
".DS_Store",
|
|
291
|
+
"Thumbs.db",
|
|
292
|
+
"*.swp",
|
|
293
|
+
"*.swo",
|
|
294
|
+
"*~",
|
|
295
|
+
".idea/",
|
|
296
|
+
".vscode/",
|
|
297
|
+
"*.log"
|
|
298
|
+
];
|
|
299
|
+
function gitignore(_opts) {
|
|
300
|
+
return GITIGNORE_ENTRIES.join("\n") + "\n";
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// src/scaffolder/scaffold.ts
|
|
304
|
+
function buildManifest(options) {
|
|
305
|
+
const opts = { projectName: options.projectName, tier: options.tier };
|
|
306
|
+
const entries = [
|
|
307
|
+
// Root pointer files
|
|
308
|
+
{ relativePath: "CLAUDE.md", content: claudeMd(opts), mode: "create" },
|
|
309
|
+
{ relativePath: "AGENTS.md", content: agentsMd(opts), mode: "create" },
|
|
310
|
+
{ relativePath: ".cursorrules", content: cursorrules(opts), mode: "create" },
|
|
311
|
+
{ relativePath: ".windsurfrules", content: windsurfrules(opts), mode: "create" },
|
|
312
|
+
// .ai/ directory
|
|
313
|
+
{ relativePath: ".ai/assistant.md", content: assistantMd(opts), mode: "create" },
|
|
314
|
+
{ relativePath: ".ai/buildplan.md", content: buildplanMd(opts), mode: "create" },
|
|
315
|
+
{ relativePath: ".ai/conventions.md", content: conventionsMd(opts), mode: "create" },
|
|
316
|
+
{ relativePath: ".ai/context/README.md", content: contextReadmeMd(opts), mode: "create" },
|
|
317
|
+
// .gitignore
|
|
318
|
+
{ relativePath: ".gitignore", content: gitignore(opts), mode: "merge" }
|
|
319
|
+
];
|
|
320
|
+
if (options.tier === "team" || options.tier === "production") {
|
|
321
|
+
entries.push({
|
|
322
|
+
relativePath: ".ai/decisions/000-template.md",
|
|
323
|
+
content: decisionTemplateMd(opts),
|
|
324
|
+
mode: "create"
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
return entries;
|
|
328
|
+
}
|
|
329
|
+
function getPlannedFiles(options) {
|
|
330
|
+
return buildManifest(options).map((e) => e.relativePath);
|
|
331
|
+
}
|
|
332
|
+
function executeManifest(targetDir, manifest) {
|
|
333
|
+
const result = { created: [], skipped: [], merged: [] };
|
|
334
|
+
for (const entry of manifest) {
|
|
335
|
+
const fullPath = path2.join(targetDir, entry.relativePath);
|
|
336
|
+
if (entry.mode === "merge" && entry.relativePath === ".gitignore") {
|
|
337
|
+
const status = mergeGitignore(fullPath, GITIGNORE_ENTRIES);
|
|
338
|
+
result[status === "created" ? "created" : status === "merged" ? "merged" : "skipped"].push(
|
|
339
|
+
entry.relativePath
|
|
340
|
+
);
|
|
341
|
+
} else {
|
|
342
|
+
const status = writeFileSafe(fullPath, entry.content);
|
|
343
|
+
result[status].push(entry.relativePath);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return result;
|
|
347
|
+
}
|
|
348
|
+
function scaffold(options) {
|
|
349
|
+
const manifest = buildManifest(options);
|
|
350
|
+
return executeManifest(options.targetDir, manifest);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// src/utils/logger.ts
|
|
354
|
+
var isColorEnabled = !process.env["NO_COLOR"] && process.stdout.isTTY !== false;
|
|
355
|
+
var color = (code, text) => isColorEnabled ? `\x1B[${code}m${text}\x1B[0m` : text;
|
|
356
|
+
var green = (t) => color("32", t);
|
|
357
|
+
var yellow = (t) => color("33", t);
|
|
358
|
+
var red = (t) => color("31", t);
|
|
359
|
+
var cyan = (t) => color("36", t);
|
|
360
|
+
var bold = (t) => color("1", t);
|
|
361
|
+
var dim = (t) => color("2", t);
|
|
362
|
+
function info(msg) {
|
|
363
|
+
console.log(`${cyan("\u2139")} ${msg}`);
|
|
364
|
+
}
|
|
365
|
+
function warn(msg) {
|
|
366
|
+
console.log(`${yellow("\u26A0")} ${msg}`);
|
|
367
|
+
}
|
|
368
|
+
function error(msg) {
|
|
369
|
+
console.error(`${red("\u2716")} ${msg}`);
|
|
370
|
+
}
|
|
371
|
+
function banner() {
|
|
372
|
+
console.log();
|
|
373
|
+
console.log(bold(" create-ai-scaffold"));
|
|
374
|
+
console.log(dim(" Scaffold the AI-collaboration layer for any project"));
|
|
375
|
+
console.log();
|
|
376
|
+
}
|
|
377
|
+
function nextSteps(items) {
|
|
378
|
+
console.log();
|
|
379
|
+
console.log(bold("Next steps:"));
|
|
380
|
+
items.forEach((item, i) => {
|
|
381
|
+
console.log(` ${dim(`${i + 1}.`)} ${item}`);
|
|
382
|
+
});
|
|
383
|
+
console.log();
|
|
384
|
+
}
|
|
385
|
+
function fileResult(status, filePath) {
|
|
386
|
+
const labels = {
|
|
387
|
+
created: green("CREATE"),
|
|
388
|
+
skipped: yellow(" SKIP "),
|
|
389
|
+
merged: cyan("MERGE ")
|
|
390
|
+
};
|
|
391
|
+
console.log(` ${labels[status]} ${filePath}`);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// src/commands/init.ts
|
|
395
|
+
var VALID_TIERS = ["solo", "team", "production"];
|
|
396
|
+
function registerInitCommand(program2) {
|
|
397
|
+
program2.argument("[project-name]", 'Project name (creates subdirectory unless ".")').option("-y, --yes", "Skip prompts and use defaults", false).option("-t, --tier <tier>", "Collaboration tier: solo, team, or production").action(async (projectNameArg, opts) => {
|
|
398
|
+
banner();
|
|
399
|
+
let projectName;
|
|
400
|
+
if (projectNameArg) {
|
|
401
|
+
projectName = projectNameArg;
|
|
402
|
+
} else if (opts.yes) {
|
|
403
|
+
projectName = path3.basename(process.cwd());
|
|
404
|
+
} else {
|
|
405
|
+
projectName = await input({
|
|
406
|
+
message: "Project name:",
|
|
407
|
+
default: path3.basename(process.cwd())
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
let tier;
|
|
411
|
+
if (opts.tier) {
|
|
412
|
+
if (!VALID_TIERS.includes(opts.tier)) {
|
|
413
|
+
error(`Invalid tier "${opts.tier}". Must be one of: ${VALID_TIERS.join(", ")}`);
|
|
414
|
+
process.exit(1);
|
|
415
|
+
}
|
|
416
|
+
tier = opts.tier;
|
|
417
|
+
} else if (opts.yes) {
|
|
418
|
+
tier = "solo";
|
|
419
|
+
} else {
|
|
420
|
+
tier = await select({
|
|
421
|
+
message: "Collaboration tier:",
|
|
422
|
+
choices: [
|
|
423
|
+
{ value: "solo", name: "solo \u2014 Just you and AI assistants" },
|
|
424
|
+
{ value: "team", name: "team \u2014 Multiple contributors, ADRs, shared conventions" },
|
|
425
|
+
{ value: "production", name: "production \u2014 Full quality gates: tests, docs, security" }
|
|
426
|
+
],
|
|
427
|
+
default: "solo"
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
const isCurrentDir = !projectNameArg || projectNameArg === ".";
|
|
431
|
+
const targetDir = isCurrentDir ? process.cwd() : path3.resolve(process.cwd(), projectNameArg);
|
|
432
|
+
const plannedFiles = getPlannedFiles({ projectName, tier, targetDir });
|
|
433
|
+
info(`Scaffolding "${projectName}" (${tier} tier) in ${targetDir}`);
|
|
434
|
+
console.log();
|
|
435
|
+
plannedFiles.forEach((f) => console.log(` ${f}`));
|
|
436
|
+
console.log();
|
|
437
|
+
if (!opts.yes) {
|
|
438
|
+
const proceed = await confirm({
|
|
439
|
+
message: "Create these files?",
|
|
440
|
+
default: true
|
|
441
|
+
});
|
|
442
|
+
if (!proceed) {
|
|
443
|
+
warn("Aborted.");
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
ensureDir(targetDir);
|
|
448
|
+
const result = scaffold({ projectName, tier, targetDir });
|
|
449
|
+
console.log();
|
|
450
|
+
for (const f of result.created) fileResult("created", f);
|
|
451
|
+
for (const f of result.merged) fileResult("merged", f);
|
|
452
|
+
for (const f of result.skipped) fileResult("skipped", f);
|
|
453
|
+
const steps = [
|
|
454
|
+
`Edit ${isCurrentDir ? "" : `${projectName}/`}.ai/assistant.md with your project-specific instructions`,
|
|
455
|
+
`Edit ${isCurrentDir ? "" : `${projectName}/`}.ai/conventions.md with your code style rules`,
|
|
456
|
+
`Write your implementation plan in ${isCurrentDir ? "" : `${projectName}/`}.ai/buildplan.md`,
|
|
457
|
+
"Start a conversation with your AI assistant!"
|
|
458
|
+
];
|
|
459
|
+
nextSteps(steps);
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// src/index.ts
|
|
464
|
+
var program = new Command();
|
|
465
|
+
program.name("create-ai-scaffold").description("Scaffold the AI-collaboration layer for any project").version("0.1.0");
|
|
466
|
+
registerInitCommand(program);
|
|
467
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-ai-scaffold",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Scaffold the AI-collaboration layer for any project",
|
|
5
|
+
"homepage": "https://github.com/kylewebdev/create-ai-scaffold#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/kylewebdev/create-ai-scaffold/issues"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/kylewebdev/create-ai-scaffold.git"
|
|
12
|
+
},
|
|
13
|
+
"license": "ISC",
|
|
14
|
+
"author": "Kyle Garcia",
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "src/index.ts",
|
|
17
|
+
"bin": {
|
|
18
|
+
"create-ai-scaffold": "dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"directories": {
|
|
21
|
+
"test": "tests"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsup",
|
|
28
|
+
"dev": "tsup --watch",
|
|
29
|
+
"test": "vitest run",
|
|
30
|
+
"lint": "tsc --noEmit"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@inquirer/prompts": "^7.0.0",
|
|
34
|
+
"commander": "^13.0.0",
|
|
35
|
+
"diff": "^8.0.3",
|
|
36
|
+
"ignore": "^7.0.5"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/node": "^22.0.0",
|
|
40
|
+
"tsup": "^8.0.0",
|
|
41
|
+
"typescript": "^5.7.0",
|
|
42
|
+
"vitest": "^3.0.0"
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=18"
|
|
46
|
+
},
|
|
47
|
+
"pnpm": {
|
|
48
|
+
"onlyBuiltDependencies": [
|
|
49
|
+
"esbuild"
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { registerInitCommand } from './commands/init.js';
|
|
3
|
+
|
|
4
|
+
const program = new Command();
|
|
5
|
+
|
|
6
|
+
program
|
|
7
|
+
.name('create-ai-scaffold')
|
|
8
|
+
.description('Scaffold the AI-collaboration layer for any project')
|
|
9
|
+
.version('0.1.0');
|
|
10
|
+
|
|
11
|
+
registerInitCommand(program);
|
|
12
|
+
|
|
13
|
+
program.parse();
|