Reading a Point
A point is a place in history: a ref (heads/main, tags/v1, remotes/heads/main) or a bare block
id, 64 lowercase hex characters, as prikk log prints it. Any block the repository holds is a point,
including an older block on a branch and a block only received history reaches. Reading a point adopts
nothing and trusts nothing (RFC 157).
prikk tree — the files at a point
prikk tree [path] [--ref <ref|block-id>] [--prefix <p>] [--format json]
tree lists every file present at the point, in canonical path order (byte order of the path). There
are no directory entries: prikk records paths, not directories, so a directory is just the shared
leading components of the paths under it.
tree repository: /path/to/repo/.prikk
ref: heads/main
target block: 7c1e…
entries: 3
100755 text 18 run.sh
100644 binary 240128 src/big.bin
100644 text 1834 src/main.rs
Each line is the file’s mode (octal), its encoding, its exact size in bytes, and its path. With a block id
the header reads block: <id> instead of ref: <name>.
-
Encoding.
textorbinary, by the same classificationcheckout --patch-plan --format json --content-pathreports. A file is text when it was committed as text. -
The mode is one number, shown two ways. The prose prints it octal, as
ls -landgit ls-treedo (100644,100755); the JSON prints the same number in decimal, ascheckoutalready reports it (33188,33261).100644octal is33188decimal — the two forms never disagree:file prose JSON modean ordinary file 10064433188an executable 10075533261On Windows, expect
100644for files committed there. Windows has no executable bit, so prikk cannot observe one: a file first committed on Windows is recorded100644, and committing on Windows never changes a mode that history already records. That is a platform limit, not lost data. History committed on Linux or macOS still carries100755for its executables, andtreeshows every recorded mode on every platform, so a Windows reader of that history sees100755where it was recorded. See Platform Support. -
Size is exact: a text file’s content is reconstructed by replay, and its length is counted, not estimated.
-
--prefix <p>keeps the paths at or underp, by whole path components:--prefix src/(orsrc) listssrc/main.rsand neversrcx/a.txtorsrc.rs. The replay is whole-tree either way, so a prefix shortens the output, not the work. -
Without
--refit lists the current branch. In a fresh repository whose branch has never been sealed, that is an empty listing with exit0— and naming that same branch explicitly with--refanswers exactly the same way, since the current branch is never absent, published or not. An explicit--refnaming any other absent name refuses withref <name> does not exist in this repository. -
A received ref (
remotes/…) lists like any other. -
Cost. One replay of the point, anchored at its nearest checkpoint, like
checkout --patch-plan.
--format json: tree-listing-v1
{
"schema_version": "tree-listing-v1",
"point": "heads/main",
"target_block_id": "7c1e…",
"prefix": "src/",
"entries": [
{"path": "src/big.bin", "kind": "file", "encoding": "binary", "mode": 33188, "size": 240128, "content_id": "9f02…"},
{"path": "src/main.rs", "kind": "file", "encoding": "text", "mode": 33188, "size": 1834}
]
}
pointis the point exactly as given;target_block_idis the block it resolved to, so a consumer can cache by block. For an unpublished current branch it isnull, with no entries.prefixis--prefixexactly as given, ornull.kindisfile. (symlinkis reserved for when replay supports symlinks; until then a history holding a symlink operation fails the whole call rather than listing part of the tree.)modeis the full file mode, the same numbercheckoutreports (33188is100644,33261is100755).content_idis present only for a binary file: its stored blob id. A text file never has one, even when a checkpoint happens to store its content, so a listing does not change with checkpoint cadence. Treat it as a cache hint, not as a way to fetch content.
prikk cat — one file’s bytes at a point
prikk cat --path <p> [--ref <ref|block-id>] [--output <file> [--force]] [--max-bytes <N>] [--format json]
cat writes the file’s bytes at the point — text and binary alike — to stdout, or to --output. It is the
one command whose job is bytes: diff never prints binary content, and checkout --content-path reports
text inside a plan.
prikk cat --path src/main.rs # to stdout
prikk cat --path src/big.bin --output ./big.bin # to a file
prikk cat --path src/main.rs --ref <block-id> # at an older block
- All or nothing. The content is resolved in full before one byte is written. A failure anywhere — an unsupported operation, damage, a bound — writes nothing at all.
--max-bytes <N>refuses content larger than N, naming the size and the bound, and writes nothing, not even a partial file. Read exactly what it promises:- It bounds what is written — exactly, and all or nothing. When it refuses, nothing reaches stdout and no file is created or replaced.
- It does not bound memory.
catreads the point through the same replaycheckout --patch-planuses, which holds every file’s content while it builds the tree, so a large file is already in memory when the bound is compared. Peak memory is that replay’s own cost, proportional to the size of the whole tree at the point, and--max-bytesdoes not lower it. A caller bounding hostile input gets a bound on the output, not on the process. A memory bound would need the replay to stream, which is planned separately (RFC 158) and not somethingcatcan add on its own.
--output <file>refuses an existing file unless you pass--force(bundle export’s own rule), and refuses any path inside.prikk/. The write goes to a temporary file beside the destination and is renamed into place, so a failed or interrupted write leaves the destination untouched rather than half written.- Binary content never reaches a terminal. With stdout on a terminal, a binary file refuses and names
--output; nothing is written. History from someone else must not be able to drive your terminal by being printed. Text goes to a terminal as-is, exactly ascheckoutwould materialize it. Redirecting or piping stdout is not a terminal, soprikk cat --path src/big.bin > big.binwrites the bytes. - A path that is not a file at that point — never existed, deleted by then, or a directory prefix like
src— refuses withpath <p> does not exist at <point>.
--format json: path-content-v1
{
"schema_version": "path-content-v1",
"point": "heads/main",
"target_block_id": "7c1e…",
"path": "src/big.bin", "kind": "file", "encoding": "binary", "mode": 33188, "size": 240128,
"content_id": "9f02…"
}
No bytes. The fields are the same as one tree-listing-v1 entry, computed by the same code, so a
consumer can decide between rendering inline and downloading — and show a size — before fetching anything.
When tree and cat refuse
- An absent ref (never the current branch, which is never absent, published or not), a block id the
repository does not hold, or an id naming another kind of object: the point resolver’s preconditions,
exit
1— see Commands. - A
--refvalue that is neither a ref name nor a block id, or a--prefixthat is not a repository-relative path: usage, exit2. - An operation replay does not support, anywhere in the history: the whole call fails, and nothing is listed.
- Damage the store reports:
integrity error. A binary file whose blob is missing or no longer recomputes fails the whole call, fortreeand forcatalike: a state with a hole is not a state, so no entry is listed as unavailable and no partial listing is printed (RFC 157 §5a).
cat refuses the same things, plus a path that is not a file at the point, a --max-bytes bound the content
exceeds, an existing --output without --force, an --output inside .prikk/, and binary content to a
terminal.