feat: CLI improvements for CI/CD, local development, and security#14
Merged
numman-ali merged 4 commits intomainfrom Dec 14, 2025
Merged
feat: CLI improvements for CI/CD, local development, and security#14numman-ali merged 4 commits intomainfrom
numman-ali merged 4 commits intomainfrom
Conversation
Features: - #3: Support symlinked skill directories in findAllSkills() - #5: Add --output flag to sync for configurable output path - #6: Make --yes flag skip all prompts including overwrites - #10: Support local paths and private git repos for install Security (from PR #8): - Add path traversal protection before cpSync - Use dereference: true to copy symlink targets safely - Fix YAML regex to be non-greedy Changes: - src/utils/skills.ts: Add isDirectoryOrSymlinkToDirectory() helper - src/commands/sync.ts: Add --output option, auto-create file if missing - src/commands/install.ts: Add local path detection, git URL handling, security checks, and pass --yes through to overwrite prompts - src/utils/yaml.ts: Non-greedy regex fix 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Tests added: - tests/utils/skills.test.ts: Symlink support, skill discovery, deduplication - tests/commands/install.test.ts: Local paths, git URLs, path traversal security - tests/commands/sync.test.ts: --output flag, auto-create, utilities - tests/integration/e2e.test.ts: End-to-end CLI tests - tests/utils/yaml.test.ts: Security tests for regex (non-greedy, ReDoS) Coverage: - 88 tests across 6 test files - Unit tests for helper functions - Integration tests for CLI commands - Security tests for path traversal and regex 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changed complex ReturnType<typeof readdirSync<...>> type to simple Dirent import for better TypeScript version compatibility in CI. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
E2E tests require dist/cli.js to exist. Move build step before test step in CI workflow. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR addresses multiple open issues and incorporates security fixes to improve CLI usability for CI/CD pipelines, local development workflows, and overall security.
Issues Covered
✅ #3 - Don't skip symlinked skill directories
What: Added support for symlinked skill directories in
findAllSkills().Why: Users who clone the anthropics/skills repo and symlink skills into
~/.claude/skills/were not having those skills discovered. This enables git-based skill updates and local development workflows.Implementation: Added
isDirectoryOrSymlinkToDirectory()helper insrc/utils/skills.tsthat usesstatSync()to follow symlinks and verify targets are directories. Broken symlinks are gracefully skipped.✅ #5 - Sync & append to
.ruler/AGENT.mdWhat: Added
--output/-oflag to thesynccommand for configurable output path.Why: Users of ruler want to sync skills to
.ruler/AGENTS.mdinstead of the rootAGENTS.md. This also enables any custom output path.Implementation:
--output <path>option to sync command.mdUsage:
✅ #6 -
--yesshould overwriteWhat: Made
--yes/-yflag skip ALL interactive prompts, including overwrite confirmations.Why: Users automating openskills in CI/CD pipelines or scripts couldn't run fully non-interactively because overwrite prompts still appeared even with
-y.Implementation: Added
skipPromptparameter towarnIfConflict()function and passedoptions.yesthrough all install code paths. When skipping, showsOverwriting: <skill-name>message.Usage:
openskills install anthropics/skills -y # Fully non-interactive, overwrites existing✅ #10 - Support local skills and private git repo
What: Added support for installing skills from local paths and private git repositories.
Why: Users wanted to:
Implementation:
isLocalPath()to detect/absolute,./relative,../parent,~/homepathsisGitUrl()to detectgit@,git://,https://, and.gitURLsexpandPath()for tilde expansioninstallFromLocal()andinstallSingleLocalSkill()functionsUsage:
✅ Security Fixes (from PR #8)
Incorporated security fixes from PR #8:
cpSyncto ensure target paths stay within the target directorydereference: truetocpSynccalls to copy symlink targets safely.+to.+?inextractYamlField()to prevent potential issuesIssues NOT Covered (and why)
⏸️ #13 - Support skill switch
Why deferred: This would require persistent state management (config file or marker files) to track enabled/disabled skills. The current architecture is stateless - skills are just directories, and sync regenerates the XML from scratch. Adding toggle state would be a significant architectural change.
⏸️ #9 - Document workflow for updating skills from upstream
Why deferred: This requires storing metadata about where skills were originally installed from. Would need a manifest file or similar. Can revisit after core features stabilize.
Partially addressed: The symlink support (#3) enables local development - users can symlink a skill being developed into their skills directory. Additional convenience commands (
openskills create,openskills promote) could be added later.PRs That Can Be Closed
This PR supersedes:
Test Coverage
Added 77 new tests across 5 test files (88 total):
tests/utils/skills.test.tstests/commands/install.test.tstests/commands/sync.test.tstests/integration/e2e.test.tstests/utils/yaml.test.tsFiles Changed
src/utils/skills.ts- Symlink supportsrc/commands/sync.ts---outputflag, auto-createsrc/commands/install.ts- Local paths, git URLs, security checks, --yes overwritessrc/utils/yaml.ts- Non-greedy regex fixsrc/cli.ts- Added --output option🤖 Generated with Claude Code