start-vibing 4.4.4 → 4.4.5

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.
Files changed (2) hide show
  1. package/dist/cli.js +230 -56
  2. package/package.json +42 -42
package/dist/cli.js CHANGED
@@ -121,15 +121,133 @@ async function copyClaudeSetup(targetDir, options = {}) {
121
121
  return result;
122
122
  }
123
123
 
124
+ // src/cleanup.ts
125
+ import { existsSync as existsSync2, readFileSync as readFileSync2, statSync as statSync2, unlinkSync } from "fs";
126
+ import { createHash } from "crypto";
127
+ import { homedir } from "os";
128
+ import { join as join2, resolve, sep } from "path";
129
+ var STALE_FILES = [
130
+ {
131
+ category: "agents",
132
+ relPath: "research-web.md",
133
+ replacedBy: "research skill (scout \u2192 query \u2192 synthesize \u2192 verify)",
134
+ staleChecksums: [
135
+ "49d0cb862d199d1dcb59ed932ed04d8abd0064de3b65ef4f346268528dc21772",
136
+ "72ba14b6cad76a2d8718234775883242e94e82497e4edeec7fb35faf24327d6a",
137
+ "37c6ace245e2d8441e4f472e0123b5e7693e12bb869ced31f304fa17b7c75398",
138
+ "4f50d0080c54a972b6ec7053a6b6e3d36e6b27d14207357db26150707426bb2c"
139
+ ]
140
+ },
141
+ {
142
+ category: "agents",
143
+ relPath: "domain-updater.md",
144
+ replacedBy: "documenter agent (removed in start-vibing v4)",
145
+ staleChecksums: ["7499e0dd753805e6e459e687ce905ac3e949f28231e25bb2ab71036043b00f93"]
146
+ }
147
+ ];
148
+ var VALID_CATEGORIES = new Set(["agents", "skills", "hooks", "commands"]);
149
+ var MAX_FILE_BYTES = 1e6;
150
+ function sha256OfFile(path) {
151
+ const buf = readFileSync2(path);
152
+ return createHash("sha256").update(buf).digest("hex");
153
+ }
154
+ function isInside(parent, child) {
155
+ const p = resolve(parent) + sep;
156
+ const c = resolve(child);
157
+ return c === resolve(parent) || c.startsWith(p);
158
+ }
159
+ function safeRelPath(rel) {
160
+ if (typeof rel !== "string" || rel.length === 0)
161
+ return null;
162
+ const normalized = rel.replace(/\\/g, "/");
163
+ if (normalized.startsWith("/"))
164
+ return null;
165
+ if (normalized.split("/").some((seg) => seg === ".." || seg === "" || seg === ".")) {
166
+ return null;
167
+ }
168
+ return normalized;
169
+ }
170
+ function tryDelete(claudeDir, locationLabel, stale, result) {
171
+ if (!VALID_CATEGORIES.has(stale.category))
172
+ return;
173
+ const safeRel = safeRelPath(stale.relPath);
174
+ if (safeRel === null)
175
+ return;
176
+ const categoryDir = join2(claudeDir, stale.category);
177
+ if (!existsSync2(categoryDir))
178
+ return;
179
+ const fullPath = join2(categoryDir, ...safeRel.split("/"));
180
+ if (!isInside(categoryDir, fullPath))
181
+ return;
182
+ if (!existsSync2(fullPath))
183
+ return;
184
+ let stat;
185
+ try {
186
+ stat = statSync2(fullPath);
187
+ } catch {
188
+ return;
189
+ }
190
+ if (!stat.isFile())
191
+ return;
192
+ if (stat.size > MAX_FILE_BYTES)
193
+ return;
194
+ let actual;
195
+ try {
196
+ actual = sha256OfFile(fullPath);
197
+ } catch {
198
+ return;
199
+ }
200
+ if (!stale.staleChecksums.includes(actual)) {
201
+ result.keptCustomized.push({
202
+ file: `${stale.category}/${safeRel}`,
203
+ location: locationLabel
204
+ });
205
+ return;
206
+ }
207
+ let preDeleteCheck;
208
+ try {
209
+ preDeleteCheck = sha256OfFile(fullPath);
210
+ } catch {
211
+ return;
212
+ }
213
+ if (preDeleteCheck !== actual)
214
+ return;
215
+ try {
216
+ unlinkSync(fullPath);
217
+ result.deleted.push({
218
+ file: `${stale.category}/${safeRel}`,
219
+ location: locationLabel,
220
+ replacedBy: stale.replacedBy
221
+ });
222
+ } catch {
223
+ }
224
+ }
225
+ function cleanupStaleAgents(targetDir) {
226
+ const result = { deleted: [], keptCustomized: [] };
227
+ const globalClaude = join2(homedir(), ".claude");
228
+ if (existsSync2(globalClaude)) {
229
+ for (const stale of STALE_FILES) {
230
+ tryDelete(globalClaude, "~/.claude", stale, result);
231
+ }
232
+ }
233
+ const projectClaude = join2(targetDir, ".claude");
234
+ if (existsSync2(projectClaude)) {
235
+ for (const stale of STALE_FILES) {
236
+ tryDelete(projectClaude, ".claude", stale, result);
237
+ }
238
+ }
239
+ return result;
240
+ }
241
+
124
242
  // src/cli.ts
125
- import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
126
- import { join as join5, dirname as dirname2 } from "path";
243
+ import { existsSync as existsSync6, readFileSync as readFileSync5, appendFileSync, writeFileSync as writeFileSync5 } from "fs";
244
+ import { join as join6, dirname as dirname2 } from "path";
127
245
  import { fileURLToPath as fileURLToPath2 } from "url";
128
246
  import { execSync as execSync3 } from "child_process";
129
247
 
130
248
  // src/update.ts
131
- import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
132
- import { join as join2 } from "path";
249
+ import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
250
+ import { join as join3 } from "path";
133
251
 
134
252
  // src/platform.ts
135
253
  import { platform } from "os";
@@ -200,8 +318,8 @@ function getHomeDir() {
200
318
 
201
319
  // src/update.ts
202
320
  var NPM_REGISTRY_URL = "https://registry.npmjs.org/start-vibing/latest";
203
- var CACHE_DIR = join2(getHomeDir(), ".start-vibing-cache");
204
- var CACHE_FILE = join2(CACHE_DIR, "version-check.json");
321
+ var CACHE_DIR = join3(getHomeDir(), ".start-vibing-cache");
322
+ var CACHE_FILE = join3(CACHE_DIR, "version-check.json");
205
323
  var CACHE_TTL_MS = 60 * 60 * 1000;
206
324
  function compareVersions(a, b) {
207
325
  const partsA = a.replace(/^v/, "").split(".").map(Number);
@@ -218,10 +336,10 @@ function compareVersions(a, b) {
218
336
  }
219
337
  function readCache() {
220
338
  try {
221
- if (!existsSync2(CACHE_FILE)) {
339
+ if (!existsSync3(CACHE_FILE)) {
222
340
  return null;
223
341
  }
224
- const content = readFileSync2(CACHE_FILE, "utf-8");
342
+ const content = readFileSync3(CACHE_FILE, "utf-8");
225
343
  const entry = JSON.parse(content);
226
344
  if (typeof entry.timestamp !== "number" || typeof entry.latestVersion !== "string") {
227
345
  return null;
@@ -233,7 +351,7 @@ function readCache() {
233
351
  }
234
352
  function writeCache(latestVersion) {
235
353
  try {
236
- if (!existsSync2(CACHE_DIR)) {
354
+ if (!existsSync3(CACHE_DIR)) {
237
355
  mkdirSync2(CACHE_DIR, { recursive: true });
238
356
  }
239
357
  const entry = {
@@ -311,9 +429,9 @@ function getUpdateCommand() {
311
429
 
312
430
  // src/claude.ts
313
431
  import { spawn, execSync as execSync2, spawnSync } from "child_process";
314
- import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "fs";
315
- import { join as join3 } from "path";
316
- import { homedir } from "os";
432
+ import { existsSync as existsSync4, readFileSync as readFileSync4, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "fs";
433
+ import { join as join4 } from "path";
434
+ import { homedir as homedir2 } from "os";
317
435
  function isClaudeInstalled() {
318
436
  return commandExists("claude");
319
437
  }
@@ -423,11 +541,11 @@ function encodeProjectPath(absolutePath) {
423
541
  }
424
542
  function hasExistingSession(projectDir) {
425
543
  const encodedPath = encodeProjectPath(projectDir);
426
- const sessionDir = join3(homedir(), ".claude", "projects", encodedPath);
427
- const indexFile = join3(sessionDir, "sessions-index.json");
428
- if (existsSync3(indexFile)) {
544
+ const sessionDir = join4(homedir2(), ".claude", "projects", encodedPath);
545
+ const indexFile = join4(sessionDir, "sessions-index.json");
546
+ if (existsSync4(indexFile)) {
429
547
  try {
430
- const raw = readFileSync3(indexFile, "utf-8");
548
+ const raw = readFileSync4(indexFile, "utf-8");
431
549
  const index = JSON.parse(raw);
432
550
  if (Array.isArray(index.entries)) {
433
551
  const mainSessions = index.entries.filter((e) => !e.isSidechain);
@@ -437,7 +555,7 @@ function hasExistingSession(projectDir) {
437
555
  } catch {
438
556
  }
439
557
  }
440
- if (existsSync3(sessionDir)) {
558
+ if (existsSync4(sessionDir)) {
441
559
  try {
442
560
  const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.jsonl$/;
443
561
  return readdirSync2(sessionDir).some((f) => uuidPattern.test(f));
@@ -479,12 +597,12 @@ function launchClaude(cwd, options = {}) {
479
597
  }
480
598
  function ensureHooksEnabled() {
481
599
  try {
482
- const home = homedir();
483
- const globalSettingsPath = join3(home, ".claude", "settings.json");
484
- if (!existsSync3(globalSettingsPath)) {
600
+ const home = homedir2();
601
+ const globalSettingsPath = join4(home, ".claude", "settings.json");
602
+ if (!existsSync4(globalSettingsPath)) {
485
603
  return { modified: false };
486
604
  }
487
- const content = readFileSync3(globalSettingsPath, "utf-8");
605
+ const content = readFileSync4(globalSettingsPath, "utf-8");
488
606
  let settings;
489
607
  try {
490
608
  settings = JSON.parse(content);
@@ -577,7 +695,7 @@ async function installMcp(server) {
577
695
  if (isMcpInstalled(server.name)) {
578
696
  return { server: server.name, success: true, message: "Already installed", skipped: true };
579
697
  }
580
- return new Promise((resolve) => {
698
+ return new Promise((resolve2) => {
581
699
  const args = ["mcp", "add", "-s", "user", server.name, "--", server.command, ...server.args];
582
700
  const proc = spawn2("claude", args, {
583
701
  shell: true,
@@ -592,14 +710,14 @@ async function installMcp(server) {
592
710
  stderr += data.toString();
593
711
  });
594
712
  proc.on("close", (code) => {
595
- resolve(code === 0 ? { server: server.name, success: true, message: "Installed" } : { server: server.name, success: false, message: stderr || stdout || `Exit code: ${code}` });
713
+ resolve2(code === 0 ? { server: server.name, success: true, message: "Installed" } : { server: server.name, success: false, message: stderr || stdout || `Exit code: ${code}` });
596
714
  });
597
715
  proc.on("error", (err) => {
598
- resolve({ server: server.name, success: false, message: err.message });
716
+ resolve2({ server: server.name, success: false, message: err.message });
599
717
  });
600
718
  setTimeout(() => {
601
719
  proc.kill();
602
- resolve({ server: server.name, success: false, message: "Installation timed out" });
720
+ resolve2({ server: server.name, success: false, message: "Installation timed out" });
603
721
  }, 60000);
604
722
  });
605
723
  }
@@ -674,7 +792,7 @@ async function installPlugin(plugin) {
674
792
  if (isPluginInstalled(plugin.name, plugin.marketplace)) {
675
793
  return { plugin: pluginId, success: true, message: "Already installed", skipped: true };
676
794
  }
677
- return new Promise((resolve) => {
795
+ return new Promise((resolve2) => {
678
796
  const args = ["plugin", "install", pluginId, "--scope", "user"];
679
797
  const proc = spawn3("claude", args, {
680
798
  shell: true,
@@ -695,14 +813,14 @@ async function installPlugin(plugin) {
695
813
  stderr += data.toString();
696
814
  });
697
815
  proc.on("close", (code) => {
698
- resolve(code === 0 ? { plugin: pluginId, success: true, message: "Installed" } : { plugin: pluginId, success: false, message: stderr || stdout || `Exit code: ${code}` });
816
+ resolve2(code === 0 ? { plugin: pluginId, success: true, message: "Installed" } : { plugin: pluginId, success: false, message: stderr || stdout || `Exit code: ${code}` });
699
817
  });
700
818
  proc.on("error", (err) => {
701
- resolve({ plugin: pluginId, success: false, message: err.message });
819
+ resolve2({ plugin: pluginId, success: false, message: err.message });
702
820
  });
703
821
  setTimeout(() => {
704
822
  proc.kill();
705
- resolve({ plugin: pluginId, success: false, message: "Installation timed out" });
823
+ resolve2({ plugin: pluginId, success: false, message: "Installation timed out" });
706
824
  }, 30000);
707
825
  });
708
826
  }
@@ -729,8 +847,8 @@ function getRecommendedPlugins() {
729
847
  }
730
848
 
731
849
  // src/skills.ts
732
- import { existsSync as existsSync4, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
733
- import { join as join4 } from "path";
850
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
851
+ import { join as join5 } from "path";
734
852
  import https from "https";
735
853
  var GITHUB_RAW = "https://raw.githubusercontent.com";
736
854
  var RECOMMENDED_SKILLS = [
@@ -753,12 +871,12 @@ var RECOMMENDED_SKILLS = [
753
871
  { name: "typeui-paper", url: `${GITHUB_RAW}/bergside/awesome-design-skills/main/skills/paper/SKILL.md`, description: "paper design system" }
754
872
  ];
755
873
  function fetchUrl(url) {
756
- return new Promise((resolve, reject) => {
874
+ return new Promise((resolve2, reject) => {
757
875
  const request = https.get(url, { headers: { "User-Agent": '"start-vibing"' } }, (res) => {
758
876
  if (res.statusCode === 301 || res.statusCode === 302) {
759
877
  const location = res.headers["location"];
760
878
  if (location) {
761
- fetchUrl(location).then(resolve, reject);
879
+ fetchUrl(location).then(resolve2, reject);
762
880
  return;
763
881
  }
764
882
  }
@@ -770,7 +888,7 @@ function fetchUrl(url) {
770
888
  res.on("data", (chunk) => {
771
889
  data += chunk;
772
890
  });
773
- res.on("end", () => resolve(data));
891
+ res.on("end", () => resolve2(data));
774
892
  res.on("error", reject);
775
893
  });
776
894
  request.on("error", reject);
@@ -782,9 +900,9 @@ function fetchUrl(url) {
782
900
  }
783
901
  async function installSkill(skill) {
784
902
  try {
785
- const skillDir = join4(process.cwd(), ".claude", "skills", skill.name);
786
- const skillFile = join4(skillDir, "SKILL.md");
787
- if (existsSync4(skillFile)) {
903
+ const skillDir = join5(process.cwd(), ".claude", "skills", skill.name);
904
+ const skillFile = join5(skillDir, "SKILL.md");
905
+ if (existsSync5(skillFile)) {
788
906
  return { skill: skill.name, success: true, message: "Already installed", skipped: true };
789
907
  }
790
908
  const content = await fetchUrl(skill.url);
@@ -912,12 +1030,12 @@ var TOTAL_PHASES = 6;
912
1030
  function getVersion() {
913
1031
  try {
914
1032
  const paths = [
915
- join5(__dirname3, "..", "package.json"),
916
- join5(__dirname3, "..", "..", "package.json")
1033
+ join6(__dirname3, "..", "package.json"),
1034
+ join6(__dirname3, "..", "..", "package.json")
917
1035
  ];
918
1036
  for (const pkgPath of paths) {
919
- if (existsSync5(pkgPath)) {
920
- const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
1037
+ if (existsSync6(pkgPath)) {
1038
+ const pkg = JSON.parse(readFileSync5(pkgPath, "utf-8"));
921
1039
  return pkg.version || "4.0.0";
922
1040
  }
923
1041
  }
@@ -927,28 +1045,67 @@ function getVersion() {
927
1045
  }
928
1046
  }
929
1047
  var VERSION = getVersion();
930
- function autoCommitClaudeFiles(targetDir) {
1048
+ var MANAGED_PATHS = [
1049
+ ".claude/agents/",
1050
+ ".claude/skills/",
1051
+ ".claude/commands/",
1052
+ ".claude/hooks/",
1053
+ ".claude/scripts/",
1054
+ ".claude/config/",
1055
+ ".claude/settings.json",
1056
+ ".claude/settings.local.json",
1057
+ ".claude/CLAUDE.md",
1058
+ "CLAUDE.md"
1059
+ ];
1060
+ function isPathTracked(targetDir, path) {
931
1061
  try {
932
- try {
933
- execSync3("git rev-parse --git-dir", { cwd: targetDir, stdio: "pipe" });
934
- } catch {
935
- return { success: false, message: "Not a git repository" };
936
- }
937
- const status = execSync3("git status --porcelain .claude CLAUDE.md .claude/", {
1062
+ const out = execSync3(`git ls-files -- "${path}"`, {
938
1063
  cwd: targetDir,
939
1064
  encoding: "utf-8",
940
1065
  stdio: ["pipe", "pipe", "pipe"]
941
1066
  }).trim();
942
- if (!status) {
943
- return { success: true, message: "No changes to commit" };
944
- }
945
- execSync3("git add .claude/ CLAUDE.md", { cwd: targetDir, stdio: "pipe" });
946
- execSync3(`git commit --no-verify -m "chore: update Claude Code setup (start-vibing v${VERSION})"`, { cwd: targetDir, stdio: "pipe" });
947
- return { success: true, message: "Changes committed" };
1067
+ return out.length > 0;
948
1068
  } catch {
949
- return { success: false, message: "Commit failed (non-critical)" };
1069
+ return false;
950
1070
  }
951
1071
  }
1072
+ function syncGitignore(targetDir) {
1073
+ try {
1074
+ execSync3("git rev-parse --git-dir", { cwd: targetDir, stdio: "pipe" });
1075
+ } catch {
1076
+ return { success: false, added: [], tracked: [], message: "Not a git repository" };
1077
+ }
1078
+ const toIgnore = [];
1079
+ const tracked = [];
1080
+ for (const p of MANAGED_PATHS) {
1081
+ if (isPathTracked(targetDir, p))
1082
+ tracked.push(p);
1083
+ else
1084
+ toIgnore.push(p);
1085
+ }
1086
+ const gitignorePath = join6(targetDir, ".gitignore");
1087
+ const header = "# start-vibing (local Claude setup - not tracked in this repo)";
1088
+ let current = "";
1089
+ if (existsSync6(gitignorePath))
1090
+ current = readFileSync5(gitignorePath, "utf-8");
1091
+ const existing = new Set(current.split(/\r?\n/).map((l) => l.trim()).filter(Boolean));
1092
+ const missing = toIgnore.filter((e) => !existing.has(e));
1093
+ if (missing.length === 0) {
1094
+ return { success: true, added: [], tracked, message: "Already in .gitignore" };
1095
+ }
1096
+ if (current.length === 0) {
1097
+ writeFileSync5(gitignorePath, `${header}\n${missing.join("\n")}\n`, "utf-8");
1098
+ } else {
1099
+ const prefix = current.endsWith("\n") ? "" : "\n";
1100
+ appendFileSync(gitignorePath, `${prefix}\n${header}\n${missing.join("\n")}\n`, "utf-8");
1101
+ }
1102
+ return {
1103
+ success: true,
1104
+ added: missing,
1105
+ tracked,
1106
+ message: `Added ${missing.length} entr${missing.length === 1 ? "y" : "ies"} to .gitignore`
1107
+ };
1108
+ }
952
1109
  var HELP = `${createBanner(VERSION)}
953
1110
  Setup Claude Code agents, skills, plugins, and MCP servers.
954
1111
 
@@ -1022,13 +1179,30 @@ async function main() {
1022
1179
  const spinner1 = createSpinner(phaseHeader(1, TOTAL_PHASES, "Copying template files..."));
1023
1180
  try {
1024
1181
  const result = await copyClaudeSetup(targetDir, { force });
1025
- autoCommitClaudeFiles(targetDir);
1182
+ const cleanup = cleanupStaleAgents(targetDir);
1183
+ const ignoreResult = syncGitignore(targetDir);
1026
1184
  ensureHooksEnabled();
1027
1185
  const counts = `${result.agents} agents, ${result.skills} skills`;
1028
1186
  spinner1.succeed(phaseHeader(1, TOTAL_PHASES, `Template files ${c.dim}${"\xB7".repeat(14)}${c.reset} ${counts} ${c.dim}${formatElapsed(phase1Start)}${c.reset}`));
1187
+ if (ignoreResult.success && ignoreResult.added.length > 0) {
1188
+ console.log(` ${c.dim}gitignored ${ignoreResult.added.length} path(s) not tracked upstream (remove from .gitignore to commit)${c.reset}`);
1189
+ }
1190
+ if (ignoreResult.success && ignoreResult.tracked.length > 0) {
1191
+ console.log(` ${c.dim}left ${ignoreResult.tracked.length} tracked path(s) alone (e.g. shared settings)${c.reset}`);
1192
+ }
1029
1193
  if (result.preserved > 0) {
1030
1194
  console.log(` ${c.dim}(preserved ${result.preserved} custom file(s))${c.reset}`);
1031
1195
  }
1196
+ if (cleanup.deleted.length > 0) {
1197
+ for (const d of cleanup.deleted) {
1198
+ console.log(` ${c.yellow}removed${c.reset} ${d.location}/${d.file} ${c.dim}-> ${d.replacedBy}${c.reset}`);
1199
+ }
1200
+ }
1201
+ if (cleanup.keptCustomized.length > 0) {
1202
+ for (const k of cleanup.keptCustomized) {
1203
+ console.log(` ${c.dim}kept customized ${k.location}/${k.file} (checksum diverges from any known stale version)${c.reset}`);
1204
+ }
1205
+ }
1032
1206
  } catch (error) {
1033
1207
  spinner1.fail(phaseHeader(1, TOTAL_PHASES, `Template files failed`));
1034
1208
  console.error(` ${c.red}${error}${c.reset}`);
package/package.json CHANGED
@@ -1,42 +1,42 @@
1
- {
2
- "name": "start-vibing",
3
- "version": "4.4.4",
4
- "description": "Setup Claude Code with 9 plugins, 6 community skills, and 8 MCP servers. Parallel install, auto-accept, superpowers + ralph-loop. e2e-audit 0.2.0 refactor (skill-only, no agents): SessionStart hook + slash command make the skill keyword-invokable (\"e2e audit\", \"roda o e2e\", \"integration test\", \"test coverage gaps\"). Source-first discovery via detect-stack, discover-routes (Next app/pages/Remix/SvelteKit/Nuxt/Astro), discover-api-surface (HTTP handlers, tRPC procedures, GraphQL, server actions, middleware auth), inventory-existing-tests (preserve prior corpus + sha256 drift hash), and detect-uncovered (branch-diff vs origin/main finds changes not covered by existing specs). Report-then-ask between mapping and Playwright run; post-run-feedback report before writing findings. SHOT+TRACE+ASSERT+SOURCE evidence quad per non-meta finding; meta rules (coverage-gap-*, uncovered-*, test-drift, stack-detect, post-run-feedback) exempt. verify-audit.sh enforces schema + quad. Generic (no project leakage). super-design 0.7.0 carries over.",
5
- "type": "module",
6
- "bin": {
7
- "start-vibing": "./dist/cli.js"
8
- },
9
- "files": [
10
- "dist",
11
- "template"
12
- ],
13
- "scripts": {
14
- "build": "bun build ./src/cli.ts --outdir ./dist --target node",
15
- "dev": "bun run ./src/cli.ts",
16
- "prepublishOnly": "bun run build"
17
- },
18
- "keywords": [
19
- "claude",
20
- "claude-code",
21
- "ai",
22
- "agents",
23
- "skills",
24
- "hooks",
25
- "automation",
26
- "workflow",
27
- "cli"
28
- ],
29
- "author": "joaov",
30
- "license": "MIT",
31
- "repository": {
32
- "type": "git",
33
- "url": "https://github.com/LimaTechnologies/ai-development"
34
- },
35
- "engines": {
36
- "node": ">=18.0.0"
37
- },
38
- "devDependencies": {
39
- "@types/node": "^20.0.0",
40
- "typescript": "^5.0.0"
41
- }
42
- }
1
+ {
2
+ "name": "start-vibing",
3
+ "version": "4.4.5",
4
+ "description": "Setup Claude Code with 9 plugins, 6 community skills, and 8 MCP servers. Parallel install, auto-accept, superpowers + ralph-loop. e2e-audit 0.2.0 refactor (skill-only, no agents): SessionStart hook + slash command make the skill keyword-invokable (\"e2e audit\", \"roda o e2e\", \"integration test\", \"test coverage gaps\"). Source-first discovery via detect-stack, discover-routes (Next app/pages/Remix/SvelteKit/Nuxt/Astro), discover-api-surface (HTTP handlers, tRPC procedures, GraphQL, server actions, middleware auth), inventory-existing-tests (preserve prior corpus + sha256 drift hash), and detect-uncovered (branch-diff vs origin/main finds changes not covered by existing specs). Report-then-ask between mapping and Playwright run; post-run-feedback report before writing findings. SHOT+TRACE+ASSERT+SOURCE evidence quad per non-meta finding; meta rules (coverage-gap-*, uncovered-*, test-drift, stack-detect, post-run-feedback) exempt. verify-audit.sh enforces schema + quad. Generic (no project leakage). super-design 0.7.0 carries over.",
5
+ "type": "module",
6
+ "bin": {
7
+ "start-vibing": "./dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "template"
12
+ ],
13
+ "scripts": {
14
+ "build": "bun build ./src/cli.ts --outdir ./dist --target node",
15
+ "dev": "bun run ./src/cli.ts",
16
+ "prepublishOnly": "bun run build"
17
+ },
18
+ "keywords": [
19
+ "claude",
20
+ "claude-code",
21
+ "ai",
22
+ "agents",
23
+ "skills",
24
+ "hooks",
25
+ "automation",
26
+ "workflow",
27
+ "cli"
28
+ ],
29
+ "author": "joaov",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/LimaTechnologies/ai-development"
34
+ },
35
+ "engines": {
36
+ "node": ">=18.0.0"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^20.0.0",
40
+ "typescript": "^5.0.0"
41
+ }
42
+ }