rebar-mcp 2.2.0 → 2.4.0

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 (36) hide show
  1. package/.claude/settings.json +49 -19
  2. package/.claude/skills/bmmov0lh5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
  3. package/.claude/skills/bmmovah7zxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/SKILL.md +21 -0
  4. package/.claude/skills/bnd-mmov0lh8/SKILL.md +21 -0
  5. package/.claude/skills/bnd-mmovah83/SKILL.md +21 -0
  6. package/.claude/skills/nl-mmov0lhi/SKILL.md +25 -0
  7. package/.claude/skills/nl-mmovah8b/SKILL.md +25 -0
  8. package/.rebar/prereview.json +9 -0
  9. package/CLAUDE.md +17 -67
  10. package/dist/cli.d.ts.map +1 -1
  11. package/dist/cli.js +165 -5
  12. package/dist/cli.js.map +1 -1
  13. package/dist/index.js +1 -1
  14. package/dist/services/context-builder.d.ts +41 -0
  15. package/dist/services/context-builder.d.ts.map +1 -0
  16. package/dist/services/context-builder.js +248 -0
  17. package/dist/services/context-builder.js.map +1 -0
  18. package/dist/services/license.d.ts +52 -0
  19. package/dist/services/license.d.ts.map +1 -0
  20. package/dist/services/license.js +194 -0
  21. package/dist/services/license.js.map +1 -0
  22. package/dist/services/prereview-llm.d.ts +15 -0
  23. package/dist/services/prereview-llm.d.ts.map +1 -0
  24. package/dist/services/prereview-llm.js +266 -0
  25. package/dist/services/prereview-llm.js.map +1 -0
  26. package/dist/services/prereview-memory.d.ts +101 -0
  27. package/dist/services/prereview-memory.d.ts.map +1 -0
  28. package/dist/services/prereview-memory.js +301 -0
  29. package/dist/services/prereview-memory.js.map +1 -0
  30. package/package.json +1 -1
  31. package/src/cli.ts +200 -5
  32. package/src/index.ts +1 -1
  33. package/src/services/context-builder.ts +325 -0
  34. package/src/services/license.ts +252 -0
  35. package/src/services/prereview-llm.ts +365 -0
  36. package/src/services/prereview-memory.ts +439 -0
@@ -1,24 +1,54 @@
1
1
  {
2
- "permissions": {
3
- "allow": [
4
- "Bash(npm run build)",
5
- "Bash(npm run lint)",
6
- "Bash(npm run test *)",
7
- "Bash(npm run dev)",
8
- "Bash(npx tsc --noEmit)",
9
- "Bash(git status)",
10
- "Bash(git diff *)",
11
- "Bash(git log *)",
12
- "Bash(git add *)",
13
- "Bash(git commit *)"
14
- ],
15
- "deny": [
16
- "Bash(rm -rf *)",
17
- "Read(./.env)",
18
- "Read(./.env.*)"
19
- ]
20
- },
21
2
  "hooks": {
3
+ "PostToolCall": [
4
+ {
5
+ "matcher": "Write(*.ts)|Write(*.tsx)|Write(*.js)|Write(*.jsx)",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "npm run format \"$CLAUDE_FILE_PATH\" 2>/dev/null || true"
10
+ }
11
+ ]
12
+ },
13
+ {
14
+ "matcher": "Write(*.ts)|Write(*.tsx)|Write(*.js)|Write(*.jsx)",
15
+ "hooks": [
16
+ {
17
+ "type": "command",
18
+ "command": "RESULT=$(npm run lint \"$CLAUDE_FILE_PATH\" 2>&1); EXITCODE=$?; if [ $EXITCODE -ne 0 ]; then echo \"$RESULT\" | head -20; echo '\\n❌ LINT ERRORS — Fix these before continuing.' >&2; exit 2; fi; exit 0"
19
+ }
20
+ ]
21
+ },
22
+ {
23
+ "matcher": "Write(*.ts)|Write(*.tsx)|Write(*.js)|Write(*.jsx)|Edit(*.ts)|Edit(*.tsx)|Edit(*.js)|Edit(*.jsx)",
24
+ "hooks": [
25
+ {
26
+ "type": "command",
27
+ "command": "node --test dist/**/*.test.js 2>&1 | tail -10; EXIT_CODE=${PIPESTATUS[0]}; if [ $EXIT_CODE -ne 0 ]; then echo '\\n❌ TESTS FAILED — Fix failing tests before continuing. Do not move to the next task.' >&2; exit 2; fi; exit 0"
28
+ }
29
+ ]
30
+ }
31
+ ],
32
+ "PreToolCall": [
33
+ {
34
+ "matcher": "Bash",
35
+ "hooks": [
36
+ {
37
+ "type": "command",
38
+ "command": "BLOCKED='rm -rf|rm -fr|git push --force|git push -f|DROP TABLE|DROP DATABASE|TRUNCATE TABLE|chmod -R 777'; if echo \"$CLAUDE_BASH_COMMAND\" | grep -qiE \"$BLOCKED\"; then echo 'BLOCKED: Destructive command detected. Ask the developer for explicit approval.' >&2; exit 2; fi; exit 0"
39
+ }
40
+ ]
41
+ },
42
+ {
43
+ "matcher": "Bash(git commit*)|Bash(git add*)",
44
+ "hooks": [
45
+ {
46
+ "type": "command",
47
+ "command": "STAGED=$(git diff --cached --name-only 2>/dev/null); if [ -z \"$STAGED\" ]; then exit 0; fi; SECRETS=$(git diff --cached | grep -inE '(api[_-]?key|secret|password|token|private[_-]?key|aws_access|AKIA[A-Z0-9]{16})\\s*[:=]\\s*[\"\\x27]?[A-Za-z0-9+/=_-]{8,}' | head -5); if [ -n \"$SECRETS\" ]; then echo \"BLOCKED: Potential secrets in staged files:\" >&2; echo \"$SECRETS\" >&2; exit 2; fi; exit 0"
48
+ }
49
+ ]
50
+ }
51
+ ],
22
52
  "InvalidEvent": [
23
53
  {
24
54
  "description": "A test hook",
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: bmmov0lh5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3
+ description: A test skill
4
+ invocation: undefined
5
+ context: undefined
6
+ ---
7
+
8
+ # bmmov0lh5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
9
+
10
+ A test skill
11
+
12
+ ## Instructions
13
+
14
+ <!-- Replace this with your skill instructions.
15
+ Good skill instructions:
16
+ 1. Define the agent's role clearly
17
+ 2. Specify the exact output format
18
+ 3. List what to check/do step by step
19
+ 4. Include examples of good output
20
+ -->
21
+
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: bmmovah7zxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3
+ description: A test skill
4
+ invocation: undefined
5
+ context: undefined
6
+ ---
7
+
8
+ # bmmovah7zxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
9
+
10
+ A test skill
11
+
12
+ ## Instructions
13
+
14
+ <!-- Replace this with your skill instructions.
15
+ Good skill instructions:
16
+ 1. Define the agent's role clearly
17
+ 2. Specify the exact output format
18
+ 3. List what to check/do step by step
19
+ 4. Include examples of good output
20
+ -->
21
+
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: bnd-mmov0lh8
3
+ description: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
4
+ invocation: undefined
5
+ context: undefined
6
+ ---
7
+
8
+ # bnd-mmov0lh8
9
+
10
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
11
+
12
+ ## Instructions
13
+
14
+ <!-- Replace this with your skill instructions.
15
+ Good skill instructions:
16
+ 1. Define the agent's role clearly
17
+ 2. Specify the exact output format
18
+ 3. List what to check/do step by step
19
+ 4. Include examples of good output
20
+ -->
21
+
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: bnd-mmovah83
3
+ description: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
4
+ invocation: undefined
5
+ context: undefined
6
+ ---
7
+
8
+ # bnd-mmovah83
9
+
10
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
11
+
12
+ ## Instructions
13
+
14
+ <!-- Replace this with your skill instructions.
15
+ Good skill instructions:
16
+ 1. Define the agent's role clearly
17
+ 2. Specify the exact output format
18
+ 3. List what to check/do step by step
19
+ 4. Include examples of good output
20
+ -->
21
+
@@ -0,0 +1,25 @@
1
+ ---
2
+ name: nl-mmov0lhi
3
+ description: Line one
4
+ Line two
5
+ Line three
6
+ invocation: undefined
7
+ context: undefined
8
+ ---
9
+
10
+ # nl-mmov0lhi
11
+
12
+ Line one
13
+ Line two
14
+ Line three
15
+
16
+ ## Instructions
17
+
18
+ <!-- Replace this with your skill instructions.
19
+ Good skill instructions:
20
+ 1. Define the agent's role clearly
21
+ 2. Specify the exact output format
22
+ 3. List what to check/do step by step
23
+ 4. Include examples of good output
24
+ -->
25
+
@@ -0,0 +1,25 @@
1
+ ---
2
+ name: nl-mmovah8b
3
+ description: Line one
4
+ Line two
5
+ Line three
6
+ invocation: undefined
7
+ context: undefined
8
+ ---
9
+
10
+ # nl-mmovah8b
11
+
12
+ Line one
13
+ Line two
14
+ Line three
15
+
16
+ ## Instructions
17
+
18
+ <!-- Replace this with your skill instructions.
19
+ Good skill instructions:
20
+ 1. Define the agent's role clearly
21
+ 2. Specify the exact output format
22
+ 3. List what to check/do step by step
23
+ 4. Include examples of good output
24
+ -->
25
+
@@ -0,0 +1,9 @@
1
+ {
2
+ "enabled": true,
3
+ "tier": "pro",
4
+ "strictness": "strict",
5
+ "operations": ["write", "edit", "bash"],
6
+ "customRules": [],
7
+ "auditEnabled": true,
8
+ "auditRetentionDays": 90
9
+ }
package/CLAUDE.md CHANGED
@@ -1,76 +1,26 @@
1
1
  # rebar-mcp
2
2
 
3
- ## Project Overview
4
- Reinforcement for AI-generated code. An MCP server that generates, validates, and manages Claude Code configuration artifacts (CLAUDE.md, skills, agents, hooks, commands, MCP configs, knowledge docs) with enforcement hooks that prevent AI coding tools from shipping broken code.
3
+ Reinforcement for AI-generated code. Enforcement hooks, quality audits, and opinionated templates that prevent AI coding tools from shipping broken code.
5
4
 
6
5
  ## Tech Stack
7
- - TypeScript (strict mode) targeting ES2022
8
- - Node.js 18+ runtime
9
- - @modelcontextprotocol/sdk for MCP server
10
- - Zod for input validation
11
- - stdio transport (primary), streamable HTTP (secondary)
6
+ - TypeScript (strict mode)
12
7
 
13
8
  ## Architecture Rules
14
- - ALWAYS use server.registerTool() (never deprecated server.tool())
15
- - All tool names use rebar_ prefix with snake_case
16
- - All Zod schemas use .strict() enforcement
17
- - No use of `any` type use `unknown` or proper types
18
- - All async functions have explicit Promise<T> return types
19
- - Log to stderr ONLY (stdout is reserved for MCP protocol)
20
- - Never use console.log() — use console.error() for debug output
21
- - All file writes are atomic (write to temp, then rename)
22
- - Never overwrite files without checking merge_existing flag
23
-
24
- ## Tool Annotations
25
- Every tool MUST include annotations:
26
- - readOnlyHint: true for read operations, false for writes
27
- - destructiveHint: false (we never delete without explicit request)
28
- - idempotentHint: true if re-running produces same result
29
- - openWorldHint: false (we only touch local filesystem)
30
-
31
- ## File Structure
32
- - src/index.ts — Entry point, server init, transport
33
- - src/types.ts — Shared TypeScript interfaces
34
- - src/constants.ts — Enums, defaults, limits
35
- - src/tools/*.ts — Tool implementations (one file per domain)
36
- - src/services/*.ts — Shared utilities (file ops, templates, validation)
37
- - src/schemas/*.ts — Zod schemas
38
- - templates/**/*.md — Raw template files
9
+ - No use of `any` type — use `unknown` with type narrowing or proper generics
10
+ - Prefer `interface` for object shapes, `type` for unions and intersections
11
+ - Never store secrets in code, config files, or version control
12
+ - All external data (user input, API responses, env vars) must be validated before use
39
13
 
40
14
  ## Build & Test
41
- - Build: `npm run build` (must pass with zero errors)
42
- - Lint: `npx tsc --noEmit`
43
- - Test: `npm run test`
44
- - Dev: `npx tsx src/index.ts` (for local MCP testing)
45
-
46
- ## Template Conventions
47
- - Variables: `{{variable_name}}` (double curly braces)
48
- - Conditionals: `{{#if condition}}...{{/if}}`
49
- - Templates are plain markdown with substitution markers
50
- - All generated YAML must parse cleanly
51
- - All generated JSON must be valid
52
- - Skills MUST have name (max 64 chars) and description (max 200 chars)
15
+ - Build: `npm run build` (runs: `tsc`)
16
+ - Test: `npm run test` (runs: `node --test dist/**/*.test.js`)
53
17
 
54
- ## Code Quality
55
- - Extract common functionality into src/services/
56
- - DRY: if logic appears twice, extract to a function
57
- - Every tool description includes: purpose, args, return schema, examples
58
- - Error messages suggest next steps (not just what failed)
59
- - No hardcoded paths use path.join() and respect project_path input
60
-
61
- ## MCP Server Best Practices
62
- - Use Zod schemas with .describe() on every field for self-documenting APIs
63
- - Tool descriptions must include: purpose summary, all args with types, return schema with field descriptions, 2-3 usage examples, and error handling notes
64
- - Support both JSON and Markdown response formats where applicable
65
- - Paginate list results with has_more, next_offset, total_count
66
- - Return { isError: true, content: [...] } for recoverable errors with actionable suggestions
67
-
68
- ## Implementation Priority
69
- 1. src/index.ts + transport setup
70
- 2. src/services/ (file-ops, template-engine, validation)
71
- 3. src/types.ts + src/constants.ts + src/schemas/
72
- 4. src/tools/scaffolding.ts (init_project, generate_claudemd, create_skill, create_agent, create_hook, create_command)
73
- 5. templates/ (CLAUDE.md templates, skill templates, agent templates, hook templates)
74
- 6. src/tools/knowledge.ts (create_knowledge, create_adr)
75
- 7. src/tools/management.ts (list_artifacts, validate_config, audit_context)
76
- 8. src/tools/enterprise.ts (apply_compliance, create_ci_workflow, create_security_hook, generate_mcp_config)
18
+ ## File Structure
19
+ - `src/` Source code
20
+
21
+ ## Code Conventions
22
+ - TypeScript strict mode with no `any` types
23
+ - Prefer named exports over default exports
24
+ - Interface names: `PascalCase` (no `I` prefix)
25
+ - Constants: `UPPER_SNAKE_CASE`
26
+ - Zod schemas for runtime validation of external data
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAg2BA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAmH5D"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAshCA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAgI5D"}
package/dist/cli.js CHANGED
@@ -21,7 +21,10 @@ import { generateCodexConfig } from "./services/codex-generator.js";
21
21
  import { atomicWrite } from "./services/file-ops.js";
22
22
  import { CONTEXT_WINDOW_TOKENS } from "./constants.js";
23
23
  import { runPrereview, loadPrereviewConfig, } from "./services/prereview-engine.js";
24
- const VERSION = "2.0.0";
24
+ import { runHybridPrereview } from "./services/prereview-llm.js";
25
+ import { loadLicense, loadUsage, canUseLLMReview } from "./services/license.js";
26
+ import { loadMemory, clearMemory, learnFromHistory, exportMemorySummary, } from "./services/prereview-memory.js";
27
+ const VERSION = "2.4.0";
25
28
  function parseArgs(args) {
26
29
  const options = {
27
30
  path: ".",
@@ -555,8 +558,20 @@ async function cmdPrereview(options, operation, filePath, command) {
555
558
  if (!content) {
556
559
  return 0;
557
560
  }
558
- // Run pre-review
559
- const result = runPrereview(content, op, filePath, config);
561
+ // Run local pre-review first
562
+ const localResult = runPrereview(content, op, filePath, config);
563
+ // Try hybrid review (LLM + local) if tier supports it
564
+ let result = localResult;
565
+ let engine = "local";
566
+ if (config.tier !== "free") {
567
+ const hybridResult = await runHybridPrereview(projectPath, op, filePath || "", content, undefined, // existingContent for diffs
568
+ localResult);
569
+ // Check if LLM was actually used
570
+ if ("engine" in hybridResult && hybridResult.engine === "llm") {
571
+ engine = "hybrid";
572
+ result = hybridResult;
573
+ }
574
+ }
560
575
  // Write to audit trail
561
576
  if (config.auditEnabled) {
562
577
  const now = new Date();
@@ -578,7 +593,7 @@ async function cmdPrereview(options, operation, filePath, command) {
578
593
  decision: result.decision,
579
594
  severity: result.severity,
580
595
  tier: config.tier,
581
- engine: "local",
596
+ engine,
582
597
  latencyMs: result.latencyMs,
583
598
  patterns: result.patterns.map((p) => ({
584
599
  id: p.id,
@@ -686,9 +701,143 @@ async function cmdPrereviewStats(options) {
686
701
  console.log(` • ${name}: ${count}`);
687
702
  }
688
703
  }
704
+ // Show LLM usage info
705
+ const license = await loadLicense(projectPath);
706
+ const usage = await loadUsage(projectPath);
707
+ console.log();
708
+ console.log("LLM Review Usage");
709
+ console.log("----------------");
710
+ console.log(`Tier: ${license.tier}`);
711
+ console.log(`LLM reviews this month: ${usage.llmReviews}/${license.monthlyLimit || "∞"}`);
712
+ const llmCheck = await canUseLLMReview(projectPath);
713
+ if (!llmCheck.allowed) {
714
+ console.log(`Status: ${llmCheck.reason}`);
715
+ }
716
+ else {
717
+ console.log(`Remaining: ${llmCheck.remaining}`);
718
+ }
689
719
  }
690
720
  return 0;
691
721
  }
722
+ async function cmdLicense(options) {
723
+ const projectPath = resolveProjectPath(options.path);
724
+ const license = await loadLicense(projectPath);
725
+ const usage = await loadUsage(projectPath);
726
+ const llmCheck = await canUseLLMReview(projectPath);
727
+ if (options.format === "json") {
728
+ console.log(JSON.stringify({
729
+ tier: license.tier,
730
+ features: license.features,
731
+ usage: {
732
+ llmReviews: usage.llmReviews,
733
+ localReviews: usage.localReviews,
734
+ blockedCount: usage.blockedCount,
735
+ month: usage.month,
736
+ },
737
+ limits: {
738
+ monthlyLimit: license.monthlyLimit,
739
+ remaining: llmCheck.remaining,
740
+ },
741
+ llmAvailable: llmCheck.allowed,
742
+ reason: llmCheck.reason,
743
+ }, null, 2));
744
+ }
745
+ else {
746
+ console.log("Rebar License Status");
747
+ console.log("====================");
748
+ console.log();
749
+ console.log(`Tier: ${license.tier.toUpperCase()}`);
750
+ console.log();
751
+ console.log("Features:");
752
+ console.log(` • LLM Review: ${license.features.llmReview ? "✓" : "✗"}`);
753
+ console.log(` • Cross-session Memory: ${license.features.crossSessionMemory ? "✓" : "✗"}`);
754
+ console.log(` • Audit Retention: ${license.features.auditRetentionDays} days`);
755
+ console.log();
756
+ console.log(`Usage (${usage.month}):`);
757
+ console.log(` • LLM Reviews: ${usage.llmReviews}/${license.monthlyLimit || "N/A"}`);
758
+ console.log(` • Local Reviews: ${usage.localReviews}`);
759
+ console.log(` • Blocked: ${usage.blockedCount}`);
760
+ console.log();
761
+ if (llmCheck.allowed) {
762
+ console.log(`LLM Status: Available (${llmCheck.remaining} reviews remaining)`);
763
+ }
764
+ else {
765
+ console.log(`LLM Status: ${llmCheck.reason}`);
766
+ }
767
+ if (license.tier === "free") {
768
+ console.log();
769
+ console.log("Upgrade to Pro for LLM-powered semantic analysis:");
770
+ console.log(" export REBAR_API_KEY=your_anthropic_key");
771
+ console.log(" export REBAR_TIER=pro");
772
+ }
773
+ }
774
+ return 0;
775
+ }
776
+ async function cmdMemory(options, action) {
777
+ const projectPath = resolveProjectPath(options.path);
778
+ switch (action) {
779
+ case "show":
780
+ case "": {
781
+ const memory = await loadMemory(projectPath);
782
+ if (options.format === "json") {
783
+ console.log(await exportMemorySummary(projectPath));
784
+ }
785
+ else {
786
+ console.log("Pre-Review Memory");
787
+ console.log("=================");
788
+ console.log();
789
+ console.log(`Last updated: ${memory.updatedAt}`);
790
+ console.log();
791
+ console.log("Statistics:");
792
+ console.log(` • Total reviews: ${memory.stats.totalReviews}`);
793
+ console.log(` • Blocks: ${memory.stats.totalBlocks}`);
794
+ console.log(` • Warnings: ${memory.stats.totalWarns}`);
795
+ console.log(` • Avg latency: ${memory.stats.avgLatencyMs.toFixed(0)}ms`);
796
+ console.log();
797
+ if (memory.learnedPatterns.length > 0) {
798
+ console.log("Learned Patterns:");
799
+ const topPatterns = memory.learnedPatterns
800
+ .sort((a, b) => b.blockCount - a.blockCount)
801
+ .slice(0, 5);
802
+ for (const p of topPatterns) {
803
+ console.log(` • ${p.name} (${p.blockCount}x, ${p.severity})`);
804
+ }
805
+ console.log();
806
+ }
807
+ if (memory.projectInsights.length > 0) {
808
+ console.log("Project Insights:");
809
+ const topInsights = memory.projectInsights
810
+ .filter((i) => i.confidence >= 0.7)
811
+ .slice(0, 3);
812
+ for (const i of topInsights) {
813
+ console.log(` • ${i.description}`);
814
+ }
815
+ }
816
+ }
817
+ return 0;
818
+ }
819
+ case "learn": {
820
+ console.log("Learning from decision history...");
821
+ const result = await learnFromHistory(projectPath);
822
+ console.log(`✓ Learned ${result.patternsLearned} patterns`);
823
+ console.log(`✓ Generated ${result.insightsGenerated} insights`);
824
+ return 0;
825
+ }
826
+ case "clear": {
827
+ await clearMemory(projectPath);
828
+ console.log("✓ Memory cleared");
829
+ return 0;
830
+ }
831
+ case "export": {
832
+ console.log(await exportMemorySummary(projectPath));
833
+ return 0;
834
+ }
835
+ default:
836
+ console.error(`Unknown memory action: ${action}`);
837
+ console.error("Usage: rebar memory [show|learn|clear|export]");
838
+ return 1;
839
+ }
840
+ }
692
841
  async function cmdBadge(options) {
693
842
  const projectPath = resolveProjectPath(options.path);
694
843
  // Run audit to get current score
@@ -825,6 +974,10 @@ export async function runCLI(args) {
825
974
  }
826
975
  case "prereview-stats":
827
976
  return cmdPrereviewStats(options);
977
+ case "license":
978
+ return cmdLicense(options);
979
+ case "memory":
980
+ return cmdMemory(options, positional[0] || "show");
828
981
  case "version":
829
982
  case "--version":
830
983
  case "-v":
@@ -845,6 +998,8 @@ Usage:
845
998
  rebar badge [options] Generate quality score badge SVG
846
999
  rebar prereview [options] Run pre-review analysis (invoked by hooks)
847
1000
  rebar prereview-stats View pre-review decision statistics
1001
+ rebar license View license status and LLM usage
1002
+ rebar memory [action] Manage cross-session memory (show|learn|clear|export)
848
1003
  rebar version Print version
849
1004
  rebar help Show this help
850
1005
 
@@ -870,7 +1025,12 @@ Examples:
870
1025
  Strictness Levels:
871
1026
  standard - Notify on issues (tests, lint, secrets)
872
1027
  strict - Block on test/lint failures
873
- paranoid - Block + file size limits + TODO guards`);
1028
+ paranoid - Block + file size limits + TODO guards
1029
+
1030
+ LLM Review (Pro/Team tier):
1031
+ export REBAR_API_KEY=your_anthropic_key
1032
+ export REBAR_TIER=pro # 1,000 LLM reviews/month
1033
+ export REBAR_TIER=team # 5,000 LLM reviews/month`);
874
1034
  return 0;
875
1035
  default:
876
1036
  console.error(`Unknown command: ${command}`);