awguard 1.4.0 → 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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.5.0
4
+
5
+ - Add `--format inventory` to map agentic repository surfaces by workflows, agent context files, and MCP configs.
6
+ - Scan GitHub Copilot custom agents, reusable prompts, and repository skills under `.github/agents`, `.github/prompts`, and `.github/skills`.
7
+ - Add a scope expansion roadmap for policy mode, agent capability SBOMs, trend reports, and adoption tooling.
8
+
3
9
  ## 1.4.0
4
10
 
5
11
  - Add `AWG013` for project MCP configs that start mutable packages, unpinned containers, or shell wrappers.
package/README.md CHANGED
@@ -113,7 +113,7 @@ jobs:
113
113
  ## CLI
114
114
 
115
115
  ```bash
116
- awguard [path] [--config file] [--preset name] [--format text|json|markdown|github|sarif|graph|html|migration|score|badge] [--output file] [--baseline file] [--write-baseline file] [--fix-dry-run] [--fail-on none|low|medium|high|critical]
116
+ awguard [path] [--config file] [--preset name] [--format text|json|markdown|github|sarif|graph|html|migration|score|badge|inventory] [--output file] [--baseline file] [--write-baseline file] [--fix-dry-run] [--fail-on none|low|medium|high|critical]
117
117
  ```
118
118
 
119
119
  Examples:
@@ -124,6 +124,7 @@ node ./bin/awguard.js . --config awguard.config.json
124
124
  node ./bin/awguard.js . --preset strict --format graph
125
125
  node ./bin/awguard.js . --format html --output awguard-report.html
126
126
  node ./bin/awguard.js . --format migration --output awguard-migration.md
127
+ node ./bin/awguard.js . --format inventory
127
128
  node ./bin/awguard.js . --format score
128
129
  node ./bin/awguard.js . --format badge --output awguard-badge.json
129
130
  node ./bin/awguard.js . --fix-dry-run
@@ -241,6 +242,16 @@ Then add a badge to your README:
241
242
 
242
243
  The score starts at 100 and subtracts risk for critical, high, medium, and low findings. This makes AWGuard easy to show in a README without hiding the detailed SARIF, graph, and migration reports.
243
244
 
245
+ ## Agentic Surface Inventory
246
+
247
+ Generate a repository map of agent-related surfaces:
248
+
249
+ ```bash
250
+ node ./bin/awguard.js . --format inventory
251
+ ```
252
+
253
+ The inventory groups scanned files into GitHub Actions workflows, persistent agent context files, and MCP configs. It shows which surfaces exist, which rules fired, and what to review next. This is useful before a team enables new coding agents because it answers: "Where can agents read instructions, get tools, or act in CI?"
254
+
244
255
  ## Agent Context Guard
245
256
 
246
257
  AWGuard also scans persistent agent instruction files:
@@ -251,6 +262,9 @@ AWGuard also scans persistent agent instruction files:
251
262
  - `GEMINI.md`
252
263
  - `.github/copilot-instructions.md`
253
264
  - `.github/instructions/*.instructions.md`
265
+ - `.github/agents/*.md`
266
+ - `.github/prompts/*.prompt.md`
267
+ - `.github/skills/**/SKILL.md`
254
268
  - `.cursor/rules/*.{md,mdc,txt}`
255
269
  - `.cursorrules`, `.windsurfrules`, and `.clinerules`
256
270
 
@@ -330,6 +344,9 @@ If you omit rule ids, the suppression applies to all findings on the target line
330
344
  - Hosted AWI score API for dynamic cross-repository badges.
331
345
  - Agent instruction file rule packs for Copilot, Claude Code, Codex, Gemini, Cursor, and Windsurf.
332
346
  - MCP config rule packs for Claude Code, Copilot, VS Code, Cursor, Windsurf, Cline, and Roo.
347
+ - Policy mode for approved MCP packages, actions, token scopes, and agent context files.
348
+ - Agent capability SBOM for prompts, tools, MCP servers, permissions, and write paths.
349
+ - Trend reports that show newly added agent surfaces and newly introduced findings.
333
350
  - GitHub App integration for always-on repository monitoring.
334
351
  - Rule packs for Claude Code, Codex, Gemini, Copilot, Aider, and custom agents.
335
352
  - Public vulnerable workflow lab with attack and fix walkthroughs.
@@ -337,3 +354,4 @@ If you omit rule ids, the suppression applies to all findings on the target line
337
354
  ## Research Backing
338
355
 
339
356
  See [docs/market-analysis.md](docs/market-analysis.md) for the demand analysis, gap, audience, and launch plan.
357
+ See [docs/roadmap.md](docs/roadmap.md) for the scope expansion roadmap.
package/action.yml CHANGED
@@ -7,7 +7,7 @@ inputs:
7
7
  required: false
8
8
  default: .
9
9
  format:
10
- description: Output format: github, text, json, markdown, sarif, graph, html, migration, score, or badge.
10
+ description: Output format: github, text, json, markdown, sarif, graph, html, migration, score, badge, or inventory.
11
11
  required: false
12
12
  default: github
13
13
  fail-on:
@@ -39,20 +39,27 @@ Short pitch:
39
39
  ```
40
40
 
41
41
  9. Show the README badge and say: "Add an AWI risk badge to your repo before adding AI agents to CI."
42
- 10. Show an unsafe `AGENTS.md` or `.github/copilot-instructions.md` line and run:
42
+ 10. Run:
43
+
44
+ ```bash
45
+ node ./bin/awguard.js . --format inventory
46
+ ```
47
+
48
+ 11. Show the surface map and say: "Before you secure agent workflows, find every place the repository gives agents instructions or tools."
49
+ 12. Show an unsafe `AGENTS.md` or `.github/copilot-instructions.md` line and run:
43
50
 
44
51
  ```bash
45
52
  node ./bin/awguard.js . --format text
46
53
  ```
47
54
 
48
- 11. Explain that AWGuard scans both the workflow and the persistent agent instructions that shape agent behavior.
49
- 12. Show an unsafe `.mcp.json` with `npx @modelcontextprotocol/server-github` and a committed token, then run:
55
+ 13. Explain that AWGuard scans both the workflow and the persistent agent instructions that shape agent behavior.
56
+ 14. Show an unsafe `.mcp.json` with `npx @modelcontextprotocol/server-github` and a committed token, then run:
50
57
 
51
58
  ```bash
52
59
  node ./bin/awguard.js examples/.mcp.json --format text
53
60
  ```
54
61
 
55
- 13. Explain the new hook: "This scanner checks repo-provided MCP tool wiring without executing the MCP server."
62
+ 15. Explain the new hook: "This scanner checks repo-provided MCP tool wiring without executing the MCP server."
56
63
 
57
64
  ## Release Checklist
58
65
 
@@ -197,6 +197,24 @@ Agentic Workflow Guard now supports:
197
197
 
198
198
  This keeps the project focused: AWGuard does not try to replace MCP runtime scanners. It gives maintainers a GitHub-native, zero-dependency first check before an agent or scanner executes repo-provided MCP server commands.
199
199
 
200
+ ## Deep Research Refresh: Agentic Surface Inventory
201
+
202
+ The next scope expansion is an inventory view. GitHub now documents repository-level custom agents in `.github/agents`, Copilot MCP configuration, and custom instructions. VS Code documents workspace MCP config. This means the repository itself can contain multiple agent-control surfaces before a single workflow runs.
203
+
204
+ The useful maintainer question is no longer only "is this workflow unsafe?" It is:
205
+
206
+ ```text
207
+ what agent surfaces does this repository expose, and which ones changed?
208
+ ```
209
+
210
+ Agentic Workflow Guard now supports:
211
+
212
+ - `--format inventory` for a surface map grouped by workflows, agent context files, and MCP configs.
213
+ - scanning `.github/agents/*.md`, `.github/prompts/*.prompt.md`, and `.github/skills/**/SKILL.md` as persistent agent context.
214
+ - a roadmap that moves toward policy mode, agent capability SBOMs, trend reports, and adoption generators.
215
+
216
+ This widens the project while preserving its niche: AWGuard remains a zero-execution repository scanner for agentic risk, not a broad runtime agent firewall.
217
+
200
218
  ## Distribution Plan
201
219
 
202
220
  1. Publish the repo with a short demo GIF or screenshot.
@@ -0,0 +1,71 @@
1
+ # Scope Expansion Roadmap
2
+
3
+ ## Research Signal
4
+
5
+ AWGuard should widen from "workflow scanner" into an agentic repository safety map while staying small and zero-dependency.
6
+
7
+ Current research points:
8
+
9
+ - GitHub Copilot now documents repository-level custom agents in `.github/agents`, repository MCP configuration, and repo-scoped agent behavior.
10
+ - VS Code and Copilot document MCP configuration in repository or workspace files such as `.vscode/mcp.json`.
11
+ - GitHub Actions security docs still warn that attacker-controlled GitHub context must be treated as untrusted input.
12
+ - OpenSSF Scorecard shows that security tools travel further when they produce a simple public score, badge, and clear adoption path.
13
+ - Existing MCP scanners focus on live server/tool inspection; AWGuard's lane is zero-execution repository scanning before those tools start.
14
+
15
+ ## Feature List
16
+
17
+ 1. Agentic Surface Inventory
18
+ - Add `--format inventory`.
19
+ - Group scanned files into GitHub Actions workflows, agent context files, and MCP configs.
20
+ - Show findings, highest severity, and recommended next steps per surface.
21
+
22
+ 2. Wider Agent Context Coverage
23
+ - Scan `.github/agents/*.md` for Copilot custom agents.
24
+ - Scan `.github/prompts/*.prompt.md` for reusable prompts.
25
+ - Scan `.github/skills/**/SKILL.md` for repository skills.
26
+ - Keep using `AWG012` for risky persistent instructions.
27
+
28
+ 3. Policy Mode
29
+ - Add an `awguard.policy.json` format for explicit allowlists.
30
+ - Allow approved MCP commands, package pins, Docker digests, action owners, and workflow write scopes.
31
+ - Report drift when the repository adds a new agent surface without policy.
32
+
33
+ 4. Setup And Adoption Generator
34
+ - Add a command that prints a starter GitHub Action, strict config, baseline command, and badge snippet.
35
+ - Keep it as a print-only generator first so it remains safe.
36
+
37
+ 5. Agent Capability SBOM
38
+ - Export a machine-readable inventory of agent prompts, tools, MCP servers, permissions, secrets exposure, and write capabilities.
39
+ - Make it useful for security reviews and audits.
40
+
41
+ 6. Trend Reports
42
+ - Compare current scan output with a previous JSON report.
43
+ - Show newly added agent surfaces and newly introduced rules.
44
+
45
+ 7. Vulnerable Lab
46
+ - Add a set of intentionally unsafe mini-repositories under examples or a separate demo repo.
47
+ - Each lab should include exploit explanation, AWGuard output, and fixed pattern.
48
+
49
+ 8. GitHub App Or Scheduled Monitor
50
+ - Long-term: run continuously across repositories.
51
+ - Open issues when new agent surfaces appear or risk score drops.
52
+
53
+ ## Work Plan
54
+
55
+ ### Now
56
+
57
+ - Ship `--format inventory`.
58
+ - Expand `AWG012` coverage to Copilot custom agents, prompts, and skills.
59
+ - Document the widened project roadmap.
60
+
61
+ ### Next
62
+
63
+ - Add policy mode for MCP server allowlists and approved agent context files.
64
+ - Add a setup generator for the GitHub Action, config, baseline, and README badge.
65
+ - Add JSON inventory output for downstream dashboards.
66
+
67
+ ### Later
68
+
69
+ - Add trend reports for "new agent surface introduced" diffs.
70
+ - Build the vulnerable lab and screenshot-friendly walkthroughs.
71
+ - Explore a GitHub App after the CLI and Action adoption path is stable.
@@ -14,6 +14,7 @@ Try:
14
14
  node ../bin/awguard.js unsafe-agent.yml --format graph
15
15
  node ../bin/awguard.js unsafe-agent.yml --format html --output awguard-report.html
16
16
  node ../bin/awguard.js unsafe-agent.yml --format migration
17
+ node ../bin/awguard.js . --format inventory
17
18
  node ../bin/awguard.js unsafe-agent.yml --format score
18
19
  node ../bin/awguard.js safe-agent.yml --format badge
19
20
  node ../bin/awguard.js .mcp.json --format text
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "awguard",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Scan GitHub Actions workflows, agent instructions, and MCP configs for AI-agent injection and unsafe tool boundaries.",
5
5
  "type": "module",
6
6
  "homepage": "https://github.com/Mughal-Baig/agentic-workflow-guard#readme",
package/src/cli.js CHANGED
@@ -5,12 +5,24 @@ import { applyBaseline, createBaseline, loadBaseline, writeBaseline } from './ba
5
5
  import { loadConfig } from './config.js';
6
6
  import { renderFixDryRun } from './remediation.js';
7
7
  import { scanWorkflows, severityRank } from './scanner.js';
8
- import { renderBadge, renderGithubAnnotations, renderGraph, renderHtml, renderJson, renderMarkdown, renderMigration, renderSarif, renderScore, renderText } from './reporters.js';
8
+ import {
9
+ renderBadge,
10
+ renderGithubAnnotations,
11
+ renderGraph,
12
+ renderHtml,
13
+ renderJson,
14
+ renderMarkdown,
15
+ renderMigration,
16
+ renderSarif,
17
+ renderScore,
18
+ renderSurfaceInventory,
19
+ renderText
20
+ } from './reporters.js';
9
21
 
10
22
  const HELP = `Agentic Workflow Guard
11
23
 
12
24
  Usage:
13
- awguard [path] [--config file] [--preset name] [--format text|json|markdown|github|sarif|graph|html|migration|score|badge] [--output file] [--baseline file] [--write-baseline file] [--fix-dry-run] [--fail-on none|low|medium|high|critical]
25
+ awguard [path] [--config file] [--preset name] [--format text|json|markdown|github|sarif|graph|html|migration|score|badge|inventory] [--output file] [--baseline file] [--write-baseline file] [--fix-dry-run] [--fail-on none|low|medium|high|critical]
14
26
 
15
27
  Examples:
16
28
  awguard .
@@ -20,6 +32,7 @@ Examples:
20
32
  awguard .github/workflows/agent.yml --format markdown --fail-on high
21
33
  awguard . --format html --output awguard-report.html
22
34
  awguard . --format migration --output awguard-migration.md
35
+ awguard . --format inventory
23
36
  awguard . --format score
24
37
  awguard . --format badge --output awguard-badge.json
25
38
  awguard . --fix-dry-run
@@ -121,7 +134,19 @@ export function parseArgs(args, env = {}) {
121
134
  }
122
135
  }
123
136
 
124
- validateEnum('format', options.format, ['text', 'json', 'markdown', 'github', 'sarif', 'graph', 'html', 'migration', 'score', 'badge']);
137
+ validateEnum('format', options.format, [
138
+ 'text',
139
+ 'json',
140
+ 'markdown',
141
+ 'github',
142
+ 'sarif',
143
+ 'graph',
144
+ 'html',
145
+ 'migration',
146
+ 'score',
147
+ 'badge',
148
+ 'inventory'
149
+ ]);
125
150
  validateEnum('fail-on', options.failOn, ['none', 'low', 'medium', 'high', 'critical']);
126
151
 
127
152
  return options;
@@ -141,6 +166,7 @@ function render(result, format) {
141
166
  if (format === 'migration') return renderMigration(result);
142
167
  if (format === 'score') return renderScore(result);
143
168
  if (format === 'badge') return renderBadge(result);
169
+ if (format === 'inventory') return renderSurfaceInventory(result);
144
170
  if (format === 'github') return renderGithubAnnotations(result);
145
171
  return renderText(result);
146
172
  }
@@ -0,0 +1,148 @@
1
+ import path from 'node:path';
2
+ import { classifyScanFile, severityRank } from './scanner.js';
3
+
4
+ const surfaceLabels = {
5
+ 'github-workflow': 'GitHub Actions workflows',
6
+ 'agent-context': 'Agent context files',
7
+ 'mcp-config': 'MCP configs',
8
+ other: 'Other scanned files'
9
+ };
10
+
11
+ const surfaceOrder = ['github-workflow', 'agent-context', 'mcp-config', 'other'];
12
+
13
+ export function buildInventory(result) {
14
+ const fileRows = result.scannedFiles.map((file) => {
15
+ const relativeFile = path.relative(result.root, file) || file;
16
+ const surface = classifyScanFile(file, result.root);
17
+ const findings = result.findings.filter((finding) => finding.file === relativeFile);
18
+
19
+ return {
20
+ file: relativeFile,
21
+ surface,
22
+ label: surfaceLabels[surface] || surfaceLabels.other,
23
+ findings: findings.length,
24
+ highest: highestSeverity(findings),
25
+ rules: [...new Set(findings.map((finding) => finding.ruleId))]
26
+ };
27
+ });
28
+
29
+ const surfaces = surfaceOrder
30
+ .map((surface) => {
31
+ const files = fileRows.filter((file) => file.surface === surface);
32
+ const findings = result.findings.filter((finding) => files.some((file) => file.file === finding.file));
33
+
34
+ return {
35
+ surface,
36
+ label: surfaceLabels[surface],
37
+ files: files.length,
38
+ findings: findings.length,
39
+ highest: highestSeverity(findings),
40
+ rules: [...new Set(findings.map((finding) => finding.ruleId))]
41
+ };
42
+ })
43
+ .filter((surface) => surface.files > 0);
44
+
45
+ return {
46
+ summary: {
47
+ scannedFiles: result.scannedFiles.length,
48
+ surfaces: surfaces.length,
49
+ findings: result.findings.length,
50
+ highest: result.summary.highest
51
+ },
52
+ surfaces,
53
+ files: fileRows,
54
+ recommendations: recommendationsFor(surfaces, result.findings)
55
+ };
56
+ }
57
+
58
+ export function renderInventory(result) {
59
+ const inventory = buildInventory(result);
60
+ const lines = [
61
+ '# Agentic Surface Inventory',
62
+ '',
63
+ `Scanned files: **${inventory.summary.scannedFiles}**`,
64
+ `Agentic surfaces: **${inventory.summary.surfaces}**`,
65
+ `Findings: **${inventory.summary.findings}**`,
66
+ `Highest severity: **${inventory.summary.highest}**`,
67
+ '',
68
+ '## Surface Summary',
69
+ '',
70
+ '| Surface | Files | Findings | Highest | Rules |',
71
+ '| --- | ---: | ---: | --- | --- |'
72
+ ];
73
+
74
+ if (inventory.surfaces.length === 0) {
75
+ lines.push('| None found | 0 | 0 | none | |');
76
+ } else {
77
+ for (const surface of inventory.surfaces) {
78
+ lines.push(
79
+ `| ${surface.label} | ${surface.files} | ${surface.findings} | ${surface.highest} | ${
80
+ surface.rules.length > 0 ? surface.rules.join(', ') : ''
81
+ } |`
82
+ );
83
+ }
84
+ }
85
+
86
+ lines.push('', '## Files', '', '| Surface | File | Findings | Highest | Rules |', '| --- | --- | ---: | --- | --- |');
87
+
88
+ if (inventory.files.length === 0) {
89
+ lines.push('| None found | | 0 | none | |');
90
+ } else {
91
+ for (const file of inventory.files) {
92
+ lines.push(
93
+ `| ${file.label} | \`${escapeMarkdown(file.file)}\` | ${file.findings} | ${file.highest} | ${
94
+ file.rules.length > 0 ? file.rules.join(', ') : ''
95
+ } |`
96
+ );
97
+ }
98
+ }
99
+
100
+ lines.push('', '## Recommended Next Steps', '');
101
+ for (const recommendation of inventory.recommendations) {
102
+ lines.push(`- ${recommendation}`);
103
+ }
104
+
105
+ return lines.join('\n');
106
+ }
107
+
108
+ function recommendationsFor(surfaces, findings) {
109
+ const surfaceNames = new Set(surfaces.map((surface) => surface.surface));
110
+ const rules = new Set(findings.map((finding) => finding.ruleId));
111
+ const recommendations = [];
112
+
113
+ if (rules.has('AWG014')) {
114
+ recommendations.push('Remove and rotate committed MCP credentials before widening agent access.');
115
+ }
116
+
117
+ if (rules.has('AWG013')) {
118
+ recommendations.push('Pin MCP server packages, container images, and startup commands before enabling repository-scoped tools.');
119
+ }
120
+
121
+ if (rules.has('AWG012')) {
122
+ recommendations.push('Review persistent agent context files before relying on workflow permission boundaries.');
123
+ }
124
+
125
+ if (!surfaceNames.has('agent-context')) {
126
+ recommendations.push('Add an explicit `AGENTS.md` or `.github/copilot-instructions.md` with conservative safety rules before introducing agents.');
127
+ }
128
+
129
+ if (!surfaceNames.has('mcp-config')) {
130
+ recommendations.push('Keep MCP configs absent until there is a reviewed tool allowlist and credential handling plan.');
131
+ }
132
+
133
+ if (recommendations.length === 0) {
134
+ recommendations.push('Keep this inventory in CI so new agent surfaces are visible during review.');
135
+ }
136
+
137
+ return recommendations;
138
+ }
139
+
140
+ function highestSeverity(findings) {
141
+ return findings.reduce((current, finding) => {
142
+ return severityRank[finding.severity] > severityRank[current] ? finding.severity : current;
143
+ }, 'none');
144
+ }
145
+
146
+ function escapeMarkdown(value) {
147
+ return String(value).replaceAll('|', '\\|');
148
+ }
package/src/reporters.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import path from 'node:path';
2
2
  import { findingFingerprint } from './fingerprints.js';
3
3
  import { renderGraphMarkdown, renderHtmlReport } from './graph.js';
4
+ import { renderInventory } from './inventory.js';
4
5
  import { renderMigrationPlan } from './migration.js';
5
6
  import { renderBadgeJson, renderScorecard } from './score.js';
6
7
  import { ruleCatalog } from './scanner.js';
@@ -83,7 +84,7 @@ export function renderSarif(result) {
83
84
  driver: {
84
85
  name: 'Agentic Workflow Guard',
85
86
  informationUri: 'https://github.com/Mughal-Baig/agentic-workflow-guard',
86
- semanticVersion: '1.4.0',
87
+ semanticVersion: '1.5.0',
87
88
  rules: Object.entries(ruleCatalog).map(([id, rule]) => ({
88
89
  id,
89
90
  name: id,
@@ -205,6 +206,10 @@ export function renderBadge(result) {
205
206
  return renderBadgeJson(result);
206
207
  }
207
208
 
209
+ export function renderSurfaceInventory(result) {
210
+ return renderInventory(result);
211
+ }
212
+
208
213
  export function renderGithubAnnotations(result) {
209
214
  if (result.findings.length === 0) {
210
215
  return 'Agentic Workflow Guard: no findings.';
package/src/scanner.js CHANGED
@@ -306,6 +306,13 @@ export function scanMcpConfigText(text, file = '.mcp.json', root = process.cwd()
306
306
  return context.findings;
307
307
  }
308
308
 
309
+ export function classifyScanFile(file, root = process.cwd()) {
310
+ if (isMcpConfigFile(file, root)) return 'mcp-config';
311
+ if (isAgentInstructionFile(file, root)) return 'agent-context';
312
+ if (workflowExtensions.has(path.extname(file))) return 'github-workflow';
313
+ return 'other';
314
+ }
315
+
309
316
  function scanFile(file, root, config) {
310
317
  const text = fs.readFileSync(file, 'utf8');
311
318
  if (isAgentInstructionFile(file, root)) {
@@ -831,6 +838,21 @@ function discoverAgentInstructionFiles(root) {
831
838
  files.push(...walk(githubInstructionsDir).filter((file) => file.endsWith('.instructions.md')));
832
839
  }
833
840
 
841
+ const githubAgentsDir = path.join(root, '.github', 'agents');
842
+ if (fs.existsSync(githubAgentsDir)) {
843
+ files.push(...walk(githubAgentsDir).filter((file) => file.endsWith('.md')));
844
+ }
845
+
846
+ const githubPromptsDir = path.join(root, '.github', 'prompts');
847
+ if (fs.existsSync(githubPromptsDir)) {
848
+ files.push(...walk(githubPromptsDir).filter((file) => file.endsWith('.prompt.md')));
849
+ }
850
+
851
+ const githubSkillsDir = path.join(root, '.github', 'skills');
852
+ if (fs.existsSync(githubSkillsDir)) {
853
+ files.push(...walk(githubSkillsDir).filter((file) => path.basename(file).toLowerCase() === 'skill.md'));
854
+ }
855
+
834
856
  const cursorRulesDir = path.join(root, '.cursor', 'rules');
835
857
  if (fs.existsSync(cursorRulesDir)) {
836
858
  files.push(...walk(cursorRulesDir).filter((file) => ['.md', '.mdc', '.txt'].includes(path.extname(file))));
@@ -859,6 +881,12 @@ function isAgentInstructionFile(file, root) {
859
881
  /\/\.github\/copilot-instructions\.md$/i.test(normalizedFile) ||
860
882
  /^\.github\/instructions\/.+\.instructions\.md$/i.test(relativeFile) ||
861
883
  /\/\.github\/instructions\/.+\.instructions\.md$/i.test(normalizedFile) ||
884
+ /^\.github\/agents\/.+\.md$/i.test(relativeFile) ||
885
+ /\/\.github\/agents\/.+\.md$/i.test(normalizedFile) ||
886
+ /^\.github\/prompts\/.+\.prompt\.md$/i.test(relativeFile) ||
887
+ /\/\.github\/prompts\/.+\.prompt\.md$/i.test(normalizedFile) ||
888
+ /^\.github\/skills\/.+\/skill\.md$/i.test(relativeFile) ||
889
+ /\/\.github\/skills\/.+\/skill\.md$/i.test(normalizedFile) ||
862
890
  /^\.cursor\/rules\/.+\.(?:md|mdc|txt)$/i.test(relativeFile) ||
863
891
  /\/\.cursor\/rules\/.+\.(?:md|mdc|txt)$/i.test(normalizedFile)
864
892
  );