Take a snapshot of the tracked tree that can be read, or checked, somewhere else.
Take a snapshot of the tracked tree that can be read, or checked, somewhere else.
generated-output-mutating
system
--json
The file set is the git index, so nothing untracked — no build output, no cache, no .ai/local/ — can travel. What a profile drops beyond that is declared in share/archive.yaml; a profile that drops the derived paths reads .gitattributes rather than keeping a second list of generated paths. Every entry's mode is taken from the index and written into the archive's manifest, and the restore script inside the archive puts the modes back and builds a local git index, because a copy whose scripts are not executable fails checks for reasons of its own.
Only the codes this command can produce. The full contract is on the commands index.
0ok
2usage
10contract unmet
12missing artifact
13internal error
15refused
A snapshot that can be read, or checked, somewhere else
A repository leaves the machine more often than it looks: to a model that will read all of it, to a reviewer who cannot clone, to an auditor who must run the gates on a copy. What travels is the git index and only the git index, so nothing untracked can escape; what is dropped beyond that is a profile in share/archive.yaml, and a profile that drops the generated projections reads .gitattributes rather than keeping a second list of them.
What snapshots there are, and which is the default
layer installed
yes
Given this repository
# A repository with Majordomus installed and projections generated, and one commit of work.
"$MJ" init >/dev/null
"$MJ" update >/dev/null
mkdir -p lib docs
echo a > lib/a
echo d > docs/d
git add . && git commit -qm base
Run
$ majordomus archive --list
Output contains
context
\(default\)
audit
governance
exit0
The profiles are declarations, not flags: each one names a different reader, and the summary says what that reader is owed. A repository may add its own in .ai/repo/archive.yaml without changing the tool.
What would travel, and why the rest would not
layer installed
yes
Given this repository
# A repository with Majordomus installed and projections generated, and one commit of work.
"$MJ" init >/dev/null
"$MJ" update >/dev/null
mkdir -p lib docs
echo a > lib/a
echo d > docs/d
git add . && git commit -qm base
Run
$ majordomus archive --dry-run
Output contains
profile context
tracked file
nothing written
exit0
The count of tracked files is stated beside the count archived, so a selection that quietly matched nothing cannot look like a selection that matched everything. Every file left out is attributed to the rule that left it out.
Written, and then read back
layer installed
yes
Given this repository
# A repository with Majordomus installed and projections generated, and one commit of work.
"$MJ" init >/dev/null
"$MJ" update >/dev/null
mkdir -p lib docs
echo a > lib/a
echo d > docs/d
git add . && git commit -qm base
Run
$ majordomus archive --format tar.gz
Output contains
OK archive
read back
wrote tmp/archives/
exit0
The archive is opened again before the command returns. The entry count must match what was staged, and executables that went in must come back out — the failure this command exists to answer is a container that silently discarded the file modes.
Asking for a snapshot nobody declared
layer installed
yes
Given this repository
# A repository with Majordomus installed and projections generated, and one commit of work.
"$MJ" init >/dev/null
"$MJ" update >/dev/null
mkdir -p lib docs
echo a > lib/a
echo d > docs/d
git add . && git commit -qm base
Run
$ majordomus archive nosuch
Output contains
no profile
archive --list
exit12
Exit 12 is MISSING_ARTIFACT, and the message names the command that lists what does exist rather than listing it here.
Reference
Take a snapshot of the tracked tree that can be read, or checked, somewhere else.
A repository leaves the machine more often than it looks: to a language model that will
read all of it at once, to a reviewer who cannot clone, to an auditor who has to run the
gates on a copy. Those were being done by hand, differently each time, and the hand-made
version got two things wrong that only surface at the far end.
What travels is the git index and only the git index. Nothing untracked is ever
archived — not the build output, not the caches, and not .ai/local/, which is this
checkout's own state and is never shared. That is one rule instead of a list of
exclusions, and it is what makes the command safe to point at a repository nobody has
read.
What is left out beyond that is declared, not coded.share/archive.yaml holds the
profiles; a repository may add or replace one in an archive.yaml of its own under .ai/repo/. A profile that
drops the derived paths reads .gitattributes — every projection in this repository is
already marked merge=derived there, for a different reason — rather than keeping a
second list of generated paths, which is the duplication
.ai/repo/rules/project/commands-are-projections.v1.md refuses.
Modes are carried explicitly.zip -X strips the extra fields that hold the Unix
mode, and the unpacked tree then has no executable in it: every script fails to run, and
at the far end that is indistinguishable from the repository being broken. So the mode of
each entry is read from the index — the authority, not the working tree — written into
_ARCHIVE/MANIFEST.txt, and _ARCHIVE/restore.sh inside the archive puts the modes back
and creates a local git index, because the checks here enumerate the repository with
git ls-files and without an index they examine nothing and report that nothing is wrong.
Every archive is read back before the command returns: the entry count must match what
was staged, and if executables went in and none came out, that is a failure rather than a
surprise for the recipient.
Reads:share/archive.yaml, an archive.yaml under .ai/repo/ when the repository has one,
.gitattributes, and the git index.
Writes:tmp/archives/ — or wherever --out says.
The profiles shipped:
Profile
For
context
A model that will read the repository. Every tracked source, without the projections generated from it.
audit
Running the repository's own checks on a copy. Every tracked file, nothing dropped, modes and a git index restored.
governance
The operating contract alone: .ai/, docs/, AGENTS.md, CLAUDE.md, and no code.
$ majordomus archive --dry-runarchive: profile context — 2299 of 2757 tracked file(s), 12919 KB of content left out: 10 (binary) left out: 443 (derived) left out: 5 (excluded) nothing written (--dry-run)$ majordomus archiveOK archive prismatic-majordomus-context-20260911.zip — 2303 entr(ies) read back, 76 of them executablearchive: profile context — 2299 of 2757 tracked file(s), 12919 KB of content wrote tmp/archives/prismatic-majordomus-context-20260911.zip (5044 KB)
Behaviour:
--list prints the profiles with what each one is for, and marks the default.
--dry-run reports the selection and the reason every file was left out, and writes
nothing.
--out overrides the destination; --format zip|tar.gz overrides the container.
An existing output file is refused with 15 unless --force is given, so an archive
someone is uploading cannot be replaced underneath them.
A path the index names and the working tree no longer has is counted and reported, not
silently absent.
--json emits one object with the counts, the reasons and the path.
Exit 2 on a usage error, 12 when there is no such profile or zip is not on PATH,
10 when a profile selects none of the tracked files, 15 when the output exists, 13
when the container could not be written or does not read back as what went in.
Evidence
Every case below runs in CI on Linux and macOS. The site refuses to build if a public command has no behavioural case, no negative case, or no demonstration.