Skip to content

Commit 5356ec8

Browse files
mglamanclaude
andauthored
fix: install drupalorg-issue-summary-update skill via skill:install (#307)
* fix: install drupalorg-issue-summary-update skill via skill:install The skill existed in skills/ but was never copied to the destination in the Install command. Add it alongside the existing drupalorg-cli and drupal-work-on-issue installs. Fixes #306 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: auto-discover skills instead of hard-coding each one Extract a private installSkill() method and iterate the skills/ directory so new skills are installed automatically without touching Install.php. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 1cf9774 commit 5356ec8

1 file changed

Lines changed: 33 additions & 38 deletions

File tree

src/Cli/Command/Skill/Install.php

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,45 +13,62 @@ protected function configure(): void
1313
{
1414
$this
1515
->setName('skill:install')
16-
->setDescription('Installs the drupalorg-cli agent skill into .claude/skills/drupalorg-cli/ in the current directory.');
16+
->setDescription('Installs all drupalorg-cli agent skills into .claude/skills/ in the current directory.');
1717
}
1818

1919
protected function execute(InputInterface $input, OutputInterface $output): int
2020
{
21-
$skillSourceDir = __DIR__ . '/../../../../skills/drupalorg-cli';
21+
$skillsRootSrc = __DIR__ . '/../../../../skills';
2222
$cwd = (string) getcwd();
23-
$destDir = $cwd . DIRECTORY_SEPARATOR . '.claude' . DIRECTORY_SEPARATOR . 'skills' . DIRECTORY_SEPARATOR . 'drupalorg-cli';
23+
$skillsRootDest = $cwd . DIRECTORY_SEPARATOR . '.claude' . DIRECTORY_SEPARATOR . 'skills';
2424

25+
foreach (new \DirectoryIterator($skillsRootSrc) as $skillDir) {
26+
if ($skillDir->isDot() || !$skillDir->isDir()) {
27+
continue;
28+
}
29+
$result = $this->installSkill(
30+
$skillDir->getPathname(),
31+
$skillsRootDest . DIRECTORY_SEPARATOR . $skillDir->getFilename()
32+
);
33+
if ($result !== 0) {
34+
return $result;
35+
}
36+
}
37+
38+
return 0;
39+
}
40+
41+
private function installSkill(string $srcDir, string $destDir): int
42+
{
2543
if (!is_dir($destDir) && !mkdir($destDir, 0755, true) && !is_dir($destDir)) {
2644
$this->stdErr->writeln(sprintf('<error>Failed to create directory: %s</error>', $destDir));
2745
return 1;
2846
}
2947

30-
$skillMdSrc = $skillSourceDir . DIRECTORY_SEPARATOR . 'SKILL.md';
31-
$skillMdDest = $destDir . DIRECTORY_SEPARATOR . 'SKILL.md';
32-
$content = file_get_contents($skillMdSrc);
48+
$srcFile = $srcDir . DIRECTORY_SEPARATOR . 'SKILL.md';
49+
$destFile = $destDir . DIRECTORY_SEPARATOR . 'SKILL.md';
50+
$content = file_get_contents($srcFile);
3351
if ($content === false) {
34-
$this->stdErr->writeln(sprintf('<error>Could not read skill source: %s</error>', $skillMdSrc));
52+
$this->stdErr->writeln(sprintf('<error>Could not read skill source: %s</error>', $srcFile));
3553
return 1;
3654
}
37-
if (file_put_contents($skillMdDest, $content) === false) {
38-
$this->stdErr->writeln(sprintf('<error>Failed to write skill file: %s</error>', $skillMdDest));
55+
if (file_put_contents($destFile, $content) === false) {
56+
$this->stdErr->writeln(sprintf('<error>Failed to write skill file: %s</error>', $destFile));
3957
return 1;
4058
}
41-
$this->stdOut->writeln(sprintf('<comment>Skill installed to %s</comment>', $skillMdDest));
59+
$this->stdOut->writeln(sprintf('<comment>Skill installed to %s</comment>', $destFile));
60+
61+
$refSrcDir = $srcDir . DIRECTORY_SEPARATOR . 'references';
62+
if (!is_dir($refSrcDir)) {
63+
return 0;
64+
}
4265

43-
$refSrcDir = $skillSourceDir . DIRECTORY_SEPARATOR . 'references';
4466
$refDestDir = $destDir . DIRECTORY_SEPARATOR . 'references';
4567
if (!is_dir($refDestDir) && !mkdir($refDestDir, 0755, true) && !is_dir($refDestDir)) {
4668
$this->stdErr->writeln(sprintf('<error>Failed to create directory: %s</error>', $refDestDir));
4769
return 1;
4870
}
4971

50-
if (!is_dir($refSrcDir) || !is_readable($refSrcDir)) {
51-
$this->stdErr->writeln(sprintf('<error>Skill references directory is missing or not readable: %s</error>', $refSrcDir));
52-
return 1;
53-
}
54-
5572
try {
5673
foreach (new \DirectoryIterator($refSrcDir) as $fileInfo) {
5774
if ($fileInfo->isDot() || !$fileInfo->isFile() || $fileInfo->getExtension() !== 'md') {
@@ -83,28 +100,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int
83100
return 1;
84101
}
85102

86-
// Install the standalone /drupal-work-on-issue skill.
87-
$woiSrcDir = __DIR__ . '/../../../../skills/drupal-work-on-issue';
88-
$woiDestDir = $cwd . DIRECTORY_SEPARATOR . '.claude' . DIRECTORY_SEPARATOR . 'skills' . DIRECTORY_SEPARATOR . 'drupal-work-on-issue';
89-
90-
if (!is_dir($woiDestDir) && !mkdir($woiDestDir, 0755, true) && !is_dir($woiDestDir)) {
91-
$this->stdErr->writeln(sprintf('<error>Failed to create directory: %s</error>', $woiDestDir));
92-
return 1;
93-
}
94-
95-
$woiSrc = $woiSrcDir . DIRECTORY_SEPARATOR . 'SKILL.md';
96-
$woiDest = $woiDestDir . DIRECTORY_SEPARATOR . 'SKILL.md';
97-
$woiContent = file_get_contents($woiSrc);
98-
if ($woiContent === false) {
99-
$this->stdErr->writeln(sprintf('<error>Could not read skill source: %s</error>', $woiSrc));
100-
return 1;
101-
}
102-
if (file_put_contents($woiDest, $woiContent) === false) {
103-
$this->stdErr->writeln(sprintf('<error>Failed to write skill file: %s</error>', $woiDest));
104-
return 1;
105-
}
106-
$this->stdOut->writeln(sprintf('<comment>Skill installed to %s</comment>', $woiDest));
107-
108103
return 0;
109104
}
110105
}

0 commit comments

Comments
 (0)