MCP HubMCP Hub
Retour aux compétences

audit-discovery-symlinks

pjt222
Mis à jour 2 days ago
1 vues
17
2
17
Voir sur GitHub
Métaaidesign

À propos

Cette compétence audite et répare les liens symboliques de découverte de Claude Code en comparant les registres aux répertoires .claude/ pour détecter les liens manquants, cassés ou superflus. Elle distingue le contenu de l'almanach des projets externes et peut optionnellement réparer les problèmes de synchronisation. Utilisez-la après l'ajout de nouvelles compétences/agents, des modifications du dépôt, ou lorsque les commandes slash cessent de fonctionner, comme une vérification de maintenance.

Installation rapide

Claude Code

Recommandé
Principal
npx skills add pjt222/agent-almanac -a claude-code
Commande PluginAlternatif
/plugin add https://github.com/pjt222/agent-almanac
Git CloneAlternatif
git clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/audit-discovery-symlinks

Copiez et collez cette commande dans Claude Code pour installer cette compétence

Documentation

audit-discovery-symlinks

使用タイミング

  • almanac に新しいスキル、エージェント、チームを追加した後
  • 絶対パス symlink を壊しうるリポジトリのリネーム・移動後
  • Claude Code でスラッシュコマンドやエージェントが見つからないとき
  • レジストリと検出パス間のドリフトを捕まえるための定期的な健全性チェックとして
  • 共有 almanac コンテンツを発見すべき新規プロジェクトのオンボーディング時

使用しない: ゼロから初期 symlink ハブを作成する場合。初回セットアップは symlink-architecture guide を参照。

入力

ParameterTypeRequiredDescription
almanac_pathstringNoagent-almanac ルートの絶対パス。省略時は .claude/ symlink ターゲットまたは cwd から自動検出
scopeenumNoprojectglobalboth(既定: both
fix_modeenumNoreport(既定: 監査のみ)、auto(安全な問題をすべて修正)、interactive(各修正前にプロンプト)

手順

ステップ1: Almanac パスを特定する

agent-almanac ルートディレクトリを見つける。

# Auto-detect from current project's .claude/agents symlink
ALMANAC_PATH=$(readlink -f .claude/agents 2>/dev/null | sed 's|/agents$||')

# Fallback: check if cwd is the almanac
if [ -z "$ALMANAC_PATH" ] || [ ! -f "$ALMANAC_PATH/skills/_registry.yml" ]; then
  if [ -f "skills/_registry.yml" ]; then
    ALMANAC_PATH=$(pwd)
  fi
fi

# Fallback: check global agents symlink
if [ -z "$ALMANAC_PATH" ] || [ ! -f "$ALMANAC_PATH/skills/_registry.yml" ]; then
  ALMANAC_PATH=$(readlink -f ~/.claude/agents 2>/dev/null | sed 's|/agents$||')
fi

echo "Almanac path: $ALMANAC_PATH"

期待結果: ALMANAC_PATHskills/_registry.ymlagents/_registry.ymlteams/_registry.yml を含むディレクトリを指している。

失敗時: 自動検出が失敗したらユーザーに almanac_path 入力を求める。almanac ルートは skills/agents/teams/ とそれらのレジストリを含むディレクトリ。

ステップ2: レジストリをインベントリする

スキル、エージェント、チームの正規リストをそれぞれのレジストリから抽出する。

# Count registered skills (entries with "- id:" under domain sections)
REGISTERED_SKILLS=$(grep '^ \{6\}- id:' "$ALMANAC_PATH/skills/_registry.yml" | awk '{print $3}' | sort)
REGISTERED_SKILL_COUNT=$(echo "$REGISTERED_SKILLS" | wc -l)

# Count registered agents
REGISTERED_AGENTS=$(grep '^ \{2\}- id:' "$ALMANAC_PATH/agents/_registry.yml" | awk '{print $3}' | sort)
REGISTERED_AGENT_COUNT=$(echo "$REGISTERED_AGENTS" | wc -l)

# Count registered teams
REGISTERED_TEAMS=$(grep '^ \{2\}- id:' "$ALMANAC_PATH/teams/_registry.yml" | awk '{print $3}' | sort)
REGISTERED_TEAM_COUNT=$(echo "$REGISTERED_TEAMS" | wc -l)

echo "Registered: $REGISTERED_SKILL_COUNT skills, $REGISTERED_AGENT_COUNT agents, $REGISTERED_TEAM_COUNT teams"

期待結果: カウントが各レジストリヘッダの total_skillstotal_agentstotal_teams 値と一致する。

失敗時: カウントがヘッダの合計と乖離する場合、レジストリ自体が同期していない。レポートに不一致を記しつつ、実際の - id: エントリを真実の源として続行する。

ステップ3: プロジェクトレベルの symlink を監査する

カレントプロジェクトディレクトリの .claude/skills/*.claude/agents.claude/teams を確認する。

PROJECT_CLAUDE=".claude"

# --- Skills ---
# Items on disk (excluding _template)
PROJECT_SKILLS=$(ls "$PROJECT_CLAUDE/skills/" 2>/dev/null | grep -v '^_template$' | sort)
PROJECT_SKILL_COUNT=$(echo "$PROJECT_SKILLS" | grep -c .)

# Missing: in registry but not in project .claude/skills/
MISSING_PROJECT_SKILLS=$(comm -23 <(echo "$REGISTERED_SKILLS") <(echo "$PROJECT_SKILLS"))

# Broken: symlink exists but target doesn't resolve
BROKEN_PROJECT_SKILLS=$(find "$PROJECT_CLAUDE/skills/" -maxdepth 1 -type l ! -exec test -e {} \; -printf '%f\n' 2>/dev/null | sort)

# Extraneous: in project but not in registry (and not external)
EXTRA_PROJECT_SKILLS=$(comm -13 <(echo "$REGISTERED_SKILLS") <(echo "$PROJECT_SKILLS"))

# --- Agents ---
if [ -L "$PROJECT_CLAUDE/agents" ] || [ -d "$PROJECT_CLAUDE/agents" ]; then
  PROJECT_AGENT_STATUS="OK"
  test -d "$PROJECT_CLAUDE/agents" || PROJECT_AGENT_STATUS="BROKEN"
  PROJECT_AGENT_COUNT=$(ls "$PROJECT_CLAUDE/agents/"*.md 2>/dev/null | wc -l)
else
  PROJECT_AGENT_STATUS="MISSING"
  PROJECT_AGENT_COUNT=0
fi

# --- Teams ---
# Teams are NOT symlinked. TeamCreate uses ~/.claude/teams/ for runtime state.
# A .claude/teams symlink is a misconfiguration — warn if found.
if [ -L "$PROJECT_CLAUDE/teams" ]; then
  PROJECT_TEAM_STATUS="MISCONFIGURED"
  PROJECT_TEAM_COUNT=0
  # Stale symlink — should be removed to avoid collision with TeamCreate
else
  PROJECT_TEAM_STATUS="OK"
  PROJECT_TEAM_COUNT=0
fi

期待結果: 欠落ゼロ、破損ゼロ。余剰項目は分類され説明される。

失敗時: .claude/ がそもそも存在しない場合、プロジェクトには検出セットアップがない。これを記してグローバル監査へスキップする。

ステップ4: グローバル symlink を監査する

~/.claude/skills/*~/.claude/agents を確認する。また、~/.claude/teams が symlink でないことも確認する(TeamCreate のランタイム状態用に欠落しているかディレクトリであるべき)。

GLOBAL_CLAUDE="$HOME/.claude"

# --- Skills ---
GLOBAL_SKILLS_ALL=$(ls "$GLOBAL_CLAUDE/skills/" 2>/dev/null | sort)

# Classify each entry: almanac vs external
ALMANAC_GLOBAL_SKILLS=""
EXTERNAL_GLOBAL_SKILLS=""
for item in $GLOBAL_SKILLS_ALL; do
  target=$(readlink -f "$GLOBAL_CLAUDE/skills/$item" 2>/dev/null)
  if [ -z "$target" ]; then
    # Real directory (not a symlink) — external
    EXTERNAL_GLOBAL_SKILLS="$EXTERNAL_GLOBAL_SKILLS $item"
  elif echo "$target" | grep -q "^$ALMANAC_PATH"; then
    ALMANAC_GLOBAL_SKILLS="$ALMANAC_GLOBAL_SKILLS $item"
  else
    EXTERNAL_GLOBAL_SKILLS="$EXTERNAL_GLOBAL_SKILLS $item"
  fi
done

# Filter: _template is always extraneous for almanac content
ALMANAC_GLOBAL_SKILLS=$(echo "$ALMANAC_GLOBAL_SKILLS" | tr ' ' '\n' | grep -v '^_template$' | grep -v '^$' | sort)

# Missing: in registry but not in global almanac skills
MISSING_GLOBAL_SKILLS=$(comm -23 <(echo "$REGISTERED_SKILLS") <(echo "$ALMANAC_GLOBAL_SKILLS"))

# Broken: symlink exists but target doesn't resolve
BROKEN_GLOBAL_SKILLS=$(find "$GLOBAL_CLAUDE/skills/" -maxdepth 1 -type l ! -exec test -e {} \; -printf '%f\n' 2>/dev/null | sort)

# Stale almanac entries: in global almanac set but not in registry
STALE_GLOBAL_SKILLS=$(comm -13 <(echo "$REGISTERED_SKILLS") <(echo "$ALMANAC_GLOBAL_SKILLS"))

# --- Agents ---
if [ -L "$GLOBAL_CLAUDE/agents" ] || [ -d "$GLOBAL_CLAUDE/agents" ]; then
  GLOBAL_AGENT_STATUS="OK"
  test -d "$GLOBAL_CLAUDE/agents" || GLOBAL_AGENT_STATUS="BROKEN"
  GLOBAL_AGENT_COUNT=$(ls "$GLOBAL_CLAUDE/agents/"*.md 2>/dev/null | wc -l)
else
  GLOBAL_AGENT_STATUS="MISSING"
  GLOBAL_AGENT_COUNT=0
fi

# --- Teams ---
# Teams are NOT symlinked. TeamCreate uses ~/.claude/teams/ for runtime state.
# A ~/.claude/teams symlink is a misconfiguration — warn if found.
if [ -L "$GLOBAL_CLAUDE/teams" ]; then
  GLOBAL_TEAM_STATUS="MISCONFIGURED"
  GLOBAL_TEAM_COUNT=0
  # Stale symlink — should be removed to avoid collision with TeamCreate
else
  GLOBAL_TEAM_STATUS="OK"
  GLOBAL_TEAM_COUNT=0
fi

期待結果: almanac スキルの欠落ゼロ、破損ゼロ。外部コンテンツ(peon-ping など)は列挙されるがエラーとはみなされない。

失敗時: ~/.claude/ が存在しない場合、グローバルハブはセットアップされていない。初期セットアップは symlink-architecture guide を参照。

ステップ5: 監査レポートを生成する

両層をカバーする概要表を作成する。

# Discovery Symlink Audit Report

**Date**: YYYY-MM-DD
**Almanac**: <almanac_path>
**Scope**: both | project | global

## Summary

| Content | Registered | Project | Global (almanac) | Global (external) |
|---------|------------|---------|-------------------|-------------------|
| Skills  | N          | N       | N                 | N                 |
| Agents  | N          | STATUS  | STATUS            | —                 |
| Teams   | N          | STATUS  | STATUS            | —                 |

## Issues

### Missing (registered but no symlink)
- Project skills: [list or "none"]
- Global skills: [list or "none"]

### Broken (symlink exists, target gone)
- Project: [list or "none"]
- Global: [list or "none"]

### Extraneous
- Stale almanac (in discovery but not registry): [list or "none"]
- _template in discovery path: [yes/no]
- External content (non-almanac): [list — informational only]

期待結果: 明確で実行可能なレポート。問題ゼロは健全性の証明。

失敗時: レポート生成自体が失敗する場合、フォールバックとして生のカウントとリストをコンソールに出力する。

ステップ6: 修復(任意)

fix_modeauto または interactive なら、見つかった問題を修正する。

6a. 欠落しているプロジェクト symlink を作成:

for skill in $MISSING_PROJECT_SKILLS; do
  ln -s "../../skills/$skill" "$PROJECT_CLAUDE/skills/$skill"
done

6b. 欠落しているグローバル symlink を作成:

for skill in $MISSING_GLOBAL_SKILLS; do
  ln -s "$ALMANAC_PATH/skills/$skill" "$GLOBAL_CLAUDE/skills/$skill"
done

6c. 破損 symlink を削除:

# Project
for broken in $BROKEN_PROJECT_SKILLS; do
  rm "$PROJECT_CLAUDE/skills/$broken"
done

# Global
for broken in $BROKEN_GLOBAL_SKILLS; do
  rm "$GLOBAL_CLAUDE/skills/$broken"
done

6d. 古い almanac エントリを削除:

# Only remove items that target the almanac path but aren't in the registry
for stale in $STALE_GLOBAL_SKILLS; do
  rm "$GLOBAL_CLAUDE/skills/$stale"
done

# Remove _template if present
rm -f "$GLOBAL_CLAUDE/skills/_template"
rm -f "$PROJECT_CLAUDE/skills/_template"

6e. 欠落ディレクトリ symlink(agents/teams)を修正:

# Project agents
if [ "$PROJECT_AGENT_STATUS" = "MISSING" ]; then
  ln -s ../agents "$PROJECT_CLAUDE/agents"
fi

# Project teams
if [ "$PROJECT_TEAM_STATUS" = "MISSING" ]; then
  ln -s ../teams "$PROJECT_CLAUDE/teams"
fi

# Global agents
if [ "$GLOBAL_AGENT_STATUS" = "MISSING" ]; then
  ln -s "$ALMANAC_PATH/agents" "$GLOBAL_CLAUDE/agents"
fi

# Global teams
if [ "$GLOBAL_TEAM_STATUS" = "MISSING" ]; then
  ln -sf "$ALMANAC_PATH/teams" "$GLOBAL_CLAUDE/teams"
fi

重要: 外部に分類された項目は決して削除しない。これらは他プロジェクト(例: peon-ping)に属し、保護されなければならない。

期待結果: 欠落 symlink がすべて作成され、破損 symlink がすべて削除され、古い almanac エントリがすべて掃除される。外部コンテンツは触れられない。

失敗時: ターゲットパスに既存のファイル/ディレクトリがあり ln -s が失敗する場合(例: symlink ではなく空ディレクトリ)、まず rmdir(空ディレクトリ用)でブロッカーを除去するか、手動レビュー用にフラグを立てる(非空ディレクトリ用)。

ステップ7: 検証

ステップ3-4の監査チェックを再実行して修復を確認する。

echo "=== Post-repair verification ==="
echo "Project skills: $(ls "$PROJECT_CLAUDE/skills/" 2>/dev/null | grep -v '^_template$' | wc -l)"
echo "Global skills (almanac): $(echo "$ALMANAC_GLOBAL_SKILLS" | wc -w)"
echo "Broken project: $(find "$PROJECT_CLAUDE/skills/" -maxdepth 1 -type l ! -exec test -e {} \; -print 2>/dev/null | wc -l)"
echo "Broken global:  $(find "$GLOBAL_CLAUDE/skills/" -maxdepth 1 -type l ! -exec test -e {} \; -print 2>/dev/null | wc -l)"
echo "Project agents: $PROJECT_AGENT_STATUS ($PROJECT_AGENT_COUNT .md files)"
echo "Global agents:  $GLOBAL_AGENT_STATUS ($GLOBAL_AGENT_COUNT .md files)"
echo "Project teams:  $PROJECT_TEAM_STATUS ($PROJECT_TEAM_COUNT .md files)"
echo "Global teams:   $GLOBAL_TEAM_STATUS ($GLOBAL_TEAM_COUNT .md files)"

期待結果: 欠落ゼロ、破損ゼロ。カウントは登録済み合計と一致する(almanac コンテンツについて)。外部コンテンツは別途列挙される。

失敗時: 修復後も問題が残る場合、具体的な失敗をレポートする。よくある原因: ~/.claude/ の権限エラー、/mnt/ パスの NTFS パス長制限、symlink 作成を阻む非空ディレクトリ。

バリデーション

  • Almanac パスが正しく特定され、3 つのレジストリすべてを含む
  • レジストリカウントが total_* ヘッダ値と一致する(または不一致が記されている)
  • プロジェクトレベルのスキル、エージェント、チームが監査されている
  • グローバルレベルのスキル、エージェント、チームが監査されている
  • 外部コンテンツ(非 almanac)が特定され、問題カウントから除外されている
  • _template エントリが余剰としてフラグされている(検出パスには決して属さない)
  • 監査レポートが明確なカウントと実行可能なリストと共に生成されている
  • fix_modeauto の場合: すべての安全な修復が適用され、外部コンテンツは触れられていない
  • 修復後の検証で欠落ゼロ、破損ゼロが確認されている

よくある落とし穴

  1. 外部コンテンツを欠落 almanac コンテンツと混同する: ~/.claude/skills/ には他プロジェクトのスキル(例: peon-ping)が含まれる場合がある。古いまたは余剰と分類する前に、symlink ターゲットが almanac パスの下にあるかを必ず確認する。

  2. 外部コンテンツの削除: almanac を指していない項目は決して削除しない。それらは他プロジェクトに属し意図的にそこにある。

  3. _template ディレクトリの symlink 化: テンプレートはスキャフォールディングであり消費されるコンテンツではない。_template ディレクトリは .claude/skills/.claude/agents/ には決して現れるべきでない。一括同期スクリプトはこれを明示的にスキップしなければならない。

  4. 古い .claude/teams symlink: チーム定義を指す .claude/teams symlink は誤設定である。Claude Code の TeamCreate~/.claude/teams/ をランタイム状態(config.json、inboxes)に使用する。このパスが almanac の teams/ ディレクトリへの symlink なら、ランタイム成果物が git 管理下のリポジトリに書き込まれる。プロジェクトまたはグローバルレベルで見つかった .claude/teams symlink は除去する。

  5. 相対パスと絶対パス: プロジェクトレベルのスキル symlink は相対パス(../../skills/<name>)を使う。グローバル symlink は絶対パス(/path/to/almanac/skills/<name>)を使う。これらのパターンを混在させると移動時に破損する。

  6. レジストリヘッダ vs 実際のカウント: レジストリヘッダの total_skills フィールドは、誰かがカウント更新なしにエントリを追加すると古くなりうる。ヘッダではなく実際の - id: エントリを信頼する。

関連スキル

Dépôt GitHub

pjt222/agent-almanac
Chemin: i18n/ja/skills/audit-discovery-symlinks
0
agentsagentskillsai-assisted-developmentclaude-codeskillsteams

Compétences associées

content-collections

Méta

Cette compétence propose une configuration éprouvée en production pour Content Collections, un outil axé sur TypeScript qui transforme des fichiers Markdown/MDX en collections de données typées de manière sûre avec une validation Zod. Utilisez-la lors de la création de blogs, de sites de documentation ou d'applications Vite + React riches en contenu pour garantir la sécurité de typage et la validation automatique du contenu. Elle couvre tout, de la configuration du plugin Vite et de la compilation MDX à l'optimisation des déploiements et la validation des schémas.

Voir la compétence

polymarket

Méta

Cette compétence permet aux développeurs de créer des applications avec la plateforme de marchés prédictifs Polymarket, incluant l'intégration d'API pour le trading et les données de marché. Elle fournit également une diffusion de données en temps réel via WebSocket pour surveiller les transactions en direct et l'activité du marché. Utilisez-la pour mettre en œuvre des stratégies de trading ou pour créer des outils traitant les mises à jour de marché en direct.

Voir la compétence

creating-opencode-plugins

Méta

Cette compétence aide les développeurs à créer des plugins OpenCode qui s'interconnectent avec plus de 25 types d'événements tels que les commandes, les fichiers et les opérations LSP. Elle fournit la structure du plugin, les spécifications de l'API événementielle et les modèles d'implémentation pour les modules JavaScript/TypeScript. Utilisez-la lorsque vous avez besoin d'intercepter, de surveiller ou d'étendre le cycle de vie de l'assistant IA OpenCode avec une logique personnalisée pilotée par les événements.

Voir la compétence

sglang

Méta

SGLang est un framework de service LLM haute performance spécialisé dans la génération rapide et structurée pour les workflows JSON, regex et agentiques grâce à son cache de préfixe RadixAttention. Il offre une inférence nettement plus rapide, particulièrement pour les tâches avec des préfixes répétés, ce qui le rend idéal pour les sorties complexes et structurées ainsi que les conversations multi-tours. Choisissez SGLang plutôt que des alternatives comme vLLM lorsque vous avez besoin d'un décodage contraint ou que vous construisez des applications avec un partage étendu de préfixes.

Voir la compétence