clud-bug 0.6.6 → 0.6.7

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/bin/clud-bug.js CHANGED
@@ -27,7 +27,7 @@ function parseArgs(argv) {
27
27
  const args = {
28
28
  _: [], offline: false, acceptAll: false, commit: false, help: false, version: false,
29
29
  since: null, changedIn: null, scopes: [], out: null,
30
- setProtection: true,
30
+ setProtection: true, quiet: false,
31
31
  };
32
32
  for (let i = 0; i < argv.length; i++) {
33
33
  const a = argv[i];
@@ -36,6 +36,7 @@ function parseArgs(argv) {
36
36
  else if (a === '--commit') args.commit = true;
37
37
  else if (a === '--help' || a === '-h') args.help = true;
38
38
  else if (a === '--version' || a === '-v') args.version = true;
39
+ else if (a === '--quiet' || a === '-q') args.quiet = true;
39
40
  else if (a === '--since') args.since = argv[++i];
40
41
  else if (a === '--changed-in') args.changedIn = argv[++i];
41
42
  else if (a === '--scope') args.scopes.push(argv[++i]);
@@ -68,6 +69,11 @@ Options:
68
69
  --offline Skip skills.sh; pin only the bundled baseline specimens.
69
70
  --accept-all,-y Accept the recommended specimens without prompting.
70
71
  --commit git add + commit the generated kit when done (init only).
72
+ --quiet,-q Token-frugal mode for agent invocations. Suppresses
73
+ progress chatter; emits exactly one final
74
+ \`ok <key-value>\` summary line per command. Errors
75
+ and warnings still print. Also honored via the
76
+ CLUD_BUG_QUIET=1 env var.
71
77
  --no-set-protection Skip the prompt that offers to enable
72
78
  required_conversation_resolution on the default
73
79
  branch (init only). Use for repos that manage
@@ -89,6 +95,7 @@ async function main() {
89
95
  const args = parseArgs(process.argv.slice(2));
90
96
  if (args.help) { process.stdout.write(HELP); return; }
91
97
  if (args.version) { process.stdout.write((await readPkgVersion()) + '\n'); return; }
98
+ if (args.quiet) setQuiet(true);
92
99
 
93
100
  const cmd = args._[0];
94
101
  switch (cmd) {
@@ -275,6 +282,10 @@ async function runInit(args) {
275
282
  log('Strict mode is ON by default (clud-bug-review fails the check on critical findings).');
276
283
  log(' • Add `clud-bug-review` to your branch protection required checks for full enforcement.');
277
284
  log(' • Opt out by setting "strictMode": false in .claude/skills/.clud-bug.json.');
285
+
286
+ // Final agent-friendly summary line (always emitted, even with --quiet).
287
+ const version = await readPkgVersion();
288
+ ok(`initialized: .claude/skills/ ${chosen.length} specimens, workflow @v${version}`);
278
289
  }
279
290
 
280
291
  async function promptForSkills(recommended) {
@@ -413,6 +424,7 @@ async function runList(_args) {
413
424
  const total = groups.baseline.length + groups.remote.length + groups.custom.length;
414
425
  if (total === 0) {
415
426
  log('Empty collection. Run `clud-bug init` to open field season.');
427
+ ok('list: 0 skills installed (run `clud-bug init` first)');
416
428
  return;
417
429
  }
418
430
  log(`🐛 ${total} specimen${total === 1 ? '' : 's'} pinned in .claude/skills/`);
@@ -433,6 +445,7 @@ async function runList(_args) {
433
445
  log(` • ${s.slug}${s.description ? ` — ${s.description}` : ''}`);
434
446
  }
435
447
  }
448
+ ok(`list: ${total} skills (baseline=${groups.baseline.length}, remote=${groups.remote.length}, custom=${groups.custom.length})`);
436
449
  }
437
450
 
438
451
  async function runAdd(args) {
@@ -457,6 +470,7 @@ async function runAdd(args) {
457
470
  await writeManifest(skillsDir, manifest);
458
471
  log(` ✓ pinned ${entry.slug} → .claude/skills/${entry.slug}/SKILL.md`);
459
472
  log(' Commit + push to apply on the next PR.');
473
+ ok(`added: .claude/skills/${entry.slug}/SKILL.md`);
460
474
  }
461
475
 
462
476
  async function runRemove(args) {
@@ -468,6 +482,7 @@ async function runRemove(args) {
468
482
  const skillsDir = join(process.cwd(), '.claude', 'skills');
469
483
  const entry = await removeSkill(skillsDir, slug);
470
484
  log(` ✓ unpinned ${entry.slug}${entry.kind === 'baseline' ? ' (baseline — returns on next init)' : ''}`);
485
+ ok(`removed: ${entry.slug}${entry.kind === 'baseline' ? ' (baseline)' : ''}`);
471
486
  }
472
487
 
473
488
  async function runRefresh(args) {
@@ -476,6 +491,7 @@ async function runRefresh(args) {
476
491
  const manifest = await readManifest(skillsDir);
477
492
  if (manifest.installed.length === 0) {
478
493
  log('No clud-bug-managed specimens found. Run `clud-bug init` first.');
494
+ ok('refreshed: 0 skills installed (run `clud-bug init` first)');
479
495
  return;
480
496
  }
481
497
 
@@ -520,6 +536,7 @@ async function runRefresh(args) {
520
536
  if (diff.add.length === 0 && diff.remove.length === 0) {
521
537
  log('');
522
538
  log('Collection in sync with skills.sh — nothing to update.');
539
+ ok(`refreshed: ${diff.unchanged.length} skills in sync, 0 changes`);
523
540
  return;
524
541
  }
525
542
 
@@ -541,6 +558,7 @@ async function runRefresh(args) {
541
558
  if (diff.add.length) await writeSkills(skillsDir, diff.add, client);
542
559
  for (const entry of diff.remove) await removeSkill(skillsDir, entry.slug);
543
560
  log(' ✓ collection updated. Commit + push to apply on the next PR.');
561
+ ok(`refreshed: +${diff.add.length} -${diff.remove.length} (${diff.unchanged.length} unchanged)`);
544
562
  }
545
563
 
546
564
  async function runEditWorkflow(_args) {
@@ -557,6 +575,7 @@ async function runEditWorkflow(_args) {
557
575
 
558
576
  if (pending.files.length === 0) {
559
577
  log('Nothing to commit. Edit your .github/workflows/clud-bug-*.yml file(s) first, then re-run.');
578
+ ok('branch: (none — no pending workflow edits)');
560
579
  return;
561
580
  }
562
581
  if (!pending.allWorkflow) {
@@ -596,6 +615,7 @@ async function runEditWorkflow(_args) {
596
615
  log('');
597
616
  log('Done. Open the PR:');
598
617
  log(` gh pr create --title "Edit clud-bug workflow" --body "Workflow tweak. The clud-bug-review check on this PR will fail with a 401 (Anthropic's self-protection against PRs that modify the reviewer's own workflow); merge once and subsequent PRs work normally."`);
618
+ ok(`branch: ${branch} (${pending.files.length} file${pending.files.length === 1 ? '' : 's'})`);
599
619
  }
600
620
 
601
621
  async function runUpdateCmd(_args) {
@@ -612,6 +632,7 @@ async function runUpdateCmd(_args) {
612
632
 
613
633
  if (result.missing === 'init') {
614
634
  log(' No clud-bug installation detected. Run `clud-bug init` first.');
635
+ ok('updated: 0 changes (no clud-bug install detected)');
615
636
  return;
616
637
  }
617
638
 
@@ -619,6 +640,7 @@ async function runUpdateCmd(_args) {
619
640
 
620
641
  if (result.changed.length === 0 && skipped.length === 0) {
621
642
  log(' Already current. Nothing to update.');
643
+ ok(`updated: @v${ourVersion}, 0 changes`);
622
644
  return;
623
645
  }
624
646
 
@@ -639,6 +661,7 @@ async function runUpdateCmd(_args) {
639
661
  }
640
662
  log('');
641
663
  log('Commit + push to apply the refreshed kit on the next PR.');
664
+ ok(`updated: @v${ourVersion}, ${result.changed.length} changed, ${result.unchanged.length} unchanged${skipped.length ? `, ${skipped.length} skipped` : ''}`);
642
665
  }
643
666
 
644
667
  async function runAudit(args) {
@@ -670,6 +693,7 @@ async function runAudit(args) {
670
693
 
671
694
  if (files.length === 0) {
672
695
  log(' Nothing in scope. Try widening --scope or --changed-in.');
696
+ ok(`audit: 0 files in scope`);
673
697
  return;
674
698
  }
675
699
 
@@ -680,12 +704,25 @@ async function runAudit(args) {
680
704
  log('');
681
705
  log('Stub is empty findings — populated by the GitHub Action.');
682
706
  log('Run locally without the workflow if you want — Clud Bug review needs the action runner + ANTHROPIC_API_KEY.');
707
+ ok(`audit: ${files.length} file${files.length === 1 ? '' : 's'} surveyed; stub at ${rel(cwd, outPath)}`);
683
708
  }
684
709
 
685
710
  function rel(from, to) {
686
711
  return to.startsWith(from + '/') ? to.slice(from.length + 1) : to;
687
712
  }
688
- function log(msg) { process.stdout.write(msg + '\n'); }
713
+
714
+ // Quiet-mode mechanism (v0.6.7+):
715
+ // - Default: log() emits progress to stdout (today's behavior).
716
+ // - When CLUD_BUG_QUIET=1 OR --quiet/-q is passed: log() is suppressed.
717
+ // ok() ALWAYS emits its single-line summary so agents get positive
718
+ // confirmation with a chainable key-value (commit SHA, file count,
719
+ // branch name) regardless of quiet state.
720
+ // - warn() / die() emit unconditionally — quiet must not silence real
721
+ // problems.
722
+ let QUIET = process.env.CLUD_BUG_QUIET === '1';
723
+ function setQuiet(flag) { QUIET = !!flag; }
724
+ function log(msg) { if (!QUIET) process.stdout.write(msg + '\n'); }
725
+ function ok(msg) { process.stdout.write('ok ' + msg + '\n'); }
689
726
  function warn(msg) { process.stderr.write(` ! ${msg}\n`); }
690
727
 
691
728
  main().catch(err => {
package/lib/agents-md.js CHANGED
@@ -63,6 +63,10 @@ Read that skill before pushing fixes addressing prior review threads.
63
63
  Strict mode is ${strictNote}. Toggle via \`.claude/skills/.clud-bug.json\`
64
64
  (read from PR **base ref**, so PRs can't disable strict-mode on themselves).
65
65
 
66
+ For agent invocations of the \`clud-bug\` CLI, prefer \`CLUD_BUG_QUIET=1\`
67
+ (or pass \`--quiet\`) — suppresses progress chatter and emits a single
68
+ \`ok <key-value>\` summary line per command.
69
+
66
70
  ${versionLine}
67
71
  ${END_MARKER}`;
68
72
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clud-bug",
3
- "version": "0.6.6",
3
+ "version": "0.6.7",
4
4
  "description": "Skill-driven Claude PR review. Ship a brand-voice skill, get brand reviews. Each finding cites the skill that motivated it. CLI installs the workflow + a baseline kit; add more from skills.sh.",
5
5
  "homepage": "https://cludbug.dev",
6
6
  "bugs": "https://github.com/thrillmade/clud-bug/issues",
@@ -79,6 +79,6 @@ jobs:
79
79
  # Strict-mode gate — composite action; see workflow.yml.tmpl for design notes.
80
80
  - name: Strict mode — fail check on critical findings
81
81
  if: success()
82
- uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.6
82
+ uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.7
83
83
  with:
84
84
  github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -79,6 +79,6 @@ jobs:
79
79
  # Strict-mode gate — composite action; see workflow.yml.tmpl for design notes.
80
80
  - name: Strict mode — fail check on critical findings
81
81
  if: success()
82
- uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.6
82
+ uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.7
83
83
  with:
84
84
  github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -130,6 +130,6 @@ jobs:
130
130
  # Letting the action's own failure fail the check is louder and right.
131
131
  - name: Strict mode — fail check on critical findings
132
132
  if: success()
133
- uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.6
133
+ uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.7
134
134
  with:
135
135
  github-token: ${{ secrets.GITHUB_TOKEN }}