reviewer-harness 1.4.1 → 1.5.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.
package/README.md CHANGED
@@ -47,20 +47,23 @@ The harness is **not the AI model** — it is what prepares everything the AI re
47
47
  harness.config.json ← your master spec (ONE file)
48
48
  │ validate() ← quality checks + secret scanning
49
49
  ▼
50
- lib/adapters/*.js ← adapters: opencode, claude, gemini, cline
50
+ lib/adapters/*.js ← adapters: opencode, claude, gemini, cline,
51
+ freebuff, copilot, antigravity
51
52
  │ renderInstructions()
52
53
  ▼
53
54
  .opencode/instructions.md ← OpenCode
54
55
  CLAUDE.md ← Claude Code
55
56
  GEMINI.md ← Gemini CLI
56
57
  .clinerules ← Cline
58
+ .agents/skills/<skill>/SKILL.md ← Freebuff, Antigravity (project skills)
59
+ .github/skills/<skill>/SKILL.md ← GitHub Copilot CLI (project skills)
57
60
  ```
58
61
 
59
62
  Change the rules in **one** place (`harness.config.json`), and `sync` propagates them to every runtime.
60
63
 
61
64
  ## Quickstart
62
65
 
63
- You can use reviewer-harness in two ways: **Modular Mode** (zero-install: add individual skills to any project, no setup) or **Full Harness Mode** (one master config synced across all 4 runtimes).
66
+ You can use reviewer-harness in two ways: **Modular Mode** (zero-install: add individual skills to any project, no setup) or **Full Harness Mode** (one master config synced across all 7 runtimes).
64
67
 
65
68
  ### 1. Modular Skills (zero-install via npx)
66
69
 
@@ -77,9 +80,9 @@ npx reviewer-harness skills add no-hallucination
77
80
 
78
81
  > Prefer a global CLI? Install once with `npm install -g reviewer-harness` and run `reviewer-harness skills add <name>` anywhere.
79
82
 
80
- ### 2. Full Harness Synchronization (4 runtimes)
83
+ ### 2. Full Harness Synchronization (7 runtimes)
81
84
 
82
- `init` creates your master config, `validate` checks it (including secret scanning), and `sync` generates the native instruction file for every runtime you enable: `.opencode/instructions.md`, `CLAUDE.md`, `GEMINI.md`, and `.clinerules`.
85
+ `init` creates your master config, `validate` checks it (including secret scanning), and `sync` generates the native instruction file for every runtime you enable: `.opencode/instructions.md`, `CLAUDE.md`, `GEMINI.md`, and `.clinerules` — plus Agent Skills bundles (`.agents/skills/<skill>/SKILL.md` for Freebuff and Antigravity, `.github/skills/<skill>/SKILL.md` for GitHub Copilot CLI), so your skills follow you even when you switch CLIs.
83
86
 
84
87
  ```bash
85
88
  # Using npx (zero-install, recommended)
@@ -152,7 +155,7 @@ Guardrails that run before any file is written:
152
155
 
153
156
  ## This repo governs itself
154
157
 
155
- reviewer-harness eats its own cooking: the instruction files at this repo's root — `.opencode/instructions.md`, `CLAUDE.md`, `GEMINI.md`, `.clinerules` — plus the agents and commands in `.opencode/` and `.claude/` are **generated by reviewer-harness itself** from its own `harness.config.json`. Open this repo in any AI coding tool and the tool follows the harness's own rules while working on the harness. To refresh them after editing the config, just run `node bin/cli.js sync` here.
158
+ reviewer-harness eats its own cooking: the instruction files at this repo's root — `.opencode/instructions.md`, `CLAUDE.md`, `GEMINI.md`, `.clinerules` — plus the agents and commands in `.opencode/` and `.claude/` and the skill bundles in `.agents/skills/` and `.github/skills/` are **generated by reviewer-harness itself** from its own `harness.config.json`. Open this repo in any AI coding tool and the tool follows the harness's own rules while working on the harness. To refresh them after editing the config, just run `node bin/cli.js sync` here.
156
159
 
157
160
  ## Local Memory (graph-style, Obsidian-ready)
158
161
 
@@ -238,7 +241,7 @@ Running from a source checkout instead? The same commands work as `node bin/cli.
238
241
  - `lib/memory.js` — local memory: notes vault, graph builder, index generator
239
242
  - `lib/skills.js` — skills system: bundled store, install/enable, section rendering
240
243
  - `lib/agents.js` / `lib/commands.js` — one source → OpenCode + Claude formats
241
- - `lib/adapters/` — registry + one adapter per runtime (opencode, claude, gemini, cline)
244
+ - `lib/adapters/` — registry + one adapter per runtime (opencode, claude, gemini, cline, freebuff, copilot, antigravity)
242
245
  - `skills/` — bundled skills · `agents/` — bundled sub-agents · `commands/` — bundled slash commands
243
246
 
244
247
  ## How it was built (the lessons)
package/bin/cli.js CHANGED
@@ -13,7 +13,7 @@ import { sync, writeSafe } from "../lib/sync.js";
13
13
  import { initProject } from "../lib/init.js";
14
14
  import { initMemory, buildIndex, readNotes, memoryDir } from "../lib/memory.js";
15
15
  import { validateConfig } from "../lib/validate.js";
16
- import { listBundledSkills, addSkill, removeSkill, loadBundledSkills, skillCommandContent } from "../lib/skills.js";
16
+ import { listBundledSkills, addSkill, removeSkill, loadBundledSkills, skillCommandContent, skillBundleContent } from "../lib/skills.js";
17
17
  import { listBundledAgents, addAgent } from "../lib/agents.js";
18
18
  import { listBundledCommands, addCommand } from "../lib/commands.js";
19
19
 
@@ -45,7 +45,7 @@ Usage (run inside your project):
45
45
  reviewer-harness commands list List bundled slash commands
46
46
  reviewer-harness commands add <name> Install a slash command (OpenCode + Claude)
47
47
 
48
- reviewer-harness global [--dry-run] Install EVERY bundled skill as a slash command for ALL projects (global OpenCode + Claude "/" menus)
48
+ reviewer-harness global [--dry-run] Install EVERY bundled skill for ALL projects (OpenCode + Claude "/" menus; Freebuff, Copilot CLI, Antigravity skill bundles)
49
49
 
50
50
  reviewer-harness memory init Start the local memory (memory/ folder)
51
51
  reviewer-harness memory index Rebuild the memory INDEX.md + graph.json
@@ -62,7 +62,11 @@ function cmdStatus() {
62
62
  console.log(`Runtimes:`);
63
63
  for (const name of config.runtimes) {
64
64
  const adapter = adapters[name];
65
- console.log(` - ${name} → ${adapter ? adapter.targetFile() : "(no adapter!)"}`);
65
+ const target = !adapter ? "(no adapter!)"
66
+ : typeof adapter.targetFile === "function" ? adapter.targetFile()
67
+ : typeof adapter.skillBundleDir === "function" ? `${adapter.skillBundleDir()}/<skill>/SKILL.md`
68
+ : "(unknown)";
69
+ console.log(` - ${name} → ${target}`);
66
70
  }
67
71
  console.log(`Skills : ${config.skills?.length ? config.skills.join(", ") : "(none)"}`);
68
72
  }
@@ -82,6 +86,17 @@ function cmdSync() {
82
86
  }
83
87
  } else if (r.skipped) {
84
88
  console.log(`- ${r.runtime}: SKIP — ${r.skipped}`);
89
+ } else if (r.skillBundles) {
90
+ const files = r.skillBundles;
91
+ const written = files.filter((f) => f.written).length;
92
+ const pending = files.filter((f) => f.dryRun && f.changed).length;
93
+ const unchanged = files.filter((f) => f.unchanged || (f.dryRun && !f.changed)).length;
94
+ const where = `${r.bundleDir}/<skill>/SKILL.md`;
95
+ if (dryRun) {
96
+ console.log(`- ${r.runtime} → ${where}: ${pending} would be written/updated, ${unchanged} unchanged (Agent Skills bundles)`);
97
+ } else {
98
+ console.log(`- ${r.runtime} → ${where}: ${written} written ✓, ${unchanged} unchanged`);
99
+ }
85
100
  } else if (r.dryRun) {
86
101
  console.log(`- ${r.runtime} → ${r.file}: ${r.changed ? "WOULD WRITE (changes pending)" : "no changes"}`);
87
102
  } else if (r.unchanged) {
@@ -213,21 +228,31 @@ function cmdGlobal() {
213
228
  const targets = [
214
229
  { runtime: "OpenCode", dir: join(homedir(), ".config", "opencode", "commands") },
215
230
  { runtime: "Claude", dir: join(homedir(), ".claude", "commands") },
231
+ // Skill-bundle runtimes (Agent Skills open standard: <skill>/SKILL.md)
232
+ { runtime: "Freebuff", dir: join(homedir(), ".agents", "skills"), bundle: true },
233
+ { runtime: "Copilot CLI", dir: join(homedir(), ".copilot", "skills"), bundle: true },
234
+ { runtime: "Antigravity", dir: join(homedir(), ".gemini", "config", "skills"), bundle: true },
216
235
  ];
217
236
  if (dryRun) console.log("(dry-run: nothing was written)\n");
218
- for (const { runtime, dir } of targets) {
237
+ for (const { runtime, dir, bundle } of targets) {
219
238
  let written = 0, unchanged = 0, pending = 0;
220
239
  for (const skill of skills) {
221
- const outcome = writeSafe(join(dir, `${skill.name}.md`), skillCommandContent(skill, skills), dryRun);
240
+ const rel = bundle ? join(skill.name, "SKILL.md") : `${skill.name}.md`;
241
+ const content = bundle
242
+ ? skillBundleContent(skill, skills)
243
+ : skillCommandContent(skill, skills);
244
+ const outcome = writeSafe(join(dir, rel), content, dryRun);
222
245
  if (outcome.written) written++;
223
246
  else if (outcome.dryRun && outcome.changed) pending++;
224
247
  else unchanged++;
225
248
  }
226
- if (dryRun) console.log(`- ${runtime} (global): ${pending} would be written/updated, ${unchanged} unchanged → ${dir}`);
227
- else console.log(`- ${runtime} (global): ${written} written ✓, ${unchanged} unchanged → ${dir}`);
249
+ const where = bundle ? `${dir} (<skill>/SKILL.md)` : dir;
250
+ if (dryRun) console.log(`- ${runtime} (global): ${pending} would be written/updated, ${unchanged} unchanged → ${where}`);
251
+ else console.log(`- ${runtime} (global): ${written} written ✓, ${unchanged} unchanged → ${where}`);
228
252
  }
229
253
  console.log(
230
- `\nDone: ${skills.map((s) => "/" + s.name).join(", ")} are now in the "/" menu of EVERY project.` +
254
+ `\nDone: ${skills.map((s) => "/" + s.name).join(", ")} are now available in EVERY project.` +
255
+ `\n(OpenCode + Claude: "/" menu commands. Freebuff, Copilot CLI, Antigravity: Agent Skills bundles.)` +
231
256
  `\n(Per-project rules still come from "sync" inside a project.)`
232
257
  );
233
258
  }
@@ -0,0 +1,15 @@
1
+ // lib/adapters/antigravity.js — ADAPTER for Google Antigravity.
2
+ //
3
+ // Antigravity follows the Agent Skills open standard (agentskills.io):
4
+ // workspace skills at `<workspace>/.agents/skills/<name>/SKILL.md`
5
+ // (with backward compatibility for `.agent/skills/`), and global
6
+ // skills at `~/.gemini/config/skills/<name>/SKILL.md`. This adapter
7
+ // covers the workspace side (used by `sync`); the global side is
8
+ // covered by the `global` command.
9
+ //
10
+ // Like Freebuff and Copilot CLI, Antigravity is skills-only here:
11
+ // it exports skillBundleDir() instead of targetFile()/renderInstructions().
12
+
13
+ export function skillBundleDir() {
14
+ return ".agents/skills";
15
+ }
@@ -0,0 +1,15 @@
1
+ // lib/adapters/copilot.js — ADAPTER for GitHub Copilot CLI.
2
+ //
3
+ // GitHub Copilot CLI reads Agent Skills (agentskills.io) from skill
4
+ // folders: project skills at `<project>/.github/skills/<name>/SKILL.md`
5
+ // (it also recognizes `.claude/skills/` and `.agents/skills/`), and
6
+ // personal skills at `~/.copilot/skills/<name>/SKILL.md` (or
7
+ // `~/.agents/skills/`). This adapter covers the project side (used by
8
+ // `sync`); the personal side is covered by the `global` command.
9
+ //
10
+ // Like Freebuff and Antigravity, Copilot CLI is skills-only here:
11
+ // it exports skillBundleDir() instead of targetFile()/renderInstructions().
12
+
13
+ export function skillBundleDir() {
14
+ return ".github/skills";
15
+ }
@@ -0,0 +1,16 @@
1
+ // lib/adapters/freebuff.js — ADAPTER for Freebuff (Codebuff platform).
2
+ //
3
+ // Freebuff follows the Agent Skills open standard (agentskills.io):
4
+ // skills are folders containing a SKILL.md with `name` + `description`
5
+ // frontmatter. Personal skills live at `~/.agents/skills/<name>/SKILL.md`;
6
+ // project skills live at `<project>/.agents/skills/<name>/SKILL.md`.
7
+ // This adapter covers the project side (used by `sync`); the personal
8
+ // side is covered by the `global` command.
9
+ //
10
+ // Freebuff has no single instruction file like CLAUDE.md, so this
11
+ // adapter is skills-only: it exports skillBundleDir() instead of
12
+ // targetFile()/renderInstructions().
13
+
14
+ export function skillBundleDir() {
15
+ return ".agents/skills";
16
+ }
@@ -9,7 +9,18 @@ import * as opencode from "./opencode.js";
9
9
  import * as claude from "./claude.js";
10
10
  import * as gemini from "./gemini.js";
11
11
  import * as cline from "./cline.js";
12
+ import * as freebuff from "./freebuff.js";
13
+ import * as copilot from "./copilot.js";
14
+ import * as antigravity from "./antigravity.js";
12
15
 
13
- export const adapters = { opencode, claude, gemini, cline };
16
+ export const adapters = {
17
+ opencode,
18
+ claude,
19
+ gemini,
20
+ cline,
21
+ freebuff,
22
+ copilot,
23
+ antigravity,
24
+ };
14
25
 
15
26
  export const supportedRuntimes = Object.keys(adapters);
package/lib/init.js CHANGED
@@ -11,7 +11,7 @@ const TEMPLATE = {
11
11
  version: "1.0.0",
12
12
  problem:
13
13
  "The problem — an AI with no guardrails: it sometimes breaks existing code it was never asked to touch, and hallucinates — inventing functions, libraries, or output that do not actually exist. These rules are the guardrails against that.",
14
- runtimes: ["opencode", "claude", "gemini", "cline"],
14
+ runtimes: ["opencode", "claude", "gemini", "cline", "freebuff", "copilot", "antigravity"],
15
15
  skills: [],
16
16
  rules: [
17
17
  "Edit surgically: change only the code the task requires — never rewrite a whole file.",
package/lib/skills.js CHANGED
@@ -168,3 +168,17 @@ export function skillCommandContent(skill, allSkills = []) {
168
168
  content += `\nApply this playbook to the following: $ARGUMENTS\n`;
169
169
  return content;
170
170
  }
171
+
172
+ // Skill BUNDLE content — the Agent Skills open standard (agentskills.io):
173
+ // one folder per skill, containing a SKILL.md with `name` + `description`
174
+ // frontmatter. Freebuff, GitHub Copilot CLI, and Antigravity all read
175
+ // this format. The body is identical to the slash-command version
176
+ // (companions included) so every runtime enforces the same disciplines;
177
+ // only the frontmatter gains the required `name` field.
178
+ export function skillBundleContent(skill, allSkills = []) {
179
+ const command = skillCommandContent(skill, allSkills);
180
+ return command.replace(
181
+ `---\ndescription: `,
182
+ `---\nname: ${skill.name}\ndescription: `
183
+ );
184
+ }
package/lib/sync.js CHANGED
@@ -27,7 +27,7 @@ import { join, dirname } from "node:path";
27
27
  import { loadConfig } from "./config.js";
28
28
  import { adapters, supportedRuntimes } from "./adapters/index.js";
29
29
  import { validateConfig } from "./validate.js";
30
- import { loadSkills, skillCommandContent } from "./skills.js";
30
+ import { loadSkills, skillCommandContent, skillBundleContent } from "./skills.js";
31
31
 
32
32
  // Write one file the safe way. Returns what happened:
33
33
  // dry-run → { dryRun: true, changed } · no change → { unchanged: true }
@@ -86,9 +86,26 @@ export function sync({ targetDir, dryRun = false }) {
86
86
  continue;
87
87
  }
88
88
 
89
- const rel = adapter.targetFile();
90
- const outcome = writeSafe(join(targetDir, rel), adapter.renderInstructions(config), dryRun);
91
- results.push({ runtime: name, file: rel, ...outcome });
89
+ // Instruction-file runtimes (OpenCode, Claude, Gemini, Cline):
90
+ // one rendered rules file per runtime.
91
+ if (typeof adapter.targetFile === "function") {
92
+ const rel = adapter.targetFile();
93
+ const outcome = writeSafe(join(targetDir, rel), adapter.renderInstructions(config), dryRun);
94
+ results.push({ runtime: name, file: rel, ...outcome });
95
+ }
96
+
97
+ // Skill-bundle runtimes (Freebuff, Copilot CLI, Antigravity):
98
+ // one <skill>/SKILL.md per enabled skill, following the Agent
99
+ // Skills open standard (agentskills.io).
100
+ if (typeof adapter.skillBundleDir === "function") {
101
+ const files = [];
102
+ for (const skill of skills) {
103
+ const rel = `${adapter.skillBundleDir()}/${skill.name}/SKILL.md`;
104
+ const content = skillBundleContent(skill, skills);
105
+ files.push({ file: rel, ...writeSafe(join(targetDir, rel), content, dryRun) });
106
+ }
107
+ results.push({ runtime: name, bundleDir: adapter.skillBundleDir(), skillBundles: files });
108
+ }
92
109
  }
93
110
 
94
111
  // SLASH COMMANDS: one per enabled skill, for the two runtimes whose
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "bin": {
4
4
  "reviewer-harness": "./bin/cli.js"
5
5
  },
6
- "description": "Your own AI harness \u2014 one master config that syncs guardrail rules, skills, and a local memory to Claude, OpenCode, Gemini, and Cline. No API key, no dependencies.",
6
+ "description": "Your own AI harness — one master config that syncs guardrail rules, skills, and a local memory to Claude, OpenCode, Gemini, Cline, Freebuff, Copilot CLI, and Antigravity. No API key, no dependencies.",
7
7
  "engines": {
8
8
  "node": ">=18"
9
9
  },
@@ -14,7 +14,10 @@
14
14
  "opencode",
15
15
  "claude-code",
16
16
  "gemini",
17
- "cline"
17
+ "cline",
18
+ "freebuff",
19
+ "copilot-cli",
20
+ "antigravity"
18
21
  ],
19
22
  "license": "MIT",
20
23
  "name": "reviewer-harness",
@@ -23,7 +26,7 @@
23
26
  "url": "https://github.com/xcell321/reviewer-harness.git"
24
27
  },
25
28
  "type": "module",
26
- "version": "1.4.1",
29
+ "version": "1.5.0",
27
30
  "files": [
28
31
  "bin",
29
32
  "lib",
@@ -12,5 +12,6 @@ When to use: every change to existing code.
12
12
  - Do not reformat, reorder, or rename unrelated lines.
13
13
  - Code as a seasoned senior developer with many years of experience shipping real products — websites and mobile apps deployed to production: clear names, small focused functions, no duplication, no clever hacks, edge cases handled, production-ready and maintainable — every change must be easy to understand at a glance.
14
14
  - Keep the code well structured: separate concerns into files and modules with clear organization and placement. Never leave spaghetti code behind — if the change touches messy code, refactor that part (and only that part) so the result stays clean.
15
+ - Never hardcode: values that can change — URLs, endpoints, file paths, credentials, API keys, user-specific data, magic numbers — must come from config, environment variables, parameters, or named constants, never buried as literals in code. Secrets must never be hardcoded, ever.
15
16
  - If another file truly must change too, say why before doing it.
16
17
  - Afterwards, show the diff and describe in one sentence what changed.