Manifest format
Plain UTF-8 text, one record per line, LF endings on every platform.
#ferrule 1
#tree ./build
#hash blake3-256
f 412 0644 6f1c…a93b bin/ferrule
l - 0777 - bin/frl -> ferrule
d - 0755 - share/
f 1904 0644 02de…77c1 share/man/man1/ferrule.1
Header
Lines beginning with # come first and are ordered. #ferrule is the format version and is bumped only when an existing field changes meaning. #tree is informational; nothing reads it back. #hash names the digest, currently always blake3-256.
Records
| Field | Notes |
|---|---|
| type | f file, d directory, l symlink, h hardlink to an earlier f. |
| size | Bytes, or - where it carries no information. |
| mode | Octal permission bits only. Setuid and setgid are recorded; the file type is already in the first column. |
| hash | Lowercase hex, truncated in display only. Directories and symlinks carry -. |
| path | Slash-separated, relative, never leading. Sorted bytewise, so the order does not shift with your locale. |
Columns are separated by two spaces and the path is last, which means a path may contain a single space without quoting. Anything else — newlines, control characters, invalid UTF-8 — is escaped in the manner of C string literals, and a manifest containing escapes still sorts by the unescaped bytes.
Stability
Format 1 has not changed since 0.7 and I do not expect it to change before 1.0. If it does, verify will keep reading older manifests; only seal will move forward.
Reading a manifest with awk is a supported use case, not an accident. If a change would break that, it is the wrong change.