Skip to content
Avalanche-ioPublic

About

Go package implementation of C4 Asset ID

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

43 stars

Watchers

8 watching

Forks

C4 — Universal Content Identification

Everything in Unix is a file, except for the filesystem itself. Until now.

CI Go Report Card Go Reference Apache 2.0

C4 is a file management system designed to simplify distributed systems. It decouples file storage and transport from organization and metadata by providing a standardized content-derived identifier, and using these identifiers in place of file content in a simple, readable, text-based filesystem format.

$ echo "hello" | c4
c447Fm3BJZQ62765jMZJH4m28hrDM7Szbj9CUmj4F4gnvyDYXYz4WfnK2nYRhFvRgYEectEXYBYWLDpLo6XGNAfKdt

That 90-character string is a SMPTE ST 2114:2017 identifier — an international standard built on SHA-512. Run it on any machine, in any language, ten years from now. Same input, same ID. Unlike a UUID, which is assigned arbitrarily and requires coordination to be meaningful, a C4 ID is discovered from the data itself. If two people have a file with the same ID, they have identical copies of the same file.

C4 extends this idea to entire filesystems. c4 id produces a c4m file — a plain-text description that captures the identity of every file and directory in a tree:

$ c4 id ./project/
-rw-r--r-- 2026-03-18T22:22:57Z 13 README.md c44iCq6un9W47x7ydjJSWp4arMJ...
drwxr-xr-x 2026-03-18T22:22:57Z - src/ -
  -rw-r--r-- 2026-03-18T22:22:57Z 66 main.go c43Q4j81SxGkV9FhbeW23YrMTj6...
drwxr-xr-x 2026-03-18T22:22:57Z 66 src/ c44nbgL6nkBWsEBDCUCr4LufsjVhJt...
c45k2Jd...                                  ← the final line is the tree's ID

Each line looks like ls -l with a content ID at the end — and the output streams: file lines print the moment they're hashed (directory aggregates fill in via a refinement patch at the end, because a folder's ID is the fingerprint of its contents). The final line is always the whole tree's ID. Need machine-independent identity? c4 id -q -m c projects modes and timestamps away, so the same bytes give the same ID on any machine, clock, or umask.

A c4m file is just text. Pipe it, grep it, diff it, email it. The format is designed to compose with awk, sort, grep, and the rest of the Unix toolkit — no special tools required, though C4 provides some that are useful.

Install

Homebrew (recommended: c4, c4sh, c4git, and the farm tools)

brew install mrjoshuak/tap/c4

Binary downloads

Pre-built archives for macOS, Linux, and Windows: c4toolkit releases

From source

go install github.com/Avalanche-io/c4/cmd/c4@latest
go install github.com/Avalanche-io/c4sh@latest

Other languages

pip install c4py                    # Python
npm install @avalanche-io/c4        # TypeScript / JavaScript

See c4toolkit for the full suite and version matrix.

Farms

The install brings c4-farm (and c4-agent on macOS and Linux), and c4 farm ... runs it. Join a studio's farm from any machine with only c4 installed, with no Docker, kubectl or cluster credentials:

c4 farm login https://farm.studio.example   # sign in once
c4 farm submit render shot010.c4m           # plan, estimate, submit
c4 farm ls                                  # the queue, in run order
c4 farm watch JOB                           # progress, deadline, slack
c4 farm get JOB ./out/                      # the output, every ID checked

Or make a farm on this machine, which is the one command that needs Docker:

c4 farm up

c4 <name> runs any c4-<name> on PATH the way git finds its plugins; c4 help lists the tools installed. The farm itself is c4-operator and its console is c4-hud; their READMEs take it from here.

What can you do with it?

Know what changed. Snapshot a directory, come back later, compare:

c4 id ./deliverables/ > monday.c4m
# ... work happens ...
c4 diff monday.c4m ./deliverables/

Build history. Append diffs to a c4m file to create a version chain:

c4 id ./project/ > project.c4m                                  # snapshot
c4 diff project.c4m ./project/ >> project.c4m                    # append changes

c4 log project.c4m          # see what changed
c4 patch -n 1 project.c4m   # recover the original state

Snapshot into the store. One command, one ID back. The ID prints only after everything it names is on stable media — if it printed, you can get it back, even after kill -9 or power loss:

c4 id -s ./final/                    # snapshot; streams the listing,
                                     # ends with the durable ID
SNAP=$(c4 id -s -q ./final/)         # script capture: THE ID, one line
c4 cat "$SNAP"                       # the root listing
c4 cat "$SNAP"/src/parser.go         # extract one file, verified
c4 log                               # every snapshot the store holds

The store can be a local directory, an S3-compatible object store, or both. Content goes in once, comes out by ID.

Make a directory match a description. Declarative — you say what the result should be, C4 figures out how to get there. Dry run by default; --force snapshots the directory first, so every restore is undoable:

c4 restore "$SNAP" ./dir/            # dry run: print the plan
out=$(c4 restore --force "$SNAP" ./dir/)
undo=$(printf '%s\n' "$out" | sed -n 1p)
c4 restore --force "$undo" ./dir/    # undo — which prints its own undo

Nothing starts until all required content is confirmed available, and the undo handle is journaled before the first destructive operation.

Work with Unix tools. One entry per line, fields in predictable positions:

awk '{print $NF}' project.c4m | sort | uniq -d       # find duplicates
grep '\.exr ' project.c4m | wc -l                    # count EXR files

Merge two trees. Combine branches, deliveries, or any two c4m files into one:

c4 merge branch-a.c4m branch-b.c4m > merged.c4m

Conflicts (same path, different content) are reported. Non-overlapping entries are combined.

Re-scan fast. A prior full description is a reuse guide: files whose size and mtime are unchanged (and safely older than the guide's scan — git's racy-index rule) keep their recorded IDs without being re-read:

c4 id ./project/ > full.c4m           # full description once
c4 id -c full.c4m -q ./project/       # fast re-scan (trusted mtimes)
c4 id --verify -c full.c4m ./project/ # audit: full re-hash, report
                                      # changes hidden under unchanged
                                      # size+mtime

Commands

Command What it does
c4 id Describe files, directories, or c4m files; snapshot with -s
c4 restore Make a directory match a description (dry run by default)
c4 cat Retrieve a store object by ID or ID/path, verified
c4 diff Compare two states (directories, c4m files, or store IDs)
c4 patch Resolve patch chains to c4m text (never touches directories)
c4 merge Combine two or more trees
c4 log List the store journal, or a chain's sections
c4 split Split a patch chain
c4 explain Human-readable narration of what a command would do
c4 paths Convert between c4m format and plain path lists
c4 intersect Find common entries between two c4m files

Nothing is written anywhere without -s (or restore --force), and -s writes only inside the store. c4 <path> is a read-only shortcut for c4 id <path>; c4 -s <path> snapshots. echo "data" | c4 prints the ID of stdin (nothing stored); echo "data" | c4 -s stores it. Every verb's --help is its reference page.

The c4m format

A c4m file is a complete filesystem description in plain text. Each line has permissions, timestamp, size, name, and C4 ID. Readable, editable, diffable, composable.

A 10,000-entry c4m file is about 1.4 MB. It describes the identity of every file in the tree regardless of how large those files are. The description is the lightweight handle; the content is the heavy thing it refers to.

Go library

import "github.com/Avalanche-io/c4"

id := c4.Identify(strings.NewReader("hello"))
fmt.Println(id)
// c447Fm3BJZQ62765jMZJH4m28hrDM7Szbj9CUmj4F4gnvyDYXYz4WfnK2nYRhFvRgYEectEXYBYWLDpLo6XGNAfKdt

C4 IDs are 90-character base58 strings — SHA-512 with a c4 prefix. URL-safe, filename-safe, double-click selectable.

Zero external dependencies. Go 1.16+.

Links

The C4 toolkit

C4 is part of a cross-language ecosystem. Every tool reads and writes the same c4m format and produces identical C4 IDs:

Tool Language What it does
c4 Go CLI — identify, snapshot, restore, diff
c4sh Go Shell — cd into c4m files, browse, copy
c4py Python Library — scan, diff, verify, store
c4git Go Git filter — version large files
c4ts TypeScript Browser + Node.js — zero dependencies
c4-swift Swift Apple platforms — Sendable, Codable
libc4 C Embed in any application

See c4toolkit for the full suite, install options, and version matrix.

License

Apache 2.0

About

Go package implementation of C4 Asset ID

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

43 stars

Watchers

8 watching

Forks

Releases

Packages

Used by

Contributors

Languages