start-vibing 3.0.10 → 4.0.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/README.md +7 -8
- package/dist/cli.js +197 -150
- package/package.json +3 -3
- package/template/.claude/CLAUDE.md +367 -901
- package/template/.claude/README.md +208 -208
- package/template/.claude/agents/commit-manager.md +1 -1
- package/template/.claude/config/README.md +27 -32
- package/template/.claude/settings.json +74 -70
- package/template/CLAUDE.md +290 -305
- package/template/.claude/agents/documenter.md +0 -178
- package/template/.claude/agents/domain-updater.md +0 -134
- package/template/.claude/config/domain-mapping.json +0 -138
- package/template/.claude/skills/codebase-knowledge/SKILL.md +0 -145
- package/template/.claude/skills/codebase-knowledge/TEMPLATE.md +0 -35
- package/template/.claude/skills/codebase-knowledge/domains/claude-system.md +0 -96
- package/template/.claude/skills/codebase-knowledge/domains/mcp-integration.md +0 -128
- package/template/.claude/skills/docs-tracker/SKILL.md +0 -239
package/README.md
CHANGED
|
@@ -53,10 +53,8 @@ Creates a `.claude/` folder with:
|
|
|
53
53
|
|
|
54
54
|
```
|
|
55
55
|
.claude/
|
|
56
|
-
├── agents/ #
|
|
56
|
+
├── agents/ # 4 specialized AI subagents
|
|
57
57
|
│ ├── research-web.md # Best practices research
|
|
58
|
-
│ ├── documenter.md # Domain documentation
|
|
59
|
-
│ ├── domain-updater.md # Session learnings
|
|
60
58
|
│ ├── commit-manager.md # Git workflow
|
|
61
59
|
│ ├── claude-md-compactor.md # CLAUDE.md maintenance
|
|
62
60
|
│ └── tester-unit.md # Unit testing
|
|
@@ -68,7 +66,6 @@ Creates a `.claude/` folder with:
|
|
|
68
66
|
│ └── ...
|
|
69
67
|
├── config/ # Project configuration
|
|
70
68
|
│ ├── project-config.json
|
|
71
|
-
│ ├── domain-mapping.json
|
|
72
69
|
│ └── ...
|
|
73
70
|
└── commands/ # Slash commands
|
|
74
71
|
```
|
|
@@ -83,18 +80,16 @@ Checks for updates on every run (cached for 1 hour) and notifies you when a new
|
|
|
83
80
|
|
|
84
81
|
## Architecture
|
|
85
82
|
|
|
86
|
-
###
|
|
83
|
+
### 4 Subagents
|
|
87
84
|
|
|
88
85
|
| Agent | Purpose |
|
|
89
86
|
| ------------------ | ------------------------------------ |
|
|
90
87
|
| research-web | Researches best practices (2024-2026)|
|
|
91
|
-
| documenter | Maps files to domains, creates docs |
|
|
92
|
-
| domain-updater | Records learnings in domain docs |
|
|
93
88
|
| commit-manager | Manages git commits |
|
|
94
89
|
| claude-md-compactor| Compacts CLAUDE.md when > 40k chars |
|
|
95
90
|
| tester-unit | Creates unit tests with Vitest |
|
|
96
91
|
|
|
97
|
-
###
|
|
92
|
+
### 9 Plugins (auto-install)
|
|
98
93
|
|
|
99
94
|
| Plugin | Mechanism | Purpose |
|
|
100
95
|
| ------------------ | ---------------- | -------------------------- |
|
|
@@ -103,6 +98,10 @@ Checks for updates on every run (cached for 1 hour) and notifies you when a new
|
|
|
103
98
|
| code-review | /code-review cmd | Code quality analysis |
|
|
104
99
|
| commit-commands | /commit cmd | Git commit/push/PR flows |
|
|
105
100
|
| frontend-design | /frontend-design | Production-grade UI design |
|
|
101
|
+
| superpowers | Skills + cmds | TDD, planning, debugging |
|
|
102
|
+
| ralph-loop | /ralph-loop cmd | Autonomous iteration loop |
|
|
103
|
+
| context7 | Skill + agent | Auto library documentation |
|
|
104
|
+
| code-simplifier | /simplify cmd | Code refinement |
|
|
106
105
|
|
|
107
106
|
### 20 Skills
|
|
108
107
|
|
package/dist/cli.js
CHANGED
|
@@ -122,8 +122,8 @@ async function copyClaudeSetup(targetDir, options = {}) {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
// src/cli.ts
|
|
125
|
-
import { existsSync as
|
|
126
|
-
import { join as
|
|
125
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
|
|
126
|
+
import { join as join5, dirname as dirname2 } from "path";
|
|
127
127
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
128
128
|
import { execSync as execSync3 } from "child_process";
|
|
129
129
|
|
|
@@ -508,12 +508,6 @@ function ensureHooksEnabled() {
|
|
|
508
508
|
// src/mcp.ts
|
|
509
509
|
import { spawnSync as spawnSync2, spawn as spawn2 } from "child_process";
|
|
510
510
|
var CORE_MCPS = [
|
|
511
|
-
{
|
|
512
|
-
name: "context7",
|
|
513
|
-
description: "real-time docs",
|
|
514
|
-
command: "npx",
|
|
515
|
-
args: ["-y", "@upstash/context7-mcp@latest"]
|
|
516
|
-
},
|
|
517
511
|
{
|
|
518
512
|
name: "sequential-thinking",
|
|
519
513
|
description: "structured reasoning",
|
|
@@ -581,20 +575,10 @@ function isMcpInstalled(name) {
|
|
|
581
575
|
}
|
|
582
576
|
async function installMcp(server) {
|
|
583
577
|
if (isMcpInstalled(server.name)) {
|
|
584
|
-
return {
|
|
585
|
-
server: server.name,
|
|
586
|
-
success: true,
|
|
587
|
-
message: "Already installed",
|
|
588
|
-
skipped: true
|
|
589
|
-
};
|
|
578
|
+
return { server: server.name, success: true, message: "Already installed", skipped: true };
|
|
590
579
|
}
|
|
591
580
|
return new Promise((resolve) => {
|
|
592
|
-
|
|
593
|
-
if (server.transport === "http" && server.url) {
|
|
594
|
-
args = server.args;
|
|
595
|
-
} else {
|
|
596
|
-
args = ["mcp", "add", "-s", "user", server.name, "--", server.command, ...server.args];
|
|
597
|
-
}
|
|
581
|
+
const args = ["mcp", "add", "-s", "user", server.name, "--", server.command, ...server.args];
|
|
598
582
|
const proc = spawn2("claude", args, {
|
|
599
583
|
shell: true,
|
|
600
584
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -608,54 +592,30 @@ async function installMcp(server) {
|
|
|
608
592
|
stderr += data.toString();
|
|
609
593
|
});
|
|
610
594
|
proc.on("close", (code) => {
|
|
611
|
-
|
|
612
|
-
resolve({
|
|
613
|
-
server: server.name,
|
|
614
|
-
success: true,
|
|
615
|
-
message: "Installed"
|
|
616
|
-
});
|
|
617
|
-
} else {
|
|
618
|
-
resolve({
|
|
619
|
-
server: server.name,
|
|
620
|
-
success: false,
|
|
621
|
-
message: stderr || stdout || `Exit code: ${code}`
|
|
622
|
-
});
|
|
623
|
-
}
|
|
595
|
+
resolve(code === 0 ? { server: server.name, success: true, message: "Installed" } : { server: server.name, success: false, message: stderr || stdout || `Exit code: ${code}` });
|
|
624
596
|
});
|
|
625
597
|
proc.on("error", (err) => {
|
|
626
|
-
resolve({
|
|
627
|
-
server: server.name,
|
|
628
|
-
success: false,
|
|
629
|
-
message: err.message
|
|
630
|
-
});
|
|
598
|
+
resolve({ server: server.name, success: false, message: err.message });
|
|
631
599
|
});
|
|
632
600
|
setTimeout(() => {
|
|
633
601
|
proc.kill();
|
|
634
|
-
resolve({
|
|
635
|
-
server: server.name,
|
|
636
|
-
success: false,
|
|
637
|
-
message: "Installation timed out"
|
|
638
|
-
});
|
|
602
|
+
resolve({ server: server.name, success: false, message: "Installation timed out" });
|
|
639
603
|
}, 60000);
|
|
640
604
|
});
|
|
641
605
|
}
|
|
642
606
|
async function installMcps(onProgress) {
|
|
643
607
|
if (!isClaudeMcpReady()) {
|
|
644
|
-
return {
|
|
645
|
-
installed: 0,
|
|
646
|
-
failed: 0,
|
|
647
|
-
skipped: CORE_MCPS.length,
|
|
648
|
-
results: []
|
|
649
|
-
};
|
|
608
|
+
return { installed: 0, failed: 0, skipped: CORE_MCPS.length, results: [] };
|
|
650
609
|
}
|
|
651
|
-
const results = [];
|
|
652
610
|
const total = CORE_MCPS.length;
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
onProgress?.(i + 1, total, server.name);
|
|
611
|
+
let completed = 0;
|
|
612
|
+
const promises = CORE_MCPS.map(async (server) => {
|
|
656
613
|
const result = await installMcp(server);
|
|
657
|
-
|
|
658
|
-
|
|
614
|
+
completed++;
|
|
615
|
+
onProgress?.(completed, total, server.name);
|
|
616
|
+
return result;
|
|
617
|
+
});
|
|
618
|
+
const results = await Promise.all(promises);
|
|
659
619
|
const installed = results.filter((r) => r.success && !r.skipped).length;
|
|
660
620
|
const failed = results.filter((r) => !r.success).length;
|
|
661
621
|
const skipped = results.filter((r) => r.skipped).length;
|
|
@@ -668,31 +628,15 @@ function getCoreMcps() {
|
|
|
668
628
|
// src/plugins.ts
|
|
669
629
|
import { spawn as spawn3, spawnSync as spawnSync3 } from "child_process";
|
|
670
630
|
var RECOMMENDED_PLUGINS = [
|
|
671
|
-
{
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
},
|
|
676
|
-
{
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
},
|
|
681
|
-
{
|
|
682
|
-
name: "security-guidance",
|
|
683
|
-
marketplace: "claude-plugins-official",
|
|
684
|
-
description: "OWASP protection"
|
|
685
|
-
},
|
|
686
|
-
{
|
|
687
|
-
name: "commit-commands",
|
|
688
|
-
marketplace: "claude-plugins-official",
|
|
689
|
-
description: "git workflows"
|
|
690
|
-
},
|
|
691
|
-
{
|
|
692
|
-
name: "frontend-design",
|
|
693
|
-
marketplace: "claude-plugins-official",
|
|
694
|
-
description: "UI design"
|
|
695
|
-
}
|
|
631
|
+
{ name: "typescript-lsp", marketplace: "claude-plugins-official", description: "code intelligence" },
|
|
632
|
+
{ name: "security-guidance", marketplace: "claude-plugins-official", description: "OWASP protection" },
|
|
633
|
+
{ name: "code-review", marketplace: "claude-plugins-official", description: "PR analysis" },
|
|
634
|
+
{ name: "commit-commands", marketplace: "claude-plugins-official", description: "git workflows" },
|
|
635
|
+
{ name: "frontend-design", marketplace: "claude-plugins-official", description: "UI design" },
|
|
636
|
+
{ name: "superpowers", marketplace: "claude-plugins-official", description: "TDD, debugging, planning" },
|
|
637
|
+
{ name: "ralph-loop", marketplace: "claude-plugins-official", description: "iterative dev loop" },
|
|
638
|
+
{ name: "context7", marketplace: "claude-plugins-official", description: "auto library docs" },
|
|
639
|
+
{ name: "code-simplifier", marketplace: "claude-plugins-official", description: "code refinement" }
|
|
696
640
|
];
|
|
697
641
|
function isClaudePluginReady() {
|
|
698
642
|
if (!commandExists("claude"))
|
|
@@ -728,12 +672,7 @@ function isPluginInstalled(name, marketplace) {
|
|
|
728
672
|
async function installPlugin(plugin) {
|
|
729
673
|
const pluginId = `${plugin.name}@${plugin.marketplace}`;
|
|
730
674
|
if (isPluginInstalled(plugin.name, plugin.marketplace)) {
|
|
731
|
-
return {
|
|
732
|
-
plugin: pluginId,
|
|
733
|
-
success: true,
|
|
734
|
-
message: "Already installed",
|
|
735
|
-
skipped: true
|
|
736
|
-
};
|
|
675
|
+
return { plugin: pluginId, success: true, message: "Already installed", skipped: true };
|
|
737
676
|
}
|
|
738
677
|
return new Promise((resolve) => {
|
|
739
678
|
const args = ["plugin", "install", pluginId, "--scope", "user"];
|
|
@@ -743,6 +682,12 @@ async function installPlugin(plugin) {
|
|
|
743
682
|
});
|
|
744
683
|
let stdout = "";
|
|
745
684
|
let stderr = "";
|
|
685
|
+
if (proc.stdin) {
|
|
686
|
+
proc.stdin.write("y\n");
|
|
687
|
+
proc.stdin.write("y\n");
|
|
688
|
+
proc.stdin.write("y\n");
|
|
689
|
+
proc.stdin.end();
|
|
690
|
+
}
|
|
746
691
|
proc.stdout?.on("data", (data) => {
|
|
747
692
|
stdout += data.toString();
|
|
748
693
|
});
|
|
@@ -750,54 +695,30 @@ async function installPlugin(plugin) {
|
|
|
750
695
|
stderr += data.toString();
|
|
751
696
|
});
|
|
752
697
|
proc.on("close", (code) => {
|
|
753
|
-
|
|
754
|
-
resolve({
|
|
755
|
-
plugin: pluginId,
|
|
756
|
-
success: true,
|
|
757
|
-
message: "Installed"
|
|
758
|
-
});
|
|
759
|
-
} else {
|
|
760
|
-
resolve({
|
|
761
|
-
plugin: pluginId,
|
|
762
|
-
success: false,
|
|
763
|
-
message: stderr || stdout || `Exit code: ${code}`
|
|
764
|
-
});
|
|
765
|
-
}
|
|
698
|
+
resolve(code === 0 ? { plugin: pluginId, success: true, message: "Installed" } : { plugin: pluginId, success: false, message: stderr || stdout || `Exit code: ${code}` });
|
|
766
699
|
});
|
|
767
700
|
proc.on("error", (err) => {
|
|
768
|
-
resolve({
|
|
769
|
-
plugin: pluginId,
|
|
770
|
-
success: false,
|
|
771
|
-
message: err.message
|
|
772
|
-
});
|
|
701
|
+
resolve({ plugin: pluginId, success: false, message: err.message });
|
|
773
702
|
});
|
|
774
703
|
setTimeout(() => {
|
|
775
704
|
proc.kill();
|
|
776
|
-
resolve({
|
|
777
|
-
plugin: pluginId,
|
|
778
|
-
success: false,
|
|
779
|
-
message: "Installation timed out"
|
|
780
|
-
});
|
|
705
|
+
resolve({ plugin: pluginId, success: false, message: "Installation timed out" });
|
|
781
706
|
}, 30000);
|
|
782
707
|
});
|
|
783
708
|
}
|
|
784
709
|
async function installPlugins(onProgress) {
|
|
785
710
|
if (!isClaudePluginReady()) {
|
|
786
|
-
return {
|
|
787
|
-
installed: 0,
|
|
788
|
-
failed: 0,
|
|
789
|
-
skipped: RECOMMENDED_PLUGINS.length,
|
|
790
|
-
results: []
|
|
791
|
-
};
|
|
711
|
+
return { installed: 0, failed: 0, skipped: RECOMMENDED_PLUGINS.length, results: [] };
|
|
792
712
|
}
|
|
793
|
-
const results = [];
|
|
794
713
|
const total = RECOMMENDED_PLUGINS.length;
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
onProgress?.(i + 1, total, plugin.name);
|
|
714
|
+
let completed = 0;
|
|
715
|
+
const promises = RECOMMENDED_PLUGINS.map(async (plugin) => {
|
|
798
716
|
const result = await installPlugin(plugin);
|
|
799
|
-
|
|
800
|
-
|
|
717
|
+
completed++;
|
|
718
|
+
onProgress?.(completed, total, plugin.name);
|
|
719
|
+
return result;
|
|
720
|
+
});
|
|
721
|
+
const results = await Promise.all(promises);
|
|
801
722
|
const installed = results.filter((r) => r.success && !r.skipped).length;
|
|
802
723
|
const failed = results.filter((r) => !r.success).length;
|
|
803
724
|
const skipped = results.filter((r) => r.skipped).length;
|
|
@@ -807,6 +728,98 @@ function getRecommendedPlugins() {
|
|
|
807
728
|
return RECOMMENDED_PLUGINS;
|
|
808
729
|
}
|
|
809
730
|
|
|
731
|
+
// src/skills.ts
|
|
732
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
733
|
+
import { join as join4 } from "path";
|
|
734
|
+
import https from "https";
|
|
735
|
+
var GITHUB_RAW = "https://raw.githubusercontent.com";
|
|
736
|
+
var RECOMMENDED_SKILLS = [
|
|
737
|
+
{ name: "react-best-practices", url: `${GITHUB_RAW}/vercel-labs/agent-skills/main/skills/react-best-practices/SKILL.md`, description: "React/Next.js perf rules" },
|
|
738
|
+
{ name: "web-design-guidelines", url: `${GITHUB_RAW}/vercel-labs/agent-skills/main/skills/web-design-guidelines/SKILL.md`, description: "WCAG + UX audit" },
|
|
739
|
+
{ name: "composition-patterns", url: `${GITHUB_RAW}/vercel-labs/agent-skills/main/skills/composition-patterns/SKILL.md`, description: "compound components" },
|
|
740
|
+
{ name: "webapp-testing", url: `${GITHUB_RAW}/anthropics/skills/main/skills/webapp-testing/SKILL.md`, description: "real browser testing" },
|
|
741
|
+
{ name: "mcp-builder", url: `${GITHUB_RAW}/anthropics/skills/main/skills/mcp-builder/SKILL.md`, description: "MCP server development" },
|
|
742
|
+
{ name: "typeui-artistic", url: `${GITHUB_RAW}/bergside/awesome-design-skills/main/skills/artistic/SKILL.md`, description: "artistic design system" },
|
|
743
|
+
{ name: "typeui-application", url: `${GITHUB_RAW}/bergside/awesome-design-skills/main/skills/application/SKILL.md`, description: "application design system" },
|
|
744
|
+
{ name: "typeui-ant", url: `${GITHUB_RAW}/bergside/awesome-design-skills/main/skills/ant/SKILL.md`, description: "ant design system" },
|
|
745
|
+
{ name: "typeui-dashboard", url: `${GITHUB_RAW}/bergside/awesome-design-skills/main/skills/dashboard/SKILL.md`, description: "dashboard design system" },
|
|
746
|
+
{ name: "typeui-dramatic", url: `${GITHUB_RAW}/bergside/awesome-design-skills/main/skills/dramatic/SKILL.md`, description: "dramatic design system" },
|
|
747
|
+
{ name: "typeui-doodle", url: `${GITHUB_RAW}/bergside/awesome-design-skills/main/skills/doodle/SKILL.md`, description: "doodle design system" },
|
|
748
|
+
{ name: "typeui-bento", url: `${GITHUB_RAW}/bergside/awesome-design-skills/main/skills/bento/SKILL.md`, description: "bento design system" },
|
|
749
|
+
{ name: "typeui-bold", url: `${GITHUB_RAW}/bergside/awesome-design-skills/main/skills/bold/SKILL.md`, description: "bold design system" },
|
|
750
|
+
{ name: "typeui-clean", url: `${GITHUB_RAW}/bergside/awesome-design-skills/main/skills/clean/SKILL.md`, description: "clean design system" },
|
|
751
|
+
{ name: "typeui-enterprise", url: `${GITHUB_RAW}/bergside/awesome-design-skills/main/skills/enterprise/SKILL.md`, description: "enterprise design system" },
|
|
752
|
+
{ name: "typeui-neobrutalism", url: `${GITHUB_RAW}/bergside/awesome-design-skills/main/skills/neobrutalism/SKILL.md`, description: "neobrutalism design system" },
|
|
753
|
+
{ name: "typeui-paper", url: `${GITHUB_RAW}/bergside/awesome-design-skills/main/skills/paper/SKILL.md`, description: "paper design system" }
|
|
754
|
+
];
|
|
755
|
+
function fetchUrl(url) {
|
|
756
|
+
return new Promise((resolve, reject) => {
|
|
757
|
+
const request = https.get(url, { headers: { "User-Agent": '"start-vibing"' } }, (res) => {
|
|
758
|
+
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
759
|
+
const location = res.headers["location"];
|
|
760
|
+
if (location) {
|
|
761
|
+
fetchUrl(location).then(resolve, reject);
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
if (res.statusCode !== 200) {
|
|
766
|
+
reject(new Error(`HTTP ${res.statusCode}`));
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
let data = "";
|
|
770
|
+
res.on("data", (chunk) => {
|
|
771
|
+
data += chunk;
|
|
772
|
+
});
|
|
773
|
+
res.on("end", () => resolve(data));
|
|
774
|
+
res.on("error", reject);
|
|
775
|
+
});
|
|
776
|
+
request.on("error", reject);
|
|
777
|
+
request.setTimeout(15000, () => {
|
|
778
|
+
request.destroy();
|
|
779
|
+
reject(new Error("Timeout"));
|
|
780
|
+
});
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
async function installSkill(skill) {
|
|
784
|
+
try {
|
|
785
|
+
const skillDir = join4(process.cwd(), ".claude", "skills", skill.name);
|
|
786
|
+
const skillFile = join4(skillDir, "SKILL.md");
|
|
787
|
+
if (existsSync4(skillFile)) {
|
|
788
|
+
return { skill: skill.name, success: true, message: "Already installed", skipped: true };
|
|
789
|
+
}
|
|
790
|
+
const content = await fetchUrl(skill.url);
|
|
791
|
+
if (!content || content.length < 10) {
|
|
792
|
+
return { skill: skill.name, success: false, message: "Empty response" };
|
|
793
|
+
}
|
|
794
|
+
mkdirSync3(skillDir, { recursive: true });
|
|
795
|
+
writeFileSync4(skillFile, content, "utf-8");
|
|
796
|
+
return { skill: skill.name, success: true, message: "Installed" };
|
|
797
|
+
} catch (err) {
|
|
798
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
799
|
+
return { skill: skill.name, success: false, message: msg };
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
async function installSkills(onProgress) {
|
|
803
|
+
const total = RECOMMENDED_SKILLS.length;
|
|
804
|
+
let completed = 0;
|
|
805
|
+
const promises = RECOMMENDED_SKILLS.map(async (skill) => {
|
|
806
|
+
const result = await installSkill(skill);
|
|
807
|
+
completed++;
|
|
808
|
+
onProgress?.(completed, total, skill.name);
|
|
809
|
+
return result;
|
|
810
|
+
});
|
|
811
|
+
const results = await Promise.all(promises);
|
|
812
|
+
const installed = results.filter((r) => r.success).length;
|
|
813
|
+
const failed = results.filter((r) => !r.success).length;
|
|
814
|
+
return { installed, failed, results };
|
|
815
|
+
}
|
|
816
|
+
function isSkillInstallReady() {
|
|
817
|
+
return true;
|
|
818
|
+
}
|
|
819
|
+
function getRecommendedSkills() {
|
|
820
|
+
return RECOMMENDED_SKILLS;
|
|
821
|
+
}
|
|
822
|
+
|
|
810
823
|
// src/ui.ts
|
|
811
824
|
var c = {
|
|
812
825
|
reset: "\x1B[0m",
|
|
@@ -824,15 +837,15 @@ var c = {
|
|
|
824
837
|
};
|
|
825
838
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
826
839
|
function createBanner(version) {
|
|
840
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
827
841
|
return `
|
|
828
|
-
${c.
|
|
829
|
-
${c.
|
|
830
|
-
${c.
|
|
831
|
-
${c.
|
|
832
|
-
${c.
|
|
833
|
-
|
|
834
|
-
${c.reset}
|
|
835
|
-
${c.bright} START VIBING${c.reset}${c.dim} \xB7 AI-powered dev workflow \xB7 v${version}${c.reset}
|
|
842
|
+
${c.cyan} __ __ ___ ____ ___ _ _ ____
|
|
843
|
+
${c.cyan} \\ \\ / /|_ _|| __ ) |_ _|| \\ | | / ___|
|
|
844
|
+
${c.cyan} \\ \\ / / | | | _ \\ | | | \\| || | _
|
|
845
|
+
${c.cyan} \\ \\/ / | | | |_) | | | | |\\ || |_| |
|
|
846
|
+
${c.cyan} \\__/ |___||____/ |___||_| \\_| \\____|${c.reset}
|
|
847
|
+
|
|
848
|
+
${c.bright} v${version}${c.reset}${c.dim} \xB7 ${date} \xB7 9 plugins \xB7 17 skills \xB7 8 MCPs${c.reset}
|
|
836
849
|
`;
|
|
837
850
|
}
|
|
838
851
|
function createSpinner(initialText) {
|
|
@@ -895,22 +908,22 @@ function printOptionalMcps() {
|
|
|
895
908
|
// src/cli.ts
|
|
896
909
|
var __filename3 = fileURLToPath2(import.meta.url);
|
|
897
910
|
var __dirname3 = dirname2(__filename3);
|
|
898
|
-
var TOTAL_PHASES =
|
|
911
|
+
var TOTAL_PHASES = 6;
|
|
899
912
|
function getVersion() {
|
|
900
913
|
try {
|
|
901
914
|
const paths = [
|
|
902
|
-
|
|
903
|
-
|
|
915
|
+
join5(__dirname3, "..", "package.json"),
|
|
916
|
+
join5(__dirname3, "..", "..", "package.json")
|
|
904
917
|
];
|
|
905
918
|
for (const pkgPath of paths) {
|
|
906
|
-
if (
|
|
919
|
+
if (existsSync5(pkgPath)) {
|
|
907
920
|
const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
|
|
908
|
-
return pkg.version || "
|
|
921
|
+
return pkg.version || "4.0.0";
|
|
909
922
|
}
|
|
910
923
|
}
|
|
911
|
-
return "
|
|
924
|
+
return "4.0.0";
|
|
912
925
|
} catch {
|
|
913
|
-
return "
|
|
926
|
+
return "4.0.0";
|
|
914
927
|
}
|
|
915
928
|
}
|
|
916
929
|
var VERSION = getVersion();
|
|
@@ -930,14 +943,14 @@ function autoCommitClaudeFiles(targetDir) {
|
|
|
930
943
|
return { success: true, message: "No changes to commit" };
|
|
931
944
|
}
|
|
932
945
|
execSync3("git add .claude/ CLAUDE.md", { cwd: targetDir, stdio: "pipe" });
|
|
933
|
-
execSync3(`git commit --no-verify -m "chore: update Claude Code
|
|
946
|
+
execSync3(`git commit --no-verify -m "chore: update Claude Code setup (start-vibing v${VERSION})"`, { cwd: targetDir, stdio: "pipe" });
|
|
934
947
|
return { success: true, message: "Changes committed" };
|
|
935
948
|
} catch {
|
|
936
949
|
return { success: false, message: "Commit failed (non-critical)" };
|
|
937
950
|
}
|
|
938
951
|
}
|
|
939
952
|
var HELP = `${createBanner(VERSION)}
|
|
940
|
-
Setup Claude Code agents, skills, and
|
|
953
|
+
Setup Claude Code agents, skills, plugins, and MCP servers.
|
|
941
954
|
|
|
942
955
|
${c.bright}Usage:${c.reset}
|
|
943
956
|
npx start-vibing [options]
|
|
@@ -947,16 +960,26 @@ var HELP = `${createBanner(VERSION)}
|
|
|
947
960
|
--force Overwrite all files (including custom domains)
|
|
948
961
|
--no-claude Skip Claude Code installation and launch
|
|
949
962
|
--no-mcp Skip MCP server installation
|
|
963
|
+
--no-skills Skip community skills installation
|
|
950
964
|
--no-update-check Skip checking for start-vibing updates
|
|
951
965
|
--help, -h Show this help message
|
|
952
966
|
--version, -v Show version
|
|
953
967
|
|
|
954
968
|
${c.bright}What it does:${c.reset}
|
|
955
|
-
[1] Copies template files (agents, skills,
|
|
969
|
+
[1] Copies template files (agents, skills, config)
|
|
956
970
|
[2] Sets up Claude Code (install/migrate if needed)
|
|
957
|
-
[3] Installs MCP servers (
|
|
958
|
-
[4] Installs plugins (
|
|
959
|
-
[5]
|
|
971
|
+
[3] Installs MCP servers in parallel (Playwright, Memory, etc.)
|
|
972
|
+
[4] Installs plugins in parallel (Superpowers, Ralph Loop, Context7, etc.)
|
|
973
|
+
[5] Installs community skills (Vercel, Anthropic, etc.)
|
|
974
|
+
[6] Launches Claude Code (resumes last session by default)
|
|
975
|
+
|
|
976
|
+
${c.bright}Plugins (9):${c.reset}
|
|
977
|
+
typescript-lsp, security-guidance, code-review, commit-commands,
|
|
978
|
+
frontend-design, superpowers, ralph-loop, context7, code-simplifier
|
|
979
|
+
|
|
980
|
+
${c.bright}Skills (17):${c.reset}
|
|
981
|
+
react-best-practices, web-design-guidelines, composition-patterns,
|
|
982
|
+
webapp-testing, mcp-builder, + 12 typeui.sh design systems
|
|
960
983
|
|
|
961
984
|
${c.dim}https://github.com/LimaTechnologies/ai-development${c.reset}
|
|
962
985
|
`;
|
|
@@ -973,6 +996,7 @@ async function main() {
|
|
|
973
996
|
const force = args.includes("--force");
|
|
974
997
|
const skipClaude = args.includes("--no-claude");
|
|
975
998
|
const skipMcp = args.includes("--no-mcp");
|
|
999
|
+
const skipSkills = args.includes("--no-skills");
|
|
976
1000
|
const skipUpdateCheck = args.includes("--no-update-check");
|
|
977
1001
|
const newSession = args.includes("--new");
|
|
978
1002
|
const targetDir = process.cwd();
|
|
@@ -1000,7 +1024,7 @@ async function main() {
|
|
|
1000
1024
|
const result = await copyClaudeSetup(targetDir, { force });
|
|
1001
1025
|
autoCommitClaudeFiles(targetDir);
|
|
1002
1026
|
ensureHooksEnabled();
|
|
1003
|
-
const counts = `${result.agents} agents, ${result.skills} skills
|
|
1027
|
+
const counts = `${result.agents} agents, ${result.skills} skills`;
|
|
1004
1028
|
spinner1.succeed(phaseHeader(1, TOTAL_PHASES, `Template files ${c.dim}${"\xB7".repeat(14)}${c.reset} ${counts} ${c.dim}${formatElapsed(phase1Start)}${c.reset}`));
|
|
1005
1029
|
if (result.preserved > 0) {
|
|
1006
1030
|
console.log(` ${c.dim}(preserved ${result.preserved} custom file(s))${c.reset}`);
|
|
@@ -1030,9 +1054,9 @@ async function main() {
|
|
|
1030
1054
|
spinner2.succeed(phaseHeader(2, TOTAL_PHASES, `Claude Code ${c.dim}${"\xB7".repeat(18)}${c.reset} ${claudeStatus} ${c.dim}${formatElapsed(phase2Start)}${c.reset}`));
|
|
1031
1055
|
const phase3Start = Date.now();
|
|
1032
1056
|
if (!skipMcp && isClaudeMcpReady()) {
|
|
1033
|
-
const spinner3 = createSpinner(phaseHeader(3, TOTAL_PHASES, "Installing MCP servers..."));
|
|
1034
|
-
const mcpResult = await installMcps((current, total
|
|
1035
|
-
spinner3.update(phaseHeader(3, TOTAL_PHASES, `Installing MCP servers... ${c.dim}${current}/${total} ${
|
|
1057
|
+
const spinner3 = createSpinner(phaseHeader(3, TOTAL_PHASES, "Installing MCP servers (parallel)..."));
|
|
1058
|
+
const mcpResult = await installMcps((current, total) => {
|
|
1059
|
+
spinner3.update(phaseHeader(3, TOTAL_PHASES, `Installing MCP servers... ${c.dim}${current}/${total} done${c.reset}`));
|
|
1036
1060
|
});
|
|
1037
1061
|
const mcpOk = mcpResult.installed + mcpResult.skipped;
|
|
1038
1062
|
const mcpTotal = mcpOk + mcpResult.failed;
|
|
@@ -1055,9 +1079,9 @@ async function main() {
|
|
|
1055
1079
|
}
|
|
1056
1080
|
const phase4Start = Date.now();
|
|
1057
1081
|
if (!skipMcp && isClaudePluginReady()) {
|
|
1058
|
-
const spinner4 = createSpinner(phaseHeader(4, TOTAL_PHASES, "Installing plugins..."));
|
|
1059
|
-
const pluginResult = await installPlugins((current, total
|
|
1060
|
-
spinner4.update(phaseHeader(4, TOTAL_PHASES, `Installing plugins... ${c.dim}${current}/${total} ${
|
|
1082
|
+
const spinner4 = createSpinner(phaseHeader(4, TOTAL_PHASES, "Installing plugins (parallel)..."));
|
|
1083
|
+
const pluginResult = await installPlugins((current, total) => {
|
|
1084
|
+
spinner4.update(phaseHeader(4, TOTAL_PHASES, `Installing plugins... ${c.dim}${current}/${total} done${c.reset}`));
|
|
1061
1085
|
});
|
|
1062
1086
|
const pluginOk = pluginResult.installed + pluginResult.skipped;
|
|
1063
1087
|
const pluginTotal = pluginOk + pluginResult.failed;
|
|
@@ -1074,10 +1098,33 @@ async function main() {
|
|
|
1074
1098
|
const spinner4 = createSpinner(phaseHeader(4, TOTAL_PHASES, "Installing plugins..."));
|
|
1075
1099
|
spinner4.succeed(phaseHeader(4, TOTAL_PHASES, `Plugins ${c.dim}${"\xB7".repeat(21)}${c.reset} ${c.dim}deferred (will auto-prompt)${c.reset}`));
|
|
1076
1100
|
}
|
|
1101
|
+
const phase5Start = Date.now();
|
|
1102
|
+
if (!skipSkills && isSkillInstallReady()) {
|
|
1103
|
+
const spinner5 = createSpinner(phaseHeader(5, TOTAL_PHASES, "Installing community skills (parallel)..."));
|
|
1104
|
+
const skillResult = await installSkills((current, total) => {
|
|
1105
|
+
spinner5.update(phaseHeader(5, TOTAL_PHASES, `Installing skills... ${c.dim}${current}/${total} done${c.reset}`));
|
|
1106
|
+
});
|
|
1107
|
+
const skillSummary = `${skillResult.installed}/${skillResult.installed + skillResult.failed} installed`;
|
|
1108
|
+
spinner5.succeed(phaseHeader(5, TOTAL_PHASES, `Community skills ${c.dim}${"\xB7".repeat(11)}${c.reset} ${skillSummary} ${c.dim}${formatElapsed(phase5Start)}${c.reset}`));
|
|
1109
|
+
const skills = getRecommendedSkills();
|
|
1110
|
+
for (let i = 0;i < skillResult.results.length; i++) {
|
|
1111
|
+
const r = skillResult.results[i];
|
|
1112
|
+
const skill = skills[i];
|
|
1113
|
+
const isLast = i === skillResult.results.length - 1;
|
|
1114
|
+
console.log(treeItem(skill.name, skill.description, isLast, r.success));
|
|
1115
|
+
}
|
|
1116
|
+
} else {
|
|
1117
|
+
const spinner5 = createSpinner(phaseHeader(5, TOTAL_PHASES, "Installing community skills..."));
|
|
1118
|
+
if (skipSkills) {
|
|
1119
|
+
spinner5.succeed(phaseHeader(5, TOTAL_PHASES, `Community skills ${c.dim}${"\xB7".repeat(11)}${c.reset} skipped (--no-skills)`));
|
|
1120
|
+
} else {
|
|
1121
|
+
spinner5.fail(phaseHeader(5, TOTAL_PHASES, `Community skills ${c.dim}${"\xB7".repeat(11)}${c.reset} skipped (npx not found)`));
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1077
1124
|
const sessionExists = hasExistingSession(targetDir);
|
|
1078
1125
|
const willResume = !newSession && sessionExists;
|
|
1079
1126
|
const launchMode = newSession ? "new session" : willResume ? "resuming last session" : "new session";
|
|
1080
|
-
console.log(` ${c.green}\u2713${c.reset} ${phaseHeader(
|
|
1127
|
+
console.log(` ${c.green}\u2713${c.reset} ${phaseHeader(6, TOTAL_PHASES, `Launching Claude Code ${c.dim}${"\xB7".repeat(7)}${c.reset} ${launchMode}`)}`);
|
|
1081
1128
|
printOptionalMcps();
|
|
1082
1129
|
console.log("");
|
|
1083
1130
|
console.log(` ${c.green}Setup complete${c.reset} in ${formatElapsed(globalStart)}`);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "start-vibing",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Setup Claude Code
|
|
3
|
+
"version": "4.0.1",
|
|
4
|
+
"description": "Setup Claude Code with 9 plugins, 6 community skills, and 8 MCP servers. Parallel install, auto-accept, superpowers + ralph-loop.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"start-vibing": "./dist/cli.js"
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"repository": {
|
|
32
32
|
"type": "git",
|
|
33
|
-
"url": "https://github.com/
|
|
33
|
+
"url": "https://github.com/LimaTechnologies/ai-development"
|
|
34
34
|
},
|
|
35
35
|
"engines": {
|
|
36
36
|
"node": ">=18.0.0"
|