@withmata/blueprints 0.2.0 → 0.3.1
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/{.opencode/commands/audit.md → .claude/skills/audit/SKILL.md} +8 -6
- package/.claude/skills/blueprint-catalog/SKILL.md +52 -0
- package/.claude/{commands/discover.md → skills/discover/SKILL.md} +8 -3
- package/{.cursor/commands/new-blueprint.md → .claude/skills/new-blueprint/SKILL.md} +13 -8
- package/{.cursor/commands/new-project.md → .claude/skills/new-project/SKILL.md} +11 -6
- package/.claude/{commands/scaffold-auth.md → skills/scaffold-auth/SKILL.md} +24 -23
- package/{.cursor/commands/scaffold-db.md → .claude/skills/scaffold-db/SKILL.md} +17 -16
- package/.claude/{commands/scaffold-foundation.md → skills/scaffold-foundation/SKILL.md} +17 -16
- package/ENGINEERING.md +2 -2
- package/dist/index.js +210 -166
- package/package.json +6 -7
- package/.claude/commands/audit.md +0 -179
- package/.claude/commands/new-blueprint.md +0 -265
- package/.claude/commands/new-project.md +0 -230
- package/.claude/commands/scaffold-db.md +0 -270
- package/.cursor/commands/audit.md +0 -179
- package/.cursor/commands/discover.md +0 -92
- package/.cursor/commands/scaffold-auth.md +0 -310
- package/.cursor/commands/scaffold-foundation.md +0 -158
- package/.opencode/commands/discover.md +0 -96
- package/.opencode/commands/new-blueprint.md +0 -269
- package/.opencode/commands/new-project.md +0 -234
- package/.opencode/commands/scaffold-auth.md +0 -314
- package/.opencode/commands/scaffold-db.md +0 -274
- package/.opencode/commands/scaffold-foundation.md +0 -162
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { intro, outro, log as
|
|
5
|
-
import
|
|
4
|
+
import { intro as intro2, outro as outro2, log as log6 } from "@clack/prompts";
|
|
5
|
+
import pc3 from "picocolors";
|
|
6
6
|
|
|
7
7
|
// src/constants.ts
|
|
8
8
|
var API_URL = process.env["WITHMATA_API_URL"] || "https://blueprints.withmata.dev";
|
|
9
|
-
var VERSION = "0.
|
|
9
|
+
var VERSION = "0.3.1";
|
|
10
10
|
|
|
11
11
|
// src/steps/auth.ts
|
|
12
12
|
import { log } from "@clack/prompts";
|
|
@@ -27,6 +27,15 @@ var WITHMATA_DIR = join(homedir(), ".withmata");
|
|
|
27
27
|
var BLUEPRINTS_DIR = join(WITHMATA_DIR, "blueprints");
|
|
28
28
|
var CREDENTIALS_PATH = join(WITHMATA_DIR, "credentials.json");
|
|
29
29
|
var CONFIG_PATH = join(WITHMATA_DIR, "config.json");
|
|
30
|
+
var SKILLS_SOURCE_DIR = join(BLUEPRINTS_DIR, ".claude", "skills");
|
|
31
|
+
var CLAUDE_SKILLS_DIR = join(homedir(), ".claude", "skills");
|
|
32
|
+
var OPENCODE_SKILLS_DIR = join(
|
|
33
|
+
homedir(),
|
|
34
|
+
".config",
|
|
35
|
+
"opencode",
|
|
36
|
+
"skills"
|
|
37
|
+
);
|
|
38
|
+
var CURSOR_SKILLS_DIR = join(homedir(), ".cursor", "skills");
|
|
30
39
|
var CLAUDE_COMMANDS_DIR = ".claude/commands";
|
|
31
40
|
var OPENCODE_COMMANDS_DIR = ".opencode/commands";
|
|
32
41
|
var CURSOR_COMMANDS_DIR = ".cursor/commands";
|
|
@@ -149,23 +158,11 @@ async function downloadBlueprints(_token) {
|
|
|
149
158
|
recursive: true
|
|
150
159
|
});
|
|
151
160
|
}
|
|
152
|
-
const
|
|
153
|
-
if (existsSync3(
|
|
154
|
-
const target = join3(BLUEPRINTS_DIR, ".claude", "
|
|
155
|
-
mkdirSync2(target, { recursive: true });
|
|
156
|
-
cpSync(claudeCommandsSource, target, { recursive: true });
|
|
157
|
-
}
|
|
158
|
-
const opencodeCommandsSource = join3(sourcePath, ".opencode", "commands");
|
|
159
|
-
if (existsSync3(opencodeCommandsSource)) {
|
|
160
|
-
const target = join3(BLUEPRINTS_DIR, ".opencode", "commands");
|
|
161
|
-
mkdirSync2(target, { recursive: true });
|
|
162
|
-
cpSync(opencodeCommandsSource, target, { recursive: true });
|
|
163
|
-
}
|
|
164
|
-
const cursorCommandsSource = join3(sourcePath, ".cursor", "commands");
|
|
165
|
-
if (existsSync3(cursorCommandsSource)) {
|
|
166
|
-
const target = join3(BLUEPRINTS_DIR, ".cursor", "commands");
|
|
161
|
+
const skillsSource = join3(sourcePath, ".claude", "skills");
|
|
162
|
+
if (existsSync3(skillsSource)) {
|
|
163
|
+
const target = join3(BLUEPRINTS_DIR, ".claude", "skills");
|
|
167
164
|
mkdirSync2(target, { recursive: true });
|
|
168
|
-
cpSync(
|
|
165
|
+
cpSync(skillsSource, target, { recursive: true });
|
|
169
166
|
}
|
|
170
167
|
const engineeringSource = join3(sourcePath, "ENGINEERING.md");
|
|
171
168
|
if (existsSync3(engineeringSource)) {
|
|
@@ -226,188 +223,129 @@ import {
|
|
|
226
223
|
existsSync as existsSync4,
|
|
227
224
|
mkdirSync as mkdirSync3,
|
|
228
225
|
symlinkSync,
|
|
229
|
-
readFileSync as readFileSync2,
|
|
230
|
-
appendFileSync,
|
|
231
|
-
writeFileSync as writeFileSync2,
|
|
232
226
|
lstatSync,
|
|
233
227
|
unlinkSync as unlinkSync2,
|
|
234
228
|
renameSync,
|
|
235
229
|
readdirSync as readdirSync2,
|
|
236
|
-
|
|
230
|
+
readlinkSync
|
|
237
231
|
} from "fs";
|
|
238
232
|
import { join as join4, resolve as resolve2 } from "path";
|
|
239
233
|
import { spinner as spinner2, log as log3 } from "@clack/prompts";
|
|
240
|
-
async function
|
|
241
|
-
let
|
|
242
|
-
const rulesFilesUpdated = [];
|
|
243
|
-
const targetDir = process.cwd();
|
|
234
|
+
async function installSkillsGlobally(tools) {
|
|
235
|
+
let skillsInstalled = 0;
|
|
244
236
|
for (const tool of tools) {
|
|
245
237
|
if (tool === "claude-code") {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
238
|
+
skillsInstalled += installSkills(
|
|
239
|
+
SKILLS_SOURCE_DIR,
|
|
240
|
+
CLAUDE_SKILLS_DIR,
|
|
249
241
|
"Claude Code"
|
|
250
242
|
);
|
|
251
|
-
commandsLinked += result;
|
|
252
|
-
if (updateRulesFile(targetDir, "CLAUDE.md")) {
|
|
253
|
-
rulesFilesUpdated.push("CLAUDE.md");
|
|
254
|
-
}
|
|
255
243
|
}
|
|
256
244
|
if (tool === "opencode") {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
245
|
+
skillsInstalled += installSkills(
|
|
246
|
+
SKILLS_SOURCE_DIR,
|
|
247
|
+
OPENCODE_SKILLS_DIR,
|
|
260
248
|
"OpenCode"
|
|
261
249
|
);
|
|
262
|
-
commandsLinked += result;
|
|
263
|
-
if (updateRulesFile(targetDir, "AGENTS.md")) {
|
|
264
|
-
if (!rulesFilesUpdated.includes("AGENTS.md")) {
|
|
265
|
-
rulesFilesUpdated.push("AGENTS.md");
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
250
|
}
|
|
269
251
|
if (tool === "cursor") {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
252
|
+
skillsInstalled += installSkills(
|
|
253
|
+
SKILLS_SOURCE_DIR,
|
|
254
|
+
CURSOR_SKILLS_DIR,
|
|
273
255
|
"Cursor"
|
|
274
256
|
);
|
|
275
|
-
commandsLinked += result;
|
|
276
|
-
if (updateRulesFile(targetDir, "AGENTS.md")) {
|
|
277
|
-
if (!rulesFilesUpdated.includes("AGENTS.md")) {
|
|
278
|
-
rulesFilesUpdated.push("AGENTS.md");
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
257
|
}
|
|
282
258
|
}
|
|
283
|
-
const
|
|
284
|
-
return {
|
|
259
|
+
const legacyCommandsCleaned = cleanupLegacyCommands(process.cwd());
|
|
260
|
+
return { skillsInstalled, legacyCommandsCleaned };
|
|
285
261
|
}
|
|
286
|
-
function
|
|
262
|
+
function installSkills(sourceDir, globalTargetDir, toolLabel) {
|
|
287
263
|
const s = spinner2();
|
|
288
|
-
s.start(`
|
|
289
|
-
mkdirSync3(
|
|
290
|
-
let count = 0;
|
|
264
|
+
s.start(`Installing skills for ${toolLabel}...`);
|
|
265
|
+
mkdirSync3(globalTargetDir, { recursive: true });
|
|
291
266
|
if (!existsSync4(sourceDir)) {
|
|
292
|
-
s.stop(`No
|
|
267
|
+
s.stop(`No skills found for ${toolLabel}`);
|
|
293
268
|
return 0;
|
|
294
269
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const
|
|
299
|
-
|
|
270
|
+
let count = 0;
|
|
271
|
+
for (const entry of readdirSync2(sourceDir, { withFileTypes: true })) {
|
|
272
|
+
if (!entry.isDirectory()) continue;
|
|
273
|
+
const source = resolve2(sourceDir, entry.name);
|
|
274
|
+
const target = join4(globalTargetDir, entry.name);
|
|
275
|
+
if (existsSync4(target) || lstatExists(target)) {
|
|
300
276
|
if (lstatSync(target).isSymbolicLink()) {
|
|
301
277
|
unlinkSync2(target);
|
|
302
278
|
} else {
|
|
303
|
-
|
|
279
|
+
const backup = `${target}.bak`;
|
|
280
|
+
if (existsSync4(backup)) {
|
|
281
|
+
unlinkSync2(backup);
|
|
282
|
+
}
|
|
283
|
+
renameSync(target, backup);
|
|
304
284
|
}
|
|
305
285
|
}
|
|
306
286
|
symlinkSync(source, target);
|
|
307
287
|
count++;
|
|
308
288
|
}
|
|
309
|
-
s.stop(`${count}
|
|
289
|
+
s.stop(`${count} skills installed for ${toolLabel}`);
|
|
310
290
|
return count;
|
|
311
291
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
### Lifecycle & Dependencies
|
|
349
|
-
|
|
350
|
-
Discovery \u2192 Foundation \u2192 Features is the recommended flow, but blueprints can be applied at any stage.
|
|
351
|
-
|
|
352
|
-
- **New project, no code:** Start with \`/discover\` (especially for non-technical users) or \`/scaffold-foundation\` (for monorepos)
|
|
353
|
-
- **Single-repo project:** Skip foundation \u2014 go directly to feature blueprints (\`/scaffold-db\`, \`/scaffold-auth\`)
|
|
354
|
-
- **Has monorepo, missing features:** Suggest specific feature blueprints
|
|
355
|
-
- **Existing project:** Feature blueprints adapt to existing structures \u2014 no foundation required
|
|
356
|
-
- **Dependencies:** \`/scaffold-auth\` works best after \`/scaffold-db\` (auth builds on db patterns). Install dependencies first.
|
|
357
|
-
|
|
358
|
-
### Important
|
|
359
|
-
|
|
360
|
-
- Read \`.project-context.md\` first \u2014 it tracks what is already set up. Do not recommend blueprints already recorded there.
|
|
361
|
-
- Read the full BLUEPRINT.md before scaffolding. Follow ENGINEERING.md for coding conventions.
|
|
362
|
-
- Only recommend blueprints listed above. Other blueprints are in development and not yet available.
|
|
363
|
-
- Blueprints location: \`${BLUEPRINTS_DIR}\`
|
|
364
|
-
${MARKER_END}
|
|
365
|
-
`;
|
|
366
|
-
}
|
|
367
|
-
function updateRulesFile(targetDir, filename) {
|
|
368
|
-
const filepath = join4(targetDir, filename);
|
|
369
|
-
const block = buildRulesBlock();
|
|
370
|
-
if (existsSync4(filepath)) {
|
|
371
|
-
const content = readFileSync2(filepath, "utf-8");
|
|
372
|
-
if (content.includes(MARKER_START)) {
|
|
373
|
-
const startIdx = content.indexOf(MARKER_START);
|
|
374
|
-
const endIdx = content.indexOf(MARKER_END);
|
|
375
|
-
if (endIdx === -1) {
|
|
376
|
-
appendFileSync(filepath, block);
|
|
377
|
-
} else {
|
|
378
|
-
const before = content.slice(0, startIdx);
|
|
379
|
-
const after = content.slice(endIdx + MARKER_END.length);
|
|
380
|
-
writeFileSync2(filepath, before + block.trimStart() + after);
|
|
292
|
+
function cleanupLegacyCommands(targetDir) {
|
|
293
|
+
let cleaned = 0;
|
|
294
|
+
const legacyDirs = [
|
|
295
|
+
join4(targetDir, CLAUDE_COMMANDS_DIR),
|
|
296
|
+
join4(targetDir, OPENCODE_COMMANDS_DIR),
|
|
297
|
+
join4(targetDir, CURSOR_COMMANDS_DIR)
|
|
298
|
+
];
|
|
299
|
+
for (const dir of legacyDirs) {
|
|
300
|
+
if (!existsSync4(dir)) continue;
|
|
301
|
+
let dirEmpty = true;
|
|
302
|
+
for (const file of readdirSync2(dir)) {
|
|
303
|
+
const filePath = join4(dir, file);
|
|
304
|
+
if (lstatSync(filePath).isSymbolicLink()) {
|
|
305
|
+
try {
|
|
306
|
+
const linkTarget = readlinkSync(filePath);
|
|
307
|
+
if (linkTarget.includes(BLUEPRINTS_DIR)) {
|
|
308
|
+
unlinkSync2(filePath);
|
|
309
|
+
cleaned++;
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
} catch {
|
|
313
|
+
unlinkSync2(filePath);
|
|
314
|
+
cleaned++;
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
dirEmpty = false;
|
|
319
|
+
}
|
|
320
|
+
if (dirEmpty && readdirSync2(dir).length === 0) {
|
|
321
|
+
try {
|
|
322
|
+
readdirSync2(dir);
|
|
323
|
+
if (readdirSync2(dir).length === 0) {
|
|
324
|
+
unlinkSync2(dir);
|
|
325
|
+
}
|
|
326
|
+
} catch {
|
|
381
327
|
}
|
|
382
|
-
log3.success(`Updated ${filename} (refreshed blueprint catalog)`);
|
|
383
|
-
return true;
|
|
384
328
|
}
|
|
385
|
-
appendFileSync(filepath, block);
|
|
386
|
-
} else {
|
|
387
|
-
writeFileSync2(filepath, block.trimStart());
|
|
388
329
|
}
|
|
389
|
-
|
|
390
|
-
|
|
330
|
+
if (cleaned > 0) {
|
|
331
|
+
log3.info(`Cleaned up ${cleaned} legacy command symlink(s)`);
|
|
332
|
+
}
|
|
333
|
+
return cleaned;
|
|
391
334
|
}
|
|
392
|
-
function
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
const targetContent = readFileSync2(target, "utf-8");
|
|
399
|
-
if (sourceContent === targetContent) return false;
|
|
335
|
+
function lstatExists(path) {
|
|
336
|
+
try {
|
|
337
|
+
lstatSync(path);
|
|
338
|
+
return true;
|
|
339
|
+
} catch {
|
|
340
|
+
return false;
|
|
400
341
|
}
|
|
401
|
-
cpSync2(source, target);
|
|
402
|
-
log3.success("Copied ENGINEERING.md");
|
|
403
|
-
return true;
|
|
404
342
|
}
|
|
405
343
|
|
|
406
344
|
// src/steps/summary.ts
|
|
407
345
|
import { log as log4, note } from "@clack/prompts";
|
|
408
346
|
import pc from "picocolors";
|
|
409
|
-
function showSummary({
|
|
410
|
-
const
|
|
347
|
+
function showSummary({ installed, tools, blueprintCount }) {
|
|
348
|
+
const skills = [
|
|
411
349
|
`${pc.cyan("/new-project")} Start a new project`,
|
|
412
350
|
`${pc.cyan("/scaffold-auth")} Add auth to this project`,
|
|
413
351
|
`${pc.cyan("/scaffold-db")} Set up database package`,
|
|
@@ -415,38 +353,144 @@ function showSummary({ linked, tools, blueprintCount }) {
|
|
|
415
353
|
`${pc.cyan("/discover")} Run product discovery`,
|
|
416
354
|
`${pc.cyan("/audit")} Run a project health check`
|
|
417
355
|
].join("\n");
|
|
418
|
-
note(
|
|
356
|
+
note(skills, "Available skills (global)");
|
|
419
357
|
const toolNameMap = {
|
|
420
358
|
"claude-code": "Claude Code",
|
|
421
359
|
opencode: "OpenCode",
|
|
422
360
|
cursor: "Cursor"
|
|
423
361
|
};
|
|
424
|
-
const toolNames = tools.map((t) => toolNameMap[t]).join("
|
|
425
|
-
log4.info(
|
|
426
|
-
|
|
362
|
+
const toolNames = tools.map((t) => toolNameMap[t]).join(", ");
|
|
363
|
+
log4.info(
|
|
364
|
+
`${pc.bold(String(installed.skillsInstalled))} skills installed globally for ${toolNames}.`
|
|
365
|
+
);
|
|
366
|
+
log4.info("These skills work in any project \u2014 no per-project setup needed.");
|
|
367
|
+
if (installed.legacyCommandsCleaned > 0) {
|
|
368
|
+
log4.info(
|
|
369
|
+
pc.dim(
|
|
370
|
+
`Cleaned up ${installed.legacyCommandsCleaned} legacy command symlink(s).`
|
|
371
|
+
)
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// src/steps/uninstall.ts
|
|
377
|
+
import {
|
|
378
|
+
existsSync as existsSync5,
|
|
379
|
+
readdirSync as readdirSync3,
|
|
380
|
+
lstatSync as lstatSync2,
|
|
381
|
+
readlinkSync as readlinkSync2,
|
|
382
|
+
unlinkSync as unlinkSync3,
|
|
383
|
+
rmSync as rmSync2
|
|
384
|
+
} from "fs";
|
|
385
|
+
import { join as join5 } from "path";
|
|
386
|
+
import { intro, outro, confirm, log as log5, spinner as spinner3 } from "@clack/prompts";
|
|
387
|
+
import pc2 from "picocolors";
|
|
388
|
+
var SKILL_DIRS = [CLAUDE_SKILLS_DIR, OPENCODE_SKILLS_DIR, CURSOR_SKILLS_DIR];
|
|
389
|
+
async function runUninstall() {
|
|
390
|
+
intro(
|
|
391
|
+
`${pc2.bgCyan(pc2.black(" @withmata/blueprints "))} ${pc2.dim(`v${VERSION}`)} ${pc2.yellow("uninstall")}`
|
|
392
|
+
);
|
|
393
|
+
const s = spinner3();
|
|
394
|
+
s.start("Scanning for withmata skill symlinks...");
|
|
395
|
+
let symlinksRemoved = 0;
|
|
396
|
+
for (const dir of SKILL_DIRS) {
|
|
397
|
+
if (!existsSync5(dir)) continue;
|
|
398
|
+
for (const entry of readdirSync3(dir)) {
|
|
399
|
+
const fullPath = join5(dir, entry);
|
|
400
|
+
try {
|
|
401
|
+
if (!lstatSync2(fullPath).isSymbolicLink()) continue;
|
|
402
|
+
const target = readlinkSync2(fullPath);
|
|
403
|
+
if (target.startsWith(BLUEPRINTS_DIR)) {
|
|
404
|
+
unlinkSync3(fullPath);
|
|
405
|
+
symlinksRemoved++;
|
|
406
|
+
}
|
|
407
|
+
} catch {
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
s.stop(
|
|
412
|
+
symlinksRemoved > 0 ? `Removed ${symlinksRemoved} skill symlink(s)` : "No withmata symlinks found"
|
|
413
|
+
);
|
|
414
|
+
let blueprintsRemoved = false;
|
|
415
|
+
if (existsSync5(BLUEPRINTS_DIR)) {
|
|
416
|
+
rmSync2(BLUEPRINTS_DIR, { recursive: true, force: true });
|
|
417
|
+
blueprintsRemoved = true;
|
|
418
|
+
log5.success("Removed cached blueprints (~/.withmata/blueprints/)");
|
|
419
|
+
}
|
|
420
|
+
let configRemoved = false;
|
|
421
|
+
if (existsSync5(WITHMATA_DIR)) {
|
|
422
|
+
const removeAll = await confirm({
|
|
423
|
+
message: "Also remove credentials and config (~/.withmata/)?",
|
|
424
|
+
initialValue: false
|
|
425
|
+
});
|
|
426
|
+
if (removeAll === true) {
|
|
427
|
+
rmSync2(WITHMATA_DIR, { recursive: true, force: true });
|
|
428
|
+
configRemoved = true;
|
|
429
|
+
log5.success("Removed ~/.withmata/");
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
if (!symlinksRemoved && !blueprintsRemoved && !configRemoved) {
|
|
433
|
+
outro("Nothing to clean up \u2014 already uninstalled.");
|
|
434
|
+
} else {
|
|
435
|
+
const parts = [];
|
|
436
|
+
if (symlinksRemoved > 0) parts.push(`${symlinksRemoved} symlink(s)`);
|
|
437
|
+
if (blueprintsRemoved) parts.push("cached blueprints");
|
|
438
|
+
if (configRemoved) parts.push("credentials & config");
|
|
439
|
+
outro(`Uninstalled: ${parts.join(", ")}`);
|
|
440
|
+
}
|
|
427
441
|
}
|
|
428
442
|
|
|
429
443
|
// src/index.ts
|
|
444
|
+
var HELP = `
|
|
445
|
+
Usage: @withmata/blueprints [command]
|
|
446
|
+
|
|
447
|
+
Commands:
|
|
448
|
+
install Install blueprints and skills (default)
|
|
449
|
+
uninstall Remove skills, symlinks, and cached data
|
|
450
|
+
|
|
451
|
+
Options:
|
|
452
|
+
-h, --help Show this help message
|
|
453
|
+
-v, --version Show version number
|
|
454
|
+
`.trim();
|
|
430
455
|
async function main() {
|
|
431
|
-
|
|
456
|
+
const arg = process.argv[2];
|
|
457
|
+
if (arg === "--version" || arg === "-v") {
|
|
458
|
+
console.log(VERSION);
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
if (arg === "--help" || arg === "-h") {
|
|
462
|
+
console.log(HELP);
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
if (arg === "uninstall") {
|
|
466
|
+
await runUninstall();
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
if (arg && arg !== "install") {
|
|
470
|
+
console.log(`Unknown command: ${arg}
|
|
471
|
+
`);
|
|
472
|
+
console.log(HELP);
|
|
473
|
+
process.exit(1);
|
|
474
|
+
}
|
|
475
|
+
intro2(`${pc3.bgCyan(pc3.black(" @withmata/blueprints "))} ${pc3.dim(`v${VERSION}`)}`);
|
|
432
476
|
const user = await checkAuth();
|
|
433
477
|
if (user) {
|
|
434
|
-
|
|
478
|
+
log6.success(`Logged in as ${user.email} (${user.tier} plan)`);
|
|
435
479
|
} else {
|
|
436
|
-
|
|
480
|
+
log6.info("Running in local mode");
|
|
437
481
|
}
|
|
438
482
|
const tools = await detectAndSelectTools(process.cwd());
|
|
439
483
|
const blueprints = await downloadBlueprints(user?.token);
|
|
440
|
-
const
|
|
484
|
+
const installed = await installSkillsGlobally(tools);
|
|
441
485
|
showSummary({
|
|
442
|
-
|
|
486
|
+
installed,
|
|
443
487
|
tools,
|
|
444
488
|
blueprintCount: blueprints.total
|
|
445
489
|
});
|
|
446
|
-
|
|
490
|
+
outro2("Setup complete!");
|
|
447
491
|
}
|
|
448
492
|
main().catch((err) => {
|
|
449
|
-
|
|
493
|
+
log6.error(
|
|
450
494
|
err instanceof Error ? err.message : "An unexpected error occurred"
|
|
451
495
|
);
|
|
452
496
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@withmata/blueprints",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Set up AI-powered project blueprints for Claude Code, OpenCode, and Cursor",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -9,17 +9,16 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
|
11
11
|
"blueprints",
|
|
12
|
-
".claude/
|
|
13
|
-
".opencode/commands",
|
|
14
|
-
".cursor/commands",
|
|
12
|
+
".claude/skills",
|
|
15
13
|
"ENGINEERING.md"
|
|
16
14
|
],
|
|
17
15
|
"scripts": {
|
|
18
16
|
"build": "tsup",
|
|
19
17
|
"dev": "tsup --watch",
|
|
20
18
|
"typecheck": "tsc --noEmit",
|
|
21
|
-
"copy-blueprints": "
|
|
22
|
-
"prepublishOnly": "
|
|
19
|
+
"copy-blueprints": "bun scripts/copy-blueprints.mjs",
|
|
20
|
+
"prepublishOnly": "bun scripts/copy-blueprints.mjs && tsup",
|
|
21
|
+
"release": "bun scripts/release.ts"
|
|
23
22
|
},
|
|
24
23
|
"dependencies": {
|
|
25
24
|
"@clack/prompts": "^0.11.0",
|
|
@@ -38,7 +37,7 @@
|
|
|
38
37
|
},
|
|
39
38
|
"repository": {
|
|
40
39
|
"type": "git",
|
|
41
|
-
"url": "https://github.com/With-Mata/my-blueprints.git",
|
|
40
|
+
"url": "git+https://github.com/With-Mata/my-blueprints.git",
|
|
42
41
|
"directory": "cli"
|
|
43
42
|
},
|
|
44
43
|
"keywords": [
|