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

ArgumentDescription
[<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

FlagDescriptionDefault
--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.-
--yesSkips the "Start build? [y/N]" question. A session with no terminal needs it.false
--jsonPrints the final build as one JSON object on stdout and no progress lines.false
--production | --staging | --devThe 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 codeMeaning
0The build succeeded.
1The build failed or errored, the confirmation was declined, or the poll or the start did not finish.
2The 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 staging

Arguments

ArgumentDescription
<buildId>The build to follow, by hbld_ id.

Flags

FlagDescriptionDefault
--jsonPrints the final build as one JSON object on stdout and no progress lines.false
--production | --staging | --devThe 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 codeMeaning
0The build succeeded.
1The build failed or errored, or the poll did not finish.
2The 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

ArgumentDescription
[<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

FlagDescriptionDefault
--workspace <id>The workspace of the repository, when the same slug names a repository in more than one workspace.-
--jsonPrints the rows as one JSON array.false
--first <n>Reads n builds, from 1 to 100.20
--production | --staging | --devThe 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:00Z

Exit codes

Exit codeMeaning
0The list was printed. A repository with no builds also exits 0.
1The API refused the call with its own message, or district-api did not answer.
2The command line names no repository, or a slug that several workspaces hold.