@jgiox/goodvibes 1.4.0 → 1.6.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/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
+ import { createRequire as createRequire2 } from "module";
4
5
  import { Command } from "commander";
5
6
 
6
7
  // src/commands/init.ts
@@ -12,7 +13,7 @@ import { copy } from "fs-extra";
12
13
  import { readFile as readFile2, rename } from "fs/promises";
13
14
  import { readdir } from "fs/promises";
14
15
  import { existsSync } from "fs";
15
- import { join, relative } from "path";
16
+ import { join, relative, sep } from "path";
16
17
  import { fileURLToPath } from "url";
17
18
 
18
19
  // src/utils/sentinel-merge.ts
@@ -114,6 +115,10 @@ async function copyTemplates(templateDir, destDir, dryRun, minimal, projectType
114
115
  }
115
116
  const skippedFiles = [];
116
117
  const destCiYml = join(destDir, ".github", "workflows", "ci.yml");
118
+ const workflowPrefix = join(".github", "workflows") + sep;
119
+ const destHasWorkflows = [...existingBefore].some(
120
+ (f) => f.startsWith(workflowPrefix) && f.endsWith(".yml")
121
+ );
117
122
  try {
118
123
  await copy(templateDir, destDir, {
119
124
  overwrite: false,
@@ -127,6 +132,7 @@ async function copyTemplates(templateDir, destDir, dryRun, minimal, projectType
127
132
  for (const variant of ciVariants) {
128
133
  if (src.endsWith(variant) && variant !== selectedVariant) return false;
129
134
  }
135
+ if (destHasWorkflows && rel.startsWith(workflowPrefix) && src.endsWith(".yml")) return false;
130
136
  return true;
131
137
  }
132
138
  });
@@ -198,6 +204,16 @@ async function installHeadroom(log) {
198
204
  log("Python 3.10+ not found \u2014 skipping headroom install. Install Python 3.10+ and run `goodvibes init` again.");
199
205
  return;
200
206
  }
207
+ log("headroom compresses AI context to save tokens \u2014 this keeps your costs down and sessions faster.");
208
+ try {
209
+ await execa2("headroom", ["--version"]);
210
+ log("headroom already installed \u2014 skipping");
211
+ return;
212
+ } catch (e) {
213
+ if (e.code !== "ENOENT") {
214
+ log(`headroom probe failed: ${e.message?.split("\n")[0] ?? "unknown"}`);
215
+ }
216
+ }
201
217
  log("Note: headroom will download its compression model on first use \u2014 this may take 1\u20133 minutes on a slow connection.");
202
218
  const installers = [
203
219
  { cmd: "uv", args: ["tool", "install", "headroom-ai[all]"] },
@@ -416,13 +432,6 @@ async function detectInstalledVersion(cwd) {
416
432
  const content = await readFile3(claudePath, "utf-8");
417
433
  return extractVersion(content);
418
434
  }
419
- async function detectBundledVersion(templateDir) {
420
- if (!templateDir) return null;
421
- const claudeSrc = join3(templateDir, "CLAUDE.md");
422
- if (!await pathExists2(claudeSrc)) return null;
423
- const content = await readFile3(claudeSrc, "utf-8");
424
- return extractVersion(content);
425
- }
426
435
  async function computeChanges(templateDir, destDir, projectType) {
427
436
  const allFiles = await listTemplateFiles(templateDir) ?? [];
428
437
  const managedFiles = allFiles.filter(
@@ -479,7 +488,7 @@ async function upgradeTemplates(templateDir, destDir, projectType) {
479
488
  return allDest.filter((f) => f.startsWith(".claude/skills/") || f.startsWith(".github/workflows/") || f === "CLAUDE.md").sort();
480
489
  }
481
490
  function registerUpgradeCommand(program2) {
482
- program2.command("upgrade").description("Update goodvibes-managed files to the latest version").option("--dry-run", "Preview what would change without writing").action(async (options) => {
491
+ program2.command("upgrade").alias("update").description("Update goodvibes-managed files to the latest version").option("--dry-run", "Preview what would change without writing").action(async (options) => {
483
492
  const dryRun = options.dryRun ?? false;
484
493
  const cwd = process.cwd();
485
494
  intro2("goodvibes upgrade");
@@ -502,7 +511,7 @@ function registerUpgradeCommand(program2) {
502
511
  const templateDir = resolveTemplatesDir();
503
512
  const projectType = detectProjectType(cwd);
504
513
  const installedVersion = await detectInstalledVersion(cwd);
505
- const bundledVersion = await detectBundledVersion(templateDir);
514
+ const bundledVersion = getInstalledVersion();
506
515
  if (installedVersion && bundledVersion && versionGte(installedVersion, bundledVersion)) {
507
516
  outro2(`Already up to date (v${installedVersion})`);
508
517
  return;
@@ -529,6 +538,90 @@ function registerUpgradeCommand(program2) {
529
538
  });
530
539
  }
531
540
 
541
+ // src/commands/doctor.ts
542
+ import { note as note3, outro as outro3 } from "@clack/prompts";
543
+ import { existsSync as existsSync4, readFileSync } from "fs";
544
+ import { join as join4 } from "path";
545
+ import { execa as execa5 } from "execa";
546
+ var SENTINEL_START2 = "<!-- goodvibes:start -->";
547
+ var SENTINEL_END2 = "<!-- goodvibes:end -->";
548
+ async function checkHeadroom() {
549
+ try {
550
+ await execa5("headroom", ["--version"]);
551
+ return { label: "headroom on PATH", pass: true };
552
+ } catch (e) {
553
+ if (e.code === "ENOENT") {
554
+ return {
555
+ label: "headroom on PATH",
556
+ pass: false,
557
+ remedy: 'Run: uv tool install "headroom-ai[all]" (or re-run goodvibes init)'
558
+ };
559
+ }
560
+ throw e;
561
+ }
562
+ }
563
+ async function checkGit() {
564
+ const keys = ["user.name", "user.email"];
565
+ const results = [];
566
+ for (const key of keys) {
567
+ try {
568
+ const { stdout } = await execa5("git", ["config", key]);
569
+ results.push({
570
+ label: `git ${key}`,
571
+ pass: stdout.trim().length > 0,
572
+ remedy: stdout.trim().length > 0 ? void 0 : `Run: git config --global ${key} "Your Value"`
573
+ });
574
+ } catch {
575
+ results.push({
576
+ label: `git ${key}`,
577
+ pass: false,
578
+ remedy: `Run: git config --global ${key} "Your Value"`
579
+ });
580
+ }
581
+ }
582
+ return results;
583
+ }
584
+ function checkClaudeMd(cwd) {
585
+ const present = existsSync4(join4(cwd, "CLAUDE.md"));
586
+ return {
587
+ label: "CLAUDE.md present",
588
+ pass: present,
589
+ remedy: present ? void 0 : "Run: goodvibes init"
590
+ };
591
+ }
592
+ function checkSentinel(cwd) {
593
+ const path = join4(cwd, "CLAUDE.md");
594
+ if (!existsSync4(path)) {
595
+ return { label: "goodvibes sentinel block", pass: false, remedy: "Run: goodvibes init" };
596
+ }
597
+ const content = readFileSync(path, "utf-8");
598
+ const ok = content.includes(SENTINEL_START2) && content.includes(SENTINEL_END2);
599
+ return {
600
+ label: "goodvibes sentinel block",
601
+ pass: ok,
602
+ remedy: ok ? void 0 : "Run: goodvibes init (will merge sentinel block)"
603
+ };
604
+ }
605
+ function registerDoctorCommand(program2) {
606
+ program2.command("doctor").description("Check goodvibes setup is complete").action(async () => {
607
+ const cwd = process.cwd();
608
+ const headroomResult = await checkHeadroom();
609
+ const gitResults = await checkGit();
610
+ const claudeMdResult = checkClaudeMd(cwd);
611
+ const sentinelResult = checkSentinel(cwd);
612
+ const all = [headroomResult, ...gitResults, claudeMdResult, sentinelResult];
613
+ const lines = all.map((r) => `${r.pass ? "\u2713" : "\u2717"} ${r.label}`);
614
+ note3(lines.join("\n"), "goodvibes doctor");
615
+ const failures = all.filter((r) => !r.pass);
616
+ if (failures.length > 0) {
617
+ const remediation = failures.filter((r) => r.remedy).map((r) => r.remedy).join("\n");
618
+ note3(remediation, "How to fix");
619
+ process.exit(1);
620
+ }
621
+ outro3("All checks passed.");
622
+ });
623
+ }
624
+
532
625
  // src/index.ts
533
626
  var [major] = process.version.replace("v", "").split(".").map(Number);
534
627
  if (major < 20) {
@@ -540,8 +633,11 @@ Install the latest LTS from https://nodejs.org
540
633
  );
541
634
  process.exit(1);
542
635
  }
636
+ var _require2 = createRequire2(import.meta.url);
637
+ var _pkg = _require2("../package.json");
543
638
  var program = new Command();
544
- program.name("goodvibes").version("1.0.0").description("One-command bootstrap for vibe coding projects");
639
+ program.name("goodvibes").version(_pkg.version).description("One-command bootstrap for vibe coding projects");
545
640
  registerInitCommand(program);
546
641
  registerUpgradeCommand(program);
642
+ registerDoctorCommand(program);
547
643
  await program.parseAsync(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jgiox/goodvibes",
3
- "version": "1.4.0",
3
+ "version": "1.6.1",
4
4
  "description": "One-command bootstrap for vibe coding projects",
5
5
  "type": "module",
6
6
  "bin": {
@@ -40,7 +40,7 @@
40
40
  "test:watch": "vitest"
41
41
  },
42
42
  "dependencies": {
43
- "commander": "^13",
43
+ "commander": "^15",
44
44
  "@clack/prompts": "^1",
45
45
  "fs-extra": "^11",
46
46
  "execa": "^9"
@@ -0,0 +1,11 @@
1
+ Engineering Rules for this project (goodvibes).
2
+
3
+ Think before coding. State assumptions before implementing. Stop if an assumption is security-sensitive, schema-sensitive, or has multiple materially different interpretations.
4
+
5
+ Simplicity first. Stop at the first option that works: Does this need to exist at all? Already in the codebase? Use it. Stdlib covers it? Use it. Can it be one line? One line. Only then write new code. No unrequested abstractions. No boilerplate for later. Deletion over addition.
6
+
7
+ Surgical changes. Keep diffs narrow. No opportunistic reformats. No renames unless the task requires it. Only remove what your change made unused.
8
+
9
+ Fail loud. No empty catch blocks. No silent retries. No returning fake success on real failure. Error messages must be actionable and specific.
10
+
11
+ Security. Validate input at the boundary. Keep secrets out of code and logs. Apply least privilege. Flag immediately: SQL injection, XSS, command injection, path traversal, broken auth, leaked secrets.
@@ -1,7 +1,7 @@
1
1
  # CLAUDE.md
2
2
 
3
3
  <!-- goodvibes:start -->
4
- # goodvibes: v1.3.0
4
+ # goodvibes: v1.6.1
5
5
 
6
6
  ## Engineering Rules
7
7
 
@@ -0,0 +1,31 @@
1
+ # Getting started with goodvibes
2
+
3
+ You ran `goodvibes init`. Here is what happens next.
4
+
5
+ ## What was set up
6
+
7
+ goodvibes wrote several files into your project: `CLAUDE.md` with engineering rules and the ponytail minimalism ruleset, AI rule files for your coding tool (Cursor, Windsurf, Kiro, GitHub Copilot, and others), CI workflows for automated quality checks, and docs templates including this one. Everything runs automatically — no configuration needed.
8
+
9
+ ## Your first change
10
+
11
+ 1. **Open your project in your AI coding tool.** Cursor, Windsurf, Kiro, and GitHub Copilot all pick up the goodvibes rules automatically. The AI will follow minimal-code and fail-loud principles from the first message.
12
+ 2. **Tell the AI what you want to build.** Describe the feature in plain language — the rules guide the AI to keep code simple and surgical.
13
+ 3. **Review the diff before you commit.** Check that the AI only changed what you asked. The rules encourage narrow diffs — if the change looks too large, ask the AI to trim it.
14
+ 4. **Run `git add . && git commit -m "feat: your change here"`.** This saves a checkpoint in your project history so you can always go back.
15
+ 5. **Run `git push`.** This sends your work to GitHub, where it is safe even if your machine breaks.
16
+
17
+ ## Check your setup
18
+
19
+ Run `goodvibes doctor` to verify everything is working. It checks that headroom is installed, your git identity is configured, and the goodvibes rules are in place.
20
+
21
+ ## Useful commands
22
+
23
+ | Command | What it does |
24
+ |---------|--------------|
25
+ | `goodvibes update` | Re-sync goodvibes files to the latest version |
26
+ | `goodvibes doctor` | Check that headroom, git, and rules are all working |
27
+ | `goodvibes upgrade --dry-run` | Preview what `goodvibes update` would change |
28
+
29
+ ## What is headroom?
30
+
31
+ headroom compresses the AI's memory of your project so you spend fewer tokens per session. It runs automatically in the background when Claude Code is active — you do not need to invoke it manually.
@@ -0,0 +1,40 @@
1
+ # Base44 — goodvibes setup
2
+
3
+ Base44 does not read files from your project. Instead, you paste your rules into the AI controls panel, and Base44 applies them to every AI interaction in that project.
4
+
5
+ ## Steps
6
+
7
+ 1. Go to [base44.com](https://base44.com) and sign in.
8
+ 2. Open your project.
9
+ 3. Find the **AI controls** panel — it is usually in the top-right corner or under project Settings.
10
+ 4. Click **Custom Instructions**.
11
+ 5. Paste the text below into the box.
12
+ 6. Click **Save**.
13
+
14
+ That is it. From now on, every AI action in this project follows the goodvibes engineering rules.
15
+
16
+ > If the steps above do not match what you see, look for **Custom Instructions** or **AI controls** in the project settings. The UI may change — the paste text stays the same.
17
+
18
+ > **Base44 Skills** is a separate feature for saving reusable instruction sets. goodvibes does not require it — pasting into Custom Instructions is enough.
19
+
20
+ ---
21
+
22
+ ## Paste this text
23
+
24
+ ```
25
+ Engineering Rules — goodvibes
26
+
27
+ Think before coding. State assumptions before implementing. Stop if an assumption is security-sensitive, schema-sensitive, or has multiple materially different interpretations.
28
+
29
+ Simplicity first. Stop at the first option that works: Does this need to exist at all? Already in the codebase? Use it. Stdlib covers it? Use it. Can it be one line? One line. Only then write new code. No unrequested abstractions. No boilerplate for later. Deletion over addition.
30
+
31
+ Surgical changes. Keep diffs narrow. No opportunistic reformats. No renames unless the task requires it. Only remove what your change made unused.
32
+
33
+ Fail loud. No empty catch blocks. No silent retries. No returning fake success on real failure. Error messages must be actionable and specific.
34
+
35
+ Security. Validate input at the boundary. Keep secrets out of code and logs. Apply least privilege. Flag immediately: SQL injection, XSS, command injection, path traversal, broken auth, leaked secrets.
36
+ ```
37
+
38
+ ---
39
+
40
+ ## Last verified: 2026-07-01
@@ -0,0 +1,22 @@
1
+ # Bolt.new — goodvibes setup
2
+
3
+ Bolt.new does not read project files for AI rules. You activate ponytail discipline by pasting the rules into the chat as a one-time instruction.
4
+
5
+ ## One-time setup
6
+
7
+ 1. Open your Bolt.new project.
8
+ 2. In the chat, paste: "Please follow these engineering rules for all code you write:" then copy the text from `CLAUDE.md` between `<!-- goodvibes:start -->` and `<!-- goodvibes:end -->`.
9
+ 3. Bolt.new will acknowledge and apply the rules for the rest of the session.
10
+ 4. Repeat this at the start of each new session, or save it as a pinned message if Bolt.new supports it.
11
+
12
+ ## Ponytail on Bolt.new
13
+
14
+ Once the rules are in the chat context, Bolt.new follows the ponytail minimalism rules: minimal code, surgical changes, fail loud. The AI will tell you when it is skipping something that is not needed yet.
15
+
16
+ ## Headroom
17
+
18
+ Headroom is not applicable inside Bolt.new — context is managed by the Bolt.new platform itself.
19
+
20
+ ---
21
+
22
+ ## Last verified: 2026-07-01
@@ -0,0 +1,38 @@
1
+ # ChatGPT Projects — goodvibes setup
2
+
3
+ ChatGPT does not read files from your project. Instead, you paste your rules directly into the project's custom instructions, and ChatGPT applies them to every conversation in that project.
4
+
5
+ ## Steps
6
+
7
+ 1. Go to [chatgpt.com](https://chatgpt.com) and sign in.
8
+ 2. Click **Projects** in the left sidebar. Create a new project or open an existing one.
9
+ 3. Click the project name at the top of the page. A panel opens on the right.
10
+ 4. Click **Project Instructions**.
11
+ 5. Paste the text below into the box.
12
+ 6. Click **Save**.
13
+
14
+ That is it. From now on, every conversation in this project follows the goodvibes engineering rules.
15
+
16
+ > If the steps above do not match what you see, look for **Project Instructions** or **Custom Instructions** in the project settings panel. The UI may change — the paste text stays the same.
17
+
18
+ ---
19
+
20
+ ## Paste this text
21
+
22
+ ```
23
+ Engineering Rules — goodvibes
24
+
25
+ Think before coding. State assumptions before implementing. Stop if an assumption is security-sensitive, schema-sensitive, or has multiple materially different interpretations.
26
+
27
+ Simplicity first. Stop at the first option that works: Does this need to exist at all? Already in the codebase? Use it. Stdlib covers it? Use it. Can it be one line? One line. Only then write new code. No unrequested abstractions. No boilerplate for later. Deletion over addition.
28
+
29
+ Surgical changes. Keep diffs narrow. No opportunistic reformats. No renames unless the task requires it. Only remove what your change made unused.
30
+
31
+ Fail loud. No empty catch blocks. No silent retries. No returning fake success on real failure. Error messages must be actionable and specific.
32
+
33
+ Security. Validate input at the boundary. Keep secrets out of code and logs. Apply least privilege. Flag immediately: SQL injection, XSS, command injection, path traversal, broken auth, leaked secrets.
34
+ ```
35
+
36
+ ---
37
+
38
+ ## Last verified: 2026-07-01
@@ -0,0 +1,23 @@
1
+ # Cursor — goodvibes setup
2
+
3
+ goodvibes init wrote `.cursor/rules/goodvibes.mdc` into your project. This file activates the ponytail minimalism rules automatically when you open the project in Cursor.
4
+
5
+ ## Ponytail is already active
6
+
7
+ The rules enforce simplicity-first coding, fail-loud error handling, and surgical changes — no file you did not touch, no code you did not need. You do not need to paste anything. The rules are in `.cursor/rules/goodvibes.mdc` and Cursor loads them for every AI chat in this project.
8
+
9
+ ## Verify activation
10
+
11
+ Open Cursor. In the AI chat, ask: "What are your active rules?" You should see a reference to goodvibes or ponytail in the response.
12
+
13
+ ## If you use .cursorrules (legacy)
14
+
15
+ If your project has a `.cursorrules` file from before goodvibes, the `.cursor/rules/goodvibes.mdc` file is independent. Both will apply. You may want to merge them to avoid duplication.
16
+
17
+ ## Headroom (context compression)
18
+
19
+ Cursor does not use Claude Code's MCP protocol. If you want context compression, install headroom separately and use it via its CLI. See [headroom docs](https://headroom-docs.vercel.app/).
20
+
21
+ ---
22
+
23
+ ## Last verified: 2026-07-01
@@ -0,0 +1,19 @@
1
+ # Kiro — goodvibes setup
2
+
3
+ goodvibes init wrote `.kiro/steering/goodvibes.md` into your project. Kiro applies steering files automatically to all AI interactions in the project.
4
+
5
+ ## Ponytail is already active
6
+
7
+ The ponytail rules in `.kiro/steering/goodvibes.md` enforce simplicity-first coding, fail-loud error handling, and surgical changes. You do not need to paste anything or configure anything — the steering file is active as soon as you open the project in Kiro.
8
+
9
+ ## Verify activation
10
+
11
+ Open Kiro and check the steering files panel in your project settings. You should see `goodvibes.md` listed as an always-on steering file.
12
+
13
+ ## Headroom (context compression)
14
+
15
+ Kiro does not use Claude Code's MCP protocol. If you want context compression, install headroom separately and use it via its CLI. See [headroom docs](https://headroom-docs.vercel.app/).
16
+
17
+ ---
18
+
19
+ ## Last verified: 2026-07-01
@@ -0,0 +1,26 @@
1
+ # Replit Agent — goodvibes setup
2
+
3
+ Replit Agent does not read files from your project automatically. Instead, you provide the rules as a system prompt for the Agent.
4
+
5
+ ## One-time setup
6
+
7
+ 1. Open your Repl.
8
+ 2. Find **System prompt** or **AI instructions** in the Agent settings panel.
9
+ 3. Copy the text from `CLAUDE.md` — specifically the section between `<!-- goodvibes:start -->` and `<!-- goodvibes:end -->`.
10
+ 4. Paste into the system prompt field and click **Save**.
11
+
12
+ That is it. Replit Agent will follow the goodvibes rules for every task in this project.
13
+
14
+ > If you do not see a system prompt field, look for **Agent instructions** or **Custom rules** in the project settings.
15
+
16
+ ## Ponytail on Replit
17
+
18
+ Once the system prompt is set, Replit Agent follows the ponytail rules for every task: minimal code, no over-engineering, and explicit error handling. The AI will tell you if it is skipping something because it is not needed yet.
19
+
20
+ ## Headroom
21
+
22
+ Replit manages its own context. Headroom is not applicable inside Replit — skip the headroom install step if you are Replit-only.
23
+
24
+ ---
25
+
26
+ ## Last verified: 2026-07-01
@@ -0,0 +1,19 @@
1
+ # Windsurf — goodvibes setup
2
+
3
+ goodvibes init wrote `.windsurfrules` into your project. Windsurf reads this file automatically and applies the goodvibes engineering rules to every AI interaction.
4
+
5
+ ## Ponytail is already active
6
+
7
+ The rules in `.windsurfrules` enforce simplicity-first coding, fail-loud error handling, and surgical changes. You do not need to paste anything — Windsurf picks up the file on its own.
8
+
9
+ ## Verify activation
10
+
11
+ Open Windsurf. In the Cascade AI panel, ask: "What are your active rules?" You should see a reference to goodvibes or ponytail in the response.
12
+
13
+ ## Headroom (context compression)
14
+
15
+ Windsurf does not use Claude Code's MCP protocol. If you want context compression, install headroom separately and use it via its CLI. See [headroom docs](https://headroom-docs.vercel.app/).
16
+
17
+ ---
18
+
19
+ ## Last verified: 2026-07-01
@@ -0,0 +1,32 @@
1
+ # Engineering Rules — goodvibes
2
+ <!-- Replit Agent may regenerate this file. Commit it to git to preserve your edits. -->
3
+
4
+ ## Project Overview
5
+ This project uses goodvibes engineering rules. Apply them to every task.
6
+
7
+ ## Coding Style
8
+ State assumptions before implementing. Stop if an assumption is security-sensitive, schema-sensitive, or has multiple materially different interpretations.
9
+
10
+ ## Simplicity First
11
+ Stop at the first rung that holds:
12
+
13
+ 1. Does this need to exist at all? Speculative need → skip it. (YAGNI)
14
+ 2. Already in this codebase? Reuse it.
15
+ 3. Stdlib does it? Use it.
16
+ 4. Native platform feature covers it? Use it.
17
+ 5. Already-installed dependency solves it? Use it.
18
+ 6. Can it be one line? One line.
19
+ 7. Only then: the minimum code that works.
20
+
21
+ No unrequested abstractions. No boilerplate for later. Deletion over addition.
22
+
23
+ ## Surgical Changes
24
+ Keep diffs narrow. No opportunistic reformats. Only remove what your change made unused.
25
+
26
+ ## Fail Loud
27
+ No empty catch blocks. No silent retries. No fake success on real failure. Error messages must be actionable.
28
+
29
+ ## Security
30
+ Validate input at the boundary. Keep secrets out of code and logs. Apply least privilege.
31
+
32
+ Flag immediately: SQL injection, XSS, command injection, path traversal, broken auth, leaked secrets.