Selection language
Every subcommand that operates on targets (build, test, watch,
affected) takes the same selection arguments. One language, one
matcher, used everywhere.
Targets are identified by their path-derived label, //<package>:<name>,
where the package is the directory holding the target’s giant.yaml. See
Packages for how labels are derived.
Empty: everything
Section titled “Empty: everything”giant build # all non-test targetsgiant test # all test targetsgiant build --watch # all non-test targets, continuouslygiant test --watch # all test targets, continuously (TDD loop)giant build --with-tests --watch # everything, test + non-test, continuouslyLabels and patterns
Section titled “Labels and patterns”A label or pattern picks targets out of the package tree.
| Pattern | Matches |
|---|---|
//src/go/server:server | one target by full label |
//src/go/server | shorthand for the same - name defaults to the last path segment |
//src/go:* | every target in exactly that package (no subpackages) |
//src/go/... | every target at or under src/go, crossing subpackages |
//... | every target in the whole workspace |
* matches a single path or name segment; it does not cross / or :.
... is the only construct that crosses package boundaries - it descends
recursively from its anchor.
giant build //cmd/server:server # one targetgiant build //cmd/server # same, shorthandgiant build //src/go:* # every target in the src/go packagegiant build //src/go/... # src/go and everything beneath itgiant build //... # the whole workspaceA literal label that doesn’t exist is an error - and Giant suggests the closest match:
$ giant build //go/bin:srvrno target matches "//go/bin:srvr" did you mean //go/bin:server?Glob misses (patterns containing * or ...) are silent - no targets,
no error. Only literal labels error out.
$ giant build //rust/...· no targets to build # no targets under rust/; not a typo, just emptyExclusion
Section titled “Exclusion”Prefix ! to remove matches. Shell-special, so quote it:
giant build '//src/go/...' '!//src/go/internal/...'giant build '!//src/go/...' # everything except src/go and belowIf only excludes are given, the implicit include is //... -
everything, minus your excludes.
Language and kind live in tags:, alongside any free-form labels:
- name: "server" tags: ["lang=go", "kind=bin", "release", "linux"] ...Filter with --tag (include) and --no-tag (exclude). Multiple --tag
flags union - a target passes if it carries any of them. --no-tag
drops a target that carries any excluded tag, and composes with --tag.
Each flag takes one whole tag; there’s no comma syntax:
giant build --tag kind=bin # only binariesgiant build --tag kind=bin --no-tag flaky # binaries AND NOT flakygiant build --tag lang=go --tag lang=rust # Go OR Rust (union)Tags compose with patterns:
giant build '//src/...' --tag release # release-tagged AND under src/Test mode
Section titled “Test mode”giant build excludes test: true targets by default. giant test
selects only test targets:
giant build # 12 production targetsgiant test # 47 test targetsgiant test '//src/go/...' # only Go tests under src/gogiant test //cmd/server:server # error - server isn't a testAffected
Section titled “Affected”Restrict the selection to what changed since a baseline:
giant build --affected --base main # diff against maingiant build --affected --base HEAD # since last commit (working tree)giant build --affected --file src/main.go # explicit file list (for CI)--affected composes with everything else:
giant build --affected --base main '//src/go/...' --no-tag flakyMeans: targets that (a) match //src/go/..., (b) are not flaky, AND (c)
were affected by file changes since main.
Re-running failures
Section titled “Re-running failures”failed-last re-selects the targets that failed in the most recent
build:
giant build failed-last # retry just what brokefailed-last is a whole-selection token: it must be the
only argument, and tag filters don’t apply to it (it replays exactly the
recorded set). It does still intersect with --affected, so
giant build failed-last --affected --base main retries only the failures
that touch changed files.
How it composes
Section titled “How it composes”Order of operations:
- Compute the set of eligible targets - apply test mode, then tag filters.
- Apply pattern selection (positional includes / exclusions) to the eligible set.
- If
--affectedis given, intersect with the affected set.
Same pipeline in build, test, watch, and affected. Same matcher.
A future TUI porcelain will drive it via the NDJSON event
protocol - selection.list_tags, selection.resolve
- so the UI gets the same answers as the CLI.