docs(claude): install manual skills at top level (#2160)

* docs(claude): install manual skills at top level

* test(docs): guard Claude manual skill install path

* test(docs): detect PowerShell/$HOME nested skill-install paths

Address CodeRabbit on #2160: the nested-path regression guard only matched
Unix `mkdir`/`cp` with `~`, so a reintroduced PowerShell `Copy-Item ...
$HOME/.claude/skills/ecc` (or backslash-separated) form would have slipped
through. Extend the pattern to also cover `Copy-Item`/`New-Item` (and the
`md`/`copy`/`cpi` aliases), accept `$HOME` as an alternative to `~`, allow both
`/` and `\` separators, and match case-insensitively.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kumario
2026-06-07 00:26:06 -05:00
committed by GitHub
parent be536c1a3e
commit 680cc7153b
4 changed files with 39 additions and 12 deletions
+6 -4
View File
@@ -903,13 +903,15 @@ cp -r rules/arkts ~/.claude/rules/ecc/
# Copy skills first (primary workflow surface) # Copy skills first (primary workflow surface)
# Recommended (new users): core/general skills only # Recommended (new users): core/general skills only
mkdir -p ~/.claude/skills/ecc mkdir -p ~/.claude/skills
cp -r .agents/skills/* ~/.claude/skills/ecc/ cp -r .agents/skills/* ~/.claude/skills/
cp -r skills/search-first ~/.claude/skills/ecc/ cp -r skills/search-first ~/.claude/skills/
# Claude Code loads skills only from direct children of ~/.claude/skills.
# Do not nest manual installs under ~/.claude/skills/ecc/.
# Optional: add niche/framework-specific skills only when needed # Optional: add niche/framework-specific skills only when needed
# for s in django-patterns django-tdd laravel-patterns springboot-patterns quarkus-patterns; do # for s in django-patterns django-tdd laravel-patterns springboot-patterns quarkus-patterns; do
# cp -r skills/$s ~/.claude/skills/ecc/ # cp -r skills/$s ~/.claude/skills/
# done # done
# Optional: keep maintained slash-command compatibility during migration # Optional: keep maintained slash-command compatibility during migration
+6 -4
View File
@@ -896,13 +896,15 @@ cp -r rules/arkts ~/.claude/rules/ecc/
# Zuerst Skills kopieren (primäre Workflow-Oberfläche) # Zuerst Skills kopieren (primäre Workflow-Oberfläche)
# Empfohlen (neue Nutzer): nur Kern-/allgemeine Skills # Empfohlen (neue Nutzer): nur Kern-/allgemeine Skills
mkdir -p ~/.claude/skills/ecc mkdir -p ~/.claude/skills
cp -r .agents/skills/* ~/.claude/skills/ecc/ cp -r .agents/skills/* ~/.claude/skills/
cp -r skills/search-first ~/.claude/skills/ecc/ cp -r skills/search-first ~/.claude/skills/
# Claude Code lädt Skills nur aus direkten Unterverzeichnissen von ~/.claude/skills.
# Manuelle Installationen nicht unter ~/.claude/skills/ecc/ verschachteln.
# Optional: nischen-/framework-spezifische Skills nur bei Bedarf hinzufügen # Optional: nischen-/framework-spezifische Skills nur bei Bedarf hinzufügen
# for s in django-patterns django-tdd laravel-patterns springboot-patterns quarkus-patterns; do # for s in django-patterns django-tdd laravel-patterns springboot-patterns quarkus-patterns; do
# cp -r skills/$s ~/.claude/skills/ecc/ # cp -r skills/$s ~/.claude/skills/
# done # done
# Optional: gepflegte Slash-Command-Kompatibilität während der Migration behalten # Optional: gepflegte Slash-Command-Kompatibilität während der Migration behalten
+6 -4
View File
@@ -832,13 +832,15 @@ cp -r everything-claude-code/rules/php ~/.claude/rules/ecc/
# Сначала скопировать навыки (основной рабочий интерфейс) # Сначала скопировать навыки (основной рабочий интерфейс)
# Рекомендуется для новых пользователей: только core/general skills # Рекомендуется для новых пользователей: только core/general skills
mkdir -p ~/.claude/skills/ecc mkdir -p ~/.claude/skills
cp -r everything-claude-code/.agents/skills/* ~/.claude/skills/ecc/ cp -r everything-claude-code/.agents/skills/* ~/.claude/skills/
cp -r everything-claude-code/skills/search-first ~/.claude/skills/ecc/ cp -r everything-claude-code/skills/search-first ~/.claude/skills/
# Claude Code загружает навыки только из прямых подкаталогов ~/.claude/skills.
# Не вкладывайте ручную установку в ~/.claude/skills/ecc/.
# Опционально: добавляйте нишевые/framework-specific skills только при необходимости # Опционально: добавляйте нишевые/framework-specific skills только при необходимости
# for s in django-patterns django-tdd laravel-patterns springboot-patterns; do # for s in django-patterns django-tdd laravel-patterns springboot-patterns; do
# cp -r everything-claude-code/skills/$s ~/.claude/skills/ecc/ # cp -r everything-claude-code/skills/$s ~/.claude/skills/
# done # done
# Опционально: сохранить поддерживаемую slash-command совместимость во время миграции # Опционально: сохранить поддерживаемую slash-command совместимость во время миграции
+21
View File
@@ -61,6 +61,12 @@ const publicCommandNamespaceDocs = [
'docs/zh-TW/README.md', 'docs/zh-TW/README.md',
]; ];
const manualClaudeSkillInstallDocs = [
'README.md',
'docs/de-DE/README.md',
'docs/ru/README.md',
];
for (const relativePath of pluginAndManualInstallDocs) { for (const relativePath of pluginAndManualInstallDocs) {
const content = fs.readFileSync(path.join(repoRoot, relativePath), 'utf8'); const content = fs.readFileSync(path.join(repoRoot, relativePath), 'utf8');
@@ -96,6 +102,21 @@ for (const relativePath of publicCommandNamespaceDocs) {
}); });
} }
for (const relativePath of manualClaudeSkillInstallDocs) {
const content = fs.readFileSync(path.join(repoRoot, relativePath), 'utf8');
test(`${relativePath} keeps manual Claude skill installs top-level`, () => {
assert.ok(
!/^\s*#?\s*(mkdir\s+-p|md\s+.*|cp\s+.*|copy\s+.*|cpi\s+.*|New-Item\s+.*|Copy-Item\s+.*)\s+.*(~|\$HOME)[\\/]\.claude[\\/]skills[\\/]ecc([\\/]|\b)/mi.test(content),
'Claude Code does not discover skills installed by commands targeting ~/.claude/skills/ecc'
);
assert.ok(
content.includes('~/.claude/skills/'),
'Expected manual install docs to copy skills into direct ~/.claude/skills children'
);
});
}
if (failed > 0) { if (failed > 0) {
console.log(`\nFailed: ${failed}`); console.log(`\nFailed: ${failed}`);
process.exit(1); process.exit(1);