sow create
Generate a flat RPM/DEB repository in an ordinary directory — the Plain mode entry point.
Every sow subcommand is documented here: syntax, flags, behavior, real transcripts and exit codes.
This page covers what they all have in common — how a Workspace is discovered, how a Repository and
Dist are selected, how locking works, and what --json emits — so the individual pages don’t repeat
it.
sow has exactly two isolated execution paths. sow create is Plain mode: no Workspace, no config
file, no database. Everything else is Managed mode and runs inside a Workspace.
| Command | Mode | Purpose |
|---|---|---|
sow create [DIR] | Plain | Generate a flat RPM/DEB repository in place |
sow init [DIR] | Managed | Initialize a Workspace and converge declared Repositories/Dists |
sow config check | Managed | Validate sow.yml read-only |
sow config show | Managed | Print the effective configuration |
sow repo ls|new|show|rm | Managed | Manage Repositories |
sow dist ls|new|show|rm | Managed | Manage Dists |
sow add PATH... | Managed | Add packages to Desired Membership |
sow rm PACKAGE... | Managed | Remove Desired Membership |
sow ls / show / where | Managed | Query membership and locate packages |
sow build / status / check / changes | Managed | Converge, inspect, verify and diff |
sow log / log export / log prune | Managed | Operation audit ledger |
sow [OPTIONS] COMMAND [ARGS]
Running sow with no arguments prints the command list and exits 0. sow help COMMAND and
sow help COMMAND SUBCOMMAND print per-command usage. sow version and sow --version print the
binary identity:
sow version
sow 0.2.0-dev darwin/arm64 go1.26.5
There is no global --format, --yes, --dry-run, -q/-v or --config. An unknown flag is a
usage error, never silently ignored.
Managed commands look for the nearest ancestor directory containing sow.yml, in this order:
-C/--workdir DIR — start the upward search at DIR.SOW_DIR environment variable.2.The search stops at the first sow.yml it finds and never crosses past that Workspace.
--workdir only moves the discovery start directory. It does not chdir, so relative PATH,
DIR and FILE arguments still resolve against your real working directory.
sow status
workspace discovery error: managed: workspace discovery or configuration error: workspace not found (searched cwd="/home/vonng"); run sow init or set --workdir/SOW_DIR
sow create does not participate in discovery at all.
Commands that need one Repository resolve it in this order:
-r/--repo NAME.<workspace>/<repo>/.2 and list the candidates.sow status
workspace discovery error: managed: workspace discovery or configuration error: workspace has multiple repositories (infra, pgsql); select one with --repo
repo new and repo rm take the name as a positional argument and do not accept -r.
sow where searches every Repository by default and uses -r only to narrow.
Commands that need one or more Dists resolve them in this order:
-d/--dist NAME (the flag is repeatable).<workspace>/<repo>/dists/<dist>/.2 and list the candidates.build, check and status default to all Dists of the selected Repository when -d is absent.
add, rm and ls require an unambiguous Dist set:
sow ls -r pigsty
workspace discovery error: managed: workspace discovery or configuration error: repository "pigsty" has multiple Dists (el9, trixie); select one or more with --dist
sow changes operates on the whole Repository Generation and rejects -d outright.
Every command that takes a write lock accepts -T/--timeout DUR and -N/--no-wait. The lock scope
is the Repository — except init, repo new and repo rm, which lock the Workspace.
| Flag | Default | Meaning |
|---|---|---|
-T, --timeout DUR | 0 | Maximum wait for the lock; 0 waits indefinitely. Go duration syntax (500ms, 30s, 5m, 1h). |
-N, --no-wait | false | Fail immediately if the lock is held. |
The two are mutually exclusive when --timeout is non-zero. Failing to acquire the lock exits 4:
sow build -N
lock unavailable: managed: lock unavailable
Read-only commands never take the write lock. sow status still reports lock state, and marks the
Repository as not ready to copy while somebody else is writing:
sow status
repository=pigsty status=clean ready_to_copy=false revision=6 generation=6 dirty_dists= pending=0/0 locked=true
-j/--jobs N appears only on commands that actually parse packages, hash bytes, render indexes or
verify: create, add, rm, build, check. It defaults to the logical CPU count and must be at
least 1.
sow check -j 0
usage error: --jobs must be an integer greater than or equal to 1
Parallelism never changes output ordering, selection results, version comparison or Changeset content.
--json emits one versioned envelope on stdout. Human-readable diagnostics still go to stderr.
{
"schema": "sow.cli/v1",
"command": "add",
"ok": true,
"repository": "demo",
"operation": "1430722512865805553",
"result": {},
"errors": []
}
ok is false whenever the exit code is non-zero, but result is still fully populated — a partial
batch lists every committed item alongside every failure. Each errors[] entry carries code,
class and message:
{"code": 3, "class": "partial", "message": "managed: batch partially succeeded"}
Per-command result schemas are in JSON Output.
Three commands print structured JSON on stdout even without --json, because their result has no
compact tabular form: sow build, sow rm and sow show. Adding --json wraps them in the
standard envelope.
| Code | Meaning |
|---|---|
0 | Success or idempotent no-op |
1 | Runtime I/O, parser, renderer or signing error |
2 | Usage, Workspace discovery or configuration error |
3 | Partial success — at least one item committed, at least one failed |
4 | Write lock unavailable (--no-wait, or timeout expired) |
5 | Integrity/recovery error, or check ruling the tree not deliverable |
6 | Expected rejection — conflict, protected, no match, incompatible architecture |
Full trigger tables with transcripts are in Exit Codes.
Generate a flat RPM/DEB repository in an ordinary directory — the Plain mode entry point.
Create a Workspace, and converge whatever Repositories and Dists sow.yml already declares.
Validate sow.yml without touching anything, and print the effective configuration for any scope.
List, create, inspect and remove Repositories — the lock, transaction and Generation boundary.
List, create, inspect and remove Dists — the named single-format member set clients actually consume.
Add packages to Desired Membership, apply policy, and rebuild the affected indexes.
Remove Desired Membership from selected Dists, with a no-write preview mode.
Three read-only queries: list a Dist’s membership, inspect one package object, locate a package across the Workspace.
Converge Desired state into a Built Generation, and the three commands that tell you where you stand.
Read the Operation audit ledger, export it as JSONL, and prune eligible terminal records.