evolveguard-cli
Advanced tools
+5
-3
| { | ||
| "name": "evolveguard-cli", | ||
| "version": "0.1.2", | ||
| "description": "Regression-testing CLI for self-edited Claude Agent Skills (SKILL.md, MEMORY.md) -- golden-transcript record/replay against a skill's own declared and inferred capability surface, zero hosted infrastructure.", | ||
| "version": "0.1.3", | ||
| "description": "Regression-testing CLI for self-edited Claude Agent Skills (SKILL.md, MEMORY.md): golden-transcript record/replay against a skill's own declared and inferred capability surface, zero hosted infrastructure.", | ||
| "keywords": [ | ||
@@ -15,3 +15,5 @@ "ai-agents", | ||
| "eval-harness", | ||
| "developer-tools" | ||
| "developer-tools", | ||
| "drift-detection", | ||
| "static-analysis" | ||
| ], | ||
@@ -18,0 +20,0 @@ "license": "MIT", |
+132
-103
| # evolveguard | ||
| Catch behavioral drift when a Claude Agent Skill or a Claude Code `MEMORY.md` file edits itself, before the edit ships. | ||
| [](https://github.com/RudrenduPaul/evolveguard/actions/workflows/ci.yml) | ||
| [](https://www.npmjs.com/package/evolveguard-cli) | ||
| [](https://pypi.org/project/evolveguard-cli/) | ||
| [](LICENSE) | ||
| [](package.json) | ||
| [](https://pypi.org/project/evolveguard-cli/) | ||
| Catch behavioral drift when a Claude Agent Skill edits itself, before the edit ships. | ||
| ```bash | ||
| # PyPI -- Python CLI + library (genuine port) | ||
| # PyPI -- Python CLI + library (genuine port, not a Node wrapper) | ||
| pip install evolveguard-cli | ||
@@ -22,3 +24,3 @@ ``` | ||
| > `evolveguard-cli` on npm (renamed 2026-07-19 from the old plain `evolveguard`, | ||
| > which is now deprecated). `npm install -g evolveguard-cli` and | ||
| > which is now deprecated on both registries). `npm install -g evolveguard-cli` and | ||
| > `pip install evolveguard-cli` both work today; the demo GIFs below were recorded | ||
@@ -29,16 +31,18 @@ > against the published packages, not a local build. | ||
| --- | ||
| ## Contents | ||
| Claude Code's Agent Skills can be authored by a human, or by an agent itself: `/skillify` | ||
| turns a workflow into a `SKILL.md`, and the auto-memory system in this same environment | ||
| writes `MEMORY.md` files that quietly change what an agent does in its next session. | ||
| None of that gets a regression check today. A skill edit that breaks a working workflow | ||
| looks exactly like a skill edit that fixes one, until someone notices the agent stopped | ||
| doing something it used to do. | ||
| - [What it does](#what-it-does) | ||
| - [Features](#features) | ||
| - [Quickstart](#quickstart) | ||
| - [CLI command reference](#cli-command-reference) | ||
| - [Agent-native usage](#agent-native-usage) | ||
| - [Library API](#library-api) | ||
| - [How it compares](#how-it-compares) | ||
| - [What is evolveguard, and why does it exist](#what-is-evolveguard-and-why-does-it-exist) | ||
| - [Status](#status) | ||
| - [FAQ](#faq) | ||
| - [Contributing](#contributing) | ||
| - [Security](#security) | ||
| - [License](#license) | ||
| evolveguard records a baseline of a skill's own capability surface (what tools it's | ||
| declared or shown to use), then re-derives that surface every time the skill file | ||
| changes and diffs the result against the baseline: same tool-call sequence, or a flagged | ||
| drift with a specific reason. | ||
| ## What it does | ||
@@ -65,53 +69,55 @@ | ||
| That's real output from this repo's own `fixtures/labeled-non-breaking-edits/case-03-add-write-capability/` | ||
| test case, wired to `filesystem: read-only` -> `read-write` in the skill's frontmatter. | ||
| test case, wired to `filesystem: read-only` becoming `read-write` in the skill's frontmatter. | ||
| Reproduce it yourself: `evolveguard record` the `before/SKILL.md` in that folder against its | ||
| `fixtures.json`, then `evolveguard check` the `after/SKILL.md`. | ||
|  | ||
| ## How it works | ||
| ## Features | ||
| evolveguard does not run a live LLM agent, and it does not replay a real conversation | ||
| transcript. It is a static, deterministic tool by design: | ||
| **Static analysis, not a live agent run.** `record` parses a skill file's YAML | ||
| frontmatter (declared `tools`, `network`, `filesystem`, `scope`, and any bundled | ||
| `hooks`), scans the skill's body text and hook scripts for evidence of network calls | ||
| or filesystem writes, and combines both into a capability surface. `check` re-parses | ||
| the edited file with the same logic and diffs the result. Neither command runs | ||
| `eval`, shells out to a subprocess, or executes a skill's hook scripts, in either the | ||
| TypeScript or the Python distribution. | ||
| 1. **`record`** parses a skill file's YAML frontmatter (declared `tools`, `network`, | ||
| `filesystem`, `scope`, and any bundled `hooks`), scans the skill's body text and any | ||
| hook scripts for static evidence of network calls or filesystem writes, and combines | ||
| both into a **capability surface** -- the set of tools the skill is declared or shown | ||
| to use. Each fixture's `expectedToolCalls` filters that surface down to the tools the | ||
| fixture author says it cares about; the result is the recorded baseline. | ||
| 2. **`check`** re-reads the (possibly edited) skill file, re-derives its capability | ||
| surface with the exact same logic, and re-filters it per fixture. | ||
| 3. **`diff`** compares baseline vs. current per fixture (PASS if the tool set and scopes | ||
| match, DRIFT with a specific reason otherwise), and separately diffs the _whole_ | ||
| capability surface so a new capability that no fixture's `expectedToolCalls` happened | ||
| to cover still gets caught, instead of silently passing. | ||
| **Two-level diffing catches drift a single fixture can miss.** Each fixture's | ||
| `expectedToolCalls` filters the recorded capability surface down to what that fixture | ||
| cares about, but `check` also diffs the skill's *whole* capability surface separately. | ||
| A new capability that no fixture's `expectedToolCalls` happens to cover still shows | ||
| up as a `surfaceChanges` entry instead of passing silently. Confirmed against this | ||
| repo's own `case-04-scope-widened` fixture, where a `fs.write` scope widens from | ||
| `./workspace/**` to `./**`. | ||
| evolveguard detects changes in what a skill is _declared or shown_ to be capable of. It | ||
| can't tell you whether a live agent run would actually behave differently on a given | ||
| prompt -- that's a real, intentional scope limit. The tradeoff: it just needs a | ||
| `SKILL.md` file and a fixtures file, with nothing hosted and no SDK to integrate against, | ||
| which is also why it runs fully offline in a pre-commit hook or CI job. | ||
| **0% false positives on a labeled corpus, reproducibly.** `npx vitest run | ||
| src/evolveguard/benchmark.test.ts` runs the record/check/diff pipeline against | ||
| `fixtures/labeled-non-breaking-edits/`: 2 cases hand-labeled non-breaking (a wording | ||
| tweak, a typo fix) and 3 labeled breaking (a new write capability, a widened scope, a | ||
| hook script gaining a network call). As of this commit, both non-breaking cases stay | ||
| clean: 0 of 2 flagged as drift. The corpus is small and grows as more real skill edits | ||
| get reported. | ||
| ## How it's different | ||
| **A path-traversal guard on hook scripts.** A skill's declared hook paths are resolved | ||
| and validated against that skill's own directory before being read, including a | ||
| symlink-escape re-check that runs after the lexical containment check passes | ||
| (`src/evolveguard/paths.ts` and `python/src/evolveguard/paths.py`). | ||
| **Braintrust** is a general LLM eval and observability platform. It is a strong choice | ||
| if you're already logging traces from a live agent and want statistical eval scoring | ||
| across runs, but it needs SDK integration and an eval-definition step per app. evolveguard | ||
| needs neither: point it at one `SKILL.md` file and a fixtures JSON, and it works. | ||
| **Every subcommand supports `--json`.** `record`, `check`, and `report` all take a | ||
| `--json` flag and return a stable `schemaVersion`-tagged structure, so a coding agent | ||
| can call any of them as a subprocess and parse the result directly. | ||
| **[agent-eval](https://github.com/RudrenduPaul/agent-eval)** (this same author's other | ||
| repo) answers a different, more general question: "did my agent's behavior change | ||
| between two versions I define," for any agent, framework-agnostic, requiring you to | ||
| stand up and run both versions yourself. evolveguard answers a narrower, structurally | ||
| different question, triggered directly by a file diff on `SKILL.md`/`MEMORY.md`: did | ||
| _this specific edit_ change the capability surface the baseline recorded. It parses the | ||
| skill artifact itself and never asks you to define or run anything live. | ||
| **Two independently maintained, format-compatible distributions.** The npm package | ||
| (TypeScript, repo root) and the PyPI package (Python, `python/`) parse the same | ||
| frontmatter schema and produce byte-compatible baseline and report JSON. A baseline | ||
| recorded with one CLI can be checked with the other; see | ||
| [docs/concepts.md](./docs/concepts.md#file-formats-and-cross-distribution-compatibility) | ||
| for the file-format details. | ||
| | | evolveguard | Braintrust | agent-eval | | ||
| | -------------- | -------------------------------------------- | ---------------------------------- | --------------------------------- | | ||
| | Setup | `record` + `check` against one file | SDK integration, eval definitions | Define and run two agent versions | | ||
| | Trigger | `SKILL.md`/`MEMORY.md` file diff | Manual eval run | Manual A/B run | | ||
| | Mechanism | Static capability-surface diff | Live-run trace scoring | Statistical behavior comparison | | ||
| | Hosted infra | None | Hosted platform | None | | ||
| | Live LLM calls | None | Yes (scores real runs) | Yes (runs both versions) | | ||
| | Best for | Self-edited Claude Agent Skills specifically | General LLM app eval/observability | Any agent, generic A/B regression | | ||
| evolveguard detects changes in what a skill is *declared or shown* to be capable of. | ||
| It does not run a live LLM agent or replay a real conversation transcript, so it | ||
| cannot tell you whether an agent would actually behave differently on a given prompt. | ||
| That is an intentional scope limit, and also why it needs nothing hosted and runs | ||
| fully offline in a pre-commit hook or CI job. | ||
@@ -145,3 +151,3 @@ ## Quickstart | ||
| `expectedToolCalls` is optional -- omit it and the fixture is treated as exercising the | ||
| `expectedToolCalls` is optional; omit it and the fixture is treated as exercising the | ||
| skill's entire capability surface. `scopeMatches` (a glob) narrows a tool to a specific | ||
@@ -152,3 +158,4 @@ filesystem scope, e.g. `{ "tool": "fs.write", "scopeMatches": "./workspace/**" }`. | ||
| Generated from the actual `--help` output of the built CLI. | ||
| Generated from the actual `--help` output of the installed CLI (verified against both | ||
| the npm and PyPI builds; flags and defaults are identical across distributions). | ||
@@ -258,2 +265,7 @@ <details> | ||
| Note: the npm build's `evolveguard --version` currently prints `0.1.0` even though the | ||
| published package is at a newer `package.json` version; the PyPI build reads its version | ||
| from installed package metadata and reports it correctly. Use the badges above, not | ||
| `--version`, if you need the exact currently-published version number of the npm package. | ||
| ## Agent-native usage | ||
@@ -286,4 +298,4 @@ | ||
| `evolveguard mcp` is documented but not implemented yet -- see the CLI reference above. | ||
| Until it ships, call `record`/`check`/`report --json` directly as a subprocess from your | ||
| `evolveguard mcp` is documented but not implemented yet, in either distribution. Until | ||
| it ships, call `record`/`check`/`report --json` directly as a subprocess from your | ||
| coding agent. | ||
@@ -293,6 +305,6 @@ | ||
| evolveguard also exports a programmatic API for the same pipeline, if you'd rather | ||
| integrate it into your own tooling than shell out to the CLI. Both distributions | ||
| expose the same functions and the same JSON-compatible file format -- a baseline | ||
| recorded with one CLI can be checked with the other (see | ||
| evolveguard also exports a programmatic API for the same pipeline, for teams who want | ||
| to integrate it into their own tooling instead of shelling out to the CLI. Both | ||
| distributions expose the same functions and the same JSON-compatible file format; a | ||
| baseline recorded with one CLI can be checked with the other (see | ||
| [docs/concepts.md](./docs/concepts.md#file-formats-and-cross-distribution-compatibility)). | ||
@@ -344,16 +356,26 @@ | ||
| ## False-positive rate | ||
| ## How it compares | ||
| No accuracy claim ships without the command that produced it. Run: | ||
| **Braintrust** is a general LLM eval and observability platform. It is a strong choice | ||
| if you are already logging traces from a live agent and want statistical eval scoring | ||
| across runs, but it needs SDK integration and an eval-definition step per app. | ||
| evolveguard needs neither: point it at one `SKILL.md` file and a fixtures JSON, and it | ||
| works. | ||
| ```bash | ||
| npx vitest run src/evolveguard/benchmark.test.ts | ||
| ``` | ||
| **[agent-eval](https://github.com/RudrenduPaul/agent-eval)** (this same author's other | ||
| repo) answers a different question: whether an agent's behavior changed between two | ||
| versions you define, for any agent, framework-agnostic, by running both versions | ||
| yourself and computing a p-value on the difference. evolveguard is triggered directly | ||
| by a file diff on `SKILL.md`/`MEMORY.md` and answers whether *this specific edit* | ||
| changed the capability surface a baseline recorded. It parses the skill artifact | ||
| itself and never asks you to define or run anything live. | ||
| against `fixtures/labeled-non-breaking-edits/` -- a small, hand-labeled corpus of real | ||
| before/after `SKILL.md` pairs (wording tweaks and typo fixes labeled non-breaking; a | ||
| filesystem-scope widen, a new write capability, and a hook script gaining a network call | ||
| labeled breaking). As of this commit: **0% false positives** (0 of 2 non-breaking cases | ||
| flagged as drift). The corpus is small and will grow as more real skill edits are | ||
| reported; see `fixtures/labeled-non-breaking-edits/README.md`. | ||
| | | evolveguard | Braintrust | agent-eval | | ||
| | -------------- | --------------------------------------------- | ----------------------------------- | ----------------------------------- | | ||
| | Setup | `record` + `check` against one file | SDK integration, eval definitions | Define and run two agent versions | | ||
| | Trigger | `SKILL.md`/`MEMORY.md` file diff | Manual eval run | Manual A/B run | | ||
| | Mechanism | Static capability-surface diff | Live-run trace scoring | Statistical behavior comparison (p-value) | | ||
| | Hosted infra | None | Hosted platform | None | | ||
| | Live LLM calls | None | Yes (scores real runs) | Yes (runs both versions) | | ||
| | Best for | Self-edited Claude Agent Skills specifically | General LLM app eval/observability | Any agent, generic A/B regression | | ||
@@ -378,3 +400,3 @@ ## What is evolveguard, and why does it exist | ||
| - **PyPI (`evolveguard-cli`, Python)** -- live at | ||
| - **PyPI (`evolveguard-cli`, Python)**, live at | ||
| [pypi.org/project/evolveguard-cli](https://pypi.org/project/evolveguard-cli/). A | ||
@@ -384,5 +406,5 @@ genuine independent port, not a wrapper around the Node binary (see | ||
| directly. The package was originally published under the name `evolveguard`; that | ||
| older PyPI project is retired and no longer receives updates -- install | ||
| older PyPI project is retired and no longer receives updates, install | ||
| `evolveguard-cli` instead. | ||
| - **npm (`evolveguard-cli`, TypeScript)** -- live at | ||
| - **npm (`evolveguard-cli`, TypeScript)**, live at | ||
| [npmjs.com/package/evolveguard-cli](https://www.npmjs.com/package/evolveguard-cli). | ||
@@ -399,3 +421,3 @@ `npm install -g evolveguard-cli` installs it directly. Renamed 2026-07-19 from the | ||
| edited. It is not a self-evolving agent framework and does not build, run, or host | ||
| agents itself -- it is a regression-testing CI gate that reacts to a file diff on a | ||
| agents itself. It is a regression-testing CI gate that reacts to a file diff on a | ||
| skill artifact that already changed, by a human or an agent. See "What is evolveguard, | ||
@@ -405,3 +427,4 @@ and why does it exist" above for the full definition. | ||
| **Does evolveguard call an LLM?** | ||
| No. Record and check are both fully static and deterministic -- see "How it works" above. | ||
| No. Record and check are both fully static and deterministic; see "Features" above for | ||
| exactly what each command parses and scans. | ||
@@ -411,16 +434,16 @@ **What's the core differentiator versus a general testing or eval tool?** | ||
| fixtures JSON, and `record`/`check` work immediately, with zero SDK integration and no | ||
| live agent run. That is the tradeoff the "How it's different" table above documents -- | ||
| live agent run. That is the tradeoff the "How it compares" table above documents: | ||
| narrower scope than a general eval platform, in exchange for zero setup. | ||
| **How does evolveguard compare to Braintrust?** | ||
| Braintrust is a general LLM eval and observability platform: it needs SDK integration | ||
| Braintrust is a general LLM eval and observability platform that needs SDK integration | ||
| and an eval-definition step, and it scores real traces from a live agent run. | ||
| evolveguard needs neither -- it parses the skill file itself and never calls an LLM. Use | ||
| Braintrust if you're already logging traces and want statistical eval scoring across | ||
| runs; use evolveguard if you want a pre-commit or CI check that a `SKILL.md`/`MEMORY.md` | ||
| edit didn't silently widen what the skill can do. See the comparison table in "How it's | ||
| different" above for the full breakdown, including how it compares to this same | ||
| author's [agent-eval](https://github.com/RudrenduPaul/agent-eval). | ||
| evolveguard needs neither; it parses the skill file itself and never calls an LLM. Use | ||
| Braintrust if you are already logging traces and want statistical eval scoring across | ||
| runs. Use evolveguard if you want a pre-commit or CI check that a `SKILL.md`/`MEMORY.md` | ||
| edit did not silently widen what the skill can do. See the comparison table in "How it | ||
| compares" above for the full breakdown, including how it compares to this same author's | ||
| [agent-eval](https://github.com/RudrenduPaul/agent-eval). | ||
| **Does it work with MEMORY.md files, which have no frontmatter?** | ||
| **Does it work with `MEMORY.md` files, which have no frontmatter?** | ||
| Yes. A file with no frontmatter is parsed with an empty declared scope, so its capability | ||
@@ -431,20 +454,22 @@ surface comes entirely from static evidence found in the body text. | ||
| The npm package requires Node.js >=20.12 (any OS Node supports) and installs with | ||
| `npm install -g evolveguard-cli`. The PyPI package requires Python >=3.9 and installs with | ||
| `pip install evolveguard-cli`; both distributions are pure-library/CLI packages with no | ||
| native bindings, so there is no OS-specific build step on either side. | ||
| `npm install -g evolveguard-cli`. The PyPI package requires Python >=3.9 and installs | ||
| with `pip install evolveguard-cli`. Both distributions are pure-library/CLI packages | ||
| with no native bindings, so there is no OS-specific build step on either side. | ||
| **What's a real limitation to know about before relying on this?** | ||
| It only sees _declared or shown_ capability, not runtime behavior -- a skill could pass | ||
| `check` and still behave differently on a given prompt in ways that don't touch its | ||
| capability surface. The false-positive benchmark (see "False-positive rate" above) is | ||
| also currently a small, hand-labeled corpus of 5 before/after pairs, not a large dataset, | ||
| so treat the 0% figure as a starting measurement, not a statistical guarantee. The | ||
| `mcp` subcommand is also documented but not implemented yet in either distribution. | ||
| It only sees *declared or shown* capability, not runtime behavior. A skill could pass | ||
| `check` and still behave differently on a given prompt in ways that do not touch its | ||
| capability surface. The false-positive benchmark (see "Features" above) is also | ||
| currently a small, hand-labeled corpus of 5 before/after pairs, not a large dataset, so | ||
| treat the 0% figure as a starting measurement, not a statistical guarantee. The `mcp` | ||
| subcommand is also documented but not implemented yet in either distribution, and the | ||
| npm build's `evolveguard --version` output currently lags the package's real published | ||
| version (see "CLI command reference" above). | ||
| **Is this a general agent-evolution framework?** | ||
| No. See "How it's different" above -- evolveguard deliberately does not build or host a | ||
| No. See "How it compares" above. evolveguard deliberately does not build or host a | ||
| self-evolving agent framework; it only tests skill/memory edits that already happened. | ||
| **Is evolveguard free to use, including commercially?** | ||
| Yes. It's MIT-licensed with no proprietary tier or paid version -- see | ||
| Yes. It is MIT-licensed with no proprietary tier or paid version; see | ||
| [LICENSE](LICENSE). You can use, modify, and redistribute it, including in commercial | ||
@@ -455,7 +480,11 @@ projects, under the standard MIT terms. | ||
| See [CONTRIBUTING.md](CONTRIBUTING.md). | ||
| See [CONTRIBUTING.md](CONTRIBUTING.md). Every change lands with tests in both | ||
| distributions; a change to the frontmatter schema, the capability-surface derivation, | ||
| or the diff verdict logic must be made in both `src/evolveguard/` (TypeScript) and | ||
| `python/src/evolveguard/` (Python), with equivalent coverage added to both suites. | ||
| ## Security | ||
| See [SECURITY.md](SECURITY.md). | ||
| See [SECURITY.md](SECURITY.md). evolveguard reads local files you point it at and | ||
| never executes any of them; it makes no network calls and does not run a live agent. | ||
@@ -462,0 +491,0 @@ ## License |
92581
2.2%478
6.46%