@yawlabs/ctxlint 0.19.0 → 0.21.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
@@ -386,12 +386,17 @@ Create a `.ctxlintrc` or `.ctxlintrc.json` in your project root:
386
386
  "tierBreakdown": 1000,
387
387
  "tierAggregate": 4000
388
388
  },
389
- "contextFiles": ["CONVENTIONS.md", "docs/ai-rules.md"]
389
+ "contextFiles": ["CONVENTIONS.md", "docs/ai-rules.md"],
390
+ "exclude": ["fixtures/**", "examples/**"]
390
391
  }
391
392
  ```
392
393
 
393
394
  The `contextFiles` array adds custom file patterns to scan alongside the built-in list. Useful for project-specific context files like `CONVENTIONS.md`.
394
395
 
396
+ The `exclude` array is its counterpart: globs of context files to drop from the scan entirely. Use it for files that are not this project's agent context at all — test fixtures, example projects, vendored templates.
397
+
398
+ `exclude` removes **files**, where `ignore` / `ignoreRules` / `.ctxlintignore` suppress **findings**. That distinction matters for the cross-file checks: `contradictions` and `redundancy/duplicate-content` compare the discovered set and report against the literal `(project)` path, which no per-file glob can match. Excluding the files is the only way to silence a conflict between two files you never wanted linted. Reach for `.ctxlintignore` when a real context file has one noisy finding; reach for `exclude` when the file shouldn't be in the corpus.
399
+
395
400
  ### Config Reference
396
401
 
397
402
  | Field | Type | Default | Meaning |
@@ -407,6 +412,7 @@ The `contextFiles` array adds custom file patterns to scan alongside the built-i
407
412
  | `tokenThresholds.tierBreakdown` | `number` | `1000` | Always-loaded file threshold for `tier-tokens/section-breakdown`. |
408
413
  | `tokenThresholds.tierAggregate` | `number` | `4000` | Combined always-loaded threshold for `tier-tokens/aggregate`. |
409
414
  | `contextFiles` | `string[]` | `[]` | Extra glob patterns to scan alongside the built-in list. |
415
+ | `exclude` | `string[]` | `[]` | Globs of context files to drop from the scan entirely, matched against each file's project-relative path. Removes files rather than suppressing findings, so excluded files are also invisible to the cross-file checks. |
410
416
  | `mcp` | `boolean` | `false` | Enable MCP config checks by default (same as `--mcp`). |
411
417
  | `mcpOnly` | `boolean` | `false` | Run only MCP config checks, skip context-file checks (same as `--mcp-only`). |
412
418
  | `mcpGlobal` | `boolean` | `false` | Also scan user/global MCP configs (same as `--mcp-global`). |
@@ -511,9 +517,9 @@ ctxlint is the reference implementation of four open specifications for linting
511
517
 
512
518
  | Spec | What it covers |
513
519
  | -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
514
- | **[AI Context File Linting Spec](./CONTEXT_LINT_SPEC.md)** | 39 rules for validating context files (CLAUDE.md, .cursorrules, AGENTS.md, etc.) across 16 clients. Covers file formats, frontmatter schemas, path/command validation, staleness, token budgets, redundancy, and contradictions. |
520
+ | **[AI Context File Linting Spec](./CONTEXT_LINT_SPEC.md)** | 41 rules for validating context files (CLAUDE.md, .cursorrules, AGENTS.md, etc.) across 16 clients. Covers file formats, frontmatter schemas, path/command validation, staleness, token budgets, redundancy, and contradictions. |
515
521
  | **[MCP Config Linting Spec](./MCP_CONFIG_LINT_SPEC.md)** | 29 rules for validating MCP server configs (.mcp.json, .cursor/mcp.json, .vscode/mcp.json, etc.) across 8 clients. Covers schema validation, hardcoded secrets, env var syntax, deprecated transports, and cross-file consistency. |
516
- | **[Agent Session Linting Spec](./AGENT_SESSION_LINT_SPEC.md)** | 11 rules for auditing agent session data (history, memory) across 8 agents. Covers cross-project secret consistency, config drift, stale memory, and loop detection. |
522
+ | **[Agent Session Linting Spec](./AGENT_SESSION_LINT_SPEC.md)** | 12 rules for auditing agent session data (history, memory) across 8 agents. Covers cross-project secret consistency, config drift, stale memory, and loop detection. |
517
523
  | **[Agent Skill Linting Spec](./AGENT_SKILL_LINT_SPEC.md)** | 5 rules for auditing Claude Code skill (`SKILL.md`) and agent (`.md`) definitions under `~/.claude`. Covers frontmatter presence, broken refs, trigger-phrase collisions, orphaned skills, and dead tool restrictions. (v1, experimental) |
518
524
 
519
525
  All specs include machine-readable rule catalogs for programmatic consumption:
@@ -134,6 +134,16 @@
134
134
  "message": "{count} files edited on '{branch}' with no intervening commit",
135
135
  "fixable": false,
136
136
  "stability": "stable"
137
+ },
138
+ {
139
+ "id": "session/unresolvable-sha",
140
+ "category": "session",
141
+ "severity": "warning",
142
+ "description": "A memory cites a git SHA that does not resolve in the repository.",
143
+ "trigger": "A 7-40 character hex token outside code fences, preceded on the same line by a commit-citation cue (commit, SHA, HEAD, landed in, reverted, ...), does not resolve via git cat-file. UUID members, digest prefixes, decimal ids and version fragments are excluded before resolution; without a git repository the rule reports nothing.",
144
+ "message": "cited commit {sha} does not resolve in this repository",
145
+ "fixable": false,
146
+ "stability": "experimental"
137
147
  }
138
148
  ],
139
149
  "dataSources": [
@@ -170,6 +170,26 @@
170
170
  "fixable": false,
171
171
  "stability": "stable"
172
172
  },
173
+ {
174
+ "id": "commands/exit-status-masked",
175
+ "category": "commands",
176
+ "severity": "warning",
177
+ "description": "A verification command's exit status is discarded by a pipe into a filter, so the success claim that follows cannot fail.",
178
+ "trigger": "A verifier (tsc, eslint, biome, vitest, pytest, cargo test, or an npm/pnpm/yarn/bun script resolving to one) heads a pipeline whose last stage is a filter or pager (head, tail, grep, sed, awk, less, cat, tee, wc), and the pipeline is followed by && plus a success-announcing echo/printf, or by an echo of $?, with no set -o pipefail in scope.",
179
+ "message": "\"{cmd}\" — exit status comes from \"{filter}\", not \"{verifier}\"; the success claim cannot fail",
180
+ "fixable": false,
181
+ "stability": "experimental"
182
+ },
183
+ {
184
+ "id": "commands/unknown-subcommand",
185
+ "category": "commands",
186
+ "severity": "error",
187
+ "description": "A documented invocation of the project's own binary uses a subcommand the CLI does not implement.",
188
+ "trigger": "A command invokes a name declared in package.json#bin with a leading non-flag argument that is not in the CLI's known subcommand set, where that set was statically resolved as closed from the entry file.",
189
+ "message": "\"{cmd}\" — \"{sub}\" is not a subcommand of {bin} (known: {known})",
190
+ "fixable": false,
191
+ "stability": "experimental"
192
+ },
173
193
  {
174
194
  "id": "staleness/stale",
175
195
  "category": "staleness",