mcpField
S
skill-authoring

skill-authoring

github.com/theodoreadエージェントワークフロー039 回インストール4 週間前に更新
リポジトリ

skill-authoring について

skill-authoringは、Agent Skillsの作成、保守、インストール、検証を支援するスキルです。編集内容をエージェントに反映するため、ソースの確認、再インストール、再読み込みまで扱います。

主な機能

  1. 01スキル形式とフロントマターの説明
  2. 02ソースを基準にした編集・公開手順
  3. 03インストール・再読み込み・検証
  4. 04スキル名の重複チェック

活用シーン

  1. 01共有スキルリポジトリでのスキル作成
  2. 02インストール済みスキルの更新反映
  3. 03採用前のスキル名の重複確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/theodoread/agent-skills --skill skill-authoring

インストール後、Claude Code で/skill-authoringを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
naming.md
rationale.md
scripts/
names.py

詳細

Agent Skills の作成と更新

スキルは、ルートに SKILL.md を置いたディレクトリです。YAML フロントマターと Markdown の指示で構成されます。 references/ には必要に応じて読み込むものを、scripts/ にはスキルが実行するものを格納します。形式はこれだけで、Agent Skills の規約に対応するすべてのエージェントが読み取ります。

フロントマターには仕様で定められた6つのキーだけを指定します。すべてのエージェントが照合に使う name と description、license、最大500文字の環境要件を記載する compatibility(スキルの対象となる製品、必要なシステムパッケージ、ネットワークに接続するかどうか)、仕様で定義されていない情報を記載する文字列から文字列へのマップ metadata、そして実験的な allowed-tools です。スクリプトを含むスキル、またはセッションのリポジトリ外への書き込みを指示するスキルでは compatibility を使い、純粋な規約スキルでは省略してください。仕様の注記にも、ほとんどのスキルでこれは不要とあります。metadata のキーは、説明を自分で定めるものです。つまり、まずリポジトリの指示でその判断を記録してください。ここでは metadata: family: がその場しのぎで追加されましたが、どこからも参照されていなかったため削除しました。

このスキルでは、スキルの作成と、実際に問題が起きやすい、変更を反映させる方法を扱います。

このスキルが読み取り、実行し、書き込むもの

このスキルには、スキルのディレクトリを読み取り、公開検索エンドポイントに問い合わせるスクリプト scripts/names.py が1つ含まれています。それ以外に操作するものはすべて、実行するよう指示するコマンドを通じて操作します。

  • 読み取り:scripts/names.py は、指定したルートの下にある各スキルの SKILL.md を読み取ります。デフォルトではローダー自身のスコープである ~/.agents/skills/ と、プロジェクトの .agents/skills/ が対象です。取得するのは名前とファイルのダイジェストだけです。トランスクリプト、プロセス、Git の状態は取得しません。
  • 実行:npx skills add、skills ls、skills remove、および以下の測定に使用する skill-fitness のスクリプトです。names.py はシェルコマンドを一切実行しません。
  • 書き込み:skills add --global はスキルを ~/.agents/skills/ にコピーし、検出した各エージェント固有のスキルディレクトリをそこにリンクします。--global を指定せず、リポジトリ内で実行した場合は、作業ツリーに .agents/skills/、.claude/skills のシンボリックリンク、skills-lock.json を書き込みます。そのため、ここではこのフラグを省略できません。インストーラーがリンクを作成しなかった場合に提案する ln -s ~/.agents/skills ~/.claude/skills は、シンボリックリンクを1つ作成します。それ以外は何も書き込みません。
  • ネットワーク:skills add <owner>/<repo> は、指定したリポジトリをクローンします。names.py は skills.sh/api/search に問い合わせます。名前ごとに1回 GET リクエストを送り、送信するのは名前だけです。ただし、--offline を指定するとネットワークを使いません。

スキルの更新と再デプロイ

~/.agents/skills/<name>/(またはエージェント固有のディレクトリ、あるいはプロジェクトの .agents/skills/)にあるコピーは、ソースではありません。 インストール時に作成された単なるファイルコピーです。編集すると変更が反映されたように見えますが、次回のインストールで上書きされ、ほかのプロジェクトやマシンには反映されず、差分もコミットも変更内容のレビューもありません。スキルを編集するときは、必ず最初にソースリポジトリを探してください。

  1. ソースを探します。 通常は README またはスキルの末尾に記載されています。見つからない場合は、skills ls でインストール済みのものとその入手元を確認できます。リポジトリは通常の git clone ですぐに取得できます。スキルを所有するリポジトリが特定できない場合は、インストール済みのコピーを代わりに編集するのではなく、確認してください。

  2. ソースを編集します。セッションがそのソースリポジトリ内にある場合に限ります。 追加する形で小さく変更してください。書き換えるのではなく、補足するルールの下に箇条書きを1つ追加します。 理由 の説明は本文ではなく references/ に記載してください(下記「本文に記載する内容」を参照)。 別のリポジトリで作業中のセッションでは、この手順をここで止めてください。 自分のセッションが使っていないチェックアウトで編集やコミットを行うと、他人の作業ツリーへのコミットになります。並行セッションが動いているマシンでは、git log を見ても通常の変更に見えるため、そのリポジトリを担当するセッションが、自分の変更ではないと知らずにプッシュしてしまう可能性があります。変更はスキル自身のリポジトリに対して提出し、そこで次に作業するセッションに適用してもらってください。2026-08-30に確認済み:ある実行で、無関係なプロジェクトからスキルに対して正しいゲート通過済みの編集を2件行い、そのプロジェクトでコミットしてしまいました。この条項はその経緯で追加されました。

  3. リポジトリの品質ゲートを実行してください。 Markdownも例外ではありません。文章をリフローするフォーマッターはSKILL.mdを書き換えます。また、ゲートを実行せずにドキュメントだけを変更することは、他の人のCI実行を失敗させる最もよくある原因です。

  4. コミットしてください。その前に確認してください。 ただし、リポジトリ独自の規約で別の方法が定められている場合は、それに従ってください。スキルは共有の規約であり、その変更は今後のすべてのセッションの動作を変えます。

  5. プッシュしてください。 ここが省略されがちな手順であり、重要な手順です。インストーラーはリモートからクローンするため、コミット済みでもプッシュされていない編集はインストールに反映されません。ローカルコミットだけでは、エージェントが読み込む内容は何も変わりません。

    [PITFALL: プッシュは必要ですが、それだけでは不十分です。skills add <owner>/<repo>が使うのはリモートの_デフォルトブランチ_です。 フィーチャーブランチからのプッシュは成功し、再インストールも成功しますが、新しい内容は何もインストールされません。その後の手順7では、インストールされたコピーと、公開されていないチェックアウトが比較され、すべてのコマンドが終了コード0を返します。先にマージするか、作業中はローカルパスからインストールしてください(下記参照)。

    リンクされたワークツリーでは、ブランチを選んだつもりがなくてもこの問題が起こります。 ワークツリーは必ず何らかのブランチ上にあります。それがワークツリーの仕組みですが、作業ツリーを見てもそれはわかりません。Claude CodeのEnterWorktreeはリポジトリ内の.claude/worktrees/<name>にワークツリーを作成します。VS Codeのワークツリーサポートは、デフォルトで隣接する<repo>.worktrees/に作成し、これを変更する設定はありません。session-harvestのskills-stateはワークツリーの名前を示すworktree:行を出力します。また、git rev-parse --git-common-dirが現在のチェックアウトの.git以外を指しているかどうかが、直接的な確認方法です。]

  6. 再インストールしてください。 ソースを監視するものはありません。

    npx skills add <owner>/<repo> --global --skill <name>     # one skill
    npx skills add <owner>/<repo> --global                    # the whole repo
    

    マシンがセットアップリポジトリやドットファイルマネージャーなどを使ってスキルを宣言的にインストールしている場合は、その仕組みを実行してください。記録が正確に保たれます。内部では同じCLIが呼び出されます。

    [PITFALL: -g/--globalはデフォルトではありません。指定しない場合、現在の場所によってスコープが暗黙に決まり、どちらの場合も成功の概要が表示されます。 このフラグは「スキルをグローバル(ユーザーレベル)に、プロジェクトレベルの代わりにインストールする」と説明されています。省略すると、CLIはプロジェクト内ではプロジェクトレベルを、プロジェクト外ではグローバルを選択します。そのため、リポジトリ内で実行すると、作業ツリーに.agents/skills/、.claude/skillsのシンボリックリンク、skills-lock.jsonが書き込まれる一方で、更新するつもりだったユーザースコープのコピーは古いままになります。スキルのリポジトリ自体で実行するのが最悪のケースです。そのリポジトリの作者が使うスキルの利用者向けコピーに加え、ベンダー中立なリポジトリでは原則として拒否される可能性のあるハーネス固有のディレクトリが作成されます。これら3つはどれもGitの追跡対象外に設定されていないため、次にgit addを実行するとまとめて追加されてしまいます。] 別の場所で実行しても解決しません。必要なのはフラグです。 skills-lock.json は プロジェクト の成果物であり、skills experimental_install はそこから復元します。そのため、cwd に応じて動作する実行では、どこで実行してもその場所にファイルが作られ、その実行で扱ったスキルだけが記録されます。2026-08-30 に、両方のケースを1回のセッションで確認しました。最初にリポジトリから実行したところ、スキルはリポジトリにインストールされ、グローバルには何も更新されませんでした。次に $HOME から実行したところ、正しくインストールされ、マシン上にある10個のスキルのうち1つだけを記載した ~/skills-lock.json が残りました。これはマニフェストのように見えますが、実際にはそうではありません。-g を指定すれば、結果が cwd に左右されなくなります。セッションの cwd がリポジトリだった場合は、後で git status を確認してください。]

  7. 思い込まずに確認します。 skills ls -g --json には、インストール済みの各スキルと、それを認識できるエージェントが表示されます。スキルに scripts/ ディレクトリが含まれている場合は、インストール先のパスから、ドキュメントに記載されたコマンドを1つ実行してください。 一覧でわかるのはスキルがインストール済みだということだけで、ファイルが届いたことまではわかりません。2026-08-29 に実環境で確認しました。すべてのセッションに python3 ~/.agents/skills/<name>/scripts/<file> の実行を指示する SKILL.md(および常時読み込まれる指示ファイルにデプロイされたルール)を持つスキルが、scripts/ が追加される前のコミットからインストールされていたため、2つの文書には存在すると記載されていたものの、マシン上にドキュメント記載のパスは存在しませんでした。実際に実行されるまで、何のエラーも起きませんでした。

    [PITFALL: 一覧だけでは証拠として不十分であり、インストーラーの概要も同様です。 2026-08-27 に計測しました。Claude Code とユニバーサルエージェントのいずれかを併せてインストールすると、プランには symlink → Claude Code と表示されますが、.claude/skills はまったく作成されず、最終概要からその行がひっそりと消えます。Claude Code が読み込むのは .agents/skills ではなく .claude/skills です。そのため、そのシンボリックリンクがまだ存在しないマシンでは、どのレポートも正常に見える一方で、Claude Code には何も届きません。リンクを確認してください(ls -l ~/.claude/skills)。存在しない場合は、ハブを参照するように設定してください(ln -s ~/.agents/skills ~/.claude/skills)。]

  8. 変更を加えたセッションでその変更を反映させる場合は、再読み込みします。 再インストールするとディスク上のファイルは更新されますが、実行中のセッションが開始時に読み込んだコピーは古いままです。そのため、スキルを編集してからそのスキルに従うセッションは、置き換えた内容に従い続けます。Claude Code では、/reload-skills を実行してから、スキルを再度呼び出すと新しい内容が読み込まれます。2026-09-01 に確認しました。あるセッションで session-harvest の手順を書き換えてプッシュし、再インストールして、インストール済みのコピーがチェックアウトと一致することを確認しましたが、ユーザーが再読み込みを指示するまで、置き換えられた文言がそのまま残っていました。ループが完了したかのように「再インストール済み」と報告するのではなく、プッシュ、再インストール、再読み込みのどれが未完了かを明記してください。ここへ移動したのは2026-09-13 で、それ以降 session-harvest はインストール状態を報告し、この手順を含まなくなりました。

スキルの名前を変更または削除する場合は、別途もう1つ手順が必要です。 インストールは追加のみの操作です。CLI はソースから公開されているものを追加・更新しますが、ソースからなくなったものは削除しないため、名前を変更したスキルは古い名前のまま新しいスキルと併存し、いつまでもインストールされたままになります。2026-08-28 に1つのスキルの名前を変更して計測したところ、リポジトリ全体を再インストールすると、ソースが10個なのにスキルが11個あると報告されました。古いスキルは引き続き読み込み可能で、古い説明がトリガーをめぐって競合していました。単に散らかるだけでは済みません。重複は、まさに次のセクションで対策を設計するよう述べているトリガーの競合そのものです。名前の変更または削除後は、skills remove -g --skill <old-name> -y を実行し、件数を再確認してください。

編集のたびにプッシュせずに反復する方法。 CLI はローカルパスを通常のソースとして受け付けるため、skills add ../my-skills --skill <name> を実行すると、作業ツリーの内容がそのままインストールされます。草案の作成中はこれを使ってください。変更を完了扱いにする前にプッシュしてください。そうしないと、次にリモートからインストールした際、変更がひそかに元に戻ります。

どちらの方向でも、インストールされるのはコピーです。エージェントがチェックアウトから直接リロードするモードはありません。どのような手順で進めても、編集内容が反映されるのはインストール後だけです。

スキルリポジトリの公開

公開リポジトリの skills/<name>/SKILL.md にスキルを配置します。マニフェストやマーケットプレイスへの登録、ベンダーディレクトリは不要です。CLI は標準の場所にあるスキルを最大3階層まで検出し、誰でもインストールできるようになります。

npx skills add <owner>/<repo> --global

リポジトリ独自のインターフェースを説明するスキルは、そのリポジトリ内の .agents/skills/ にコミットします。そうすれば、そこで作業する人はインストールする必要がありません。プロジェクト横断の規約に関するスキルは、専用のスキルリポジトリに配置します。どちらも同じコマンドでインストールできます。

名前は主キーですが、何の警告もありません

名前は自由に決めてかまいませんが、採用する前に空いていることを確認してください。名前はラベルというより識別子であり、名前を使うあらゆる仕組みが、失敗しても何も通知しないためです。

python3 <path>/names.py check <candidate>     # before adopting it
python3 <path>/names.py audit --mine <you>    # every skill you already have
python3 <path>/names.py audit --offline       # local duplicates only, no network

終了コード 0 は問題なし、1 は競合、3 は判定不能です。到達不能なレジストリは「問題なし」ではなく「不明」として報告します。実行できなかったのにチェックが黙って成功するのは、チェックがないより悪いからです。

このスクリプトが防ぐ問題は、いずれもインストーラーのソースコードで確認されています。

  • 重複した名前は、通知なしに除外されます。 vercel-labs/skills は、すでに確認した名前のスキルをスキップします。探索順で最初に見つかったものが優先されます。そのため、他人のリポジトリをインストールすると、自分のスキルが一覧から消えることがありますが、そのことをどこかで知らせてくれるわけではありません。
  • ロックファイルは名前をキーにしているため、名前を変更しても移動として認識されません。削除として扱われ、新しい名前はインストールされたことのないスキルとして扱われます。
  • 名前は比較の前に正規化されます。大文字と小文字は統一され、空白とアンダースコアはハイフンに置き換えられます。そのため、My Skill、my_skill、my-skill は別々の名前ではなく、同じ識別子です。
  • スキルには回避策がありませんが、プラグインにはあります。 Anthropic がプラグインに displayName と有効な renames マップの両方を用意したのは、スラッグの変更がインストールを壊すからです。スキル形式にはそのどちらもないため、名前は識別子とラベルを兼ねています。

2026-09-12 に公開インデックスを調査したところ、このコーパスの 15 個の名前のうち5 個が、すでに他のリポジトリで公開されていました。そのうち skill-authoring は 6 つのリポジトリで使われており、ベンダーのリポジトリも 2 つ含まれていました。作成者側からはそのどれも見えず、5 個すべてがこのチェックを導入する前から存在していました。

[PITFALL: ローカルでの競合は必ず スコープ間 で発生し、ソースのチェックアウトはスコープではありません。 競合する 2 つのスキルを同じハブに置くことはできず、後から追加した方が先のものを上書きします。そのため、実際に衝突するのはユーザーハブとプロジェクト独自の .agents/skills です。仕様ではプロジェクト側が優先され、警告が出ることが期待されています。ソースの skills/ とハブを並べて監査すると、インストールより先にあるだけのスキルまで毎回すべて報告されますが、これは日常的な作成作業で起こることです。このセクションの執筆中にも確認されました。このファイルを編集したところ、チェックは skill-authoring をインストール済みの同名スキルと照合して警告しました。したがって、デフォルトのルートにはローダーのスコープを使い、--root skills は意図的な作成者向けの指定とします。また、2 つのコピーが同じファイルなのか別のファイルなのかは、ダイジェストで判定します。]

公開済みのスキルの名前変更は、互換性を壊す変更です。 既存のインストールはすべて取り残され、古いスラッグは公開インデックスに永久に残ります。このリポジトリでは、あるスキルの名前を変更しましたが、変更前のスラッグは独自のインストール数とともに、現行の名前の横に今も掲載されています。名前の変更は編集ではなく非推奨化として扱い、まだ誰も使っていないうちに名前を決めることを優先してください。

従うべき命名規則はありません。これは見落としではなく、調査で明らかになった事実です。 仕様書の作成者向けページには命名規則がなく、公開済みの評価でスキル名を変えて比較したものもありません。文書化された選択手順では説明文だけが使われています。唯一存在するコミュニティのルールである「動詞や動名詞を優先する」という考え方は、コーパスの実態とおよそ 6 対 1 の割合で矛盾しており、実際には名詞を先頭に置く名前が多数です。そのため、選択に実際に使われる説明文に力を注ぎ、名前については、このチェックにかかる 2 秒だけ使ってください。

references/naming.md には、コーパス(1,043 個のスキル、40 個のリポジトリ)、仕様で必須とされることと実際に拘束力を持つ範囲の狭さ、予算が厳しい状況で説明文を一切表示せず名前だけを表示する唯一のハーネス、そして命名規則を適用できるものとできないものに分けた周辺エコシステムについて記載されています。

責任範囲ごとにスキルを分け、トリガーが競合しないようにする

新しいスキルを書く前に、2つのことを決めてください。これは、作成者側と検索側から見た同じ判断です。

  • 明確な責任範囲を1つに絞る。 テーマでも、たまたま一緒に必要になることの寄せ集めでもありません。2つの責任範囲を扱うスキルは、両方を1つの description に記述しなければなりません。実際に選択時の照合に使われるフィールドがこれなので、その希薄化はすべてのプロンプトで影響します。
  • インストール済みの他のスキルと競合しないトリガー条件にする。 競合しないことは要件であり、あれば望ましいという程度のものではありません。兄弟スキル向けのプロンプトに対して勝ってしまう description は、それ自体のケースで正しく動作していても不具合です。間違ったスキルが読み込まれても正しいスキルが読み込まれたときとまったく同じように見えるため、失敗に気づけません。

新しいスキルのトリガーが既存のスキルと重なる場合、解決策は境界を引き直すことであり、description の表現をもっと慎重にすることではありません。実例を挙げると、このスキルと mcp-server-shipping は2026-08-28まで1つのスキルで、「MCP サーバーまたはスキルのリポジトリを開発または配布する」と説明されていました。1つの description に2つの責任範囲が含まれており、スキルの編集に関するプロンプトは、半分がMCPサーバーについての説明に勝たなければなりませんでした。責任範囲で分割したところ、それぞれの description がより短く、明確になりました。

description は依頼する側の言葉で書いてください。つまり、そのトピック固有の用語ではなく、実際に誰かが入力する言葉を使います。内部の専門用語で作られた説明は、運が悪かったのではなく、構造的にトリガーされにくいのです。実際に測定されたケースでは、テスト規約のスキルの description に、スキル自身の言葉である test structure (DAMP vs DRY, fixture scope) と書かれていたため、「write tests」、「pytest」、「fixtures」、「parametrize」でトリガーされませんでした。

依頼する側の言葉とは、解決に使うツールではなく、_問題_を表す言葉です。 これは同じルールをより明確にしたもので、慎重な作成者でもなお間違えやすい点です。2026-08-31に測定したケースでは、tasks.py、inv、「namespace」を description に含むスキルが、これらの言葉を使ったあらゆる依頼で起動しました。一方、「自動化スクリプトが散らかって一貫性もなくなってきたのですが、どこから整理すればよいでしょうか?」という、問題が実際にどのように感じられるかを表した依頼では、3回中3回、何も選択されませんでした。競合相手に負けたのではなく、何も選ばれなかったのです。この種の失敗は、競合チェックでは見つけられません。

これらの判断を読むだけで済ませないでください。この節で述べている仕組みを担う skill-fitness で測定してください。

python3 <skill-fitness>/scripts/fitness.py overlap        # ranked pairs, and directional shadowing
python3 <skill-fitness>/scripts/trigger.py run <cases>    # which skill a real request actually selects
python3 <skill-fitness>/scripts/trigger.py candidate ...  # score a proposed description before adopting it
python3 <skill-fitness>/scripts/trigger.py split ...      # how requests distribute across a proposed split

このツールから得られた2つの結果によって、この節の適用方法が変わります。静的な重複フラグは仮説を生み出すためのものであり、結論ではありません。フラグが示した検証可能な予測は実際の実行で否定されたため、境界を引き直すなら、重複スコアではなく trigger.py によって正当化してください。また、候補の description のスコアは、両方向に誤差が出る推定値です。提案はコマンドファイルとして登録され、実際のスキルは登録されないため、明確な合格に届かなくても改善につながる表現なら採用する価値があります。ただし、公開後の run の結果が実績であり、単なる形式ではありません。 ここでは2026-09-01まで下限値と呼んでいましたが、あるスキルは候補として測定した際に12/12、本番環境へのインストール後は同じケースで11/12でした。

付随する原則として、調査結果をどこかに反映する必要がある場合は、新しいスキルを追加するより、すでにそのトピックを担当しているスキルを拡張してください。スキルの数そのものがコンテキストへの負担であり、スキルを追加するたびに、選択が取り違える可能性のある description も1つ増えます。

そもそもスキルにすべきではない場合

スキルは、トリガーに応じて条件付きで読み込まれます。その動作をすべてのセッションで、すべてのエージェントツールに対して無条件に適用する必要があるなら、スキルではなくAGENTS.mdに記述します。常に読み込まれるこの指示ファイルは、トリガーを見逃すことなく、すべてのハーネスで読み込まれます。

覚えておく価値のある方針転換で、これが確認されています。簡潔なコミュニケーションスタイルのスキルを導入した後、ツールをまたいで常に有効にするために、その内容もAGENTS.mdにコピーしました。両方が存在するとスキルは重複し、唯一残った違い(強度レベルを切り替えられること)は、その動作に見合わない複雑さをもたらしました。スキルはアンインストールし、常時有効な1つのモードに整えたAGENTS.mdだけを残しました。

逆の基準が役に立ちます。見落とすと気づかれないまま大きな損害につながるルールは、常時読み込まれるファイルに適しています。一方、明確なトリガーがあり、見落としても損害が小さく、やり直しがきくルールにはスキルが適しています。

本文に書くこととreferences/に書くこと

本文には、エージェントが従うべき内容を書きます。それ以外のもの――先行事例、測定結果、却下した代替案、ルールが生まれた経緯――はreferences/に記述し、必要なときだけ読み込みます。

  • ルールが実際に起きた出来事に基づく場合は、日付とともに根拠を示します(「2026-08-23に実環境で確認:…」)。経緯のあるルールはレビューを経ても維持されますが、根拠のない断言は、異論を持つ次の編集者によって弱められます。
  • 実践で見落とされていることがわかったルールは、**説明を長くするのではなく、表現を強めます。**正当化の説明を長くしても遵守率は上がりません。より鋭い命令形にするほうが効果的です。
  • マシン固有の事実は含めないか、明示します。特定のdotfile、ローカルにインストールされたタスクランナー、あるマシンにしか存在しないリポジトリなど、1台のマシンのセットアップに依存するルールは、その依存関係を明記するか、公開するスキルには含めないようにします。
  • **ルールは公開前に試験運用し、その結果は単に合否を出すのではなく、ルールをより明確にするものだと考えます。**実際のリポジトリ1つで慣例を試すおなじみの理由は、ノイズや落とし穴になるルールを見つけることです。それ以上に価値のある成果は、判断可能なルールが得られることです。2026-09-01に確認された事例では、当初の見解は「NamedTupleは非常に低コストで、可読性を大幅に向上させる」というものでした。これを3,200行のモジュール1つに適用した結果、単純な「はい」か「いいえ」では答えられないルールが生まれました。通常のタプルをNamedTupleにするのは改善ですが、凍結データクラスをNamedTupleにするのは改悪です。利点と危険性は、同じ性質を両面から見たものだからです。どれだけ読んでも、この結論には至らなかったでしょう。公開されたルールは、好みを示すのではなく、作成者が適用できる基準になっています。したがって、すでに信じていたことを確認するだけの試験運用は、疑ってかかるべきです。

スキルで決定論的に導き出せることは、文章ではなくスクリプトにする

有能なスクリプトで答えを生成できるなら、そのスクリプトをスキルに含め、本文では実行するフラグを示します。 SKILL.md は、モデルが毎回最初から読み直す指示書です。そのため、コマンドの書き方を説明する段落は、実行のたびに正しく従わなければならないルールですが、スクリプトなら一度作成すれば、あとは呼び出すだけです。また、誤りのコストも均等ではありません。文章の誤りは気づかれず、もっともらしく見える形で発生します。ブランチ名を間違えたり、フラグを落としたり、フィルターが終了コードを飲み込んだりしても、出力は答えのように見えてしまいます。

これは、実際の構文を持つインターフェースで特に顕著です。CLI のフラグとサブコマンド、HTTP API のリクエストとレスポンスの形式、SQL クエリ、JSON の走査、あるツールの出力を解析するパーサーなどです。 こうした処理は決定論的で、単純ではなく、モデルが再導出しても何の利点もありません。複数の手順を伴う処理も、一段階上から見れば同じです。「これを実行し、その結果を読み、内容に応じて別の処理を実行する」はプログラムです。それを文章で書くのは、エージェントにインタープリターの役割を担わせることになります。

測定した事例は、2026-09-02 のものです。session-harvest は 967 行の文章で、機械的な処理の半分は実行のたびに再導出されていました。このマシンで 1,134 件のトランスクリプトに対して実行された Bash 呼び出しは 24,429 回。その中には、plans-store のステータス確認 568 回、手書きの ahead 件数確認 498 回、トランスクリプトを処理する独自の Python ヒアドキュメント 164 件が含まれ、同じものは 2 つとありませんでした。具体的なミスが繰り返されたために作られたルールが 6 つあり、それぞれ文章としてすでに改善されていましたが、それでもミスは繰り返されていました。コード化すると、ミスは繰り返されなくなりました。表現が改善されたからではなく、従うべき文章がなくなったからです。

正当に文章で残すものを示します。「SKILL.md にコマンドを書いてはいけない」という話ではありません。

  • 読者が一度だけ実行する固定のリテラルで、コンテキストから組み立てる部分がないもの (npx skills add <owner>/<repo> --global);
  • スキル独自のスクリプトを呼び出す単一のコマンド。プレースホルダーも含め、それこそが委譲です;
  • 年に 2 回も実行しない、履歴の全消去のような一度限りの緊急手順。スクリプトを読む頻度が文章を読む頻度より低くなります;
  • 利用側のリポジトリ独自のツールを指定するコマンド。ポータブルなスクリプトにハードコードしてはいけません。リポジトリのゲートが inv quality.precommit なのか、別のものなのかをスキルは知ることができないため、「リポジトリのゲートを実行する」と示すにとどめます。

まさにここが変化しやすい部分なので、鵜呑みにせず監査してください。 スキルは一文ずつ改善され、追加されるコマンド行はどれも問題なさそうに見えます。 python3 <skill-fitness>/scripts/fitness.py derivable は、コーパス内の各コードフェンスのコマンドを、委譲・導出可能・固定に分類し、それぞれの導出の種類をタグ付けしたうえで、保存済みのベースラインと差分を取ります。スキルの導出可能な件数が増えていることが、見つけるべき問題です。スキルの状態が良好なときにベースラインを保存し、編集を重ねたあとで比較してください。

scripts/ 内のスクリプトは依存関係を自ら宣言するか、依存関係がない状態にします

標準ライブラリのみを使うのがデフォルトであり、謝るべき制約ではありません。 スキルはファイルをコピーしてインストールされ、その後にインストール手順が実行されることはありません。そのため、実行前に何かを解決する必要があるスクリプトは、そのスキルをインストールした人には動作しません。

  1. 標準ライブラリのみ。 python3 <skill>/scripts/foo.py は、Python がインストールされているどのマシンでも、宣言も解決も一切せずに動作します。このリポジトリには、この方式で作られた実用的なツールが 2 つあります。plan-docs/scripts/plans.py と session-bash-audit/scripts/audit.py です。後者は ~/.claude/projects/*.jsonl(Claude Code 独自のトランスクリプト保存場所であり、そのため別のハーネスでは何も読み取りません)を、argparse/json/re/dataclasses/pathlib だけで解析します。単純な YAML フロントマターに PyYAML は不要です。
  2. 依存関係が本当に必要になった場合は、PEP 723 と uv run を使います。ファイル内にインラインで # /// script TOML ブロックを記述すれば、単一ファイルのまま可搬性を保てます。これはスキルのスクリプトに関する文書化された規約であり、独自の慣習ではありません。
  3. スキル内の venv、requirements.txt、pyproject.toml は不可です。skills CLI が実行しないインストール手順を誰かが実行するまで、スキルが実行できなくなります。

スクリプトはスキルディレクトリのルートからの相対パスで参照してください。これにより、スキルをインストールした全員が同じように実行できます。

使用言語を問わず、ここにあるスクリプトを実行するのはターミナルの利用者ではなくエージェントです。対話的なプロンプトは使わないでください(エージェントのシェルは非対話型であり、TTY プロンプトは永久に停止します)。エージェントがインターフェースを理解するための、実際に機能する --help を用意し、標準出力には構造化された出力、標準エラー出力には診断情報を出し、終了コードを文書化し、ハーネスによる切り詰めを考慮して出力を制限してください。

スキルの出力は、スキルを実行した人に向けたものです

検出した事項をスキルが出力する前に、それに対処できるのは誰かを確認してください。 答えがほかの誰か(スキルの作成者、別のリポジトリのセッション、実行者が所有していないマシン)なら、その事項を対処できる場所に振り分けるか、デフォルトでは出力しないでください。読み手が変更できないことの報告は情報ではありません。実行のたびに支払うコストであり、出力を読むのをやめるよう教えることになります。

確認する価値の高い順に、次の 3 つの対応方法があります。

検出事項への対処を担う人スキルの対応
実行した人出力する
別のリポジトリまたはセッション振り分ける — 対処できる場所に記録する
スキルの作成者オプトイン方式 — 名前付きサブコマンドの背後に置き、デフォルトでは実行しない

[PITFALL: このバグは自分のマシンでは見つからないため、気づくのではなく確認する必要があります。 作成者のマシンでは、インストールハブとソースのチェックアウトで同じ名前が使われているため、「インストール済みスキル」に関する報告は、作成者が編集できるファイルに関する報告でもあり、正しいように見えます。しかし、2 つが異なるすべてのマシンでは誤りです。つまり、1 台を除くすべてのマシンで誤っています。2026-09-02 に確認済みです。見知らぬ人と同じ方法で実行した監査では、34 件の検出事項が返されましたが、読み手が対処できるものは 1 件もなく、実際に使う 2 つの経路のどちらも示されませんでした。報告が読み手にとって有用だと信じる前に、偽の HOME のもとで再現してください。]

測定値がどの対象を表すのかを明記してください。 件数は特定のファイル集合について述べるものであり、ツールが対象にできる集合はたいてい複数あり、それぞれ結果が異なります。たとえば、作業ツリー、公開済みの内容、インストール済みの内容です。2026-09-03 に、作業ツリーがクリーンで特に変わったことのない 1 台のマシンで測定したところ、3 つすべてが異なっていました。ヘッダーに対象データを記載してください。また、修正がコミット済みでもプッシュされていなければ、誰にとっても修正されていないことを忘れないでください。

スキルがファイルを配置できる場所と、マシンについて前提にできること

スクリプトでローカルパスをハードコードすることはありません。まして作者の開発環境のパスなど、決してありません。 ガード付きの最終手段としても使いません。こうしたパスは、1 台のマシンでしか役に立たず、他の場所では見えないため、レビューをすり抜けてしまいます。そして、他の誰かのディレクトリがたまたま一致したときに、初めて問題になります。--checkout <path> を指定してもらう(このフラグを明記したエラーを出す)のが、誠実な失敗の仕方です。

配置先は 6 つで、それぞれ用途は 1 つだけです。キーには**スキル自身の name**を使います。

配置先格納するものWindows のデフォルト
$HOME/<name>ユーザー自身の素材:参照でき、多くの場合 git リポジトリ%USERPROFILE%\<name>
$XDG_CONFIG_HOME → ~/.config/<skill>/人が編集する設定%APPDATA%\<skill>\
$XDG_STATE_HOME → ~/.local/state/<skill>/履歴、統計、ベースライン、最終実行記録%LOCALAPPDATA%\<skill>\
$XDG_DATA_HOME → ~/.local/share/<skill>/ツールに必要で、再生成できないデータ%LOCALAPPDATA%\<skill>\
$XDG_CACHE_HOME → ~/.cache/<skill>/再生成可能で、いつでも安全に削除できるもの%LOCALAPPDATA%\<skill>\Cache\
tempfile.mkdtemp()一時的な作業領域 — 固定の /tmp/<name> は決して使わない同じ呼び出し — リテラルのパスは決して使わない

環境変数はすべての環境で尊重し、デフォルト値だけをプラットフォームごとに変えます。 Windows で $XDG_STATE_HOME を設定したユーザーの指定はそのまま使います。そのため、環境変数の確認を先に行い、os.name == "nt" の分岐では何も設定されていない場合の処理だけを決めます。Windows では、ローミングの有無が 2 つの基底ディレクトリを分ける軸です。設定は別のマシンにも持ち運びたいものですが、状態とキャッシュは この マシンの記録です。各スクリプトに 3 行ずつ重複して書きます。platformdirs は適切なライブラリですが、何もインストールされていない python3 でこれらのスクリプトを実行し、--global でスキルをインストールする場合はインストール手順がまったく実行されないため、利用できません。

判断の軸は、ユーザーの素材か、ツールの記録管理かです。人が開き、grep し、バージョン管理する素材は、見える $HOME ディレクトリに置きます。XDG の基底ディレクトリは アプリケーション が管理するもののための場所です。だからこそ、ユーザー用ディレクトリに関する補足仕様があるのです。~/Documents を ~/.local/share の下に置く人はいません。具体的な判断基準は、人がここで cd することがあるかです。あるなら、それは記録管理ではありません。また、git の作業ツリーを XDG 基底ディレクトリに置いてはいけません。

ここから導かれるルールは 4 つあります。どれも簡単ですが、痛い経験から学んだものです。

  • どこでも同じ順序で解決します:明示的な引数 → スキル専用の環境変数 → $XDG_* → デフォルト。XDG の保存先には新しい変数は不要です。ユーザーがすでに制御している変数を引き継ぐため、これを使えば設定を増やすのではなく減らせます。
  • 自分がインストールされたディレクトリには書き込みません。 再インストール時に置き換えられる成果物だからです。2026-09-03 に確認:あるスキルが、ベースラインを ~/.agents/skills/<name>/references/baselines/ に保存するよう読者に案内していました。つまり、マシンごとに保持するよう求めた、真にマシン固有の唯一の状態が、上書きされるよう設計された場所に保存されていました。
  • ほかのツールのディレクトリは常に読み取り専用です。存在しない場合はゼロではなく利用不可と報告してください。そうしないと、そのツールを一度も実行したことがないマシンが、何も起きなかったマシンとして扱われます。
  • 内容がプライベートな場合は、作成時に 0700 を設定し、その後は確認しません。 モードの指定は無料です。umask は権限をさらに狭めるだけで、Windows では無視されるため、分岐も機能テストも必要ありません。ルートに設定してください。parents=True は中間ディレクトリに適用されず、0700 のルートがその下にあるすべてへのアクセスを遮断するためです。確認は無料ではありません。Windows では st_mode がファイル属性から合成されるため、ディレクトリは全ユーザーからアクセス可能であるかのように表示されます。その結果、そこで実際には存在しない概念に対する警告が発生し、読者が実行できない対処法を示すことになります。無料で利用できるデフォルトは維持する価値があります。誰も対処できない警告こそ、このファイルが大半の文字数を費やして反対しているものです。

スキル同士は依存できません。 スキルは個別にインストールされ、シンボリックリンクではなくコピーされ、グローバルインストールではロックファイルも書き込まれません。そのため、兄弟スキルをインポートするには、このセクションで禁止しているハブのパスをハードコードする必要があります。さらに、バージョン管理されていない境界をまたぐうえ、読者がほかに何をインストールしているかによって動作が変わります。読み書きする設定(環境変数、設定ファイルなど)として場所を共有し、何にも依存する代わりにリゾルバーの10行を複製してください。また、あるスキルが本当に別のスキルを呼び出すべき場合は、エージェントに実行させ、兄弟スキルがインストールされていないためにスキップした場合は、そのことを明示してください。

スキルが読み取り、実行し、書き込む内容を明記し、すべての書き込みを精査する

スクリプトを同梱するスキル、または読み手にセッションのリポジトリ外へ書き込むコマンドの実行を指示するスキルには、## このスキルが読み取り、実行し、書き込む内容という見出しのセクションを設けます。このセクションは、「Reads」「Runs」「Writes」「Network」の4行で構成します。最後の2行については、回答が「何もしない」であっても記載します。なぜなら、「何も書き込まない」という行は、そのスキルを信頼できるか判断する読み手にとって、ファイル内で最も役に立つ情報だからです。変更するものは、変わりやすいパスの一覧ではなく、種類(セッションリポジトリのplans/、ストア、自身が管理する設定など)で示し、どのサブコマンドが書き込みを行い、どれが行わないかも記載します。環境に関する情報、つまり製品、シェルから呼び出すツール、ネットワークアクセスは、読み手が最初に確認するcompatibilityフロントマターフィールドに記載します。純粋に規約だけを定めるスキルには、どちらも記載しません。

これは開示であり、権限のマニフェストではありません。この違いは重要です。その内容が真実かどうかを確認するものはなく、確認することもできません。スキルが自らについて述べたことは制御ではありません。MCP 自身のアノテーションにも、クライアントはその内容を信頼できないものとして扱う必要があるという注意書きがあり、ここにもそのまま当てはまります。開示に価値があるのは、コードと照らし合わせて手作業で確認できる点です。懐疑的な読み手でも、grepを1回実行すれば「ネットワーククライアントなし」を確認できます。また、レイアウトテストで開示の存在とWrites行の有無をチェックできます。テストで正直にチェックできるのは、そこまでです。

書き込みは、許可されているかではなく、何をすれば元に戻せるかで精査します。誰も許可を与えているわけではないため、「許可されているか」は適切な問いではありません。「元に戻せるか」こそが、「悪意がなくても危険」な書き込みと、日常的な書き込みを分ける基準です。Gitリポジトリ内への書き込みには、差分、取り消し、履歴があります。どのリポジトリにも属さない、バージョン管理されていないファイルへの書き込みには、そのどれもありません。開示で正当化するか、取り除くべきなのは後者です。この基準では、次の4種類の書き込みは日常的なもので、すべて明記します。暗黙の前提にはしません。

  1. 独自のコマンドを通じて、自身の設定を書き込む場合(~/.config/plan-docs/config.tomlに対するplan-docsのconfig setなど)。スキルが読み手に手作業で編集するよう指示する形にはしません。
  2. 明示された目的で指定される保存先(research-libraryが$RESEARCH_HOMEにクローンする場合、新しいリポジトリにスキャフォールダーが設定を書き込む場合など)。2つ目の事例は調査して見つかったため、個別の一覧ではなく、基準として記載します。
  3. plan-docsを通じて、両方の階層にあるプランストアに書き込む場合。そのスキル独自の条件、つまり変更のあるストアには、別のセッションが使用中かもしれないファイルを編集するのではなく、新しいファイルを作成するという条件も記載します。
  4. セッション自身のリポジトリ。それ以外はすべて対象外です。別のリポジトリのツリー、デプロイ済みの指示ファイル、インストール済みのスキルのコピーなどが含まれます。作業例として、session-harvestでは手順の冒頭に対象範囲を一度だけ記載します。

このルールの対象は、ファイルへの書き込みとコミットです。孤立したプロセスの終了やキャッシュの整理など、ファイル以外への副作用は、それを提案するスキルの規則に従います。また、それらは実行するのではなく、提案するにとどめます。

公開前および編集後のコーパス監査

このコーパスを読者が対応できない指摘34件から0件にした、2026-09-02から 2026-09-05までのループは、ほかにも応用できます。公開前に作業ツリーで実行し、SKILL.mdを編集した後にも再度実行してください。各ステップはskill-fitnessコマンドなので、ここにある内容を改めて導き出す必要はありません。

  1. portability — 出所が明記されていない参照は、次の4種類のいずれかです。修正方法は指摘ごとに選び、一括で言い換えることはしません。明記する(「この作者のマシンでは」と書く、場所を管理するハーネスを明記する、マシンが備えていたものを引用した日付付きの測定結果を示す)、一般化する(リポジトリ独自のゲート、<owner>/<repo>、名前を指定したパスではなく検出されたパスにする)、例にする(「使用例では作者のサーバーを記載しています。ご自身のものに置き換えてください」)、または削除することです。スクリプトで検出された場合に有効なのは削除だけです。コードでは明記できないためです。説明文に明記することはできないため、本文から明記を引き継ぎます。その文は本文に記述してください。
  2. 信じる前に、読者として再現する。 自分のマシンではハブとチェックアウトに同じ名前があるため、読者に影響するバグを確認できません。自分のスキルを2つインストールした偽のHOMEがテストになります。このリポジトリでは、tests/unit/test_audience.pyがその恒久的なゲートの実例です。
  3. derivable --compare <baseline> — スキルの導出可能な件数の増加が指摘事項です。サンプルを確認してください。正当な残存項目(外部CLI独自の一行コマンドや、利用側リポジトリ独自のゲート)も、ドリフトと並んで出力されるためです。
  4. 読者にとって修正済みだと言う前に、--ref origin/mainを指定する。 コミット済みでもプッシュされていない修正は、誰にとっても修正済みではありません。また、ヘッダー行には、数値がどの対象集団について示しているかが記載されます。
  5. 編集を進めた計画は、上記のセクション名を示す## Migrated toを付けて終了させます。そうすれば、次の監査は経緯ではなくルールに基づいて始められます。

判断が必要なためループに含めていないこと、そしてスクリプトに任せると誤った結果になることは、指摘に対して4つの修正方法のどれを選ぶか、説明文のトリガー語彙を削ってよいか(まずtrigger.pyで測定してください)、開示内容が真実かどうかです。

規約を定めるスキルは、実際の使用で生じた問題を受けて自ら更新する

一度きりのタスクを実行するのではなく、規約を定めるスキルは、読まれて従われるだけでなく、実際の使用を通して改善されるべきです。基本パターンは次のとおりです。使用中にルールだけでは解決できない曖昧な判断が本当に生じた場合や、ユーザーがスキルの判断を訂正した場合は、推測せずに確認します。その後、解決内容を小さく加筆してソースに反映し、上記の手順で再デプロイします。実例として、session-harvestの「摩擦が生じたら確認する」と「自己更新の仕組み」のセクションを参考にしてください。

スキルのフォローアップ確認は、ユーザーに任せる作業ではなく、スキルが実行する手順である

スキル自身の調査の結論が「1週間後に再測定する」「Xが現在も有効か確認する」「ベースラインと比較する」となった場合、その一覧はスキルの仕事であり、ユーザーの仕事ではありません。各項目を、次回の呼び出し時にスキルが実行するものとして組み込んでください。たとえば、合否を出力するスクリプトフラグ(各期待値に対する判定付きの--compare <baseline>)、スキルが差分を取る保存済みベースライン、エージェントが順に実行する、期待される結果付きの出力済みプローブ計画などです。本当に自動化できないこと(人間が権限確認のプロンプトを見ていること)は、番号付きの作業リストとして残さず、1つのはい/いいえの質問にまとめます。2026-08-24、最初のバージョンの最後に手動で「開く/再測定する」一覧が残っていたスキルについて、ユーザーはこう述べました。「手作業ではやりたくありません。スキルにやってほしいのです。」session-bash-auditの「測定/比較/プローブ」の分割が参考となるパターンです。

詳細な根拠

references/rationale.md — 自己更新が一つのスキルだけの特殊な事情ではなく、ほかにも応用できる理由と、スキルを公開するためのスキルは、作者独自の自動化ではなく移植可能な仕組みを説明すべき理由。

コメント