Builds
district build starts a build of a repository and follows it to its result. attach follows a build that is already running, and list shows a repository's recent builds. Without a subcommand the command starts a build, so district build my-app and district build start my-app are the same. A repository whose slug is start, attach or list must be named by its repo_ id.
district build
district build [<repository>] [--ref <ref>] [--workspace <id>] [--yes] [--json] [--production | --staging | --dev]Without a positional argument, the command reads the clone in the current directory: origin must be a District remote, whose path gives the repository id and whose host and namespace give the environment. An environment flag that names a different environment is a usage error. Outside such a clone, name the repository by repo_ id or by slug. The environment is then the one the last district login recorded, the one a flag names, or production. A slug is unique inside a workspace and not across them, so a slug that several workspaces hold asks for --workspace <id>.
Without --ref, the ref is the clone's HEAD object name. A branch that moves cannot change what is built. A commit that origin does not hold is refused before the build starts:
HEAD 9f1c2e4… is not pushed to origin: push it, or pass --ref <branch>The check reads the remote-tracking refs and runs no git fetch. A clone with out-of-date remote-tracking refs reports a pushed commit as unpushed. --ref <branch> passes it. With a positional repository and no --ref, the build uses the repository's default branch.
The command prints the repository, the ref and the environment, then asks Start build? [y/N]. --yes skips the question. Without a terminal and without --yes the command stops, because an agent cannot answer.
Once district-api accepts the build, the command prints its id before it waits:
build hbld_01K4… started (re-attach with: district build attach hbld_01K4…)The build runs remotely, not in the terminal. Ctrl-C does not stop the build. district build attach reports the build again. Running district build again starts a different build.
Arguments
| Argument | Description |
|---|---|
[<repository>] | The repository, by repo_ id or by slug. Without it, the clone in the current directory names one: its origin must be a District remote, which also names the environment. |
Flags
| Flag | Description | Default |
|---|---|---|
--ref <ref> | The ref to build. | the clone's HEAD, or the repository's default branch |
--workspace <id> | The workspace of the repository, when the same slug names a repository in more than one workspace. | - |
--yes | Skips the "Start build? [y/N]" question. A session with no terminal needs it. | false |
--json | Prints the final build as one JSON object on stdout and no progress lines. | false |
--production | --staging | --dev | The environment to act in. Pass one at most. Without a flag, the command uses the environment that the last district login recorded, or production. | - |
Output
The command prints one line per finished step on stderr and the result on stdout. In a terminal, a spinner marks the running step.
$ district build --yes
build hbld_01K4… started (re-attach with: district build attach hbld_01K4…)
✔ checkout succeeded 3 s
✔ install succeeded 41 s
✔ build succeeded 96 s
✔ bundle succeeded 7 s
✔ export succeeded 2 s
bundle builds/hbld_01K4…/bundle.tar (5242880 bytes)A build that fails prints the tail of the failing step's log. A build that errors prints the recorded reason. The command reads the build every 2 seconds for the first minute and every 10 seconds after that. It stops polling after 2.5 hours with build <id> did not finish; last status <status>.
--json prints the final build as one JSON object on stdout and no progress lines. It does not query logs. A script that needs the log queries HostingBuildStep.logTail.
Exit codes
| Exit code | Meaning |
|---|---|
| 0 | The build succeeded. |
| 1 | The build failed or errored, the confirmation was declined, or the poll or the start did not finish. |
| 2 | The command line names no repository, a slug that several workspaces hold, or an environment other than the clone's. HEAD is not pushed, or no terminal can confirm. |
district build attach
district build attach <buildId> [--json] [--production | --staging | --dev]Follows a build that is already running, and reports it exactly as district build does: the same step lines, the same --json object, the same failing-step log, and the same exit codes. It starts nothing, so it asks for no confirmation.
A build id names no environment, so the environment is the one a flag names, the one the last district login recorded, or production. An id the caller cannot read is a usage error:
no build hbld_01K4… in stagingArguments
| Argument | Description |
|---|---|
<buildId> | The build to follow, by hbld_ id. |
Flags
| Flag | Description | Default |
|---|---|---|
--json | Prints the final build as one JSON object on stdout and no progress lines. | false |
--production | --staging | --dev | The environment to act in. Pass one at most. Without a flag, the command uses the environment that the last district login recorded, or production. | - |
Output
$ district build attach hbld_01K4…
✔ install succeeded 41 s
✔ build succeeded 96 s
…Exit codes
| Exit code | Meaning |
|---|---|
| 0 | The build succeeded. |
| 1 | The build failed or errored, or the poll did not finish. |
| 2 | The command line names no build that the caller can read in the environment. |
district build list
district build list [<repository>] [--workspace <id>] [--json] [--first <n>] [--production | --staging | --dev]Prints a header row, then a repository's builds, newest first, one row per build: the id, the status, the ref, and when it was requested. The repository is resolved as district build resolves it, from the clone or from a positional argument. No ref is resolved, and HEAD is not read.
A repository with no builds prints nothing and exits 0.
Arguments
| Argument | Description |
|---|---|
[<repository>] | The repository, by repo_ id or by slug. Without it, the clone in the current directory names one: its origin must be a District remote, which also names the environment. |
Flags
| Flag | Description | Default |
|---|---|---|
--workspace <id> | The workspace of the repository, when the same slug names a repository in more than one workspace. | - |
--json | Prints the rows as one JSON array. | false |
--first <n> | Reads n builds, from 1 to 100. | 20 |
--production | --staging | --dev | The environment to act in. Pass one at most. Without a flag, the command uses the environment that the last district login recorded, or production. | - |
Output
$ district build list my-app --first 2
BUILD STATUS REF CREATED
hbld_01K4… succeeded main 2026-08-25T09:00:00Z
hbld_01K4… failed topic 2026-08-24T09:00:00ZExit codes
| Exit code | Meaning |
|---|---|
| 0 | The list was printed. A repository with no builds also exits 0. |
| 1 | The API refused the call with its own message, or district-api did not answer. |
| 2 | The command line names no repository, or a slug that several workspaces hold. |