vendirで、公開されているハーネスの欲しいところだけ持ってくる

vendirで、公開されているハーネスの欲しいところだけ持ってくる

AI駆動開発用のハーネスから「この一部分だけ欲しい」を実現するため、vendirというツールを試してみました。宣言的にファイルを同期できる仕組みについて、実例を交えてご紹介します。
2026.08.21

「これの一部分だけ持ってきたいんだけど」が割とある

製造ビジネステクノロジー部・浅野です。

最近、AI駆動開発のためのハーネス(エージェント定義やスキルなどの一式)がインターネット上でたくさん公開されるようになりました。

「これ良さそう!」と思って眺めていると、「全部はいらないけど、この一部分だけ欲しいな」という思いが湧いてきます。

当社ブログでもmicrosoft/apmを使ってハーネスをパッケージマネージャ的に管理する方法が紹介されています。

https://dev.classmethod.jp/articles/shuntaka-apm-agent-skills-renovate/

apmはスキルをマニフェストとlockファイルで宣言的に管理できる良い手段で、スキル単位での管理にはとても便利です。
一方で、apmが扱うのはスキルやプラグイン、エージェントプリミティブといった定義済みのアーティファクト型単位なので、「リポジトリ内の任意のファイルを選んで一部だけ取り込みたい」というケースには向きません。

例えば、Everything Claude Code(ECC)というリポジトリには、執筆時点で68個ものエージェント定義が含まれています。ECCのREADMEには導入方法として「プラグインとして一括インストール」と「手動でコピー」の2通りが記載されており、「特定のエージェントだけ使いたい」場合は手動コピーで一部分だけ入れることもできそうです。ただ、手動でコピーするのは結構大変ですし、上流側の更新に追従するのも大変です。

そこで今回は、vendirを使って「特定のリポジトリの特定のファイルだけを、宣言的に自分のリポジトリへ持ってくる」というのを試してみました。

https://carvel.dev/vendir/

vendirとは?

vendirは、Kubernetes向けツール群であるCarvelプロジェクトのひとつで、公式サイトでは「YAMLの定義を書くことで、任意の数のデータソースを一貫したディレクトリ構造に同期する」("Sync any number of data sources into a consistent structure by writing a YAML definition.")と謳われています。

特徴としては以下の3点が挙げられています。

  • Declarative(宣言的):「最終的にこうなっていてほしい構造」を宣言し、そこに至る手段はvendirに任せる
  • Purpose-built(目的特化):「ファイルを同期する」という単機能に絞られていて、あとは自由に使える
  • Repeatable(再現可能):生成されるlockファイルから同期することで、誰が何回実行しても同じファイル群が得られる

本来はytt(CarvelのYAMLテンプレートツール)向けのライブラリ管理用として開発されたそうですが、汎用ツールとして「ディレクトリに何が入っているべきかを宣言的に記述する」用途に広く使えます。

ソースとしてはgitのほか、http、OCIイメージ、GitHub Release、Helmチャートなどもサポートされています。

外部のコードを自分のリポジトリに取り込んで同梱することを一般に「vendoring」と呼びますが、vendirはまさにこのvendoringを宣言的に行うためのツールというわけですね。

やってみる

今回試した内容は、サンプルリポジトリとして公開しています。

https://github.com/ashnoa/vendir-usage-sample

題材として、先ほど触れたECCのagents/配下から、エージェント定義を5個だけ取り込んでみます。

取り込むエージェント 取り込み先
agents/architect.md vendor/ecc-agents/agents/architect.md
agents/planner.md vendor/ecc-agents/agents/planner.md
agents/code-reviewer.md vendor/ecc-agents/agents/code-reviewer.md
agents/security-reviewer.md vendor/ecc-agents/agents/security-reviewer.md
agents/python-reviewer.md vendor/ecc-agents/agents/python-reviewer.md

前提

  • 動作確認したvendirのバージョンは0.46.0です
  • vendirはgitソースの取得にgitを利用するため、gitが必要です
  • GitHubの公開リポジトリをfetchするため、ネットワーク接続が必要です

vendirをインストールする

macOSの場合、Homebrewでインストールできます。

brew tap carvel-dev/carvel
brew trust carvel-dev/carvel   # サードパーティtapのため、最近のHomebrewでは信頼の設定が必要
brew install vendir

上記でインストールできたら、以下のコマンドで呼び出せるか確認しましょう。

vendir version
# 以下のような結果が出力されていたらOK
# vendir version 0.46.0
#
# Succeeded

vendir.ymlを書く

リポジトリのルートにvendir.ymlを用意します。人が編集するのはこのファイルだけです。

apiVersion: vendir.k14s.io/v1alpha1
kind: Config

directories:
- path: vendor/ecc-agents        # ① vendirが所有するディレクトリ
  contents:
  - path: .                      # ② ①からの相対パス(ここでは直下)
    git:
      url: https://github.com/affaan-m/ECC
      ref: main                  # ③ ブランチ / タグ / コミットSHA
    includePaths:                # ④ 「一部だけ」取り込む設定
    - agents/architect.md
    - agents/planner.md
    - agents/code-reviewer.md
    - agents/security-reviewer.md
    - agents/python-reviewer.md

それぞれの項目の意味は以下のとおりです。

# 項目 意味
directories[].path 同期先のディレクトリ。vendirが所有する(後述)
contents[].path ①の中のどこに配置するか。.なら①の直下
git.ref 取得するブランチ・タグ・コミットSHA
includePaths ここに列挙したものだけ同期する

includePathsを書かなければ、対象リポジトリの中身が丸ごと指定の位置に入ってきます。includePathsを書くと、列挙したパスにマッチするファイルだけが残ります。

パスは取り込み元リポジトリのルートからの相対パスで書きます。globも使えるので、例えば「レビュー系のエージェントを全部」なら以下のようにも書けます。

    includePaths:
    - agents/*-reviewer.md

vendir syncを実行する

vendir.ymlのあるディレクトリで、以下を実行します。

vendir sync

これだけで以下のような構造でファイルが取り込まれます。

vendir-usage-sample
├── vendir.yml          # 何をどこに取り込むかの宣言
├── vendir.lock.yml     # vendir syncが自動生成。解決済みSHAを記録
└── vendor
    └── ecc-agents      # vendirが「所有」する同期先。手動編集しないようにする
        ├── agents
        │   ├── architect.md
        │   ├── code-reviewer.md
        │   ├── planner.md
        │   ├── python-reviewer.md
        │   └── security-reviewer.md
        └── LICENSE     # includePathsに書かなくてもvendirが自動で保持する

68個のエージェント定義のうち、includePathsに列挙した5個だけが取り込まれました。

なお、vendirはlegalPathsという設定の既定値として、LICENSE / NOTICE / COPYRIGHTなどをincludePathsの指定にかかわらず保持します。取り込んだコードのライセンス表示を失わせないための配慮ですね。

vendir.lock.ymlで再現性を担保する

vendir syncを実行すると、vendir.lock.ymlというファイルが自動生成されます。

apiVersion: vendir.k14s.io/v1alpha1
directories:
- contents:
  - git:
      commitTitle: 'fix: use scalar Claude agent tools (#2583)...'
      sha: 6a9f075cd97c139a5f7e84e1e3f2c9ab095adf64
      tags:
      - v2.0.0-252-g6a9f075c
    path: .
  path: vendor/ecc-agents
kind: LockConfig

vendir.ymlではref: mainという「動くポインタ」を指定していますが、lockファイルには解決結果であるコミットSHAが記録されます。これにより、次のことができるようになります。

  • 再現性vendir sync --lockedで、lockに記録されたSHAの状態を何度でも再現可能
  • チーム間での同一状態の共有:lockファイルをコミットしておけば、チームメンバー全員・CIが同じSHAのファイルを取り込める
  • 更新の可視化:上流を取り込み直すとlockのSHAが変わるので、差分レビューで「いつ何を更新したか」がわかる

vendir.lock.ymlは手で編集するものではなく、コミットして共有するものです。npmでいうpackage-lock.jsonと同じ立ち位置ですね。

上流の最新を取り込みたくなったら、--lockedを付けずに再実行します。

vendir sync

更新がある場合、最新のファイルが取り込まれた上で、以下のようにvendir.lock.ymlにも差分が生まれていることが確認できます。

% git diff
diff --git a/vendir.lock.yml b/vendir.lock.yml
index 12d19a4..cdf57c1 100644
--- a/vendir.lock.yml
+++ b/vendir.lock.yml
@@ -2,10 +2,10 @@ apiVersion: vendir.k14s.io/v1alpha1
 directories:
 - contents:
   - git:
-      commitTitle: 'fix: use scalar Claude agent tools (#2583)...'
-      sha: 6a9f075cd97c139a5f7e84e1e3f2c9ab095adf64
+      commitTitle: 'Merge pull request #2824 from affaan-m/agent/tasteforge-multimodal-20260819...'
+      sha: d8409a4b0813771235555e32e3d8046a73988bfa
       tags:
-      - v2.0.0-252-g6a9f075c
+      - v2.1.0-108-gd8409a4b
     path: .
   path: vendor/ecc-agents
 kind: LockConfig

取り込むファイルを増やす・減らす

取り込むエージェントを変えたくなったら、includePathsの行を追加・削除してvendir syncを再実行します。

    includePaths:
    - agents/architect.md
    - agents/planner.md
    - agents/code-reviewer.md
    - agents/security-reviewer.md
    - agents/python-reviewer.md
    - agents/go-reviewer.md      # ← 1行足してvendir sync

追加すればそのファイルが増え、行を消せばvendor/からもそのファイルが消えます。vendirが所有しているディレクトリ・ファイルについては「vendir.ymlの宣言と常に一致する状態」に同期されるものとなっており、差分が積み上がっていく形にはなりません。

注意点:同期先ディレクトリはvendirが所有する

directories[].pathに指定したディレクトリは、vendir syncのたびに宣言と一致するよう中身が作り直されます。よって、ここに手を加えても次のvendir syncで消えます。

  • 上流のファイルを変えたい場合は、上流にPRを出すか、取り込んだ後に加工する仕組みをvendir.ymlの外側に用意する
  • ローカル独自のファイルを置きたい場合は、vendor/の外に置く

というのが基本方針になります。上流側がOSSなどになるとPRを出して取り込まれる部分のハードルが出てくるので、基本的にはスクリプトなどで「取り込んだ後に加工」をするのが取り組みやすいのかなと思われます。

注意点:取り込み元のライセンスを確認する

サンプルリポジトリでは説明という目的とvendoringの発想に基づきvendorディレクトリを同梱していますが、実際の利用時には「自身のリポジトリにvendorディレクトリの内容を同梱するか?」から考える方が良いかと思われます。vendoringの発想としては同梱することになりますが、npmにおけるnode_modulesなどと同様に、.gitignoreで管理対象外とする判断も十分あり得る認識です。

仮にvendoringの発想に基づく管理をしていくとすると、外部のファイルを自分のリポジトリに取り込んで再配布することになるため取り込み元のライセンスの確認は必須です。

vendirのlegalPathsはリポジトリルートのLICENSEなどを自動で拾ってくれますが、これは便利機能であってライセンス適合性を保証するものではありません。MIT / BSD / Apache-2.0のような「著作権表示・許諾表示の保持」が条件のライセンスであればvendirの既定動作でおおむね満たせますが、GPL / AGPL系は取り込んだ側にライセンスが伝播する可能性がありますし、ライセンス表記のないリポジトリは原則として再配布できません。

今回のサンプルでは、取り込み元がMIT Licenseであることを確認した上で、取り込んだ内容とライセンスの対応をルートのNOTICEファイルに明示するようにしています。

まとめ

vendirを使って、インターネットで公開されているハーネス(ECC)から、欲しいエージェント定義5個だけを自分のリポジトリに取り込んでみました。

ファイルの同期という単機能を上手に行うことに特化しており、痒い所に手が届くという印象で個人的に大変気に入ったのですが、日本語での言及がそれほど多くなかったため今回紹介してみました。

今回はハーネスの管理を題材にしましたが、vendirは「外部リポジトリの一部だけ欲しい」という場面全般に使える汎用ツールです。よければぜひみなさまもお試しください。

この記事をシェアする

関連記事