With vendir, bring only the parts you want from a publicly available harness

With vendir, bring only the parts you want from a publicly available harness

I tried a tool called vendir to achieve "I only want this specific part" from a harness for AI-driven development. I will introduce the mechanism for declaratively synchronizing files, along with practical examples.
2026.08.21

This page has been translated by machine translation. View original

"I only want to bring in part of this" is a surprisingly common situation

I'm Asano from the Manufacturing Business Technology Division.

Recently, a lot of harnesses for AI-driven development (sets of agent definitions, skills, etc.) have been published on the internet.

When I look at something thinking "this looks great!", I often find myself thinking, "I don't need all of it, but I'd love to have just this one part."

Our company blog has also introduced a method for managing harnesses in a package-manager-like way using microsoft/apm.

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

apm is a great way to declaratively manage skills with manifest and lock files, and it's very convenient for managing at the skill level.
On the other hand, since apm deals with predefined artifact types such as skills, plugins, and agent primitives, it's not suited for cases where you want to "select arbitrary files within a repository and bring in only part of them."

For example, the repository called Everything Claude Code (ECC) contains as many as 68 agent definitions at the time of writing. The ECC README describes two installation methods: "bulk install as a plugin" and "manual copy," and it seems you can also bring in only part of it via manual copy if you "only want to use specific agents." However, copying manually is quite a lot of work, and keeping up with upstream updates is also challenging.

So this time, I tried using vendir to "declaratively bring only specific files from a specific repository into my own repository."

https://carvel.dev/vendir/

What is vendir?

vendir is one of the Carvel project's tools for Kubernetes, and the official site describes it as "Sync any number of data sources into a consistent structure by writing a YAML definition."

The following three points are listed as its features:

  • Declarative: Declare "the structure you want to end up with" and leave the means of getting there to vendir
  • Purpose-built: Focused on the single function of "syncing files," leaving everything else up to you
  • Repeatable: By syncing from the generated lock file, everyone gets the same set of files no matter how many times they run it

It was originally developed for library management in ytt (Carvel's YAML template tool), but it can be widely used as a general-purpose tool for "declaratively describing what should be in a directory."

In addition to git, it also supports sources such as http, OCI images, GitHub Releases, and Helm charts.

Incorporating external code into your own repository and bundling it together is generally called "vendoring," and vendir is precisely a tool for performing this vendoring declaratively.

Let's try it

The content I tried this time has been published as a sample repository.

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

As a subject, I'll bring in only 5 agent definitions from under agents/ in ECC, which I mentioned earlier.

Agent to bring in Destination
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

Prerequisites

  • The version of vendir I verified operation with is 0.46.0
  • Since vendir uses git to fetch git sources, git is required
  • A network connection is required to fetch public repositories from GitHub

Installing vendir

On macOS, you can install it with Homebrew.

brew tap carvel-dev/carvel
brew trust carvel-dev/carvel   # Required for recent Homebrew versions as this is a third-party tap
brew install vendir

Once installed as above, let's verify it can be called with the following command.

vendir version
# If you see output like the following, you're good
# vendir version 0.46.0
#
# Succeeded

Writing vendir.yml

Prepare vendir.yml at the root of your repository. This is the only file that humans need to edit.

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

directories:
- path: vendor/ecc-agents        # ① The directory owned by vendir
  contents:
  - path: .                      # ② Relative path from ① (here, directly under it)
    git:
      url: https://github.com/affaan-m/ECC
      ref: main                  # ③ Branch / tag / commit SHA
    includePaths:                # ④ Setting to bring in "only part"
    - agents/architect.md
    - agents/planner.md
    - agents/code-reviewer.md
    - agents/security-reviewer.md
    - agents/python-reviewer.md

The meaning of each item is as follows.

# Item Meaning
directories[].path The destination directory. Owned by vendir (described later)
contents[].path Where within ① to place it. . means directly under ①
git.ref The branch, tag, or commit SHA to fetch
includePaths Only the items listed here are synced

If you don't write includePaths, the entire contents of the target repository will be placed at the specified location. If you write includePaths, only files matching the listed paths will remain.

Paths are written as relative paths from the root of the source repository. Globs can also be used, so for example, "all review-type agents" could be written as follows.

    includePaths:
    - agents/*-reviewer.md

Running vendir sync

In the directory where vendir.yml is located, run the following.

vendir sync

This alone will bring in files with a structure like the following.

vendir-usage-sample
├── vendir.yml          # Declaration of what to bring in and where
├── vendir.lock.yml     # Auto-generated by vendir sync. Records the resolved SHA
└── vendor
    └── ecc-agents      # The sync destination "owned" by vendir. Avoid manual editing
        ├── agents
        │   ├── architect.md
        │   ├── code-reviewer.md
        │   ├── planner.md
        │   ├── python-reviewer.md
        │   └── security-reviewer.md
        └── LICENSE     # vendir retains this automatically even without writing it in includePaths

Of the 68 agent definitions, only the 5 listed in includePaths were brought in.

Note that vendir retains files like LICENSE / NOTICE / COPYRIGHT as default values for a setting called legalPaths, regardless of includePaths specifications. This is a consideration to prevent the loss of license notices for incorporated code.

Ensuring reproducibility with vendir.lock.yml

When you run vendir sync, a file called vendir.lock.yml is automatically generated.

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

While vendir.yml specifies a "moving pointer" like ref: main, the lock file records the commit SHA that was resolved. This enables the following:

  • Reproducibility: With vendir sync --locked, you can reproduce the state of the SHA recorded in the lock file as many times as needed
  • Sharing the same state across team members: By committing the lock file, all team members and CI can bring in files from the same SHA
  • Visualizing updates: When you re-incorporate from upstream, the SHA in the lock changes, so a diff review shows "what was updated and when"

vendir.lock.yml is not something you edit by hand—it's something you commit and share. It's in the same position as package-lock.json in npm.

When you want to bring in the latest from upstream, re-run without --locked.

vendir sync

If there are updates, the latest files will be brought in, and you can confirm that a diff has appeared in vendir.lock.yml as follows.

% 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

Adding or removing files to bring in

When you want to change the agents being brought in, add or remove lines from includePaths and re-run 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      # ← Add one line and run vendir sync

Adding a line will add that file, and removing a line will also remove that file from vendor/. For directories and files owned by vendir, they are always synced to match "the state declared in vendir.yml"—they don't accumulate diffs.

Caution: The sync destination directory is owned by vendir

The directory specified in directories[].path is rebuilt to match the declaration each time vendir sync is run. Therefore, any changes you make there will be gone with the next vendir sync.

The basic policy is:

  • If you want to change upstream files, submit a PR upstream, or prepare a mechanism outside of vendir.yml to process files after they are brought in
  • If you want to place locally unique files, place them outside of vendor/

When the upstream is OSS or similar, there's a hurdle to having PRs accepted, so I think the most approachable approach is generally to "process files after bringing them in" using scripts or similar means.

Caution: Check the license of the source you're bringing in

In the sample repository, the vendor directory is bundled for explanatory purposes based on the concept of vendoring, but in actual use, it may be better to first consider "whether to bundle the contents of the vendor directory in your own repository." While the concept of vendoring implies bundling, just as with node_modules in npm, there's certainly a valid case for excluding it from version control management via .gitignore.

If you are going to manage things based on the concept of vendoring, you will be incorporating external files into your own repository and redistributing them, so checking the license of the source is essential.

vendir's legalPaths automatically picks up the LICENSE from the repository root and similar files, but this is a convenience feature and does not guarantee license compliance. For licenses like MIT / BSD / Apache-2.0 that require "retention of copyright and permission notices," vendir's default behavior largely satisfies this, but GPL / AGPL-type licenses may propagate to the incorporating side, and repositories with no license notation cannot in principle be redistributed.

In this sample, I confirmed that the source is under the MIT License, and made sure to explicitly state the correspondence between the incorporated content and the license in a NOTICE file at the root.

Summary

Using vendir, I brought only the 5 agent definitions I wanted from a publicly available harness (ECC) into my own repository.

It specializes in doing the single function of file synchronization well, and I personally liked it very much as it scratches exactly where it itches, but since there wasn't much mention of it in Japanese, I decided to introduce it this time.

This time I used harness management as the subject, but vendir is a general-purpose tool that can be used in any situation where you "only want part of an external repository." Please feel free to give it a try.

Share this article