Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
b9fade7
release: 0.6.5
cleverhoods Oct 18, 2026
f68910e
expected-loads: the plugin's context x-ray can ask which instruction …
cleverhoods Oct 17, 2026
89656b6
expected-loads: an AGENTS.md that links to a CLAUDE.md Claude Code re…
cleverhoods Oct 17, 2026
2ed2d61
expected-loads: a user rule keeps its paths, links are found by path …
cleverhoods Oct 17, 2026
84e0bc1
expected-loads: your own ~/.claude files are listed and an empty file…
cleverhoods Oct 17, 2026
45c1636
expected-loads: a subdirectory rule keeps its paths filter, a file ho…
cleverhoods Oct 17, 2026
ecdafa5
mcp: the validate tool tells the agent which messages are announcemen…
cleverhoods Oct 18, 2026
effb6a1
expected-loads: each skipped AGENTS.md names the CLAUDE.md, .claude/C…
cleverhoods Oct 19, 2026
fd2a7cf
npm: a pinned npx or global npm install runs the version you name, ai…
cleverhoods Oct 20, 2026
97f1f09
npm: ails update prints one npm hint, the launch marker is read once …
cleverhoods Oct 20, 2026
587614b
expected-loads: the x-ray's event logs are private to you, removed af…
cleverhoods Oct 20, 2026
e002de8
expected-loads: an AGENTS.md that is a copy of a CLAUDE.md Claude Cod…
cleverhoods Oct 20, 2026
6972a15
expected-loads: an AGENTS.md is reported as a copy of a CLAUDE.md onl…
cleverhoods Oct 20, 2026
9e7c957
install: ails install checks each PATH folder's own files, so an ails…
cleverhoods Oct 20, 2026
eee2186
expected-loads: an AGENTS.md is reported as a CLAUDE.md's link or cop…
cleverhoods Oct 20, 2026
93b785d
expected-loads: a project CLAUDE.md that links to your own CLAUDE.md …
cleverhoods Oct 20, 2026
51224c8
unreleased: the x-ray changelog line names what leaves files out unde…
cleverhoods Oct 20, 2026
5ea0823
config: the server, tier, integer, text and CI settings are read in o…
cleverhoods Oct 20, 2026
e975c16
cli: programs start through one runner and environment variables are …
cleverhoods Oct 20, 2026
0013217
tests: the process floor also catches webbrowser, pty and asyncio sub…
cleverhoods Oct 20, 2026
fd031e6
npm: a first run through npx without uv installs uv and finishes the …
cleverhoods Oct 20, 2026
334996e
npm: the launcher leaves the engine's PATH as given, writes install o…
cleverhoods Oct 20, 2026
b572a29
unreleased: one copy each of the npx install line and the linked CLAU…
cleverhoods Oct 20, 2026
3bd0236
check: a left-out folder is a folder name or a path from the project …
cleverhoods Oct 21, 2026
d4aca88
MCP: a new prepare tool maps a project's instruction files without ch…
cleverhoods Oct 21, 2026
1cbc84b
tests: the event-log file-mode tests and the linked-AGENTS.md test ru…
cleverhoods Oct 22, 2026
d660fa5
MCP prepare: detects the project's files afresh on each call, so a fi…
cleverhoods Oct 22, 2026
dfb36d9
release: 0.6.5 changelog, UNRELEASED reset
cleverhoods Oct 22, 2026
db8315c
tests: the event-log pruning test checks file modes on POSIX systems …
cleverhoods Oct 22, 2026
5d94111
release: 0.6.5 changelog, UNRELEASED reset after the Windows integrat…
cleverhoods Oct 22, 2026
7ec12c6
release: 0.6.5 changelog names the ails expected-loads command and th…
cleverhoods Oct 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ jobs:
- name: Type check
run: uv run poe type

- name: Test markers
run: uv run poe test_markers

- name: Rule lint
run: uv run poe test_lint

Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/post-publish-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,10 @@ jobs:
- name: Verify npx + smoke check
shell: bash
run: |
npx --yes "@reporails/cli@$VERSION" version
out="$(npx --yes "@reporails/cli@$VERSION" version | tr -d '\r')"
echo "$out"
echo "$out" | grep -qxF "CLI: $VERSION"
echo "$out" | grep -qxF "Install: npm"
mkdir -p smoke-project
cat > smoke-project/CLAUDE.md << 'FIXTURE'
# My Project
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/release-qa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ jobs:
if: matrix.os == 'ubuntu-latest'
run: uv run mypy --platform=win32 src/

- name: Test markers
run: uv run poe test_markers

- name: Rule lint
run: uv run poe test_lint

Expand Down
44 changes: 44 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,49 @@
# Changelog

## 0.6.5

### Added

- MCP: a new `prepare` tool maps a project's instruction files without checking them, so the next `validate` returns sooner. It sees files added or removed since its last call.
- `ails expected-loads` names which instruction files Claude Code should load in a project and why an AGENTS.md is skipped; an AGENTS.md that links to, or is a copy with exactly the same text of, a CLAUDE.md that loads wherever the AGENTS.md would, is reported as that file rather than as skipped; your own `~/.claude/CLAUDE.md` and `~/.claude/rules/` files are listed; a project CLAUDE.md that links to your own `~/.claude/CLAUDE.md` is listed as the project's own file; under `managed-only` it leaves out exactly the files Claude Code leaves out at launch; an empty file, or one holding only frontmatter, which Claude Code sends nothing for, is not expected to load.

### Changed

- A global npm install stays on its version until you update it; `ails version` shows `npm` for an install from the npm package (npx included) and `ails update` prints the command that updates it.
- A run through the npm package no longer re-checks the package index for a newer release every time it starts.
- Event logs in `~/.reporails/xray/` are private to you, removed after 30 days (sooner if Claude Code is set to keep sessions for less), and the folder stays under 100 MB.
- `ails expected-loads` names, for each AGENTS.md Claude Code skips, the `CLAUDE.md`, `.claude/CLAUDE.md` or `CLAUDE.local.md` that made it skip the file.
- The MCP `validate` tool now tells the agent which messages are announcements from reporails, so it shows them as announcements rather than as account messages.
- A folder value in `--exclude-dirs` or `exclude_dirs` that holds `*`, `?`, a backslash or a `..` step stops the run with an error that names the flag or the config file it came from and points to `--exclude-files` / `exclude_files` for file patterns; such a value used to be listed as left out while leaving nothing out. `ails config set exclude_dirs` refuses it before writing, with an error that names the setting, and the MCP tools answer `config_unreadable`.

### Fixed

- A first run through `npx` on a machine without `uv` installs `uv` and finishes your command, instead of stopping to ask you to restart your shell. The install messages go to stderr, so the command's own output, such as `-f json`, stays clean.
- `ails install` run through npx, `pnpm dlx` or `bunx`, or from a project's own dependency, puts `ails` on your PATH instead of reporting that copy as already installed.
- On Windows, `ails install` no longer counts an `ails` in the current folder or in uv's cache as installed, and an empty PATHEXT no longer hides an installed `ails`.
- `ails update` reports a uv run that cannot start or times out, instead of crashing.
- A project's CLAUDE.md that a subfolder's CLAUDE.md links to is listed and checked as the project's main file, not as that subfolder's file.
- A pinned `npx @reporails/cli@X.Y.Z` or `npm install -g @reporails/cli@X.Y.Z` runs that version; a bare `npx @reporails/cli` runs the latest release unless a copy is installed globally or in the project.
- `ails check` honours Claude Code's Project instructions setting saved under the plugin ID Claude Code has used since 2.1.285 (`cc-plugin-agents-md@builtin`), as well as the older `agents-md@builtin`.
- A rules file in a subdirectory's `.claude/rules/` folder is checked as loading on demand, as Claude Code loads it, rather than at session start.
- A space before the address in `AILS_SERVER_URL` no longer stops `ails check` from reaching that server.
- `--exclude-dirs` and `exclude_dirs` read a value with a `/` as a folder path from the project root: `/docs`, `./docs`, `docs/.` and an absolute path inside the project leave out the root's `docs` folder, where `/docs` and an absolute path used to leave out nothing and `./docs` every `docs` folder. The `Excluded` line lists such a folder as `./docs`. Folder names holding `[` and `]`, such as `[slug]`, can be left out.
- A folder you leave out by path is skipped during the scan, as a folder name is, so a large left-out folder costs no scan time, and an agent whose files sit only inside a folder left out in `exclude_dirs` is not detected. The scan does not enter a left-out folder through a symlink, or on Windows a junction, that points inside it either.
- The skill entry-point check no longer reports a skill folder you left out.
- On a run that names a file and also checks a folder or a capability listing, the `Excluded` line keeps a folder or pattern the named file sits in.
- `ails check --agent <name>` no longer checks another agent's file that you named inside a left-out folder.
- A run with no findings no longer says the score covers the rest of the project, since it shows no score.
- With `generic_scanning: true`, a failure while reading the files your instruction files import or link is logged as a warning instead of silently checking none of them.
- The over-cap message never suggests leaving out a folder whose name `--exclude-dirs` would refuse, and on Pro its lines end with a full stop.

### Internal

- A build check fails when a fixed set of named values is spelled out as plain text in another list or table instead of using the names; the one place that did it, the capability-level table, now uses the names.
- Build checks fail when the environment is read, or a program is started, outside the one place that owns it.
- The event-log file-mode tests and the linked-AGENTS.md test run on POSIX systems only.
- The event-log pruning test checks file modes on POSIX systems only.
- Every build check, not only the quick local one, fails on a test that is marked as more than one kind of test or as none.

## 0.6.4

### Changed
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Reporails CLI (v0.6.4)
# Reporails CLI (v0.6.5)

> **AI Instruction Diagnostics for coding agents. Validates the entire agentic instruction system against 120+ rules across six rule packs (core + per-agent). Supports Antigravity, Claude, Codex, Copilot, and Cursor.**
>
Expand Down Expand Up @@ -99,7 +99,7 @@ Full breakdown: [Tiers and Limits](https://github.com/reporails/cli/blob/main/do
Run on every PR so instruction-quality regressions (vague or buried instructions, oversized files, weak reinforcement, instructions repeated across files) get caught the same way test or lint regressions do — before merge, not after a teammate's agent has been silently misbehaving for a week.

```yaml
- uses: reporails/cli/action@0.6.4
- uses: reporails/cli/action@0.6.5
with:
api-key: ${{ secrets.REPORAILS_API_KEY }} # optional - a Pro key unlocks the full diagnostic detail
strict: "true" # exit 1 if any rule fires
Expand Down
2 changes: 1 addition & 1 deletion docs/agent-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ A skill's supporting markdown files (`reference.md`, `examples/*.md`, anything b

## Plugin support

Recognition (above) is what `ails check` **scans**. The reporails **plugin** is how each agent **runs** the remedy loop: it delivers the `ails` skill and the reporails MCP server as a portable [Agent Plugins](https://agent-plugins.org) package. Agents that consume the portable form need no wrapper; the rest carry a thin native manifest. Installing the plugin registers the MCP server (`validate` / `remedy_brief` / `preflight` / `explain`) and loads the `ails` skill — one skill, maintained once, across all five.
Recognition (above) is what `ails check` **scans**. The reporails **plugin** is how each agent **runs** the remedy loop: it delivers the `ails` skill and the reporails MCP server as a portable [Agent Plugins](https://agent-plugins.org) package. Agents that consume the portable form need no wrapper; the rest carry a thin native manifest. Installing the plugin registers the MCP server (`validate` / `prepare` / `remedy_brief` / `preflight` / `explain`) and loads the `ails` skill — one skill, maintained once, across all five.

Install it in your agent:

Expand Down
16 changes: 12 additions & 4 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Lives at the root of your repo.

```yaml
default_agent: claude # Which agent's rules to run by default
exclude_dirs: [examples] # Extra directory names to skip during discovery (added to the built-in defaults below)
exclude_dirs: [examples] # Extra folders to skip during discovery: a name, or a path from the project root (added to the built-in defaults below)
disabled_rules: [CORE:C:0010] # Rule IDs to disable entirely
heal_exclude: ["archive/**"] # Files that are still checked and scored, but that heal never rewrites
```
Expand Down Expand Up @@ -123,7 +123,7 @@ steps:
- run: ails check
```

Install a pinned version as shown (or `uvx --from "reporails-cli==<version>" ails check` where `uv` is set up). `npx @reporails/cli` always runs the latest CLI whatever version you give it, so it cannot be pinned for this key. `actions/cache` saves only when the job succeeds: a job that fails on `ails check --strict` findings saves nothing, and the next run downloads the model again. The GitHub Action keeps the model even when the check fails.
Install a pinned version as shown (or `uvx --from "reporails-cli==<version>" ails check` where `uv` is set up). A pinned `npx @reporails/cli@<version>` or `npm install -g @reporails/cli@<version>` runs exactly that version from 0.6.5 on (earlier npm releases ran the latest release whatever version was named), so it can key the cache too; a bare `npx @reporails/cli` runs the latest release unless a copy is installed globally or in the project, where npx runs that copy. `actions/cache` saves only when the job succeeds: a job that fails on `ails check --strict` findings saves nothing, and the next run downloads the model again. The GitHub Action keeps the model even when the check fails.

When `ails` downloads the model inside GitHub Actions, it prints a line pointing to this section.

Expand Down Expand Up @@ -174,7 +174,15 @@ Use the rule ID shown next to the finding in `ails check` output (e.g. `CORE:C:0

## Excluding directories

`exclude_dirs` is a list of directory *names* (not paths). Any directory matching one of these names is skipped no matter where it appears. The setting exists because the discovery walk scans every directory looking for instruction files — without an exclude list it would descend into vendored trees (`node_modules`, `vendor/`), build output (`dist/`, `target/`), and data dumps (`data/`), surfacing third-party `CLAUDE.md` / `AGENTS.md` files you didn't author and slowing the scan.
`exclude_dirs` is a list of folders, each written as a folder name or a folder path:

- A value without a `/` (`examples`) is a folder *name*: every folder with that name is skipped, no matter where it appears.
- A value with a `/` (`.claude/rules`, `./docs`, `/docs`, `docs/.`) is a folder *path* from the project root: only that folder is skipped. `./docs` and `/docs` both mean the `docs` folder at the root, not a `docs` folder deeper down.
- A trailing `/` is ignored, so `docs/` is the name `docs`. An absolute path inside the project is read from the project root.
- `[` and `]` are ordinary characters, so `[slug]` and `app/[id]` name those folders.
- A value holding `*`, `?`, a backslash or a `..` step is not a folder and stops the run with an error that names where the value came from. For file patterns use `exclude_files` / `--exclude-files` (below).

The scan does not go into a folder you leave out, whether you gave it as a name or as a path, nor into a symlink that points inside one. The one exception is a left-out folder that holds a file you name on the command line: the scan enters it so that file can be checked, and everything else in it stays left out. The setting exists because the discovery walk scans every directory looking for instruction files — without an exclude list it would descend into vendored trees (`node_modules`, `vendor/`), build output (`dist/`, `target/`), and data dumps (`data/`), surfacing third-party `CLAUDE.md` / `AGENTS.md` files you didn't author and slowing the scan.

The [built-in list above](#built-in-directory-excludes) already covers the common cases. Add to `exclude_dirs` only when your project has a non-standard tree:

Expand Down Expand Up @@ -467,7 +475,7 @@ Always present, regardless of tier: `offline`, `server_error`, `tier`, `quality`

`not_evaluated` lists the checks that did not finish on a file, as `{rule, file}`; it is `[]` when every check finished. A check that runs out of time on a very large file reports no finding for that file rather than a guess, so a rule named here was neither passed nor failed there. Text output names them in one line per file under the results.

`excluded` lists what you left out of the run, as `{dirs, files, imported_text_counted}`. `dirs` and `files` are the patterns you pass on the command line (`--exclude-dirs`, `--exclude-files`) joined with `exclude_dirs` and `exclude_files` from your config, sorted and without repeats; neither replaces the other. Both are `[]` when you excluded nothing, and the folders skipped by default (such as `node_modules`) are not listed. A folder name matches that folder at any depth; a value with a `/` (`.claude/rules`) is a folder path from the project root; a trailing `/` is ignored. A file or capability you name on the command line is checked even inside a left-out folder. On a run narrowed to named targets, the patterns a named target matches are not listed, and a run of a single file lists none. `imported_text_counted` is `true` when text a checked file imports with `@path` comes from a left-out file (that text still counts inside the importing file), and `false` otherwise. When `dirs` or `files` is non-empty, the score covers only the rest of the project.
`excluded` lists what you left out of the run, as `{dirs, files, imported_text_counted}`. `dirs` and `files` are the patterns you pass on the command line (`--exclude-dirs`, `--exclude-files`) joined with `exclude_dirs` and `exclude_files` from your config, sorted and without repeats; neither replaces the other. Both are `[]` when you excluded nothing, and the folders skipped by default (such as `node_modules`) are not listed. A folder name matches that folder at any depth; a value with a `/` (`.claude/rules`) is a folder path from the project root and is listed that way, with a single folder at the root listed as `./docs`; a trailing `/` is ignored. A file or capability you name on the command line is checked even inside a left-out folder. On a run whose targets are all named files, the patterns a named file matches are not listed; a run that also covers a folder or a capability listing lists them. A run of a single file lists none. `imported_text_counted` is `true` when text a checked file imports with `@path` comes from a left-out file (that text still counts inside the importing file), and `false` otherwise. When `dirs` or `files` is non-empty, the score covers only the rest of the project.

Two additive fields enrich the output when the analysis service has data for the run. Both are **additive and backward-compatible** — existing JSON consumers and CI baselines that ignore them keep working unchanged:

Expand Down
4 changes: 3 additions & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ uv tool install reporails-cli
npm install -g @reporails/cli
```

A global npm install stays on the version it installed; `ails update` prints the npm command that moves it to the latest release. A bare `npx @reporails/cli` runs the latest release unless a copy is installed globally or in the project, where npx runs that copy.

`ails install` then ensures the binary is on PATH. After it runs, `ails check` works from anywhere without the `npx` / `uvx` prefix.

**2. Add the reporails plugin to your agent.** The plugin carries the `ails` skill and the MCP server; installing it registers both in one step — no per-agent config editing. The per-agent install commands are listed in [Agent Support](agent-support.md#plugin-support); `ails install` runs them for Claude Code and Codex and prints the rest. Add `--project` to install the plugin for the current repository only, shared with collaborators (Codex installs for your user); `ails update` refreshes the plugin in each agent that has it. What the plugin needs to start is stated there. Without the plugin, `ails check` in your terminal scores your instruction files, and `--heal` applies fixes on a Pro account; rewriting them needs the plugin and Pro (`/reporails:ails heal` in Claude Code).
Expand Down Expand Up @@ -114,7 +116,7 @@ ails check --heal --cwd # with --heal: opt into rewriting the whole pro

`--heal` needs an explicit target — a path or a capability like `skills` — or `--cwd` to opt into rewriting the whole project; a bare `ails check --heal` exits with an error naming both options. It also needs a Pro account: run `ails login` with one. Without one (anonymous, or signed in on a free account) the run still prints the full diagnosis, then declines the fix pass with `Applying fixes needs a Pro account.` and applies nothing. See [Tiers and Limits](tiers.md).

The JSON output groups findings under `files{path: {findings: [...], count: N}}` plus aggregate `stats`, a `notices` list of messages about your account, and (when present) `cross_file` blocks — see [Configuration → Output format](configuration.md#output-format) for the full shape, including which fields are tier-conditional.
The JSON output groups findings under `files{path: {findings: [...], count: N}}` plus aggregate `stats`, a `notices` list of messages about your account and announcements from reporails, and (when present) `cross_file` blocks — see [Configuration → Output format](configuration.md#output-format) for the full shape, including which fields are tier-conditional.

## Focus on one file or capability

Expand Down
Loading
Loading