Skip to content

Comments

feat: add .skillignore support for filtering internal skills#375

Open
anthony-maio wants to merge 6 commits intovercel-labs:mainfrom
anthony-maio:feat-skillignore
Open

feat: add .skillignore support for filtering internal skills#375
anthony-maio wants to merge 6 commits intovercel-labs:mainfrom
anthony-maio:feat-skillignore

Conversation

@anthony-maio
Copy link

Added .skillignore support plus test coverage (17 tests)

How it works:

  1. discoverSkills() reads .skillignore from the repo root (basePath)
  2. If patterns exist, skills matching those patterns are filtered out before returning
  3. Supports exact names (internal-tool) and trailing wildcards (test-*)
  4. Missing .skillignore is silently ignored — zero impact on repos without one
  5. Works for --all, --list, interactive selection, and --skill '*' since filtering happens at discovery time

Example .skillignore:

# Hide internal tooling from public discovery
validation-scripts
prompt-eval-*
scaffold-template

Copilot AI review requested due to automatic review settings February 16, 2026 14:10
@vercel
Copy link

vercel bot commented Feb 16, 2026

@anthony-maio is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a77a0b9bfd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds .skillignore support to allow skill repository maintainers to filter out internal or experimental skills from public discovery. The feature reads a .skillignore file from the repository root containing patterns (exact names or trailing wildcards) that determine which skills should be hidden.

Changes:

  • Added new src/skillignore.ts module with parsing and pattern matching logic
  • Integrated .skillignore filtering into the discoverSkills() function in src/skills.ts
  • Added comprehensive unit tests in tests/skillignore.test.ts covering parsing, pattern matching, and file loading

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 8 comments.

File Description
src/skillignore.ts New module implementing .skillignore file parsing, pattern matching (exact and trailing wildcard), and file loading with graceful error handling
src/skills.ts Integrated .skillignore filtering at the end of discoverSkills(), loading patterns from basePath and filtering discovered skills
tests/skillignore.test.ts Unit tests for parseSkillIgnore (17 test cases), isSkillIgnored, and loadSkillIgnorePatterns functions with various edge cases

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 31 to 38
export function isSkillIgnored(skillName: string, patterns: string[]): boolean {
return patterns.some((pattern) => {
if (pattern.endsWith('*')) {
return skillName.startsWith(pattern.slice(0, -1));
}
return skillName === pattern;
});
}
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wildcard pattern matching is safe but limited - it only supports trailing wildcards (e.g., "test-*"). However, the current implementation doesn't validate or sanitize patterns before using them. While the simple startsWith/equals check is safe, consider documenting the supported pattern syntax clearly or adding validation to reject unsupported patterns (like leading wildcards, middle wildcards, or regex patterns) to avoid user confusion.

Copilot uses AI. Check for mistakes.
Comment on lines +84 to +112
describe('loadSkillIgnorePatterns', () => {
let testDir: string;

beforeEach(() => {
testDir = join(tmpdir(), `skillignore-test-${Date.now()}`);
mkdirSync(testDir, { recursive: true });
});

afterEach(() => {
rmSync(testDir, { recursive: true, force: true });
});

it('reads and parses .skillignore file', async () => {
writeFileSync(join(testDir, '.skillignore'), '# Internal tools\ninternal-*\ntest-runner\n');
const patterns = await loadSkillIgnorePatterns(testDir);
expect(patterns).toEqual(['internal-*', 'test-runner']);
});

it('returns empty array when file does not exist', async () => {
const patterns = await loadSkillIgnorePatterns(testDir);
expect(patterns).toEqual([]);
});

it('returns empty array for empty file', async () => {
writeFileSync(join(testDir, '.skillignore'), '');
const patterns = await loadSkillIgnorePatterns(testDir);
expect(patterns).toEqual([]);
});
});
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test suite only includes unit tests for the skillignore parsing and matching functions, but lacks integration tests that verify .skillignore works correctly with the discoverSkills function. Consider adding integration tests that create a test directory structure with skills and a .skillignore file, then verify that discoverSkills correctly filters out the ignored skills. This would help catch issues like the early return path bypassing the filtering logic.

Copilot uses AI. Check for mistakes.
Comment on lines 9 to 10
* internal-tool # exact match
* test-* # trailing wildcard
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation comment at line 9 shows an inline comment after a pattern ("internal-tool # exact match"), but the parseSkillIgnore function does not strip inline comments. This creates a discrepancy between the documented format and the actual implementation. Either update the documentation to show that inline comments are not supported, or update the implementation to handle them.

Copilot uses AI. Check for mistakes.
Copy link

@vercel vercel bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Suggestion:

The .skillignore filtering is bypassed when discoverSkills() takes the early return path (when searchPath directly contains a SKILL.md and fullDepth is not set), allowing skills that should be ignored to be returned.

Fix on Vercel

anthony-maio and others added 3 commits February 16, 2026 09:17
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@anthony-maio
Copy link
Author

@copilot open a new pull request to apply changes based on the comments in this thread

anthony-maio and others added 2 commits February 16, 2026 09:18
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
- Fix early return bypass: .skillignore now filters even when
  discoverSkills() takes the direct SKILL.md early return path
- Load ignore patterns once and reuse across both code paths
- Clarify doc comment to document inline comment support
- Add 4 integration tests verifying discoverSkills() respects
  .skillignore (pattern filtering, early return, includeInternal bypass)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant