agentsmd-medic 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +305 -2
- package/bin/agentsmd-medic.js +12 -0
- package/dist/agents.d.ts +36 -0
- package/dist/agents.js +67 -0
- package/dist/agents.js.map +1 -0
- package/dist/cli.d.ts +16 -0
- package/dist/cli.js +248 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +12 -0
- package/dist/config.js +77 -0
- package/dist/config.js.map +1 -0
- package/dist/discover.d.ts +14 -0
- package/dist/discover.js +84 -0
- package/dist/discover.js.map +1 -0
- package/dist/doctor.d.ts +53 -0
- package/dist/doctor.js +486 -0
- package/dist/doctor.js.map +1 -0
- package/dist/format.d.ts +17 -0
- package/dist/format.js +113 -0
- package/dist/format.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/linter.d.ts +23 -0
- package/dist/linter.js +201 -0
- package/dist/linter.js.map +1 -0
- package/dist/markdown.d.ts +9 -0
- package/dist/markdown.js +88 -0
- package/dist/markdown.js.map +1 -0
- package/dist/rules/index.d.ts +3 -0
- package/dist/rules/index.js +21 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/links.d.ts +2 -0
- package/dist/rules/links.js +70 -0
- package/dist/rules/links.js.map +1 -0
- package/dist/rules/package-managers.d.ts +2 -0
- package/dist/rules/package-managers.js +76 -0
- package/dist/rules/package-managers.js.map +1 -0
- package/dist/rules/paths.d.ts +2 -0
- package/dist/rules/paths.js +86 -0
- package/dist/rules/paths.js.map +1 -0
- package/dist/rules/scripts.d.ts +2 -0
- package/dist/rules/scripts.js +249 -0
- package/dist/rules/scripts.js.map +1 -0
- package/dist/rules/secrets.d.ts +2 -0
- package/dist/rules/secrets.js +100 -0
- package/dist/rules/secrets.js.map +1 -0
- package/dist/rules/structure.d.ts +18 -0
- package/dist/rules/structure.js +151 -0
- package/dist/rules/structure.js.map +1 -0
- package/dist/rules/util.d.ts +16 -0
- package/dist/rules/util.js +63 -0
- package/dist/rules/util.js.map +1 -0
- package/dist/types.d.ts +80 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +67 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 weugit
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,306 @@
|
|
|
1
|
-
#
|
|
1
|
+
# agentsmd-medic
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Lint [AGENTS.md](https://agents.md) files: the instruction files AI coding agents read from a repository.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/weugit/agentsmd-medic/actions/workflows/ci.yml)
|
|
6
|
+
[](https://www.npmjs.com/package/agentsmd-medic)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
agentsmd-medic checks those instructions before an agent follows them. It flags empty files, broken links, paths and commands that are not in the repo, mixed package managers, unfinished placeholders, and credential-shaped strings. It is a TypeScript ESM CLI with no runtime dependencies.
|
|
10
|
+
|
|
11
|
+
The npm package is not published yet. See [Install](#install).
|
|
12
|
+
|
|
13
|
+
## Why
|
|
14
|
+
|
|
15
|
+
[AGENTS.md](https://agents.md) is the open format read by OpenAI Codex, Cursor, GitHub Copilot, and others. Codex merges `AGENTS.md` files from the repository root down to the working directory. A closer file takes precedence. `AGENTS.override.md` overrides. Project docs are capped at 32 KiB by default via `project_doc_max_bytes`.
|
|
16
|
+
|
|
17
|
+
Stale paths, stale commands, leaked secrets, and contradictions do not fail the agent run. They silently degrade what the agent does. This linter checks the files on your machine and prints a report. It does not upload them.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
After the package is on npm:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx agentsmd-medic
|
|
25
|
+
npm install -D agentsmd-medic
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
It is not published yet. Until then, clone the repository and run the built CLI:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git clone https://github.com/weugit/agentsmd-medic.git
|
|
32
|
+
cd agentsmd-medic
|
|
33
|
+
npm ci && npm run build && node bin/agentsmd-medic.js
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Node.js 20 or newer is required.
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
agentsmd-medic [options] [path...]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
A path that is a file is linted directly. A path that is a directory is searched recursively for `AGENTS.md` and `AGENTS.override.md`. The default path is `.`.
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
agentsmd-medic doctor [options] [dir]
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`doctor` reports which instruction files each agent actually loads for `dir` (default: the working directory). It walks from that directory up to the git root: the nearest ancestor that contains `.git`, or `dir` itself when there is none. Home-directory files (`~/.codex`, `~/.claude`, and similar) are not scanned. The first positional argument `doctor` selects the subcommand. A path such as `./doctor` is still linted.
|
|
51
|
+
|
|
52
|
+
| Agent | What doctor reports |
|
|
53
|
+
| --- | --- |
|
|
54
|
+
| OpenAI Codex | For each directory from the git root down to `dir`, `AGENTS.override.md` if it is present, otherwise `AGENTS.md`. Files are concatenated from the root toward the leaf. The report notes the default 32 KiB cap (`project_doc_max_bytes`) and warns when the combined size exceeds it. |
|
|
55
|
+
| Claude Code | `CLAUDE.md` and `CLAUDE.local.md` on that path. Claude Code does not read `AGENTS.md` unless a `CLAUDE.md` imports it with an `@AGENTS.md`, `@./AGENTS.md`, or other relative `@` path. The report warns `AGENTS.md is ignored by Claude Code: no CLAUDE.md imports it` when `AGENTS.md` exists and no `CLAUDE.md` imports it, including when there is no `CLAUDE.md` at all. `CLAUDE.local.md` is called out as personal, git-ignored, and able to override shared instructions. |
|
|
56
|
+
| Cursor | `AGENTS.md` at the root and in nested directories, `.cursor/rules/*.mdc`, and legacy `.cursorrules` (deprecated). |
|
|
57
|
+
| GitHub Copilot | `.github/copilot-instructions.md`, `.github/instructions/*.instructions.md`, and `AGENTS.md`. |
|
|
58
|
+
| Gemini CLI | `GEMINI.md` by default. `AGENTS.md` only when `context.fileName` includes it. The report warns when only `AGENTS.md` exists. |
|
|
59
|
+
|
|
60
|
+
Text output is grouped per agent and uses `✔` and `⚠` markers. `--color` and `--no-color` apply the same way as for lint output. `--json` (or `--format json`) prints a versioned document (`version`, `command`, `directory`, `root`, and one entry per agent with `files`, `notes`, and `warnings`). `--format github` is a usage error. `doctor` exits 0 when the directory can be read, including when the report contains warnings. A missing path, a file path, or more than one directory exits 2.
|
|
61
|
+
|
|
62
|
+
Behaviors change as agents ship updates. The snapshot and the doc links live in `src/agents.ts`.
|
|
63
|
+
|
|
64
|
+
| Flag | Meaning |
|
|
65
|
+
| --- | --- |
|
|
66
|
+
| `-c, --config <file>` | Config file. When omitted, the working directory is searched for `.agentsmd-medic.json`, then `agentsmd-medic.config.json`. |
|
|
67
|
+
| `--format <format>` | `text` (default), `json`, or `github`. |
|
|
68
|
+
| `--json` | Alias for `--format json`. When both are set, the last one wins. |
|
|
69
|
+
| `--max-warnings <n>` | Exit 1 when the warning count is greater than `<n>`. `<n>` is an integer ≥ 0. Without this flag, warnings do not change the exit code. |
|
|
70
|
+
| `--color` | Force colored text output. |
|
|
71
|
+
| `--no-color` | Disable colored text output. |
|
|
72
|
+
| `-q, --quiet` | Hide warnings in text output. Hidden warnings are left out of the summary. They still count toward the exit code. |
|
|
73
|
+
| `--list-rules` | Print each rule id, its default severity, and its description, then exit. |
|
|
74
|
+
| `-h, --help` | Show help and exit. |
|
|
75
|
+
| `-v, --version` | Show the version number and exit. |
|
|
76
|
+
|
|
77
|
+
Color defaults to on when stdout is a TTY and `NO_COLOR` is unset. `--color` and `--no-color` override that, and the last one wins. Color applies to text output only.
|
|
78
|
+
|
|
79
|
+
`--format github` prints one [GitHub Actions workflow command](https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions) per diagnostic (`::error` or `::warning` with `file`, `line`, `col`, and `title`). `--format json` prints a versioned document (`version`, `root`, counts, and per-file diagnostics) for editors and scripts.
|
|
80
|
+
|
|
81
|
+
### Exit codes
|
|
82
|
+
|
|
83
|
+
| Code | Meaning |
|
|
84
|
+
| --- | --- |
|
|
85
|
+
| 0 | No errors, and warnings do not exceed `--max-warnings`. `doctor` exits 0 when the directory can be read, including when the report contains warnings. |
|
|
86
|
+
| 1 | One or more errors, or more warnings than `--max-warnings`. |
|
|
87
|
+
| 2 | Usage error, invalid config, or a path that does not exist. The message is written to stderr and prefixed with `agentsmd-medic: `. |
|
|
88
|
+
|
|
89
|
+
## Example output
|
|
90
|
+
|
|
91
|
+
This report is the real output of `node bin/agentsmd-medic.js --no-color` in a temporary directory (exit code 1). The directory contained only the two files below.
|
|
92
|
+
|
|
93
|
+
`package.json`:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"name": "example",
|
|
98
|
+
"private": true,
|
|
99
|
+
"scripts": {
|
|
100
|
+
"test": "node --test"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`AGENTS.md`:
|
|
106
|
+
|
|
107
|
+
```md
|
|
108
|
+
# Project notes
|
|
109
|
+
|
|
110
|
+
Install dependencies with `npm run compile`, then start `pnpm dev`.
|
|
111
|
+
|
|
112
|
+
The schema is in `src/schema.ts`.
|
|
113
|
+
|
|
114
|
+
Read [the missing guide](docs/guide.md) and jump to [Setup](#setup).
|
|
115
|
+
|
|
116
|
+
## Tasks
|
|
117
|
+
|
|
118
|
+
## Tasks
|
|
119
|
+
|
|
120
|
+
TODO: describe the tasks.
|
|
121
|
+
|
|
122
|
+
api_key: "correcthorsebatterystaple"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
AGENTS.md
|
|
127
|
+
3:28 warning Script `compile` is not defined in package.json. no-missing-scripts
|
|
128
|
+
3:58 warning Instructions mix npm and pnpm; agents may run the wrong one. consistent-package-manager
|
|
129
|
+
3:58 warning Script `dev` is not defined in package.json. no-missing-scripts
|
|
130
|
+
5:19 warning Referenced path `src/schema.ts` does not exist no-missing-paths
|
|
131
|
+
7:6 error Broken link: "docs/guide.md" (resolved to docs/guide.md) does not exist. no-broken-links
|
|
132
|
+
7:53 error Anchor "#setup" does not match any heading in this file. no-broken-links
|
|
133
|
+
9:1 warning Section "Tasks" is empty. no-empty-section
|
|
134
|
+
11:1 warning Duplicate heading "Tasks" (first defined on line 9); merge the sections to avoid conflicting instructions. no-duplicate-heading
|
|
135
|
+
13:1 warning Placeholder text "TODO" found; agents may follow it literally. no-placeholder
|
|
136
|
+
15:1 error Possible API key found ("corr…"); remove it and rotate the credential. no-secrets
|
|
137
|
+
|
|
138
|
+
✖ 10 problems (3 errors, 7 warnings)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Rules
|
|
142
|
+
|
|
143
|
+
Default severities come from the rule objects in `src/rules/`. Override them in config with `error`, `warn`, or `off`.
|
|
144
|
+
|
|
145
|
+
| Rule | Default | Description |
|
|
146
|
+
| --- | --- | --- |
|
|
147
|
+
| `no-empty-file` | error | The file must contain some instructions. |
|
|
148
|
+
| `require-heading` | warn | Use at least one Markdown heading so agents (and humans) can navigate sections. |
|
|
149
|
+
| `max-size` | warn | Keep the file within the size agents actually read, using a CJK-aware token estimate. |
|
|
150
|
+
| `no-empty-section` | warn | Headings should be followed by content before the next heading of the same or higher level. |
|
|
151
|
+
| `no-duplicate-heading` | warn | Sibling sections should not share a heading; duplicated sections often carry conflicting instructions. |
|
|
152
|
+
| `no-placeholder` | warn | Flag unfinished placeholder text (TODO, TBD, lorem ipsum, <insert ...>). |
|
|
153
|
+
| `no-broken-links` | error | Relative links and in-page anchors must resolve. |
|
|
154
|
+
| `no-missing-paths` | warn | File paths in inline code should exist in the repository. |
|
|
155
|
+
| `no-missing-scripts` | warn | Package scripts and Make targets mentioned in commands should exist. |
|
|
156
|
+
| `no-secrets` | error | Instruction files must not embed credentials or secret tokens. |
|
|
157
|
+
| `consistent-package-manager` | warn | Commands should use one package manager, the one the repository locks. |
|
|
158
|
+
|
|
159
|
+
`no-broken-links` checks relative links and in-page anchors. External URLs are left alone. `no-missing-paths` checks inline code that looks like a repository path. `no-missing-scripts` checks `npm run` scripts (and `pnpm` / `yarn` / `bun` script invocations) against the nearest `package.json`, and `make` targets against a Makefile. `no-secrets` reports a short prefix of a match and asks you to rotate the credential. `max-size` compares UTF-8 bytes with `maxBytes` (default 32768) and a token estimate with `maxTokens` (default 8000). Each Han, Hiragana, Katakana, Hangul, and fullwidth character counts as one token. Other text counts as characters / 4. When those characters are more than 20% of the non-whitespace characters and the file exceeds `maxBytes`, the message notes that CJK text uses 3 bytes per character in UTF-8 and reaches the 32 KiB cap with ~11k characters.
|
|
160
|
+
|
|
161
|
+
Discovery always skips these directory names: `.git`, `node_modules`, `.hg`, `.svn`, `dist`, `build`, `coverage`, `.next`, `.turbo`, `vendor`, `.venv`, `venv`, `__pycache__`, and `target`.
|
|
162
|
+
|
|
163
|
+
## Configuration
|
|
164
|
+
|
|
165
|
+
Put one of these files in the working directory. The first match wins:
|
|
166
|
+
|
|
167
|
+
1. `.agentsmd-medic.json`
|
|
168
|
+
2. `agentsmd-medic.config.json`
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"rules": {
|
|
173
|
+
"no-secrets": "error",
|
|
174
|
+
"max-size": "warn",
|
|
175
|
+
"no-placeholder": "off"
|
|
176
|
+
},
|
|
177
|
+
"ignore": ["fixtures", "docs/drafts"],
|
|
178
|
+
"maxBytes": 32768,
|
|
179
|
+
"maxTokens": 8000
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
| Field | Meaning |
|
|
184
|
+
| --- | --- |
|
|
185
|
+
| `rules` | Map of rule id to `error`, `warn`, or `off`. Unknown ids are a usage error (exit 2). |
|
|
186
|
+
| `ignore` | Directory names or path prefixes, relative to the lint root, to skip while searching. A value without a slash matches any path segment. A value with a slash matches that path or anything under it. |
|
|
187
|
+
| `maxBytes` | Soft size limit in bytes. Default `32768` (32 KiB). Must be a positive number. |
|
|
188
|
+
| `maxTokens` | Soft token budget. CJK and fullwidth characters count as one token; other text is characters / 4. Default `8000`. Must be a positive number. |
|
|
189
|
+
|
|
190
|
+
Pass `-c` / `--config` to use a different file. If that path cannot be read, the CLI exits 2.
|
|
191
|
+
|
|
192
|
+
### Inline disable comments
|
|
193
|
+
|
|
194
|
+
In an `AGENTS.md` file:
|
|
195
|
+
|
|
196
|
+
```text
|
|
197
|
+
<!-- agentsmd-medic-disable -->
|
|
198
|
+
<!-- agentsmd-medic-disable rule-a, rule-b -->
|
|
199
|
+
<!-- agentsmd-medic-disable-next-line -->
|
|
200
|
+
<!-- agentsmd-medic-disable-next-line rule-a, rule-b -->
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
`agentsmd-medic-disable` disables every rule, or the named rules, for the whole file. `agentsmd-medic-disable-next-line` does the same for the next non-blank line. Comments inside fenced code blocks are not treated as directives, so an example in a fence does not silence a real finding.
|
|
204
|
+
|
|
205
|
+
## Use in CI
|
|
206
|
+
|
|
207
|
+
The composite action in this repository checks out its own source, installs it, builds it, and lints the caller workspace. Pin `v0` after the first release. That tag is force-moved onto each 0.x release. Leaving `version` empty (the default) builds the action's checked-out source, so the action does not need the npm package.
|
|
208
|
+
|
|
209
|
+
```yaml
|
|
210
|
+
name: AGENTS.md
|
|
211
|
+
on: [push, pull_request]
|
|
212
|
+
permissions:
|
|
213
|
+
contents: read
|
|
214
|
+
jobs:
|
|
215
|
+
agentsmd:
|
|
216
|
+
runs-on: ubuntu-latest
|
|
217
|
+
steps:
|
|
218
|
+
- uses: actions/checkout@v4
|
|
219
|
+
- uses: weugit/agentsmd-medic@v0
|
|
220
|
+
with:
|
|
221
|
+
path: .
|
|
222
|
+
# config: .agentsmd-medic.json
|
|
223
|
+
# max-warnings: "0" # -1, the default, does not fail on warnings
|
|
224
|
+
format: github
|
|
225
|
+
# version: "0.1.0" # empty builds the checked-out action source
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
| Input | Default | Meaning |
|
|
229
|
+
| --- | --- | --- |
|
|
230
|
+
| `path` | `.` | File or directory to lint. |
|
|
231
|
+
| `config` | empty | Config file. Empty uses the default search. |
|
|
232
|
+
| `max-warnings` | `-1` | Fail when warnings exceed this integer. `-1` means unlimited. |
|
|
233
|
+
| `format` | `github` | `text`, `json`, or `github`. |
|
|
234
|
+
| `version` | empty | npm version to run. Empty builds the action source. |
|
|
235
|
+
|
|
236
|
+
The same check after the package is published, without the action:
|
|
237
|
+
|
|
238
|
+
```yaml
|
|
239
|
+
- uses: actions/checkout@v4
|
|
240
|
+
- uses: actions/setup-node@v4
|
|
241
|
+
with:
|
|
242
|
+
node-version: 22
|
|
243
|
+
- run: npx agentsmd-medic --format github
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
`npx agentsmd-medic` works only once the package is on npm. Until then, use the action with an empty `version`, or the clone-and-build install above.
|
|
247
|
+
|
|
248
|
+
## Programmatic API
|
|
249
|
+
|
|
250
|
+
The package is ESM. Import it after `npm run build`, or from the published package once that exists. Types are in `dist/index.d.ts`.
|
|
251
|
+
|
|
252
|
+
```js
|
|
253
|
+
import { formatText, lint } from "agentsmd-medic";
|
|
254
|
+
|
|
255
|
+
const result = await lint({ cwd: process.cwd(), paths: ["."] });
|
|
256
|
+
process.stdout.write(formatText(result, { color: false }));
|
|
257
|
+
if (result.errorCount > 0) process.exitCode = 1;
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
| Export | Role |
|
|
261
|
+
| --- | --- |
|
|
262
|
+
| `lint({ cwd, paths?, configPath? })` | Load config, discover files, and return a `LintResult`. `configPath` is set on the result when a config file was read. Missing paths throw. Unknown rule ids throw `ConfigError`. |
|
|
263
|
+
| `lintFiles(files, root, config)` | Lint already-resolved files. |
|
|
264
|
+
| `lintText(source, { file, root, config })` | Lint one document from a string. Returns `Diagnostic[]`. |
|
|
265
|
+
| `formatText(result, { color?, quiet? })` | Text report. |
|
|
266
|
+
| `formatJson(result)` | JSON report (`version: 1`). |
|
|
267
|
+
| `formatGithub(result, cwd)` | GitHub Actions workflow commands. Paths are relative to `cwd`. |
|
|
268
|
+
| `loadConfig(root, explicitPath?)` | Returns `{ config, path? }`. |
|
|
269
|
+
| `DEFAULT_CONFIG` | `{ rules: {}, ignore: [], maxBytes: 32768, maxTokens: 8000 }`. |
|
|
270
|
+
| `CONFIG_FILE_NAMES` | `[".agentsmd-medic.json", "agentsmd-medic.config.json"]`. |
|
|
271
|
+
| `AGENT_FILE_NAMES` | `["AGENTS.md", "AGENTS.override.md"]`. |
|
|
272
|
+
| `findAgentFiles(root, ignore?)` | Recursive discovery. |
|
|
273
|
+
| `rules`, `ruleMap` | Built-in rules, in report order, and a map keyed by id. |
|
|
274
|
+
| `parseMarkdown(source)`, `slugify(text)` | The small Markdown scan the rules use. |
|
|
275
|
+
| `main(argv, io?)` | CLI entry. Resolves to exit code 0, 1, or 2. |
|
|
276
|
+
| `diagnose(dir, displayPath?)` | Build a doctor report for `dir`. |
|
|
277
|
+
| `formatDoctorText(report, { color? })` | Text doctor report. |
|
|
278
|
+
| `formatDoctorJson(report)` | JSON doctor report (`version: 1`, `command: "doctor"`). |
|
|
279
|
+
| `AGENTS` | Documented agent behaviors and documentation URLs. |
|
|
280
|
+
| `CODEX_PROJECT_DOC_MAX_BYTES` | Default Codex cap, `32768`. |
|
|
281
|
+
| `ConfigError` | Thrown for invalid config. |
|
|
282
|
+
| `DoctorUsageError` | Thrown when `doctor` is given a missing path or a file. |
|
|
283
|
+
|
|
284
|
+
Types exported from the package include `Severity`, `RuleSetting`, `Diagnostic`, `Config`, `Rule`, `RuleContext`, `LintResult`, and `FileResult`.
|
|
285
|
+
|
|
286
|
+
## Roadmap
|
|
287
|
+
|
|
288
|
+
`agentsmd-medic doctor` reports which instruction files Codex, Claude Code, Cursor, GitHub Copilot, and Gemini CLI load, including nested `AGENTS.md` files and `AGENTS.override.md`. See [Usage](#usage).
|
|
289
|
+
|
|
290
|
+
Not implemented yet:
|
|
291
|
+
|
|
292
|
+
- Autofix.
|
|
293
|
+
- SARIF output.
|
|
294
|
+
- A pre-commit hook.
|
|
295
|
+
- Editor integration.
|
|
296
|
+
- Semantic conflict detection (instructions that disagree, beyond duplicate headings and mixed package managers).
|
|
297
|
+
|
|
298
|
+
## Contributing
|
|
299
|
+
|
|
300
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, scripts, and how to add a rule. The code of conduct is [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). Security reports go through [private advisories](https://github.com/weugit/agentsmd-medic/security/advisories/new) ([SECURITY.md](SECURITY.md)).
|
|
301
|
+
|
|
302
|
+
This repository's own [AGENTS.md](AGENTS.md) is linted in CI. `README.md` and `CONTRIBUTING.md` are not.
|
|
303
|
+
|
|
304
|
+
## License
|
|
305
|
+
|
|
306
|
+
[MIT](LICENSE). Copyright (c) 2026 weugit.
|
package/dist/agents.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Documented instruction-file behavior for coding agents.
|
|
3
|
+
*
|
|
4
|
+
* These behaviors change as agents ship updates. Treat this module as a snapshot
|
|
5
|
+
* of the public docs, not a guarantee of what a future release reads. Check the
|
|
6
|
+
* linked page when a doctor report looks wrong. Doctor does not read home-directory
|
|
7
|
+
* files (`~/.codex`, `~/.claude`, `~/.gemini`, and similar).
|
|
8
|
+
*
|
|
9
|
+
* - OpenAI Codex: https://developers.openai.com/codex/guides/agents-md
|
|
10
|
+
* - Claude Code: https://code.claude.com/docs/en/memory
|
|
11
|
+
* - Cursor: https://cursor.com/docs/rules
|
|
12
|
+
* - GitHub Copilot: https://docs.github.com/en/copilot/customizing-copilot/adding-custom-instructions-for-github-copilot
|
|
13
|
+
* - Gemini CLI: https://geminicli.com/docs/cli/gemini-md
|
|
14
|
+
*/
|
|
15
|
+
/** Default `project_doc_max_bytes`. Codex stops adding project docs at this size. */
|
|
16
|
+
export declare const CODEX_PROJECT_DOC_MAX_BYTES: number;
|
|
17
|
+
/** Printed when AGENTS.md is present and no CLAUDE.md imports it. */
|
|
18
|
+
export declare const CLAUDE_AGENTS_IGNORED = "AGENTS.md is ignored by Claude Code: no CLAUDE.md imports it";
|
|
19
|
+
/** Printed when CLAUDE.local.md is on the path from the repo root to the directory. */
|
|
20
|
+
export declare const CLAUDE_LOCAL_WARNING = "CLAUDE.local.md exists (personal, git-ignored, may override shared instructions).";
|
|
21
|
+
/** Printed when a legacy .cursorrules file is present. */
|
|
22
|
+
export declare const CURSOR_LEGACY_WARNING = "Legacy .cursorrules is deprecated. Cursor recommends .cursor/rules/*.mdc instead.";
|
|
23
|
+
/**
|
|
24
|
+
* Printed when the directory has AGENTS.md and Gemini would not load it.
|
|
25
|
+
* Gemini reads GEMINI.md unless `context.fileName` says otherwise.
|
|
26
|
+
*/
|
|
27
|
+
export declare const GEMINI_ONLY_AGENTS_WARNING = "Gemini CLI reads GEMINI.md by default and loads AGENTS.md only when context.fileName includes it. Only AGENTS.md exists here.";
|
|
28
|
+
export interface AgentInfo {
|
|
29
|
+
id: "codex" | "claude" | "cursor" | "copilot" | "gemini";
|
|
30
|
+
name: string;
|
|
31
|
+
docsUrl: string;
|
|
32
|
+
/** What doctor checks, in one sentence. */
|
|
33
|
+
loads: string;
|
|
34
|
+
}
|
|
35
|
+
export declare const AGENTS: readonly AgentInfo[];
|
|
36
|
+
export declare function agentInfo(id: AgentInfo["id"]): AgentInfo;
|
package/dist/agents.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Documented instruction-file behavior for coding agents.
|
|
3
|
+
*
|
|
4
|
+
* These behaviors change as agents ship updates. Treat this module as a snapshot
|
|
5
|
+
* of the public docs, not a guarantee of what a future release reads. Check the
|
|
6
|
+
* linked page when a doctor report looks wrong. Doctor does not read home-directory
|
|
7
|
+
* files (`~/.codex`, `~/.claude`, `~/.gemini`, and similar).
|
|
8
|
+
*
|
|
9
|
+
* - OpenAI Codex: https://developers.openai.com/codex/guides/agents-md
|
|
10
|
+
* - Claude Code: https://code.claude.com/docs/en/memory
|
|
11
|
+
* - Cursor: https://cursor.com/docs/rules
|
|
12
|
+
* - GitHub Copilot: https://docs.github.com/en/copilot/customizing-copilot/adding-custom-instructions-for-github-copilot
|
|
13
|
+
* - Gemini CLI: https://geminicli.com/docs/cli/gemini-md
|
|
14
|
+
*/
|
|
15
|
+
/** Default `project_doc_max_bytes`. Codex stops adding project docs at this size. */
|
|
16
|
+
export const CODEX_PROJECT_DOC_MAX_BYTES = 32 * 1024;
|
|
17
|
+
/** Printed when AGENTS.md is present and no CLAUDE.md imports it. */
|
|
18
|
+
export const CLAUDE_AGENTS_IGNORED = "AGENTS.md is ignored by Claude Code: no CLAUDE.md imports it";
|
|
19
|
+
/** Printed when CLAUDE.local.md is on the path from the repo root to the directory. */
|
|
20
|
+
export const CLAUDE_LOCAL_WARNING = "CLAUDE.local.md exists (personal, git-ignored, may override shared instructions).";
|
|
21
|
+
/** Printed when a legacy .cursorrules file is present. */
|
|
22
|
+
export const CURSOR_LEGACY_WARNING = "Legacy .cursorrules is deprecated. Cursor recommends .cursor/rules/*.mdc instead.";
|
|
23
|
+
/**
|
|
24
|
+
* Printed when the directory has AGENTS.md and Gemini would not load it.
|
|
25
|
+
* Gemini reads GEMINI.md unless `context.fileName` says otherwise.
|
|
26
|
+
*/
|
|
27
|
+
export const GEMINI_ONLY_AGENTS_WARNING = "Gemini CLI reads GEMINI.md by default and loads AGENTS.md only when context.fileName includes it. Only AGENTS.md exists here.";
|
|
28
|
+
export const AGENTS = [
|
|
29
|
+
{
|
|
30
|
+
id: "codex",
|
|
31
|
+
name: "OpenAI Codex",
|
|
32
|
+
docsUrl: "https://developers.openai.com/codex/guides/agents-md",
|
|
33
|
+
loads: "From the git root down to the directory, AGENTS.override.md if that directory has one, otherwise AGENTS.md. Files are concatenated from the root toward the leaf and capped by project_doc_max_bytes (32 KiB by default).",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: "claude",
|
|
37
|
+
name: "Claude Code",
|
|
38
|
+
docsUrl: "https://code.claude.com/docs/en/memory",
|
|
39
|
+
loads: "CLAUDE.md and CLAUDE.local.md on the path from the git root to the directory. AGENTS.md is included only when a CLAUDE.md line imports it (@AGENTS.md, @./AGENTS.md, or another relative path to AGENTS.md).",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: "cursor",
|
|
43
|
+
name: "Cursor",
|
|
44
|
+
docsUrl: "https://cursor.com/docs/rules",
|
|
45
|
+
loads: "AGENTS.md at the repo root and in nested directories, .cursor/rules/*.mdc files, and legacy .cursorrules (deprecated).",
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: "copilot",
|
|
49
|
+
name: "GitHub Copilot",
|
|
50
|
+
docsUrl: "https://docs.github.com/en/copilot/customizing-copilot/adding-custom-instructions-for-github-copilot",
|
|
51
|
+
loads: ".github/copilot-instructions.md, .github/instructions/*.instructions.md, and AGENTS.md.",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: "gemini",
|
|
55
|
+
name: "Gemini CLI",
|
|
56
|
+
docsUrl: "https://geminicli.com/docs/cli/gemini-md",
|
|
57
|
+
loads: "GEMINI.md by default. AGENTS.md only when settings set context.fileName to include it.",
|
|
58
|
+
},
|
|
59
|
+
];
|
|
60
|
+
const AGENT_BY_ID = new Map(AGENTS.map((agent) => [agent.id, agent]));
|
|
61
|
+
export function agentInfo(id) {
|
|
62
|
+
const info = AGENT_BY_ID.get(id);
|
|
63
|
+
if (!info)
|
|
64
|
+
throw new Error(`Unknown agent: ${id}`);
|
|
65
|
+
return info;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,qFAAqF;AACrF,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,GAAG,IAAI,CAAC;AAErD,qEAAqE;AACrE,MAAM,CAAC,MAAM,qBAAqB,GAAG,8DAA8D,CAAC;AAEpG,uFAAuF;AACvF,MAAM,CAAC,MAAM,oBAAoB,GAAG,mFAAmF,CAAC;AAExH,0DAA0D;AAC1D,MAAM,CAAC,MAAM,qBAAqB,GAAG,mFAAmF,CAAC;AAEzH;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GACrC,+HAA+H,CAAC;AAUlI,MAAM,CAAC,MAAM,MAAM,GAAyB;IAC1C;QACE,EAAE,EAAE,OAAO;QACX,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,sDAAsD;QAC/D,KAAK,EACH,2NAA2N;KAC9N;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,wCAAwC;QACjD,KAAK,EACH,8MAA8M;KACjN;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,+BAA+B;QACxC,KAAK,EAAE,wHAAwH;KAChI;IACD;QACE,EAAE,EAAE,SAAS;QACb,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,sGAAsG;QAC/G,KAAK,EAAE,yFAAyF;KACjG;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,0CAA0C;QACnD,KAAK,EAAE,wFAAwF;KAChG;CACF,CAAC;AAEF,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AAEtE,MAAM,UAAU,SAAS,CAAC,EAAmB;IAC3C,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACjC,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;IACnD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
interface Io {
|
|
2
|
+
stdout: {
|
|
3
|
+
write(s: string): unknown;
|
|
4
|
+
isTTY?: boolean;
|
|
5
|
+
};
|
|
6
|
+
stderr: {
|
|
7
|
+
write(s: string): unknown;
|
|
8
|
+
};
|
|
9
|
+
cwd: string;
|
|
10
|
+
env?: Record<string, string | undefined>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Run the CLI. Returns a process exit code: 0 ok, 1 findings, 2 usage or config error.
|
|
14
|
+
*/
|
|
15
|
+
export declare function main(argv: string[], io?: Io): Promise<number>;
|
|
16
|
+
export {};
|