feat: CLI improvements for CI/CD, local development, and security #14
+1,233
−49
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