feat(cli): Support multiple skill names in dotagents add#34
Conversation
Allow users to specify multiple skills in a single command via positional args or repeated flags: dotagents add getsentry/skills foo bar baz dotagents add getsentry/skills --skill foo --skill bar All names are validated before any are added, so the command fails fast without partially modifying agents.toml. Mixing positional and flag styles is rejected as ambiguous. Co-Authored-By: Claude <noreply@anthropic.com> Agent transcript: https://claudescope.sentry.dev/share/MXM32cSDqKcIy1BXuoyD2rugHb-9BSGjQK9dFkbZVEE
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Separate the duplicate-check loop from the write loop so that adding ["review", "pdf"] when "pdf" already exists throws before "review" is written. Strengthens the no-partial-writes test to verify this. Co-Authored-By: Claude <noreply@anthropic.com> Agent transcript: https://claudescope.sentry.dev/share/eUGVONR7uFczu2YTLpOCf6BB_R8NjPTYXv3d9fdKVIU
…names Local sources (`path:...`) silently dropped all but the first skill name when multiple were specified. Now handles multiple names with the same fail-fast pattern used by git sources. Also validates user-provided skill names against VALID_SKILL_NAME regex before filesystem operations to prevent path traversal. Agent transcript: https://claudescope.sentry.dev/share/a9EaNPenz3RIDwLtbF9twJfshWmM91QsVqXmClvs2_o
| const found = await discoverSkill(cached.repoDir, nameOverride); | ||
| if (!found) { | ||
| throw new AddError( | ||
| `Skill "${nameOverride}" not found in ${sourceForStorage}. ` + |
There was a problem hiding this comment.
Local add mis-handles named skill paths
Medium Severity
For local sources with names provided, the code verifies existence via discoverSkill(localDir, name). If the specifier already points at a specific skill directory (common for local adds), localDir is the skill dir and discoverSkill may look for a nested skill and fail, rejecting valid inputs.
| const { join: pathJoin } = await import("node:path"); | ||
| const meta = await loadSkillMd(pathJoin(localDir, "SKILL.md")); | ||
| skillName = meta.name; | ||
| } |
There was a problem hiding this comment.
Local sources lack multi-skill selection flow
Medium Severity
When parsed.type === "local" and no names are provided, the implementation always reads SKILL.md from localDir and never runs the “discover all skills and pick/error” flow used for git sources. Local directories that contain multiple skills now have no way to auto-select/prompt/error consistently.
Covers single skill, multiple skills, not-found, fail-fast, and no-partial-writes scenarios for path: sources. Agent transcript: https://claudescope.sentry.dev/share/YwI-sFYZtk86f7RWMZ6uRD9EHB0KnT0fDf3c4NDbfOU
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| } | ||
| await runInstall({ scope }); | ||
| return namesOverride; | ||
| } |
There was a problem hiding this comment.
Multi-name write logic duplicated across source types
Low Severity
The multi-name duplicate-check-then-write block (iterate namesOverride to check config duplicates, iterate again to call addSkillToConfig, call runInstall, return) is copy-pasted identically between the local-source branch and the git-source branch. If the write/validation logic ever needs a fix (e.g., adjusting the duplicate check or adding ref handling), it would need to be applied in both places independently, risking divergence.
Additional Locations (1)
| // --all: add a wildcard entry | ||
| if (all) { | ||
| if (nameOverride) { | ||
| if (namesOverride?.length) { |
There was a problem hiding this comment.
Error message references only --name despite broader triggers
Low Severity
The --all conflict error message still says "Cannot use --all with --name" but namesOverride is now populated from positional args and --skill flags too, not just --name. A user running dotagents add source foo --all (positional) gets told they used --name, which they didn't. The message at line 254 was already updated to mention all input methods, but this one was missed.


Allow users to specify multiple skills in a single
dotagents addcommandinstead of running the command once per skill or going through the interactive
picker:
Both
--skilland--nameflags now acceptmultiple: trueinparseArgs.Positional skill names (args after the specifier) are also collected. Mixing
the two styles is rejected as ambiguous.
When multiple names are provided,
runAddvalidates every name exists in thesource repo before writing anything to
agents.toml, so the command failsfast without partial modifications. The repo is cloned/cached once and
install()runs once at the end.Includes 12 integration tests covering single/multi name add, fail-fast
behavior, duplicate detection,
--allconflict, auto-select for single-skillrepos, non-interactive multi-skill error, and CLI arg parsing (positional,
flags, mixed).
Agent transcript: https://claudescope.sentry.dev/share/19ET9OTfeJa25YBYiHPQ_LbdgfE7hYZY19AB0NkWm4M