# Open, Structured Metadata for Git

> Source: <https://git-meta.com/>
> Published: 2026-05-27 21:16:56+00:00

### What wrote this code, and how?

Stamp the model, prompt hash, and transcript ref onto the commits an agent produces. Audit later without parsing messages.

``` bash
$ git meta set commit:HEAD agent:model claude-4.6
$ git meta list:push branch:feat-checkout agent:chat \
    'new comment'
```

`git-meta`

is an open specification and reference CLI
tool for attaching
**arbitrary, fine-grained metadata** to Git objects
— provenance, ownership, reviews, attestations —
stored locally for fast queries and exchanged using normal Git
transfer protocols and servers.

You can think of `git meta`

as a more performant,
scalable, flexible and collaborative `git notes`

.

Attach key/values to commits, branches, paths, change-ids, or the project itself — not just whole commits.

Attach values of several types *(strings, lists, sets)* to
namespaced keys such as `agents:model`

.

Metadata is exchanged as commits on `refs/meta/*`

. If
you can `git push`

, you can share it.

git-meta is designed around Git's promisor remotes, meaning it can easily handle millions of metadata entries and get values on demand.

Metadata wants its own lane — structured, queryable, independently mutable — without polluting your working tree.

Stamp the model, prompt hash, and transcript ref onto the commits an agent produces. Audit later without parsing messages.

␃WPNCODE0␃

Keep owners, reviewers, and policy hints against paths — as sets that merge across branches instead of a single file people fight over.

``` bash
$ git meta set:add path:src/billing owners '["ali", "jin"]'
$ git meta set:add path:src/billing reviewers mira
```

Attach review threads and approvals directly to commits or ranges. Independent of any single forge.

``` bash
$ git meta set commit:314e7f0 review:status approved
$ git meta list:push commit:314e7f0 review:notes \
    "lgtm; verify the retry backoff"
```

Record test runs, SBOMs, or signatures as first-class keys — many independent fields on the same commit, each mutable on its own schedule.

``` bash
$ git meta set commit:HEAD ci:status  passed
$ git meta set commit:HEAD ci:run     gha-4912
$ git meta set commit:HEAD sbom:sha   sha256:ab…
```

Every change lands in a fast local index first. To share, git-meta
serializes that index into commits on a
`refs/meta/*`

ref and ships them with the same
`git push`

and `git fetch`

you already use
— no new daemons, protocols, or new wire formats.

`git fetch`

The reference implementation is a single Rust binary. Install with
`cargo`

, wire up a remote, set a value and push it
— then watch a teammate pull it down with the same tool.

Builds with stable Rust. The crate is
`git-meta-cli`

; the installed command is
`git meta`

.

``` bash
$ cargo install git-meta-cli
$ git meta --version
```

Metadata lives under its own ref namespace. Pin the
recommended remote in a `.git-meta`

file at the
repo root — the same repo as your code is fine —
then run `git meta setup`

to wire it up and seed
`refs/meta/main`

.

``` bash
$ cd your-project
$ printf 'url: git@github.com:you/proj.git\n' > .git-meta
$ git meta setup
```

Set a key on any target — `commit`

,
`branch`

, `path`

, or
`project`

— then push the metadata refs to
the remote.

``` bash
$ git meta set commit:HEAD review:status approved
$ git meta push
```

On a different machine, a collaborator clones the repo and
runs `git meta setup`

. The committed
`.git-meta`

file from step 02 picks the remote for
them, fetches the metadata refs, and gets them ready to
inspect the values you wrote.

``` bash
$ git clone git@github.com:you/proj.git && cd proj
$ git meta setup
$ git meta show HEAD
```

The git-meta specification was developed and proposed by
[GitButler](https://gitbutler.com) with inspiration and
feedback from several leading version control teams, to solve the
growing Git metadata problem.
[Contact us](mailto:scott@gitbutler.com) if you would
like to join this list of cool kids using it.

Both. The important part is the
**exchange format** — the agreement needed
for different implementations to interoperate. A
**reference implementation** lives alongside the
spec so you can try the ideas end-to-end.

No. git-meta uses ordinary Git objects — trees, commits,
and refs under `refs/meta/*`

. Any Git server that
accepts arbitrary refs can transport it.

`git notes`

?
`git notes`

attaches a single blob per commit.
git-meta models many small, independently mutable fields
against many kinds of targets (paths, branches, change-ids),
with typed values and deterministic merges.

Three to start: `string`

, `list`

, and
`set`

. Each has a documented merge behavior so
concurrent edits resolve without custom code.

Metadata lives on its own `refs/meta/*`

refs, so
cloning code doesn't pull metadata unless you ask for it.
Initialization uses partial fetches to only get a working set
of data, not every historical value, but older values can be
fetched on demand with any modern Git server, including
GitHub.

If that's not enough, history can even be split and unioned in special cases, or even partially made private.

Yes — that's one of the motivating use cases. Stamp model, prompt data, and transcript references onto commits or branches, and query them later without parsing commit messages.

git-meta is small and sharp. The fastest way to make it better is to use it for something real.
