# Zuke — full API reference The complete typed public surface of every package. Each section is one package: the tasks you call and the fluent settings each accepts. Use these signatures verbatim — there is a typed wrapper for every tool, so there is no need to fall back to raw shell. Regenerate with `./zuke apiDocs`. ======================================================================== # @zuke/core ======================================================================== Zuke — a code-first, strongly-typed build automation system for Deno. Public API. Define a build by extending {@link Build}, declare targets with the {@link target} fluent builder, and make the file runnable with {@link run}: ```ts import { Build, target, run } from "jsr:@zuke/core"; import { $ } from "jsr:@zuke/core/shell"; class MyBuild extends Build { test = target() .description("Run the test suite") .executes(async () => { await $`deno test -A`; }); } await run(MyBuild); ``` The shell helper `$` lives in the `./shell` submodule (`jsr:@zuke/core/shell`). @module function absolutePath(first: string, ...rest: string[]): AbsolutePath Build an {@link AbsolutePath} from one or more segments. The first segment (after joining) must be absolute — start with `/` or a drive letter, or build from an absolute base — otherwise an error is thrown. ```ts const root = absolutePath("/app"); root("src", "main.ts").path; // "/app/src/main.ts" root.join("..", "shared").path; // "/shared" absolutePath("C:\\repo", "x").path; // "C:/repo/x" ``` @param first The first path segment; must make the result absolute. @param rest Additional segments to append. async function acquireLease(store: StateStore, prefix: string, runId: string, actor: string, now: () => string, ttlMs: number, runUrl?: string): Promise Take a lease named `prefix` over `runId`, or `null` if a live holder has it. While held, the lease renews on a background heartbeat until {@link HeldLease.release}. That timer never keeps the process alive. Only an explicit refusal counts as loss. A store reports `false` from a renewal when the claim is demonstrably somebody else's; it throws for a filesystem mutex it could not take in time, or an HTTP 503, or a DNS blip — none of which say anything about who holds the lease. Treating those as loss would abort a healthy build because the state service had a bad second, so they are swallowed and the next tick tries again. A store that stays unreachable lets the claim lapse at its TTL, which is the documented backstop and the honest outcome. function affectedTargets(order: readonly TargetBuilder[], changed: readonly string[]): Set Compute the set of targets in `order` affected by the given `changed` files. `order` must be a valid execution order (dependencies before dependents, as produced by {@link plan}/{@link planGraph}) so each target's dependencies are already decided when it is visited. A target is affected when its own inputs cover a changed file, when it declares no inputs (unprovable — treated as affected), when a dependency is affected, or when an affected target triggers it. function appendJobSummary(markdown: string): boolean Append `markdown` to the Actions job summary, returning whether it was written. Outside Actions (no `GITHUB_STEP_SUMMARY`) it is a no-op returning `false`, so the same code path works locally. Best-effort by design: an unwritable summary file reports `false` rather than throwing. A report that could not be displayed must never fail the build that produced it — the build's own result is the signal that matters. async function archiveOutputs(outputs: readonly string[], host: OutputHost): Promise Archive a target's `outputs` into a gzipped tar of their current contents. A declared output that does not exist is skipped, as is anything under a `.git` or `.zuke` directory. function assert(condition: unknown, message: string): asserts condition Assert that `condition` is truthy, narrowing it for the rest of the scope. Throws an {@link AssertionError} with `message` otherwise. async function assertDirectoryExists(path: PathLike): Promise Assert that `path` exists and is a directory. Async (stats the filesystem). function assertExists(value: T, message: string): NonNullable Assert that `value` is neither `null` nor `undefined`, returning it narrowed to its non-nullable type so it can be used inline. ```ts const token = assertExists(Deno.env.get("TOKEN"), "TOKEN is required"); ``` async function assertFileExists(path: PathLike): Promise Assert that `path` exists and is a file. Async (stats the filesystem). function assertSafeEntryName(name: string): void Reject an archive entry whose name would escape the destination directory — an absolute path or one with a `..` segment (a "zip slip"). A downloaded or poisoned archive must never place files outside where it is being unpacked. function assertSafeLinkTarget(entryName: string, target: string): void Reject a symlink whose target would resolve outside the destination directory — an absolute target, or a relative one that climbs (with `..`) above the extraction root once resolved against the link's own directory. A file entry's name is bounded by {@link assertSafeEntryName}; a symlink adds a second escape vector (its target), so a poisoned tarball can't plant `bin/x -> ../../etc`. async function cancelRun(build: Build, options: CancelOptions): Promise Cancel the run `options.runId` for `build`: transition it to `cancelling` (exactly one canceller drives the walk; a live owning process observes the change and aborts), run the compensations of every succeeded target in reverse order, and settle the record as `cancelled`. Idempotent — cancelling an already-terminal run is a friendly no-op. @throws if no state store is configured, or the run does not exist. function ciHost(): string A short identifier for the detected CI host, or `"local"` when not on CI. Recognises GitHub Actions, GitLab CI, Azure Pipelines, Bitbucket Pipelines, and the generic `CI` convention. Prefer {@link detectCiHost} for new code: its values match {@link CiProvider}. This function is kept for compatibility and uses longer, host-specific names. function cicd(spec: CiFileSpec): CiFile Declare a CI file as a build field. Running the build regenerates it (and the `generate-ci` command writes it on demand), so the committed configuration is generated from code rather than hand-maintained. The provider is the only required field: `cicd({ provider: "github" })` declares a workflow at `.github/workflows/ci.yml` that runs the build on push/PR to `main`. Override only what else you need. ```ts class MyBuild extends Build { ci = cicd({ provider: "github" }); // sensible default workflow // …or customise: gitlab = cicd({ provider: "gitlab", pipeline: { jobs: [{ steps: [...] }] } }); } ``` async function createTarGzip(files: PathLike[], dest: PathLike, options: { cwd?: string; }): Promise Read `files` (relative to `cwd`), pack them into a tar archive named by their path relative to `cwd`, gzip it, and write the result to `dest`. function describeCli(build: Build, options: DescribeCliOptions): CliDescription Describe a build's full CLI surface — reserved commands, option flags, targets (with descriptions and dependencies), and declared parameters — as a plain object ready for JSON. This is the same data `zuke --list --json` prints, made available to tooling and agents that introspect a build in code. ```ts import { describeCli } from "jsr:@zuke/core"; const surface = describeCli(new MyBuild()); console.log(surface.targets.map((t) => t.name)); ``` Pass `{ omitSecrets: true }` to drop `.secret()` parameters from the result — the posture the build registry uses, so a secret never becomes a spawnable MCP input or crosses the run boundary (`zuke register` writes this form). function detectCiHost(env: (name: string) => string | undefined): CiHost Detect the CI host from the environment. Recognises GitHub Actions (`GITHUB_ACTIONS`), GitLab CI (`GITLAB_CI`), Azure Pipelines (`TF_BUILD`), and Bitbucket Pipelines (`BITBUCKET_BUILD_NUMBER`); anything else is `"local"`. The reader is injectable so detection can be unit-tested hermetically. function discoverCiFiles(build: Build): CiFile[] Find every {@link CiFile} declared on a build instance. A fan-out file is resolved here — its jobs are expanded from the build's targets — so the returned files render the same whether they fan out or not. function discoverGroups(build: Build): Map Discover all parallel {@link Group} batches declared on a build instance, binding each its property path (for labelling, e.g. in the graph). Groups that are not assigned to a build property simply stay unnamed. function discoverParameters(build: object): Map Discover all parameters declared on a build instance: scan its fields (recursing into plain-object component bundles) for {@link Parameter} values, bind each its dotted property path, and return a name → parameter map preserving declaration order. function discoverTargets(build: Build): Map Discover all targets declared on a build instance. Scans the instance's fields (recursing into plain-object component bundles) for {@link TargetBuilder} values, assigns each its dotted property path, and returns a name → target map preserving declaration order. @throws if two properties reference the same builder instance under different names (a programming error that would corrupt naming). function envBuildRegistry(readEnv: (name: string) => string | undefined, host: StateHost): BuildRegistry | undefined Resolve a {@link BuildRegistry} from the environment, or `undefined` when none is configured. `ZUKE_REGISTRY_URL` (with an optional `ZUKE_REGISTRY_TOKEN`) selects an {@link HttpBuildRegistry}; otherwise `ZUKE_REGISTRY_DIR` selects a {@link FileSystemBuildRegistry}. function envCacheStore(readEnv: (name: string) => string | undefined): RemoteCacheStore | undefined Resolve a {@link RemoteCacheStore} from the environment, or `undefined` when none is configured. `ZUKE_REMOTE_CACHE_URL` (with an optional `ZUKE_REMOTE_CACHE_TOKEN`) selects an {@link HttpCacheStore}; otherwise `ZUKE_REMOTE_CACHE_DIR` selects a {@link FileSystemCacheStore}. function envStateStore(readEnv: (name: string) => string | undefined, host: StateHost): StateStore | undefined Resolve a {@link StateStore} from the environment, or `undefined` when none is configured. `ZUKE_STATE_URL` (with an optional `ZUKE_STATE_TOKEN`) selects an {@link HttpStateStore}; otherwise `ZUKE_STATE_DIR` selects a {@link FileSystemStateStore}. function envVarName(name: string): string The environment variable for a parameter: its path in SCREAMING_SNAKE_CASE. function execSecret(configure: Configure): SecretSource A {@link SecretSource} that runs a command and takes its standard output as the secret value. Configure it through an {@link ExecSecretSettings} lambda. ```ts parameter("Vault token").secret().from( execSecret((s) => s.command("vault").arg("kv", "get", "-field=token", "secret/ci")), ); ``` async function execute(build: Build, root: TargetBuilder, options: ExecuteOptions): Promise Execute the requested target and its transitive dependencies. Runs the build's `onStart`/`onFinish` lifecycle hooks around the plan. By default targets run sequentially in deterministic order; with `parallel`, independent targets run concurrently while dependencies still complete first. Stops launching after the first failure, marks unreached targets as skipped, and returns a failing result. function executionSet(root: TargetBuilder): Set Compute the execution set for a requested target: the target plus the transitive closure of its hard dependencies. function externalSignal(name: string): WaitTrigger A trigger satisfied when a signal named `name` has been delivered to the run (via `zuke resume --signal `). The signal's payload is exposed to target bodies through {@link "./target.ts".TargetContext} `signals`. async function extractTarGzip(src: PathLike, destDir: PathLike, options: ExtractOptions): Promise Read the `.tar.gz` at `src`, gunzip and unpack it, and write each entry under `destDir` (creating parent directories as needed). Symlink entries are recreated as symlinks and directory entries as directories; pass {@link ExtractOptions.strip} to drop leading path components. async function extractZip(src: PathLike, destDir: PathLike, options: ExtractOptions): Promise Read the `.zip` at `src`, unpack it, and write each entry under `destDir` (creating parent directories as needed) — the zip counterpart of {@link extractTarGzip}. Entry names are validated so a malicious archive cannot escape `destDir`. function fail(message: string): never Throw an {@link AssertionError} with `message`. Never returns. function fanOutPipeline(targets: Map, base: CiPipeline, options: FanOutOptions): CiPipeline Expand a build's target graph into a fanned-out pipeline: one CI job per runnable target, wired together with `needs:` edges that mirror the targets' `dependsOn` dependencies — so independent targets run in parallel and a target's job waits for its prerequisites. Each job runs just its own target; upstream outputs are shared through the {@link "./remote_cache.ts" | remote cache}, so configure one (e.g. `ZUKE_REMOTE_CACHE_*` on the jobs) to avoid rebuilding dependencies in every job. `base` contributes the pipeline-level fields (name, triggers, permissions, concurrency); its `jobs` are ignored in favour of the generated ones. Targets with no body, and (unless {@link FanOutOptions.includeUnlisted}) `unlisted` targets, are omitted, and `needs` edges to omitted targets are dropped. function fileSecret(configure: Configure): SecretSource A {@link SecretSource} that reads a file and takes its content as the secret value — for a mounted Kubernetes/Docker secret or a CI-provided file. Configure it through a {@link FileSecretSettings} lambda. ```ts parameter("Registry password").secret().from( fileSecret((s) => s.path("/run/secrets/registry_password")), ); ``` function findCycle(targets: Map): string[] | null Detect a cycle in the hard-dependency (`dependsOn`) graph across all targets. @return the cycle as a path of names (e.g. `["a", "b", "a"]`) or `null`. function generateCi(pipeline: CiPipeline, provider: CiProvider): string Render `pipeline` as the YAML configuration for `provider`: `.github/workflows/*.yml`, `.gitlab-ci.yml`, `azure-pipelines.yml`, or `bitbucket-pipelines.yml`. The pipeline may be empty (`{}`) to accept every default. async function gitChangedFiles(base: string, run: (args: string[]) => Promise): Promise List the files changed since `base` (default `HEAD`) via git: tracked changes versus `base` plus untracked files not covered by `.gitignore`. `run` invokes git and returns stdout (defaults to a real `git` subprocess); override it to test without a repository. async function glob(pattern: string, options: GlobOptions): Promise Expand a glob pattern to the matching paths, relative to `cwd`, sorted for determinism. The walk starts at the pattern's static prefix, so anchor patterns (e.g. `src/**\/*.ts`) to avoid scanning the whole tree. Symlinked directories are not followed. function globToRegExp(pattern: string): RegExp Compile a glob pattern into an anchored {@link RegExp} that matches a full path. Exposed (and pure) for testing and custom matching. function group(): Group Create a parallel {@link Group}. Targets join it with {@link TargetBuilder.partOf}, and a downstream target can depend on the whole batch by passing the group to {@link TargetBuilder.dependsOn}. ```ts checks = group(); lint = target().partOf(this.checks).executes(...); format = target().partOf(this.checks).executes(...); deploy = target().dependsOn(this.checks).executes(...); ``` async function gunzip(data: Uint8Array): Promise Gunzip-decompress `data` using the platform `DecompressionStream`. async function gzip(data: Uint8Array): Promise Gzip-compress `data` using the platform `CompressionStream`. function hostPlatform(): Platform The current host's {@link Platform} (from `Deno.build`, with the OS normalised) — the analogue of {@link "./host.ts".isCI} for "what machine am I running on". Its `os` is a Zuke {@link OperatingSystem} (`macos`, not `darwin`); use the `osLabel`/`archLabel` helpers to name it for a download URL. ```ts const p = hostPlatform(); p.os; // "linux" | "macos" | "windows" const cpu = p.archLabel({ x86_64: "amd64", aarch64: "arm64" }); ``` async function httpDownload(url: string, dest: PathLike, options: HttpOptions): Promise Download `url` to `dest`, streaming the response body to the file. Creates or truncates `dest`. Throws {@link HttpError} on a non-2xx status. async function httpJson(url: string, options: HttpOptions): Promise Fetch `url` and parse its body as JSON. Throws {@link HttpError} on non-2xx. async function httpText(url: string, options: HttpOptions): Promise Fetch `url` and return its body as text. Throws {@link HttpError} on non-2xx. async function installNpmTool(spec: NpmToolSpec, options: InstallNpmToolOptions): Promise Provision an npm-registry package as a version-pinned, cached tool and return the installed bin's {@link AbsolutePath} — hand it straight to a wrapper's `.toolPath(...)`. The package installs under `/npm/@` via `npm install --prefix --no-save @`; a marker file records the pinned `{ name, version }`, so a later run whose marker matches and whose bin is still present is reused without invoking npm again. `npm` must be on `PATH` (it resolves and downloads the package). Throws — without recording a marker — if `spec` is malformed (an unsafe name, version, or bin), if npm fails, or if npm succeeds but the expected bin is absent (a typo'd `bin`, or a package that ships no executable), so a bad install fails loudly here instead of at a later `.toolPath(...)`. The marker is written only after the bin is verified present, so a matching marker always has its bin — a reader never sees a half-written install. Concurrent installs of the same pin into the same directory are not isolated; they just do redundant work (the documented ceiling — a build resolves its toolchain once, and distinct pins use distinct directories). async function installRelease(options: InstallReleaseOptions): Promise Download and install a release binary, returning its {@link AbsolutePath}. The path is ready to hand to a wrapper's `.toolPath(...)` (or `CmdTasks`). With a {@link InstallReleaseOptions.checksum}, the download is verified before anything is installed, and a matching prior install is reused without downloading again — so pinning a checksum makes the install both hermetic (tamper-evident) and cached. async function installTree(options: InstallTreeOptions): Promise Download and unpack a whole archive tree — a multi-file runtime such as Node.js, which ships `bin/node`, `bin/npm`, `bin/npx`, and `lib/node_modules/**` in one tarball — and return the {@link AbsolutePath} of its (stripped) root. `installRelease` extracts a single binary; `installTree` keeps the entire directory, symlinks included. Because {@link AbsolutePath} is callable, the root doubles as an accessor: `root("bin", "node")` is the node binary and `root("bin")` is the directory to put on `PATH` (with `prependPath`). Declared {@link InstallTreeOptions.bins} are marked executable on POSIX. With a {@link InstallTreeOptions.checksum} the archive is verified before unpacking and a matching prior install is reused. function isCI(): boolean Whether the build appears to be running in a CI environment. function lockKey(...parts: Array): string Join parts into a lock key that is safe to use as a filename and URL segment. Each part is sanitised (non-`[A-Za-z0-9._-]` runs become `_`) and empty parts are dropped, so `lockKey("deploy", repo)` is stable and injection-free. function operatingSystem(os: typeof Deno.build.os): OperatingSystem The operating system as a Zuke {@link OperatingSystem}: `darwin` becomes `macos`, `windows` stays `windows`, and every other Unix (`linux`, the BSDs, `solaris`, …) is reported as `linux`. Pass a raw `Deno.build.os` value to normalise it; defaults to the running host — the platform analogue of {@link isCI}. ```ts import { operatingSystem } from "jsr:@zuke/core"; if (operatingSystem() === "macos") { ... } ``` function ownsRun(record: RunRecord, buildId: string | undefined): boolean Whether a process whose origin is `buildId` may recover `record`. True unless both origins are known and differ — see the module documentation for why an absent origin abstains rather than refusing. function parameter(description?: string): Parameter Create a new build parameter (a `string` by default). Configure it fluently: `.number()`/`.boolean()` change the kind, `.options(...)` restricts a string, `.default(v)`/`.required()` set optionality, and `.env(name)` overrides the environment variable. function parseDuration(value: string | number): number Parse a duration to milliseconds. Accepts a number (already milliseconds) or a string of a non-negative amount and a unit — `ms`, `s`, `m`, `h`, or `d` (e.g. `"90s"`, `"4h"`, `"1.5h"`). Throws a friendly error on anything else. function plan(root: TargetBuilder, extra: readonly OrderingEdge[]): TargetBuilder[] Topologically sort the execution set for `root`, honouring hard dependencies and the soft `before`/`after` ordering hints (the latter only between nodes that are both in the set). @return target builders in a valid execution order. @throws {GraphError} if the planned graph contains a cycle (which can happen via soft edges even when the hard graph is acyclic). function prependPath(dir: PathLike, os: typeof Deno.build.os): string Prepend `dir` to the process `PATH`, and return the new value. A tool provisioned into `dir` (e.g. the `bin` directory of an {@link "./install.ts".installTree} runtime) then resolves for the rest of the build: the shell `$`, `Command`, and every tool wrapper spawn subprocesses that inherit `Deno.env`, so the `node_modules/.bin` shims and `NpmTasks` that assume a `node`/`npm` on `PATH` find the provisioned one. Idempotent — a directory already on `PATH` is left in place, not duplicated — and uses the platform separator (`;` on Windows, `:` elsewhere). @param dir the directory to place first on `PATH`. @param os the OS whose `PATH` separator to use; defaults to the host (a test seam, mirroring {@link operatingSystem}). @return the resulting `PATH` string. function remoteCacheKey(name: string, fingerprint: string): string The store key for a target's outputs: its name and input `fingerprint`. The name is sanitised so the key is safe as a filename and a URL path segment. function repoRoot(...segments: string[]): AbsolutePath The absolute path of the repository root — the directory containing {@link CONFIG_FILE} — with any `segments` appended. The returned value is an {@link AbsolutePath}, so it is itself callable for further joining. ```ts repoRoot(); // repoRoot("src", "main.ts"); // /src/main.ts repoRoot().join("dist"); // /dist ``` The root is located by walking up from the current working directory, so the path is resolved at runtime and never hard-coded into a committed file. @throws if no {@link CONFIG_FILE} is found in the cwd or any ancestor. function resolveBuildId(readEnv: (name: string) => string | undefined): string | undefined The origin of the build running in this process — `ZUKE_BUILD_ID`, else `GITHUB_REPOSITORY`, else `undefined` when neither is set. Recorded on a run at creation and compared by every recovery path. An empty value counts as unset, so an exported-but-empty variable does not become an origin that matches nothing. function resolveBuildRegistry(option: BuildRegistry | false | undefined, declared: BuildRegistry | undefined, options: ResolveRegistryOptions): BuildRegistry | undefined Pick the build registry by precedence: an explicit `option` wins (`false` disables the registry entirely), then a `declared` registry (a build's `registry()` override), then the {@link envBuildRegistry} environment fallback, then — only when {@link ResolveRegistryOptions.enableDefault} — a filesystem registry under `/.zuke/builds`. function resolveRemoteStore(option: RemoteCacheStore | false | undefined, declared: RemoteCacheStore | undefined, readEnv: (name: string) => string | undefined): RemoteCacheStore | undefined Pick the remote store for a run by precedence: an explicit `option` wins (`false` disables the remote cache entirely), then a `declared` store (a build's `remoteCache()` override), then the {@link envCacheStore} environment fallback. function resolveStateStore(option: StateStore | false | undefined, declared: StateStore | undefined, options: ResolveStateOptions): StateStore | undefined Pick the state store for a run by precedence: an explicit `option` wins (`false` disables state entirely), then a `declared` store (a build's `stateStore()` override), then the {@link envStateStore} environment fallback, then — only when {@link ResolveStateOptions.enableDefault} — a filesystem store under `/.zuke/runs`. A plain build with no durable feature and no configuration gets `undefined`, so it carries zero overhead. async function restoreOutputs(artifact: Uint8Array, host: OutputHost, outputs?: readonly string[]): Promise Restore the files in `artifact` (a gzipped tar produced by {@link archiveOutputs}) to disk, returning the paths written. Every entry is validated before anything is written, so a rejected archive leaves no half-written, partially-trusted output tree. An entry is refused when its name is absolute or escapes the workspace with `..`, when it is a symlink or directory entry (which {@link archiveOutputs} never produces), when it lands under `.git` or `.zuke`, and — when `outputs` is given — when it falls outside the target's declared outputs. @param outputs The declaring target's {@link TargetBuilder.outputs}. Pass them whenever they are known, which is what the executor does: an archive built from those outputs can only contain paths under them, so anything else is a store that has been written to by something other than a Zuke build, and restoring it would let that writer choose files anywhere in the workspace — a `deno.json`, a lockfile, a script a later target runs. Omitting them keeps the older, name-only confinement for a caller that has no output list. async function resumeCheck(build: Build, options: Omit & { runId?: string; }): Promise<{ checked: number; failed: number; }> Re-attempt every suspended run in the store (or just `runId`): predicate-based waits are re-evaluated and expired waits time out. Signal-based waits with no new signal simply re-suspend. Returns the number of runs that ended in failure. This is the sweep a cron or webhook drives (`zuke resume --check`). A run whose record is {@link "./state/types.ts".RunRecord.degraded} is counted as failed on every sweep until an operator resolves it: it cannot be advanced without deciding whether its targets are safe to repeat, and a non-zero result is the only channel a cron watches. Its refusal is reported through the reporter (the console unless silenced) so the cause is visible, and it stays `suspended`, so a later sweep with {@link ResumeOptions.resumeDegraded} still picks it up. async function resumeRun(build: Build, options: ResumeOptions): Promise Resume the suspended run `options.runId` for `build`. Transitions it to `running` (exactly one resumer wins), optionally delivers a signal, checks the graph still matches, and continues via {@link "./executor.ts".execute}, re-running only the not-yet-succeeded targets. @throws {AlreadyResumedError} if another process already resumed it. @throws if the run does not exist, is not suspended, the build lacks its root target, the graph drifted (unless {@link ResumeOptions.forceGraph}), or the record is degraded (unless {@link ResumeOptions.resumeDegraded}). function resumeWhen(check: () => boolean | Promise, options: ResumeWhenOptions): WaitTrigger A trigger satisfied when an async `check` predicate returns `true`. Zuke does not poll on its own — the predicate is evaluated when the target is reached and on each `zuke resume --check`, so a cron or webhook nudging `--check` drives it. Use it to wait on state Zuke can query (a row, a file, an API). async function run(BuildClass: new () => Build, options: RunOptions): Promise Public entry point. Instantiate the build, parse arguments, run, and set the process exit code. Call it at the bottom of your build file — no `import.meta.main` guard needed. `run` acts only when its module is the program's entry point; when the file is imported instead (for example under test) it does nothing. ```ts await run(MyBuild); // …with plugins: await run(MyBuild, { plugins: [timing] }); ``` function service(): ServiceBuilder Create a service target — a long-lived process kept running while its dependents execute. Configure it with {@link ServiceBuilder.start} / {@link ServiceBuilder.readyWhen} and depend on it from a {@link target}. async function syncCiFiles(files: readonly CiFile[], options: CiSyncOptions): Promise Bring each declared {@link CiFile} on disk in line with its definition. By default a changed file is rewritten; in `check` mode it is reported `stale` instead (so CI can fail when the committed config has drifted). function tar(entries: TarEntry[]): Uint8Array Create a `ustar` archive from the given entries (in order). function target(): TargetBuilder Create a new, empty target builder. async function tcpReachable(address: string): Promise Whether a TCP `host:port` is accepting connections — the usual readiness probe for a server. Resolves `true` once a connection succeeds (it is closed immediately), `false` while the port is still refused/unreachable, so it plugs straight into {@link ServiceBuilder.readyWhen}. ```ts .readyWhen(() => tcpReachable("localhost:5432")) ``` function toolchain(configure?: (t: Toolchain) => void): Toolchain Create a {@link Toolchain}. Configure it inline with a callback, or chain {@link Toolchain.tool} on the returned instance. ```ts const tools = toolchain((t) => t.tool((s) => s.name("helm").url(helmUrl)) .tool((s) => s.name("kubectl").url(kubectlUrl)) ); ``` function untar(archive: Uint8Array): TarEntry[] Extract the entries from a tar archive — regular files, symlinks, and directories. A path longer than the 100-byte `name` field is reconstructed from whichever long-name form the archive uses: the POSIX `ustar` `prefix` split, GNU tar's `@LongLink` pseudo-entries (typeflags `'L'` name / `'K'` link target, whose data is the following member's value — Node's Linux release tarballs use this), or pax extended headers (typeflag `'x'`, with `path=`/`linkpath=` records — bsdtar/macOS use this). These metadata pseudo-entries accumulate onto the next real member, matching GNU/bsdtar, so a mixed archive is read correctly; a pax record wins over a GNU long name, which wins over the header's own fields. async function unzip(archive: Uint8Array): Promise Read the entries of a `.zip` archive, decompressing `stored` and `deflate` members. The central directory is the source of truth. Directory entries (a trailing `/`) are skipped. Encrypted, zip64, or otherwise-compressed entries throw a friendly error naming the offending entry, and a header or data field that runs past the archive is reported as a malformed zip (not a raw out-of-bounds error). Every offset read from the archive is bounds-checked; for integrity against a tampered download, pin a `.checksum(...)`, which is verified before the archive is ever parsed. function validateGraph(targets: Map): void Validate the whole graph: unknown references first, then cycles. @throws {GraphError} with a descriptive message including the cycle path. const AnnounceTasks: AnnounceTasksApi Announcement task functions for posting build status to chat platforms. const CHECKOUT_ACTION: "actions/checkout" The action a {@link CiCheckout} is generated from when pins are resolved. const CONFIG_FILE: "zuke.json" The Zuke config file name; its presence marks a repository root. const DEFAULT_POLL_INTERVAL_MS: 200 How often {@link ServiceBuilder.readyWhen} is polled while waiting. const DEFAULT_READY_TIMEOUT_MS: 30000 The default time a service is given to become ready before it fails. const DEFAULT_TOOLS_DIR: ".zuke/tools" The default directory a {@link Toolchain} (and {@link ToolTasks}) installs into. const FileTasks: FileTasksApi Filesystem task functions for build scripts. const HARDEN_RUNNER_ACTION: "step-security/harden-runner" The action a {@link CiHardenRunner} is generated from when pins are resolved. const REDACTED: "[redacted]" The placeholder a {@link Redactor} substitutes for each secret value. const RUN_LEASE_PREFIX: "zuke-run" The lease name a run's own claim is taken under. Named once because two places have to agree on it exactly: the process claiming a run, and any sweep deciding whether that run still has an owner. const RUN_LEASE_TTL_MS: 60000 How long a lease lives before a crashed holder's claim lapses. The holder renews at half this interval, so a live process keeps its claim indefinitely while a dead one becomes reclaimable within the TTL. Sixty seconds trades promptness for tolerance: long enough that an ordinary pause — a slow step, a busy host, a paused container — does not look like death, short enough that a genuinely dead run is picked up on the next sweep rather than hours later. const ToolTasks: ToolTasksApi Provision external CLIs from a build. `ToolTasks.install((s) => …)` fetches a single release binary and `ToolTasks.npm(...)` a single npm package; group several of either with {@link toolchain}. const ZUKE_ACTION: "zuke-build/zuke" The name a {@link CiPinResolver} is asked for the prelude action, so a repository that pins its own actions can pin this one the same way. const defaultRenderer: Renderer The built-in renderer: Zuke's ruled headers and summary table. const defaultStateHost: StateHost The real, `Deno`-backed {@link StateHost}. class AlreadyResumedError extends Error Raised when a run has already been resumed by another process. constructor(readonly runId: string, readonly by: string, readonly at: string) Build the error from the run id and who is already running it. override name: string The error name. class AnnounceError extends Error Raised when an announcement is run before it is fully configured. constructor(message: string) Build the error with an explanatory message. override name: string The error name. abstract class AnnouncementSettings Fluent settings shared by every announcement: the message content (a body, an optional title, a {@link AnnouncementLevel | level}, repeatable detail fields and an action link), an optional display name, the webhook destination, and a `fetch` seam for tests. All chainers return `this`. Subclasses add any platform-specific configuration and render the payload. protected text_: string The main message body. protected title_?: string An optional heading shown above the body. protected level_: AnnouncementLevel The outcome level driving the accent colour and icon. protected readonly fields_: AnnouncementField[] Repeatable labelled detail fields. protected link_?: AnnouncementLink An optional action link rendered with the announcement. protected username_?: string An optional display name for the sender. protected webhookUrl_?: string The webhook destination URL. protected fetch_?: typeof fetch A `fetch` seam injected by tests. protected token_?: string An API/bot-mode token, when opted in with `.bot()`. protected channel_?: string The target channel in API/bot mode. text(text: string): this Set the main message body. title(title: string): this Set an optional heading shown above the body. level(level: AnnouncementLevel): this Set the outcome the message conveys (default `"info"`). success(): this Shorthand for `.level("success")`. failure(): this Shorthand for `.level("failure")`. warning(): this Shorthand for `.level("warning")`. info(): this Shorthand for `.level("info")`. field(name: string, value: string): this Add a labelled detail rendered beside the body. Repeatable. link(text: string, url: string): this Set an action link rendered with the message. username(name: string): this Override the display name the message is posted under. Honoured by Slack and Discord; ignored by Teams, which has no equivalent field. webhook(url: string): this Set the incoming-webhook URL to post to. The URL embeds the secret, so source it from a secret parameter. fetch(impl: typeof fetch): this The `fetch` implementation to use. Defaults to the global `fetch`; override it to unit-test without network access. bot(): this Post through the platform's API with a bot/access token instead of an incoming webhook. Pair with {@link token} and {@link channel}. token(token: string): this Set the bot/access token for {@link bot} mode (Slack `xoxb-…`, a Discord bot token, or a Microsoft Graph bearer token). Source it from a secret parameter; Zuke masks it in CI output. Implies {@link bot}. channel(channel: string): this Set the channel (id or name) to post to in {@link bot} mode. protected announcement(): Announcement The structured announcement assembled so far. protected requireWebhook(): string The webhook URL, or an {@link AnnounceError} if one was never set. protected botRequested(): boolean Whether the caller opted into bot mode via {@link bot} or {@link token}. protected requireToken(): string The bot/access token, or an {@link AnnounceError} if one was never set. protected requireChannel(): string The target channel, or an {@link AnnounceError} if one was never set. abstract protected payload(): Record The platform-native JSON payload for a webhook post. abstract protected sendBot(): Promise Post through the platform's API in {@link bot} mode. send(): Promise Send the announcement: through the platform's API when {@link bot} mode was requested, otherwise by posting the {@link payload} to the webhook. class AssertionError extends Error Raised by the assertion helpers when an expectation fails. override name: string The error name. class Build Base class for user-defined builds. Provides no targets of its own; subclasses declare targets as properties. Optionally override the lifecycle hooks. onStart(): void | Promise Called once before any target runs. onFinish(_result: BuildResult): void | Promise Called once after the run completes (success or failure). onTargetStart(_name: string): void | Promise Called just before a target's body executes (not for skipped/cached). onTargetEnd(_name: string, _status: TargetStatus): void | Promise Called after each target settles, with its final status. recoverWith(): Remediation[] Remediations applied to every target, running after each target's own {@link "./target.ts".TargetBuilder.recoverWith} when its body fails. Override to attach a global AI fixer once instead of repeating it per target; the default is none. Both styles compose — a target's own remediations run first, then these. ```ts class CI extends Build { key = parameter("OpenAI API key").secret(); override recoverWith() { return [aiFixer((f) => f.provider("openai").apiKey(this.key))]; } lint = target().executes(() => DenoTasks.lint()); // healed globally } ``` remoteCache(): RemoteCacheStore | undefined The {@link "./remote_cache.ts".RemoteCacheStore} that shares target {@link "./target.ts".TargetBuilder.outputs} across machines. Override to declare one in code; the default is none, and — unless overridden — the executor falls back to {@link "./remote_cache.ts".envCacheStore} (the `ZUKE_REMOTE_CACHE_*` environment variables). Applies to targets that declare both `inputs` and `outputs`. ```ts class CI extends Build { override remoteCache() { return new HttpCacheStore({ url: this.cacheUrl.value, token: this.cacheToken.value }); } build = target().inputs("src").outputs("dist").executes(...); } ``` stateStore(): StateStore | undefined The {@link "./state/store.ts".StateStore} that persists this build's run records. Override to declare one in code; the default is none, and — unless overridden — the executor falls back to the `ZUKE_STATE_URL` / `ZUKE_STATE_DIR` environment variables, then (only when the run opts into durable state) a filesystem store under `/.zuke/runs`. ```ts class CD extends Build { override stateStore() { return new HttpStateStore({ url: this.stateUrl.value, token: this.stateToken.value }); } deploy = target().executes(async (ctx) => { await ctx.state.set({ at: "sit-7" }); }); } ``` deadline(): string | number | undefined A wall-clock budget for a whole run, after which a reaping sweep settles it `failed` — a duration like `"45m"` or milliseconds. No deadline by default. It bounds running, not existing. A run parked at a `.waitsFor(...)` gate is not spending it — the deadline is pushed forward on resume by however long the run was parked, so a build with a 72-hour approval gate and a 45-minute deadline still has its 45 minutes when the approval arrives. The waiting is bounded by the gate's own `.timeout()`. A run with a live process working on it is never settled for time either: the sweep asks whether anyone is still there before it looks at the deadline. Nothing this is for escapes that — a hung process stops renewing its lease, and a run killed over and over has no holder at all. What it is really for is the run that stops making progress without failing — a process that hangs, or one killed so hard that its work is repeatedly picked up and abandoned again. Without a deadline such a run has no end state at all; with one it reaches a terminal status, which is what anything downstream is waiting for. ```ts class Ci extends Build { override deadline() { return "45m"; } } ``` extraEdges(_targets: Map): OrderingEdge[] Extra soft ordering edges to impose on the plan, beyond the `dependsOn` / `before` / `after` declared on targets. Override to feed an external graph — e.g. a monorepo's `dependency-graph.json` — into scheduling without wiring every edge by hand. Return `[before, after]` pairs from the passed `targets` map (keyed by dotted name); each means `before` runs before `after`. Edges whose endpoints are not both in a run's execution set are ignored, and a cycle is reported with the usual friendly error. These are execution-ordering edges. Like `.before()` / `.after()`, they are not reflected in CI generated by `cicd()` — a fan-out job's `needs:` mirrors hard `dependsOn` only — so an ordering that CI must also honour has to be expressed as a `dependsOn`, not a soft edge. ```ts class Monorepo extends Build { web = target().executes(...); api = target().executes(...); override extraEdges(t: Map) { // `api` must build before `web`, per the external dependency graph. const edges: OrderingEdge[] = []; const api = t.get("api"), web = t.get("web"); if (api && web) edges.push([api, web]); return edges; } } ``` orderWith(_targets: Map): OrderingEdge[] | Promise A lazy, per-run provider of soft ordering edges, merged with {@link extraEdges}. Unlike `extraEdges` — synchronous, evaluated at construction — this may be `async` and is evaluated when a run plans, so it can read an external source (a monorepo's `dependency-graph.json`, an API) to decide ordering at run time. The consumer keeps ownership of that graph; Zuke only binds it in. Return `[before, after]` edges over the run's targets; an edge whose endpoints are not both in the execution set is ignored, and cycles are reported with the usual friendly error. Like `extraEdges`, these are execution-ordering edges only: they are honoured by a run and by `zuke cancel` (the compensation order), but not by the static `graph`/`--list` views (which never run the provider) nor by `cicd()`-generated CI (whose `needs:` mirrors hard `dependsOn`). ```ts override async orderWith(t: Map): Promise { const graph = await loadDependencyGraph(); // e.g. dependency-graph.json return graph.edges.flatMap(([before, after]) => { const from = t.get(before), to = t.get(after); return from && to ? [[from, to] as OrderingEdge] : []; }); } ``` registry(): BuildRegistry | undefined The {@link "./registry/registry.ts".BuildRegistry} this build registers itself in (`zuke register`) and that a registry-backed `zuke mcp` server discovers pipelines from. Override to declare one in code; the default is none, and — unless overridden — the resolution falls back to the `ZUKE_REGISTRY_URL` / `ZUKE_REGISTRY_DIR` environment variables, then (for `zuke register`) a filesystem registry under `/.zuke/builds`. Kept a separate concern from {@link stateStore} (a run history and a build catalog are different things), so a consumer can host a richer catalog as a plugin. ```ts class CD extends Build { override registry() { return new HttpBuildRegistry({ url: this.registryUrl.value, token: this.registryToken.value }); } } ``` mcpIdentity(): McpIdentityHook | undefined A per-request identity hook for `zuke mcp` — resolve a trusted caller from the request context (an authenticating reverse proxy's header) so a shared, multi-user server attributes each call to the real engineer rather than a client-self-reported label. When set, the resolved actor overrides `--actor`, the environment, and the client label for that call, and flows to the audit trail, run records, lock holders, and (for a registry-spawned build) the child's `ZUKE_ACTOR`; a throwing hook rejects the request before anything runs. Default: none — stdio/local use is unchanged. ```ts class ControlPlane extends Build { override mcpIdentity() { return (ctx: McpRequestContext) => { // The proxy strips any client copy of this header and injects its own. const sub = ctx.headers.get("x-forwarded-user"); if (!sub) throw new Error("no identity from proxy"); return { actor: sub, via: "oauth-proxy" }; }; } } ``` class CiFile A declared CI file. Assign one (via {@link cicd}) to a build field and Zuke keeps the file on disk in sync with the definition when the build runs. constructor(spec: CiFileSpec) Build the CI file from its spec, filling in the provider's default path. readonly provider: CiProvider The provider this file renders for. readonly path: string The output path, once resolved. readonly explicitPath: boolean Whether {@link path} came from the spec rather than a default. readonly pipeline: CiPipeline The base pipeline (pipeline-level fields, and the jobs unless fanning out). readonly fanOut?: FanOutOptions Fan-out options, when this file expands the build's targets into jobs. readonly invokes?: readonly CiInvokes[] The targets this file runs as jobs, when declared with `invokes`. readonly pins?: CiPinResolver Resolves pinned action references, so a SHA is stated once per repository. get derived(): boolean Whether this file's jobs are derived from the build rather than declared. pipelineFor(targets: Map): CiPipeline The pipeline this file renders. Jobs come from the invoked targets, or from a full fan-out of the graph, or — failing both — from the declared {@link pipeline}. at(path: string): CiFile The same file bound to `path` — used to name a file from its field. render(): string Render the file's YAML content (the base pipeline; fan-out is resolved at discovery). class DiscordAnnouncementSettings extends AnnouncementSettings Fluent settings for {@link AnnounceTasksApi.discord}. Bot mode (`.bot().token(t).channel(c)`) posts through the REST API with a bot token. override protected payload(): Record Render the Discord webhook payload. override protected sendBot(): Promise Post the announcement through the Discord REST API in bot mode. class ExecSecretSettings Fluent settings for {@link execSecret}: a command whose standard output is the secret. Configure the binary with {@link ExecSecretSettings.command}, arguments with {@link ExecSecretSettings.arg}, and optionally the environment and working directory. Output is trimmed of surrounding whitespace unless {@link ExecSecretSettings.trim} is turned off (some values are whitespace-sensitive). command(binary: PathLike): this The binary to run (e.g. `op`, `vault`, `gcloud`). Required. arg(...values: Array): this Append one or more arguments to the command. env(record: Record): this Merge additional environment variables for the process. cwd(path: PathLike): this Set the working directory for the process. trim(on: boolean): this Whether to trim surrounding whitespace from stdout (default `true`). async resolve_(): Promise Run the command and return its captured stdout as the secret. Streaming is suppressed (`quiet`) so the value is never echoed to the terminal, and a non-zero exit throws a {@link SecretError} naming the command. class FileSecretSettings Fluent settings for {@link fileSecret}: read a secret from a file. Set the path with {@link FileSecretSettings.path}; the content is trimmed of surrounding whitespace unless {@link FileSecretSettings.trim} is turned off. path(path: PathLike): this The file to read the secret from. Required. trim(on: boolean): this Whether to trim surrounding whitespace from the content (default `true`). async resolve_(): Promise Read the file and return its content as the secret. A missing or unreadable file throws a {@link SecretError} naming the path. class FileSystemBuildRegistry implements BuildRegistry A {@link BuildRegistry} that writes one `.json` file per build under a directory. Security. `dir` is trusted configuration — the location you choose to store the build catalog (from `ZUKE_REGISTRY_DIR` or an explicit registry), the same posture as {@link "../state/fs_store.ts".FileSystemStateStore}. The only untrusted value that reaches a path is the build id, validated at every point a path is built, so a traversal cannot be smuggled in via an id. constructor(dir: string, host: StateHost) Build the registry over `dir` (created on first write). Filesystem access goes through `host`, which defaults to {@link "../state/store.ts".defaultStateHost}. async getBuild(id: string): Promise<{ descriptor: BuildDescriptor; version: string; } | null> Fetch a build and the content-hash version of its stored file. async register(descriptor: BuildDescriptor, expectedVersion: string | null): Promise Publish `descriptor` under an exclusive lock, guarding the expected version. async deregister(id: string): Promise Remove a registered build under an exclusive lock; a missing file is a no-op. async listBuilds(query: BuildQuery): Promise List builds matching `query`, newest first. Unreadable files are skipped. class FileSystemCacheStore implements RemoteCacheStore A {@link RemoteCacheStore} backed by a shared or mounted directory. constructor(dir: string) Build the store over a directory. @param dir The directory archives are read from and written to. get(key: string): Promise Fetch the archived outputs stored under `key`, or `null` if there are none. async put(key: string, artifact: Uint8Array): Promise Store `artifact` (a gzipped tar of a target's outputs) under `key`. class FileSystemStateStore implements StateStore A {@link StateStore} that writes one `.json` file per run under a directory. Security. `dir` is trusted configuration — the location you choose to store run state (from `ZUKE_STATE_DIR`, `--state`, or an explicit store), the same posture as {@link "../remote_cache.ts".FileSystemCacheStore}. The only untrusted value that reaches a path is the run id, which is validated at every point a path is built, so a traversal cannot be smuggled in through an id. constructor(dir: string, host: StateHost) Build the store over `dir` (created on first write). Filesystem access goes through `host`, which defaults to {@link defaultStateHost}. async getRun(id: string): Promise<{ record: RunRecord; version: string; } | null> Fetch a run and the content-hash version of its stored file. async putRun(record: RunRecord, expectedVersion: string | null): Promise Publish `record` under an exclusive lock, guarding the expected version. async listRuns(query: RunQuery): Promise List runs matching `query`, newest first. Unreadable files are skipped. async deleteRun(id: string): Promise Delete a run's file (under its lock); a missing run is a no-op. The run's lock records are deliberately left alone. It is tempting to take them with the run — they are named after it, so once it is gone nothing can look them up again — but "expired" does not mean "abandoned" in this store: {@link renewLock} extends a lock whenever the token matches, whatever its expiry, so a lapsed claim is still the holder's until somebody acquires it. Deleting the record instead makes the next renewal answer `false`, which the holder reads as the lease being lost, and a run that is merely slow — the exact case the lease exists to tell apart from a dead one — stops. Pruning must never be able to do that. The litter is small and bounded in practice: {@link releaseLock} removes a lock's file, and a run releases its lease whenever it settles, so only a holder that dies without releasing leaves one behind. Clearing those safely belongs to whoever can prove the holder is gone — a reaping sweep, which proves it by acquiring — not to a command deleting old records. async acquireLock(key: string, holder: LockHolder, ttlMs: number): Promise Atomically acquire the lock `key` for `holder`, taking over if expired. async renewLock(key: string, token: string, ttlMs: number): Promise Extend the lock `key` held under `token`; `false` if the token lost it. async releaseLock(key: string, token: string): Promise Release the lock `key` if still held under `token`; a no-op otherwise. class ForEachSettings Fluent configuration for {@link TargetBuilder.forEach}, in the settings-lambda style: `.forEach(items, factory, (s) => s.concurrency(3).continueOnItemFailure())`. Sets the {@link ForEachSettings.concurrency | concurrency} cap and whether one item's failure isolates it or stops the whole batch. concurrency_?: number Max item pipelines in flight at once; set by {@link concurrency}. continueOnItemFailure_: boolean Isolate a failed item from its siblings; set by {@link continueOnItemFailure}. concurrency(limit: number): this Cap how many item pipelines run concurrently (default: the host CPU count). Clamped to at least 1; `1` runs items one at a time. continueOnItemFailure(on: boolean): this Keep running the other items when one item's pipeline fails (the failed item's later stages are still skipped). The fan-out target still fails at the end if any item failed. Without this, the first item failure stops the batch — the default. class ForeignRunError extends Error Thrown when a recovery path is handed a run that a different build owns: the run's recorded origin and this process's disagree. A sweep treats it as "not mine" and moves on rather than counting a failure, the same way it treats a run another process has already resumed. A command that named one run reports it, because the operator asked about a run that is not this build's to touch. constructor(readonly runId: string, readonly owner: string, readonly self: string) Build the error from the run and the two disagreeing origins. override name: string The error name. class GraphError extends Error Raised when the build graph is invalid (cycle or unknown dependency). override name: string The error name. class Group A parallel batch of targets, created with {@link group}. Targets join it via {@link TargetBuilder.partOf}; its members run concurrently with one another (each still awaiting its own dependencies) regardless of the global parallel setting. Passing a group to {@link TargetBuilder.dependsOn} depends on every member at once. readonly members_: TargetBuilder[] Members that declared themselves part of this group, in declaration order. name_?: string Property name, assigned during discovery. Undefined until then. class HttpBuildRegistry implements BuildRegistry A {@link BuildRegistry} backed by HTTP. Security. The `url` and `token` are trusted configuration — build descriptors (structural CLI metadata plus a launch location) are sent to that host, so point it only at a service you control and prefer a secret parameter or environment variable over a hard-coded value. constructor(options: HttpBuildRegistryOptions) Build the registry from its URL, optional token, and `fetch` seam. async getBuild(id: string): Promise<{ descriptor: BuildDescriptor; version: string; } | null> `GET /builds/:id` → descriptor + `ETag`; a `404` is a miss. async register(descriptor: BuildDescriptor, expectedVersion: string | null): Promise `PUT /builds/:id` guarded by `If-Match` / `If-None-Match`; `412` → conflict. deregister(id: string): Promise `DELETE /builds/:id`; a missing build (`404`) is not an error. async listBuilds(query: BuildQuery): Promise `GET /builds?name=&since=` → an array of {@link BuildSummary}. class HttpCacheStore implements RemoteCacheStore A {@link RemoteCacheStore} backed by HTTP: `GET /` fetches an artifact (a `404` means a miss) and `PUT /` stores one. Works with any object store or cache server that speaks plain HTTP GET/PUT — an S3, GCS, or R2 bucket behind a URL, or a self-hosted cache endpoint. Security. The `url` (and `token`) are trusted configuration: outputs are uploaded to that host and archives are extracted from it, so point it only at a cache you control, and prefer a {@link "./params.ts" | secret parameter} or an environment variable over a hard-coded value. On CI, restrict egress to the cache host so a misconfigured or overridden URL can't exfiltrate artifacts. Restored archives are always confined to the workspace (see {@link restoreOutputs}), so a poisoned store cannot write outside it. constructor(options: HttpCacheStoreOptions) Build the store from its URL, optional token, and `fetch` seam. async get(key: string): Promise Fetch the archived outputs stored under `key`, or `null` if there are none. async put(key: string, artifact: Uint8Array): Promise Store `artifact` (a gzipped tar of a target's outputs) under `key`. class HttpError extends Error Raised when an HTTP request returns a non-2xx status. The URL appears in the message and on {@link url}, so it is passed through {@link redactUrl} first — userinfo and credential query params never reach a log. constructor(status: number, url: string) Build the error from the failing response's status and URL. override name: string The error name. readonly status: number The HTTP status code of the failing response. readonly url: string The requested URL, with any credentials redacted. class HttpStateStore implements StateStore A {@link StateStore} backed by HTTP. Security. The `url` and `token` are trusted configuration — run records (which include resolved non-secret parameters and target metadata) are sent to that host, so point it only at a service you control and prefer a {@link "../params.ts" | secret parameter} or environment variable over a hard-coded value. constructor(options: HttpStateStoreOptions) Build the store from its URL, optional token, and `fetch` seam. async getRun(id: string): Promise<{ record: RunRecord; version: string; } | null> `GET /runs/:id` → record + `ETag`; a `404` is a miss. async putRun(record: RunRecord, expectedVersion: string | null): Promise `PUT /runs/:id` guarded by `If-Match` / `If-None-Match`; `412` → conflict. async listRuns(query: RunQuery): Promise `GET /runs?status=&target=&since=` → an array of {@link RunSummary}. deleteRun(id: string): Promise `DELETE /runs/:id`; a missing run (`404`) is not an error. async acquireLock(key: string, holder: LockHolder, ttlMs: number): Promise `POST /locks/:key` → `201 { token }`, or `409` with the current holder. async renewLock(key: string, token: string, ttlMs: number): Promise `PUT /locks/:key` renews; a `409`/`404` means the token lost the lock. async releaseLock(key: string, token: string): Promise `DELETE /locks/:key` releases; a missing lock (`404`) is not an error. class LockConflictError extends Error Raised when a target's lock is already held by another run. Its `message` is the rendered guidance (from the target's `onConflict`, else a default), so it surfaces verbatim in the CLI failure footer and the run record; `holder` carries the structured identity for programmatic surfaces (e.g. MCP). constructor(readonly holder: LockHolder, guidance: string) Build the error from the current holder and the rendered guidance. override name: string The error name. class LockSettings Fluent configuration for {@link TargetBuilder.lock}, in the settings-lambda style: `.lock((s) => s.lockKey("deploy", repo).withTtl("4h"))`. Set the key (composed from sanitised parts with {@link LockSettings.lockKey}, or directly with {@link LockSettings.key}), the {@link LockSettings.withTtl | TTL}, and an optional {@link LockSettings.onConflict} message. The lambda runs after parameters resolve, so the key may read `this..value`. key_?: string The resolved lock key; set by {@link key} or {@link lockKey}. ttl_?: string | number The TTL (a duration string or milliseconds); set by {@link withTtl}. onConflict_?: (holder: LockHolder) => string The conflict-guidance renderer; set by {@link onConflict}. lockKey(...parts: Array): this Set the lock key from parts, sanitised and joined via {@link "./state/lock.ts".lockKey} — e.g. `s.lockKey("deploy", repo)`. key(key: string): this Set the lock key directly (must be filename-safe; prefer {@link lockKey}). withTtl(ttl: string | number): this How long the lock survives a killed holder — a duration string like `"4h"` / `"30m"` (see the duration parser) or raw milliseconds. A live holder renews it while it runs, so it never expires under it. onConflict(render: (holder: LockHolder) => string): this Render the guidance shown to a run that loses the lock. Receives the current {@link "./state/lock.ts".LockHolder}; the returned string becomes the failure message. Defaults to a generic "held by … then retry" line. class Parameter implements AnyParameter A typed build parameter. Declare one with {@link parameter} and configure it with the fluent methods; each method returns a new parameter whose `value` type reflects the configuration (`string`, `number`, `boolean`, and whether it can be `undefined`). `K` is the underlying value kind; `T` is the exposed `value` type, which is `K` for required/defaulted parameters and `K | undefined` for optional ones. constructor(spec: ParamSpec) Build a parameter from its resolved constructor spec. name_?: string Property name, assigned during discovery. Undefined until then. readonly description_?: string Human-readable description shown in `--help`/`--list`. readonly kind_: ParamKind The runtime value kind. readonly required_: boolean Whether a value must be supplied (no default). readonly options_?: readonly string[] The allowed string choices, if restricted with {@link Parameter.options}. readonly envName_?: string An explicit environment variable name override. readonly hasFallback_: boolean Whether the parameter has a declared default value. readonly secret_: boolean Whether the value is sensitive and should be masked in CI output. readonly array_: boolean Whether the value is a comma-separated / repeatable list (`.array()`). readonly source_?: SecretSource A provider that resolves the value when no flag/env supplied one. readonly default_?: string The declared default rendered as a string (an array default is joined with commas), or `undefined` when the parameter has no default or an empty-list one. For display in tool schemas and `--list`; never a secret value. get value(): T The resolved value. Throws if read before the build resolves parameters. isSet_(): boolean Whether the parameter resolved to a defined value (used by `.requires()`). stringValue_(): string | undefined The resolved value as a string, or `undefined` if unset (for masking). secret(): Parameter Mark the value as sensitive: it is masked in CI output (`::add-mask::`) and redacted from all of Zuke's reporter output. Pair with {@link Parameter.from} to resolve the value from a secret manager rather than the environment. from(source: SecretSource): Parameter Resolve the value from a {@link SecretSource} (see {@link execSecret} / {@link fileSecret}) when neither a `--flag` nor an environment variable supplied one — the source is a fallback provider, consulted before the declared default. Typically paired with {@link Parameter.secret} so the resolved value is redacted. number(this: Parameter): Parameter Parse the value as a number (e.g. `--workers 4`). boolean(this: Parameter): Parameter Treat the parameter as a boolean flag (e.g. `--verbose`); defaults to false. options(this: Parameter, ...values: string[]): Parameter Restrict a string parameter to a fixed set of choices. default(this: Parameter, value: K): Parameter Provide a default, making `value` non-optional (`K`). required(this: Parameter): Parameter Require a value, making `value` non-optional (`K`); errors if unsupplied. env(name: string): Parameter Override the environment variable read as a fallback for this parameter. array(this: Parameter): Parameter Accept a comma-separated list (or a repeated flag), exposing `value` as an array. `--tags a,b` and `--tags a --tags b` both yield `["a", "b"]`; blank entries are dropped, and an unsupplied optional list defaults to `[]` (a required one is reported missing — see below). Each element is parsed by this parameter's own element parser, so it composes: `.options("a", "b").array()` validates every element against the choices, and `.number().array()` yields a `number[]`, rejecting a non-numeric entry. (Apply `.options()`/`.number()` before `.array()`.) `.array()` composes last, after `.required()` too: a `.required().array()` list stays required, so an unsupplied value is reported as missing rather than silently resolving to the empty-list default. An optional (non-required) list defaults to `[]`. resolve_(raw: string | undefined): void Resolve from a raw input (or `undefined` when none was supplied). class ParameterError extends Error Raised when a parameter value is invalid or read before resolution. override name: string The error name. class Redactor Collects secret values and masks them in text. Register a value with {@link Redactor.add} and rewrite a line with {@link Redactor.redact}; empty strings are ignored (they would match everywhere) and duplicates are recorded once. Longer secrets are applied first so a secret that contains another is masked whole rather than partially. add(value: string): void Register a secret value to mask. Ignores empty strings and duplicates. A multi-line value registers each of its lines as well as the whole string, because redaction runs a line at a time and a whole-value pattern can never match one line of it. Lines are trimmed, and a very short one is skipped so it cannot mask ordinary text wherever it appears. redact(line: string): string Replace every registered secret in `line` with {@link REDACTED}. get size(): number The number of distinct patterns registered. A single-line secret contributes one; a multi-line secret contributes the whole value plus each of its qualifying lines. class RunNotSuspendedError extends Error Raised when a run is no longer `suspended` by the time a resume reaches it — it has been settled, or a cancellation is in progress. The counterpart to {@link AlreadyResumedError}, which covers a run another process is currently driving. This covers one that already finished, and a sweep treats it the same way: not its run to advance, and not a failure. Two sweeps racing the same run is the normal case — one wins, and the loser reading `succeeded` has discovered a success, not a fault. Counting it would put a false alarm in the exit code a cron watches. constructor(readonly runId: string, readonly status: RunStatus) Build the error from the run id and the status found instead. override name: string The error name. class SecretError extends Error Raised when a {@link SecretSource} cannot produce a value. override name: string The error name. class ServiceBuilder extends TargetBuilder A long-lived {@link target}. Configure how it starts ({@link ServiceBuilder.start}), how to tell it is ready ({@link ServiceBuilder.readyWhen}), and — when the started handle is not self-stopping — how it stops ({@link ServiceBuilder.stop}). It inherits the ordering methods (`dependsOn`, `before`, `after`, `description`) from {@link TargetBuilder}; a service has no `.executes` body. override effect(name: string, fn: EffectFn): this Refuse a crash-durable effect on a service. A service target's whole job is launching a process; it runs no body, so there is no point at which its effects would be driven and they would be dropped without a word. Inherited from {@link TargetBuilder} only because this is a subclass of it, so the refusal is stated here rather than left to be discovered. start(fn: () => ServiceHandle | Promise): this How to start the process. Return a {@link ServiceHandle} (e.g. `$\`…`.spawn()`) so the service can be stopped on teardown; provide a custom {@link ServiceBuilder.stop} if the handle is not self-stopping. readyWhen(fn: () => boolean | Promise): this A readiness probe, polled until it returns `true` (or the timeout is hit). Without one, the service is considered ready the moment it starts. See {@link tcpReachable} for the common "is the port accepting connections?". readyTimeout(ms: number): this Override how long to wait for {@link ServiceBuilder.readyWhen} (default 30s). stop(fn: (handle: ServiceHandle) => void | Promise): this Custom teardown, given the handle {@link ServiceBuilder.start} returned. async launch_(name: string): Promise INTERNAL: start the service and wait until it is ready, returning a handle the executor stops on teardown. Throws {@link ServiceError} if no start was configured, or if the service does not become ready in time (the just-started process is stopped first so it is not leaked). class ServiceError extends Error Raised when a service cannot start or does not become ready in time. override name: string The error name. class ServiceRegistry Holds the services started during a run and stops them in reverse order on teardown. Stopping never throws — a failure to stop one service is reported and the rest are still stopped. register(running: RunningService): void Record a started service to stop later. get size(): number The number of services currently held. async stopAll(report: (line: string) => void): Promise Stop every registered service, newest first, reporting each outcome. class SlackAnnouncementSettings extends AnnouncementSettings Fluent settings for {@link AnnounceTasksApi.slack}. Bot mode (`.bot().token(t).channel(c)`) posts through the Web API (`chat.postMessage`). override protected payload(): Record Render the Slack webhook payload. override protected sendBot(): Promise Post the announcement through the Slack Web API in bot mode. class SlackApiError extends Error Raised when the Slack Web API accepts the request but reports a logical failure (`{ ok: false }`), carrying Slack's machine-readable error code (e.g. `channel_not_found`, `not_in_channel`, `invalid_auth`). constructor(readonly error: string) Build the error from Slack's machine-readable error code. override name: string The error name. class TargetBuilder The fluent builder returned by {@link target}. All configuration methods are chainable and return `this`. A body (via {@link TargetBuilder.executes}) is required before a target can be executed. description_?: string Human-readable summary shown in `--list`. readonly dependsOn_: TargetBuilder[] Hard prerequisites: these run (transitively) before this target. readonly before_: TargetBuilder[] Soft ordering: this runs before the listed targets if both are planned. readonly after_: TargetBuilder[] Soft ordering: this runs after the listed targets if both are planned. fn_?: TargetFn The target body. readonly effects_: DeclaredEffect[] Crash-durable effects, in declaration order (set by {@link effect}). name_?: string Property name, assigned during discovery. Undefined until then. group_?: Group The parallel batch this target belongs to, if any (set by {@link partOf}). readonly inputs_: string[] Input files/directories whose contents key the cache (set by {@link inputs}). readonly outputs_: string[] Output files/directories that must exist for a cache hit (set by {@link outputs}). readonly onlyWhen_: Condition[] Conditions gating execution; all must hold or the target is skipped. readonly triggers_: TargetBuilder[] Targets pulled in and run after this one (set by {@link triggers}). readonly requires_: AnyParameter[] Parameters that must be set for this target (set by {@link requires}). proceedAfterFailure_: boolean Continue the build if this target fails (set by {@link proceedAfterFailure}). always_: boolean Run even after the build has failed (set by {@link always}). unlisted_: boolean Hide this target from `--list`/`--help` (set by {@link unlisted}). readOnly_: boolean Advertise this target as query-only over MCP (set by {@link readOnly}). dryRunnable_: boolean Run this target's body under `--dry-run` with `$` echoed (set by {@link dryRunnable}). readonly cacheKeys_: Array<() => string | Promise> Extra cache-key contributors beyond input files (set by {@link cacheKey}). readonly produces_: string[] Artifact paths this target produces (set by {@link produces}). skipDependencies_: boolean When skipped by a condition, also skip dependencies (set by {@link whenSkipped}). timeout_?: number Per-attempt timeout in milliseconds, if set by {@link timeout}. retries_: number Number of extra attempts on failure, set by {@link retry}. retryDelay_: number Delay between retry attempts in milliseconds. readonly validateBefore_: Validation[] Validations run before the body (set by {@link validateBefore}). readonly validateAfter_: Validation[] Validations run after the body (set by {@link validateAfter}). readonly recoverWith_: Remediation[] Remediations run after the body fails (set by {@link recoverWith}). recoverAttempts_: number Max fix-then-rerun cycles when the body fails (set by {@link recoverAttempts}). lock_?: Configure Cross-run lock settings lambda, set by {@link lock} and run after params resolve. waitsFor_?: Configure External-event wait settings lambda, set by {@link waitsFor} and run when reached. forEach_?: ForEachSpec Fan-out spec, set by {@link forEach}: materialises per-item sub-target pipelines. onCancel_?: () => TargetBuilder Compensation thunk, set by {@link onCancel}: runs on cancel iff this target succeeded. description(text: string): this Set the human-readable description shown in `zuke --list`. dependsOn(...targets: Array): this Declare hard prerequisites. References sibling targets via `this.x`, or a {@link group} (which expands to every member that has joined it). partOf(group: Group): this Join a parallel {@link group}. Members of the same group run concurrently with one another (each still awaiting its own dependencies) even when the build is otherwise sequential. Declare the group before the targets that join it. inputs(...paths: PathLike[]): this Declare input files or directories (directories are hashed recursively). A target with inputs is incremental: it is skipped (reported `cached`) when its inputs are unchanged since the last successful run and all its {@link outputs} still exist. Repeatable. outputs(...paths: PathLike[]): this Declare output files or directories. A cache hit also requires every output to still exist, so deleting an output forces a rebuild. Repeatable. onlyWhen(condition: Condition): this Run only when `condition` holds; otherwise the target is skipped (and its dependents still run). The predicate may be async and can read resolved parameters or the environment. Repeatable — all conditions must hold. ```ts deploy = target() .onlyWhen(() => this.environment.value === "production") .executes(...); ``` effect(name: string, fn: EffectFn): this Declare a crash-durable effect: `fn` runs only after the intent to run it has been written to the run record, so a process killed anywhere inside it leaves evidence that it was owed. That evidence is what a resume uses to drive it again. Note the precondition as it stands today: a resume only picks up a run recorded `suspended`, and a process killed outright leaves its run `running`, so an effect owed by a killed process is re-driven once something moves that run back to `suspended` — a reaping sweep, or an operator. An effect owed by a run that suspended for any other reason is re-driven by the ordinary resume. The guarantee is at-least-once, not exactly-once: a process that dies after the side effect but before recording it will repeat the effect. Write bodies that tolerate that, either because repeating is harmless or because the far side converges (an upsert rather than an append). ```ts gate = target().dependsOn(this.checks).always() .effect("post-gate", async (ctx) => { await postCheckRun(ctx.outcomeOf("checks")?.status === "succeeded"); }); ``` Pin the inputs. A re-drive happens later, sometimes much later, so a body that looks up "the current value" of anything acts on a world that has moved on. Read what the effect acts on from durable state instead — `ctx.state` or `ctx.stateOf(...)`, written by an earlier target — which is replayed from the record and cannot be overridden from outside. A parameter is nearly as good and not quite: the record seeds a resume, so a parameter nobody re-supplies keeps the value the run started with, but a resume that passes one explicitly overrides it (the only way to re-supply a secret, since secrets are kept out of the record). For a value that must not drift across a re-drive, prefer state. Effects run after the body, in declaration order, and are repeatable. A target may declare effects and no body at all. Requires a state store, which is enabled automatically — an intent that cannot be recorded is a target that fails before its effect runs, by design. executes(fn: TargetFn): this Set the target body. May be async. before(...targets: TargetBuilder[]): this Run before the listed targets if both are in the plan (soft ordering). after(...targets: TargetBuilder[]): this Run after the listed targets if both are in the plan (soft ordering). triggers(...targets: TargetBuilder[]): this Pull the listed targets into the plan and run them after this one. The inverse of {@link dependsOn}: running this target triggers the others. dependentFor(...targets: TargetBuilder[]): this Declare this target as a prerequisite of the listed targets — the reverse of {@link dependsOn}: each listed target gains this one as a dependency, so this runs before them. Declare the listed targets above this one. requires(...params: AnyParameter[]): this Require that the given parameters resolve to a value before this target runs; otherwise the target fails with a message naming the missing one. Use it when a target needs a parameter that is optional build-wide. proceedAfterFailure(): this Keep running the rest of the build even if this target fails. The build still reports failure, and this target's own dependents are skipped. unlisted(): this Hide this target from `--list` and `--help` (it can still be run by name). readOnly(): this Mark this target query-only for MCP: its `run:` tool advertises MCP's `readOnlyHint` instead of the default `destructiveHint`, and it is exempt from `--confirm-destructive`. A hint about intent only — the target still runs its real body — so declare it on targets that inspect rather than mutate (a status check, a report). always(): this Run this target even after the build has failed — for cleanup, teardown, or an aggregate that has to report on the failure. It still waits for its own dependencies, but waits for them to settle rather than to succeed: a dependency that failed releases it, the same as one that passed or was skipped. Anything else would make the modifier unusable for the case it exists for, since a target that depends on the work it is cleaning up would be held back by exactly the failure that should trigger it. Use {@link TargetContext.outcomeOf} to see what actually happened. A dependency parked at a `.waitsFor(...)` gate is the exception: it has not settled, so the target waits for the resume rather than reporting on a run that is still in progress. The build's overall result is unchanged — an `always` target that passes does not rescue a failed build. Repeatable conditions/inputs apply. dryRunnable(): this Run this target's body under `--dry-run` instead of skipping it, with the `$` shell in echo mode: each command (awaited or `.spawn()`ed) prints its resolved argv and returns an empty success without starting a process. Opt-in, because Zuke can only intercept `$`/{@link "./shell.ts".Command} — any other side effect a body performs (writing a file, calling an API directly) still happens under a dry run. Use it for bodies that are shell-command orchestration, to preview the exact commands a real run would execute. Without it, a dry run skips the body entirely (the default). Because an echoed command returns empty stdout and exit code 0, a body whose control flow or command arguments depend on a command's output (`await $\`git rev-parse HEAD`.text()`, a `.code()`loop) should branch on the {@link "./executor.ts".TargetContext}`dryRun` flag rather than trust the echoed result. cacheKey(fn: () => string | Promise): this Contribute an extra value to this target's cache fingerprint, beyond its input files — e.g. a parameter value, tool version, or git commit. The target is up-to-date only when its inputs and every cache key are unchanged. The function may be async. Repeatable. ```ts compile = target() .inputs("src") .cacheKey(() => this.configuration.value) .executes(...); ``` produces(...paths: PathLike[]): this Declare artifact files/directories this target produces (metadata). consumes(...targets: Array): this Depend on the listed targets and consume their artifacts: equivalent to {@link dependsOn} for ordering, expressing that this target uses what they {@link produces}. whenSkipped(behavior: "run-dependencies" | "skip-dependencies"): this When this target is skipped by an {@link onlyWhen} condition, also skip its dependencies that no other planned target needs. Because the dependencies would otherwise run first, the condition is evaluated up front, so it must not depend on state produced by other targets during the run. timeout(ms: number): this Fail the target if its body runs longer than `ms` milliseconds (per attempt). retry(times: number, delayMs: number): this Retry the target body up to `times` more attempts on failure, optionally pausing `delayMs` between attempts. Combined with {@link timeout}, each attempt is bounded by the timeout. validateBefore(...validations: Validation[]): this Run one or more {@link Validation}s before the target body. Each runs in declaration order; the first to throw fails the target and the body never runs. Repeatable. A cached/skipped target runs no validations. ```ts deploy = target() .validateBefore(this.securityReview) // gate before deploying .executes(...); ``` validateAfter(...validations: Validation[]): this Run one or more {@link Validation}s after the target body completes successfully. Each runs in declaration order; the first to throw fails the target. Repeatable. recoverWith(...remediations: Remediation[]): this Attach one or more {@link Remediation}s that run only if the body fails. Each is given the failure; if any returns `{ retry: true }`, the executor re-runs the body and, when it now passes, the target succeeds. This is the hook the AI fixer in `@zuke/ai` uses for self-healing builds. Repeatable. ```ts test = target() .executes(() => DenoTasks.test((s) => s.allowAll())) .recoverWith(aiFixer((f) => f.provider("claude").apiKey(this.key))); ``` recoverAttempts(times: number): this The maximum number of fix-then-rerun cycles attempted when the body fails and {@link recoverWith} remediations are configured (default 1). Each cycle runs every remediation, then re-runs the body once; the count bounds how many times that repeats before the failure is final. Clamped to at least 1. lock(configure: Configure): this Hold a cross-run lock while this target runs: only one run may hold `key` at a time, so a second run that tries to acquire it fails with a {@link "./state/lock.ts".LockConflictError} naming the current holder. The lock is released when the target settles — success, failure, or cancellation — and expires after `options.ttl` as a backstop should the holder be killed (a live holder renews it as it runs). `key` may be a thunk, evaluated after parameters resolve, so it can depend on `this..value`; compose composite keys with {@link "./state/lock.ts".lockKey}. Requires a state store (a build that uses `.lock()` gets a `.zuke/runs` filesystem store by default). ```ts promote = target() .lock((s) => s.lockKey("deploy", this.repo.value) .withTtl("4h") .onConflict((h) => `${this.repo.value} is being deployed by ${h.actor} (run ${h.runId}).`)) .executes(...); ``` waitsFor(configure: Configure): this Suspend the run at this target until an external event occurs, then let the run be resumed later (in a different process) — a settings lambda in the same style as {@link lock}. The target is a gate (no body): when its trigger is already satisfied it passes and dependents run; otherwise the run's state is saved, the run is marked suspended, its independent branches finish, and the process exits 0. Requires a state store. ```ts awaitApproval = target() .dependsOn(this.deploy) .waitsFor((s) => s.on(externalSignal("testing-approved")) .timeout("72h") .onTimeout(() => this.rollback)); ``` onCancel(compensation: OnCancel): this Register a compensation target that undoes this target's effect when the run is later cancelled (via `zuke cancel `, an MCP `cancel_run`, or a timed-out wait). The compensation runs iff this target succeeded — a target that never ran, was skipped, or failed has nothing to undo. On cancellation, compensations run in reverse order of the targets that succeeded, so later work is unwound before the work it built on. `compensation` is a sibling target, or a thunk returning one (use the thunk form to reference a target declared below this one — class fields initialise top-to-bottom). The compensation body receives a normal {@link TargetContext} whose `state` exposes this target's persisted metadata, so a deploy that recorded `{ slot: "sit-7" }` in `ctx.state` can be rolled back from exactly that slot. Compensation failures are recorded but do not stop the walk (cleanup is maximal). Requires a state store. On a {@link forEach} sub-target, the compensation is per item: cancel runs it for every item that had succeeded (or was still in-flight), each with its own item-scoped context — see the fan-out section of `docs/orchestration.md`. ```ts deploy = target() .executes((ctx) => ctx.state.set({ slot: "sit-7" })) .onCancel(() => this.rollback); rollback = target() .executes((ctx) => tearDown(ctx.state.get().slot)); // reads deploy's meta ``` forEach(items: () => readonly Item[], factory: ForEachFactory, configure?: Configure): this Fan out over a runtime list: for each item, build an ordered pipeline of sub-targets and run them with per-item failure isolation and bounded concurrency. `items` is a thunk (evaluated when the target runs, so it can read `this..value`); `factory` returns a record of sub-targets per item, each implicitly depending on the one before it. Items run concurrently, each item's stages sequentially — the pipeline model. The sub-targets are materialised at run time (named `parent[item].stage`) — `--list`/`graph` show only the one fan-out node — and each is a first-class target with its own status in the summary and the run record. The fan-out target fails if any item's pipeline fails. A fan-out cannot contain a wait gate: neither the fan-out target itself nor any stage may use {@link waitsFor} — a materialised sub-target has no resume path, so the gate would be silently swallowed. Combining them fails the target with guidance. Gate a fan-out by putting the wait on a separate target that the fan-out `.dependsOn(...)`. ```ts deployBatch = target() .forEach( () => this.repos.value, // string[] (repo) => ({ checks: target().executes(() => checkDeployable(repo)), deploy: target().executes((ctx) => applyToSit(repo, ctx)), }), (s) => s.concurrency(3).continueOnItemFailure(), ); ``` class TeamsAnnouncementSettings extends AnnouncementSettings Fluent settings for {@link AnnounceTasksApi.teams}. Bot mode (`.bot().token(t).team(id).channel(c)`) posts through Microsoft Graph with a bearer token. team(team: string): this Set the Teams team (group) id to post to in bot mode (Microsoft Graph). override protected payload(): Record Render the Teams webhook payload. override protected sendBot(): Promise Post the announcement through Microsoft Graph in bot mode. class ToolInstallSettings Fluent settings for installing a release tool. Configure it in a settings-lambda (`(s) => s.name(...).url(...)`), the same shape as Zuke's tool wrappers. `name` and `url` are required; everything else is optional and mirrors {@link InstallReleaseOptions}. name_?: string The tool name, and the installed filename. Set by {@link name}. url_?: (platform: Platform) => string Resolves the per-platform download URL. Set by {@link url}. destDir_?: PathLike Install directory (overrides the toolchain's). Set by {@link destDir}. archive_?: DownloadFormat | ((platform: Platform) => DownloadFormat) Download format (or a per-platform resolver). Set by {@link archive}. binaryPath_?: string | ((platform: Platform) => string) The binary's path within an archive (or a resolver). Set by {@link binaryPath}. strip_?: number Leading path components to strip on a tree install. Set by {@link strip}. bins_?: string[] Executable bins within a tree install. Set by {@link bins}. checksum_?: string | ((platform: Platform) => string) Expected SHA-256 (or a per-platform resolver). Set by {@link checksum}. platform_?: InstallPlatform The platform to resolve for. Set by {@link platform}. download_?: DownloadFn The download implementation. Set by {@link download}. name(name: string): this The tool name; also the installed binary's filename (`.exe` on Windows). url(resolve: (platform: Platform) => string): this Resolve the download URL for the target {@link Platform}. destDir(dir: PathLike): this The directory to install the binary into (created if missing). archive(format: DownloadFormat | ((platform: Platform) => DownloadFormat)): this Treat the download as a `"tar.gz"` or `"zip"` to unpack (default `"raw"`, the bare binary). Pair with {@link binaryPath} for the binary inside. Pass a `(platform) => format` resolver when the format is per-platform, as it is for most Go and Rust releases — `.tar.gz` on Linux and macOS, `.zip` on Windows (see {@link InstallReleaseOptions.archive}). binaryPath(path: string | ((platform: Platform) => string)): this For an archive, the binary's path within it (defaults to the name). Also accepts a `(platform) => path` resolver, for the usual case of a `.exe` inside the Windows archive only. strip(components: number): this For a tree install ({@link ToolTasksApi.installTree} / {@link Toolchain.tree}), drop this many leading path components while unpacking — `1` unwraps a release tarball's `tool-v1.2.3/` directory. Ignored by a single-binary install. bins(...paths: string[]): this For a tree install, the paths (relative to the stripped root) to mark executable on POSIX — a runtime's `bin/node`, `bin/npm`, … Ignored by a single-binary install. checksum(sha256: string | ((platform: Platform) => string)): this The expected SHA-256 (hex) of the downloaded artifact — verifies and caches the install. Pass a `({ os, arch }) => string` resolver to pin it per platform (see {@link InstallReleaseOptions.checksum}). platform(platform: InstallPlatform): this Resolve for a specific platform instead of the host (a foreign install). download(fn: DownloadFn): this Override the downloader (defaults to an HTTPS download; a test seam). options_(fallbackDestDir: PathLike): InstallReleaseOptions Build the {@link InstallReleaseOptions}, using `fallbackDestDir` when no {@link destDir} was set. Throws if a required field is missing. treeOptions_(fallbackDestDir: PathLike): InstallTreeOptions Build the {@link InstallTreeOptions} for a tree install, using `fallbackDestDir` when no {@link destDir} was set. A tree always ships packed, so the archive defaults to `"tar.gz"` and `"raw"` is rejected. Throws if a required field is missing. class Toolchain A declared set of external tools. Add tools with {@link Toolchain.tool} (a {@link ToolInstallSettings} lambda) and fetch them all with {@link Toolchain.install}. Build one with {@link toolchain}. tool(configure: Configure): this Add a release tool, configured through a settings-lambda. Chainable. tree(configure: Configure): this Add a multi-file runtime tree (see {@link ToolTasksApi.installTree}), configured through a settings-lambda with `.strip(...)`/`.bins(...)`. In {@link install}'s result its entry is the extracted tree's root — a callable {@link AbsolutePath}, so `root("bin")` is the directory to put on `PATH`. Chainable. npm(spec: NpmToolSpec): this Add an npm-registry package to provision as a version-pinned tool — installed under `/npm/@` and keyed in {@link install}'s result by its {@link NpmToolSpec.name}. See {@link installNpmTool}. Chainable. get tools(): readonly ToolInstallSettings[] The configured release tools, in declaration order. get trees(): readonly ToolInstallSettings[] The configured runtime trees, in declaration order. get npmTools(): readonly NpmToolSpec[] The configured npm-package tools, in declaration order. async install(options: ToolchainInstallOptions): Promise> Install every declared tool concurrently — reusing a cached copy where a release tool's or tree's pinned checksum, or an npm tool's `name@version` marker, matches — and return a map of tool name to installed {@link AbsolutePath}. A {@link tree}'s entry is its extracted root directory. class WaitSettings Fluent configuration for {@link TargetBuilder.waitsFor}: `.waitsFor((s) => s.on(externalSignal("approved")).timeout("72h"))`. Set the {@link WaitSettings.on | trigger}, an optional {@link WaitSettings.timeout}, and an optional {@link WaitSettings.onTimeout} disposition. The lambda runs when the target is reached, so the trigger may read `this..value`. trigger_?: WaitTrigger The trigger deciding when the wait is satisfied; set by {@link on}. timeout_?: string | number The deadline duration (string or ms); set by {@link timeout}. onTimeout_?: OnTimeout The timeout disposition thunk; set by {@link onTimeout}. on(trigger: WaitTrigger): this Set the {@link "./wait.ts".WaitTrigger} the wait is satisfied by. timeout(duration: string | number): this Give the wait a deadline (a duration like `"72h"` or milliseconds). onTimeout(disposition: OnTimeout): this What to do when the deadline passes: a thunk returning a sibling compensation target (a thunk, so it can reference a target declared below this one), or the string `"fail"` / `"cancel-run"`. Defaults to `"fail"`. interface AbsolutePath An immutable, absolute filesystem path with a fluent API. Build one with {@link absolutePath}. The value itself is callable — `path(...segments)` returns a new path with those segments appended — and the equivalent {@link AbsolutePath.join} method does the same. `toString()` yields the path string, so an `AbsolutePath` can be interpolated into the `$` shell helper and passed straight to tool `args()`. readonly path: string The normalised path string (forward slashes, `.`/`..` resolved). readonly name: string The final segment, e.g. `"main.ts"` (or `""` for a root). readonly stem: string The final segment without its extension, e.g. `"main"` (`".gitignore"` has none). readonly extension: string The extension including the dot, e.g. `".ts"` (or `""` if none). readonly isRoot: boolean Whether this path is a filesystem root (`"/"`, `"C:/"`). join(...segments: string[]): AbsolutePath Append path segments, returning a new path. parent(): AbsolutePath The parent directory; a root is its own parent. relativeTo(base: AbsolutePath | string): string This path expressed relative to `base` (e.g. `"src/main.ts"`, `"../lib"`). equals(other: AbsolutePath | string): boolean Whether `other` resolves to the same normalised path. toString(): string The normalised path string. interface AffectedOptions Configure {@link ExecuteOptions.affected}: the base revision and diff seam. base?: string The git revision to diff against. Defaults to `HEAD` (uncommitted changes). changedFiles?: ChangedFilesFn How to list changed files. Defaults to {@link gitChangedFiles}. interface AnnounceTasksApi The shape of {@link AnnounceTasks}. slack(configure?: Configure): Promise Announce to Slack. Configure a {@link SlackAnnouncementSettings}: set a `.webhook(url)` (or `.bot().token(t).channel(c)` for the Web API) and the message content. teams(configure?: Configure): Promise Announce to Microsoft Teams. Configure a {@link TeamsAnnouncementSettings}: set a `.webhook(url)` (or `.bot().token(t).team(id).channel(c)` to post through Microsoft Graph) and the message content. discord(configure?: Configure): Promise Announce to Discord. Configure a {@link DiscordAnnouncementSettings}: set a `.webhook(url)` (or `.bot().token(t).channel(c)` to post through the REST API with a bot token) and the message content. interface Announcement A structured announcement assembled by an {@link AnnouncementSettings}. text: string The main message body. title?: string An optional heading rendered above the message. level: AnnouncementLevel The outcome level driving the accent colour and icon. fields?: AnnouncementField[] Labelled details rendered beside the message. link?: AnnouncementLink A clickable action rendered with the announcement. interface AnnouncementField A labelled detail rendered beside the message (e.g. a version or environment). name: string The field's label. value: string The field's value. interface AnnouncementLink A clickable action rendered with the announcement (e.g. a link to a release). text: string The link's visible text. url: string The link's target URL. interface AnyParameter The non-generic view of a parameter, used by discovery and resolution. name_?: string Property name, assigned during discovery. Undefined until then. readonly description_?: string Human-readable description shown in `--help`/`--list`. readonly kind_: ParamKind The runtime value kind. readonly required_: boolean Whether a value must be supplied (no default). readonly options_?: readonly string[] The allowed string choices, if restricted with {@link Parameter.options}. readonly envName_?: string An explicit environment variable name override. readonly hasFallback_: boolean Whether the parameter has a declared default value. readonly secret_: boolean Whether the value is sensitive and should be masked in CI output. readonly array_: boolean Whether the value is a comma-separated / repeatable list (`.array()`). readonly source_?: SecretSource A provider that resolves the value when no flag/env supplied one. readonly default_?: string The declared default rendered as a string (an array default is joined with commas), or `undefined` when the parameter has no default or an empty-list one. For display in tool schemas and `--list`; never a secret value. resolve_(raw: string | undefined): void Resolve from a raw input (or `undefined` when none was supplied). isSet_(): boolean Whether the parameter resolved to a defined value (used by `.requires()`). stringValue_(): string | undefined The resolved value as a string, or `undefined` if unset (for masking). interface BuildCache The incremental cache used by the executor to skip up-to-date targets. upToDate(target: TargetBuilder): Promise Whether `target` is up-to-date: it declares inputs, their fingerprint matches the last successful run, and every declared output still exists. record(target: TargetBuilder): Promise Record `target`'s current fingerprint after a successful run. save(): Promise Persist the store if anything changed. interface BuildDescriptor A versioned snapshot of one registered build. Persisted as JSON; a registry's opaque `version` (an ETag / content hash) drives compare-and-swap writes so two registrations racing at the same version cannot both win. id: string Stable id of the build (its class name, unless overridden). name: string Human-facing build name (the build class name). location: BuildLocation Where the build lives, so a runner can launch it. surface: CliDescription The build's CLI surface, exactly as {@link "../describe.ts".describeCli} produces it. actor: string Who registered the build (a resolved actor; secrets never appear here). createdAt: string ISO-8601 timestamp when the build was first registered. updatedAt: string ISO-8601 timestamp of the last registration write. interface BuildQuery Filters for {@link "./registry.ts".BuildRegistry.listBuilds}; all fields optional. name?: string Keep only builds whose `name` equals this. since?: string Keep only builds registered at or after this ISO-8601 timestamp. interface BuildRegistry Pluggable persistence for {@link BuildDescriptor}s. `version` is an opaque token (an ETag or content hash) used for optimistic concurrency: a write only lands if the stored version still matches the one the writer last read, so two registrations racing at the same version cannot both win. getBuild(id: string): Promise<{ descriptor: BuildDescriptor; version: string; } | null> Fetch a build and its current version, or `null` if it is not registered. register(descriptor: BuildDescriptor, expectedVersion: string | null): Promise Write `descriptor` only if the stored version equals `expectedVersion` (`null` meaning "must not exist yet"). Returns the new version, or a conflict when the stored version has moved on — the caller re-reads and retries. deregister(id: string): Promise Remove a registered build by id; a missing build is not an error. listBuilds(query: BuildQuery): Promise List registered builds matching `query`, newest first (by `createdAt`, then `id`). interface BuildResult Result passed to the {@link Build.onFinish} lifecycle hook. ok: boolean Whether every executed target succeeded (also `true` for a suspended run). executed: string[] Names of the targets that ran, in execution order. error?: unknown The error that aborted the run, if any. suspended?: boolean True when the run suspended at a `.waitsFor(...)` gate rather than finishing — its state is saved and it can be resumed later. The process still exits 0. cancelled?: boolean True when the run was cancelled (via `options.signal` / Ctrl-C, or by another process running `zuke cancel`) rather than failing on its own. Its compensations have run and the record is `cancelled`. `ok` is `false`. runId?: string The run's id, when a run identity was established (always, in practice — every {@link "./executor.ts".execute} generates one). Lets the caller point a follow-up (`zuke runs show`, `zuke cancel`) at this run. interface BuildSummary A compact registry listing row, returned by {@link "./registry.ts".BuildRegistry.listBuilds}. id: string The build id. name: string The build name. actor: string Who last registered the build. createdAt: string ISO-8601 first-registration timestamp. updatedAt: string ISO-8601 timestamp of the last registration write. interface CancelOptions Options for {@link cancelRun}. runId: string The id of the run to cancel. stateStore?: StateStore | false Durable store the run lives in. Defaults to the same resolution as a normal run (explicit → `stateStore()` override → env → `.zuke/runs`); cancel always needs one. actor?: string Who to attribute the cancellation to in the audit trail. readEnv?: (name: string) => string | undefined Reads an environment variable (secrets re-resolve from here for compensations). silent?: boolean Suppress progress output. reporter?: Reporter Custom reporter; overrides `silent`. also?: string[] Extra compensation target names to run first (a timed-out wait whose `onTimeout` names a specific compensation target routes through here). interface CancelResult The outcome of {@link cancelRun}. runId: string The run that was cancelled. status: RunStatus The run's status after cancelling (`cancelled`, or the terminal status on a no-op). noop: boolean True when the run was already terminal and nothing was done. compensated: string[] Names of compensation targets whose bodies ran. failures: CompensationFailure[] Compensations that threw (recorded, non-fatal). interface CiActionRef A pinned action reference, and the version its commit corresponds to. The version is emitted as a trailing `# v1.2.3` comment, which is not decoration: Dependabot reads it to know which version a pinned SHA is, and rewrites both together when it bumps. A generated workflow that dropped it would leave automated bumps with no version to track. ref: string The pinned reference, `owner/repo@`. version?: string The version the SHA corresponds to, e.g. `v7.0.1`. interface CiBootstrap The single step every GitHub job starts with: the `zuke-build/zuke` composite action, which hardens the runner, checks the repository out, and installs Deno if asked — the three steps a Zuke job used to spell out separately. It is the default because those three are not three decisions. They are one prelude whose parts only work in one order, and writing them out three times per workflow meant three pinned SHAs to keep current in every generated file rather than one, inside an action that is itself versioned and tested. The {@link CiHardenRunner} and {@link CiCheckout} options are still how a job configures it — they become the action's inputs. What changes is how many steps that renders, not what a build declares. A job that opts out of either with `harden: false` or `checkout: false` falls back to the separate steps, since one action cannot do half of itself. action?: CiUses The pinned action reference. Defaults to the release this version of Zuke was built against, or to whatever a `pins` resolver returns for {@link ZUKE_ACTION} — which is the form to prefer, because a pin baked into a published package goes stale between releases and a bot's bump to the generated file would be reverted by the next regeneration. denoVersion?: string Install this Deno version, for a job that runs `deno` directly rather than through the `./zuke` launcher (which bootstraps its own). name?: string The step name. Defaults to `"Harden and check out with Zuke"`. interface CiCheckout The repository checkout, emitted as an `actions/checkout` step after any {@link CiHardenRunner} and before the job's own steps. Like hardening, the pinned {@link action} reference is required. action?: CiUses The pinned action reference. Omit it when the file supplies a `pins` resolver. persistCredentials?: boolean Keep the token in git config so a later step can push. Defaults to `false`: a job that does not push should not leave a credential behind. ref?: string The ref to check out. Defaults to the one that triggered the run. fetchDepth?: number How much history to fetch. `0` means the full history — needed by anything that walks past commits, such as a secret scan. name?: string The step name. Defaults to `"Checkout"`. interface CiConcurrency A concurrency group: at most one run per group, optionally cancelling the prior one. group: string The group key (often interpolated, e.g. `ci-${{ github.ref }}`). cancelInProgress?: boolean Cancel an in-progress run in the same group when a new one starts. interface CiFileSpec A CI configuration file declared on a build: a pipeline bound to a path. provider?: CiProvider The provider to render for. Defaults to `"github"`, which is what the `.github/workflows` default path assumes anyway. pins?: CiPinResolver Resolves each action's pinned reference by name, so hardening and checkout can be requested without restating a SHA. With a resolver, every job is hardened and checked out by default — the prelude nearly every job needs — and a job opts out with `harden: false` or adjusts the policy without naming the action again. path?: string The output path (relative to the working directory). Defaults to the field name the file is declared on, in the provider's conventional directory: `releaseWorkflow = cicd({...})` writes `.github/workflows/release.yml`. A trailing `Workflow`/`Ci`/`Yaml` is dropped, and camelCase becomes kebab-case. Recovering the name from the field is how `target()` works too, so a workflow needs no more ceremony than a target. Falls back to the provider's single conventional file (`.github/workflows/ci.yml`, `.gitlab-ci.yml`, …) when the name is not available — a file built outside a build class. pipeline?: CiPipeline The pipeline to render. Defaults to a single `build` job that runs the build. fanOut?: boolean | FanOutOptions Fan the build's targets out into one CI job per target, wired by their dependencies (see {@link fanOutPipeline}). `true` uses the defaults; pass {@link FanOutOptions} to customise. When set, {@link pipeline} supplies the pipeline-level fields (name, triggers, …) and its `jobs` are ignored. invokes?: readonly CiInvokes[] The targets this workflow runs — one job each, in place of hand-written {@link CiPipeline.jobs}. This is the intended way to declare a workflow. A job is almost entirely implied by its target, so naming the targets is usually the whole declaration: the id, the display name, the `./zuke ` command, and the `needs:` edges between jobs all come from the build graph. Pass a {@link CiInvocation} instead of a bare target only for what the runner decides rather than the build — a matrix, token scopes, an egress policy. Each job runs its target's whole subgraph in one process, exactly as `./zuke ` does locally — so dependencies inside a target run in-process and need no cache to share their output. Use {@link fanOut} instead to give every target in the graph its own job, which does need a remote cache. Targets are passed as references (`this.ci`), not names, so a rename is a compile error rather than a workflow that silently runs nothing. As with `dependsOn`, that means the declaration must appear below the targets it invokes — class fields initialise top-to-bottom, so a forward reference is `undefined`. Declaring workflows last is the simplest way to satisfy it. interface CiHardenRunner Runner hardening, emitted as a `step-security/harden-runner` step before anything else in the job. This cannot move into the build: the point of the step is to install an egress control before build code runs, so a build that set it up itself would be the very code it is meant to contain. Generating it is the next best thing — the policy is declared in one place, in code, next to the job it protects. The pinned {@link action} reference is required rather than defaulted. A default would mean either a floating tag (which supply-chain scanners reject as an unpinned use) or a commit SHA baked into `@zuke/core` that goes stale between releases. Passing it makes the pin the caller's — and lets a build source it from wherever its bumps are automated. action?: CiUses The pinned action reference, e.g. `step-security/harden-runner@`. Omit it when the file supplies a {@link CiFileSpec.pins} resolver, which is the better arrangement: the SHA is then stated once for the repository rather than at every use. egress?: "audit" | "block" `"audit"` records outbound connections; `"block"` drops everything outside {@link allowedEndpoints}. Defaults to `"audit"` — the safe choice for a job with no secrets, where a false block would be worse than an unrecorded call. allowedEndpoints?: string[] The hosts a `"block"` policy permits, as `host:port`. Ignored when auditing. Every entry should be traceable to something the build actually reaches. name?: string The step name. Defaults to `"Harden the runner"`. interface CiInvocation One job's worth of a workflow, derived from a target. A job's shape is almost entirely implied by the target it runs: the id and display name come from the target, the command is `./zuke `, and the `needs:` edges come from the target's `dependsOn`. So an invoked target usually needs nothing said about it at all — pass the target and the job is generated. The fields here are the residue that genuinely cannot be inferred, because they are properties of the runner rather than of the work: which OS matrix to fan out over, which token scopes the job needs, how much egress to permit, how long to allow. Set one only when the default is wrong. target: TargetBuilder The target this job runs. id?: string Override the job id (defaults to the target's name, CI-sanitised). name?: string Override the display name (defaults to the target's description, else its name). runsOn?: string The runner, when it differs from the pipeline default. matrix?: Record> A build matrix — fanning one target out over several OSes, say. failFast?: boolean Let the other matrix legs finish when one fails. permissions?: Record The token permissions this job needs (see {@link CiJob.permissions}). timeoutMinutes?: number Fail the job after this many minutes. harden?: CiHardenRunner | false Harden this job's runner, overriding the pipeline default. checkout?: CiCheckout | false Check out in this job, overriding the pipeline default. bootstrap?: CiBootstrap | false The prelude action for this job, overriding the pipeline default. if?: string A condition gating the job. env?: Record Environment variables for the target's own step — where a secret is mapped in, e.g. `{ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" }`. after?: readonly TargetBuilder[] Extra `needs:` edges beyond those implied by the target's `dependsOn`. Use it to order two invoked targets that are independent in the build graph but must not run concurrently in CI. before?: CiStep[] Steps to run before the target, for something no target can do (see below). then?: CiStep[] Steps to run after the target. steps?: CiStep[] Replace the generated `./zuke ` step entirely. The escape hatch of last resort — prefer {@link before}/{@link then}, and prefer moving the work into the target over either. interface CiJob A job: a named unit of work with steps, optionally fanned out by a matrix. id?: string Stable identifier, used as the job key and as a dependency target. Defaults to `"build"`. name?: string Human-readable job name. runsOn?: string The runner. Interpreted per provider: a GitHub runner label and Azure `vmImage` (default `ubuntu-latest`), or a GitLab Docker image (runner default when omitted). Ignored when a matrix defines `os` on GitHub. needs?: string[] Other jobs (by {@link id}) that must finish before this one. matrix?: Record> A build matrix: each key fans out over its values. failFast?: boolean Let the other matrix legs finish when one fails (`fail-fast: false`). Default GitHub behaviour cancels them, which hides whether a failure is platform-specific — the thing a cross-OS matrix exists to answer. permissions?: Record The token permissions this job's `GITHUB_TOKEN` carries. Set it per job rather than pipeline-wide so a job holds only what it needs — the isolation that lets one job push commits while another only reads. GitHub only. harden?: CiHardenRunner | false Harden the runner before this job's steps. Overrides {@link CiPipeline.harden}; pass `false` to opt this job out of a pipeline-wide default. checkout?: CiCheckout | false Check the repository out before this job's steps. Overrides {@link CiPipeline.checkout}; pass `false` to opt out. bootstrap?: CiBootstrap | false The prelude action for this job. Overrides {@link CiPipeline.bootstrap}; pass `false` to render hardening and checkout as separate steps instead. env?: Record Environment variables for the job. if?: string A condition gating the job. A raw provider expression: GitHub `if:`, Azure `condition:`. Ignored on GitLab. Use it to e.g. skip forked pull requests. timeoutMinutes?: number Fail the job if it runs longer than this many minutes. steps?: CiStep[] The steps to run, in order. Defaults to a single step that runs the build. interface CiPipeline A complete, provider-agnostic CI pipeline. name?: string The pipeline name. Defaults to `"CI"`. triggers?: CiTriggers When it runs. Defaults to push and pull request on `main`; pass an empty object (`{}`) for a pipeline triggered only by external means. permissions?: Record Workflow-level token permissions (GitHub only), e.g. `{ contents: "read", "pull-requests": "write" }`. Ignored elsewhere. Defaults to `{ contents: "read" }` — least privilege, and what a workflow that only reads the repository needs. A job that needs more declares it, so the wider scope sits next to the job that justifies it. Pass `{}` for no permissions at all, which is stricter than the default rather than absent. concurrency?: CiConcurrency Limit concurrent runs (GitHub only). Ignored elsewhere. harden?: CiHardenRunner Harden every job's runner, unless a job overrides it or opts out with `harden: false`. Declared once here rather than repeated per job, since the policy is usually uniform across a workflow. GitHub only. checkout?: CiCheckout Check the repository out in every job, unless a job overrides it or opts out with `checkout: false`. GitHub only. bootstrap?: CiBootstrap | false The prelude action every job starts with, unless a job says otherwise with `bootstrap: false`. Defaults to the `zuke-build/zuke` action; see {@link CiBootstrap}. GitHub only. jobs?: CiJob[] The jobs to run. Defaults to a single `build` job that runs the build. interface CiStep A single step in a job. name?: string Human-readable step name. id?: string A stable identifier for the step, so later steps can read its outputs (`${{ steps..outputs.x }}`). GitHub only. if?: string A condition gating this step — a raw provider expression, e.g. `runner.os == 'Windows'` or `always()`. GitHub only. shell?: string The shell to run `run` with (`bash`, `pwsh`, `sh`, …). Omit for the runner's default, which differs per OS. GitHub only. continueOnError?: boolean Continue the job even when this step fails (`continue-on-error`). GitHub only. run?: string A shell command to run. Portable across all providers. uses?: CiUses A GitHub Action reference (e.g. `actions/checkout@v4`). Rendered only for GitHub; skipped for GitLab and Azure. with?: Record Inputs for a {@link uses} Action (GitHub only). env?: Record Environment variables for this step. Rendered as `env:` on GitHub Actions and on Azure Pipelines `script` steps; ignored on GitLab (which sources variables from project settings, not the job YAML). interface CiSyncOptions Filesystem seams for {@link syncCiFiles} (overridable for tests). check?: boolean Verify instead of write: report an out-of-date file as `stale` rather than overwriting it. Intended for CI, where committed config must match the build. read?: (path: string) => Promise Read a file's contents, or `null` when it does not exist. write?: (path: string, content: string) => Promise Write a file, creating parent directories as needed. interface CiSyncResult The outcome of syncing one {@link CiFile}. path: string The file's path. status: CiSyncStatus Whether it was written, already current, or (in check mode) out of date. interface CiTriggers When the pipeline runs. push?: string[] Branches whose pushes trigger the pipeline. An empty array means every branch (no filter); omit the field to disable the push trigger. pullRequest?: string[] Branches whose pull/merge requests trigger the pipeline. An empty array means every branch (no filter); omit the field to disable the trigger. pullRequestTypes?: string[] Which pull-request activity types fire the pipeline, on top of the branch filter — GitHub's default is `opened`, `synchronize`, `reopened`. Add `edited` when a gate reads the pull request's own description, since editing it changes what a check should see without pushing a commit. GitHub only. manual?: boolean Allow manual runs (workflow dispatch / web). branchProtectionRule?: boolean Run when a branch protection rule is created, edited, or deleted (`branch_protection_rule`) — a supply-chain scan wants to re-score when the repository's own protections change. GitHub only. schedule?: ScheduleEntry[] Timezone-aware scheduled runs. Each entry is a 5-field cron in an optional IANA timezone (`{ cron: "30 9 * * 1-5", tz: "Europe/Sofia" }`). Fully supported on GitHub (compiled to UTC crons, with a generated guard step for daylight-saving zones) and Azure (native `schedules:`, UTC/fixed offset only); ignored on GitLab and Bitbucket, whose schedules are configured in the provider UI, not in-file. See {@link "./ci_schedule.ts"}. interface CliCommandInfo A reserved command (`graph`, `generate-ci`, `completions`). readonly name: string The command word. readonly description: string One-line summary. interface CliDescription A build's full CLI surface, suitable for JSON serialization. readonly commands: CliCommandInfo[] The reserved positional commands. readonly flags: CliFlagInfo[] The built-in option flags. readonly targets: CliTargetInfo[] The build's targets, in declaration order. readonly parameters: CliParameterInfo[] The build's declared parameters, in declaration order. interface CliFlagInfo A built-in option flag. readonly name: string The flag, with leading dashes. readonly description: string One-line summary. interface CliParameterInfo A parameter declared on the build. readonly name: string The parameter's property name — the key an MCP tool call and `execute`'s `params` map use (e.g. `skipE2e`). Distinct from {@link flag}, which is its kebab-case form. readonly flag: string The CLI flag (without leading dashes), e.g. `skip-e2e`. readonly description: string The parameter's description, or `""` when none was set. readonly required: boolean Whether a value is required. readonly kind: "string" | "number" | "boolean" The parameter's value kind. readonly boolean: boolean Whether the flag is a value-less boolean. readonly array: boolean Whether repeated flags accumulate into a list. readonly options: string[] The allowed values, when the parameter is constrained to a set. readonly default?: string The declared default rendered as a string, when the parameter has one. interface CliTargetInfo A target declared on the build. readonly name: string The target's name (its field name on the build). readonly description: string The target's description, or `""` when none was set. readonly dependsOn: string[] The names of its direct dependencies, in declaration order. readonly default: boolean Whether this is the conventional `default` target. readonly unlisted: boolean Whether the target is hidden from `--list` (still runnable by name). interface CompensationFailure A compensation that threw during the cancel walk (recorded, non-fatal). target: string The compensation target that failed. forTarget: string The original target whose compensation this was. error: string The failure message. interface CopyOptions Options for {@link FileTasksApi.copy}. overwrite?: boolean Overwrite an existing destination file (default `true`). interface CreateDirectoryOptions Options for {@link FileTasksApi.createDirectory}. recursive?: boolean Create parent directories as needed (default `true`). interface DeclaredEffect One effect declared on a target: its name and its body. name: string The effect's name, unique within the target and stable across runs. fn: EffectFn The body run once the intent is durably recorded. interface DescribeCliOptions Options for {@link describeCli}. omitSecrets?: boolean Drop `.secret()` parameters from the surface (used for registry descriptors). interface EffectContext extends TargetContext The context an effect body receives: the target's own context, plus which effect this is and whether it has been driven before. readonly effect: string The effect's declared name. readonly redriven: boolean True when a previous attempt at this effect already committed its intent — so its side effect may have happened, wholly or partly, and this run is repeating it. Effects are at-least-once. A body that can tell the difference should say so in what it writes, rather than assume it is the first to get here. interface EffectState The durable intent-and-completion row for one of a target's effects. There is no idempotency key here. An effect is identified by where it sits — the run, the target, and its declared name — which the record already spells out structurally, so a key would be a second spelling of the same fact and a place for a secret to end up. status: EffectStatus How far the effect got. intentAt: string ISO-8601 time the intent was committed — always before the body ran. settledAt?: string ISO-8601 time it settled, if it has. error?: string The failure message when `status` is `failed`. attempts: number How many times the body has been driven. Above one means it was re-driven. interface ExecuteOptions Options for {@link execute}. silent?: boolean Suppress all banner/summary output (used by tests). reporter?: Reporter Custom reporter; overrides `silent`. plugins?: Plugin[] Lifecycle observers invoked alongside the build's own hooks, in order. Lets third-party packages report/time/notify without subclassing the build. skip?: string[] Target names to skip even if they appear in the plan (CLI `--skip`). parallel?: boolean | number Run independent targets concurrently. `false`/omitted runs sequentially in deterministic order; `true` uses the host's CPU count; a number sets the maximum concurrency. Dependencies still complete before their dependents. cache?: boolean | BuildCache Incremental caching: skip targets whose declared {@link TargetBuilder.inputs} are unchanged since the last successful run (and whose outputs still exist). Defaults to on; pass `false` to disable (CLI `--no-cache`). A {@link BuildCache} may be supplied directly (used in tests). remoteCache?: RemoteCacheStore | false A {@link RemoteCacheStore} that shares target {@link TargetBuilder.outputs} across machines: a local cache miss restores outputs from it, and a successful run uploads them. `false` disables it (CLI `--no-remote-cache`). When omitted, the build's `remoteCache()` override is used, falling back to the `ZUKE_REMOTE_CACHE_*` environment variables. Ignored when `cache` is a supplied {@link BuildCache} or is `false`. params?: Record Raw parameter values from the command line, keyed by parameter (property) name. Each declared {@link Parameter} is resolved from this map, then the environment, then its declared default before any target runs. readEnv?: (name: string) => string | undefined Reads an environment variable as a parameter fallback. Defaults to `Deno.env.get` (returning `undefined` when env access is unavailable); overridable so parameter resolution can be tested hermetically. prompt?: (flag: string, description: string | undefined) => string | undefined Prompt for a missing required parameter, returning the entered value (or `undefined` to leave it unset). Defaults to an interactive terminal prompt when stdin is a TTY and the build is not on CI; overridable for testing. dryRun?: boolean Plan only: resolve and print every target that would run (honouring `--skip` and `onlyWhen` conditions) without executing any body or touching the cache (CLI `--dry-run`). affected?: AffectedOptions Restrict the run to the targets affected by files changed since a base git revision (CLI `--affected[=]`). A target is affected when a changed file falls inside its declared {@link TargetBuilder.inputs} or a dependency is affected; a target that declares no inputs is always considered affected. Unaffected targets are skipped. The base revision defaults to `HEAD`; supply `changedFiles` to inject the diff (used in tests). github?: boolean Force GitHub Actions output formatting on or off. Auto-detected from the `GITHUB_ACTIONS` environment variable when omitted. color?: boolean Force ANSI colour on or off. Auto-detected (a TTY with `NO_COLOR` unset, outside GitHub Actions) when omitted; off by default with a custom reporter. renderer?: Renderer Renderer for the per-target banners and the end-of-build summary. Defaults to Zuke's built-in {@link "./renderer.ts".defaultRenderer}; `@zuke/console` exports an alternative a build can inject to restyle its output. signal?: AbortSignal Cancel the run when this signal aborts (wired to Ctrl-C/SIGTERM by the CLI, or fired by another process running `zuke cancel`). Every target body's {@link "./target.ts".TargetContext} `signal` mirrors it, and it is applied as the shell's ambient default so an in-flight `$` command is terminated (SIGTERM) on cancellation. When the run is cancelled, the compensations of every target that had succeeded run in reverse order (see {@link "./target.ts".TargetBuilder.onCancel}) and the result is a non-ok `cancelled` outcome. A body that ignores its signal still runs to completion, so promptly-cancellable work should pass `ctx.signal` to its shell commands. stateStore?: StateStore | false Durable run state (see {@link "./state/store.ts".StateStore}). A supplied store is used directly; `false` disables state entirely. When omitted, the build's `stateStore()` override is used, falling back to `ZUKE_STATE_URL` / `ZUKE_STATE_DIR`, and finally — only when {@link state} is set — a filesystem store under `/.zuke/runs`. state?: boolean Opt a plain build into durable state (CLI `--state`): fall back to a `.zuke/runs` filesystem store when nothing else is configured. Ignored when a store is resolved from {@link stateStore}, the build, or the environment. actor?: string Who to attribute the run to in its state record (CLI `--actor`). Falls back to `ZUKE_ACTOR`, then the CI actor, then `"anonymous"`. resume?: ResumeState Continue a suspended run instead of starting a fresh one. Set by {@link "./resume.ts".resumeRun} after it has transitioned the run to `running`; carries the existing record, its store version, and the targets already succeeded (which are not re-run). Not for direct use — call `resumeRun`. interface ExtractOptions Options common to {@link extractTarGzip} and {@link extractZip}. strip?: number Drop this many leading path components from every entry (like tar's `--strip-components`). An entry left with no path — e.g. the archive's single top-level directory — is skipped. Defaults to `0`. Use `1` to unpack a release tarball that wraps everything in a `tool-v1.2.3/` directory. interface FanOutOptions Options for {@link fanOutPipeline}: how a build's targets become parallel CI jobs. command?: (target: string) => string The command a job runs for its target, given the target name. Defaults to the `./zuke ` launcher (which bootstraps Deno). Each job runs only its own target; its dependencies run in their own jobs and are shared via the {@link "./remote_cache.ts" | remote cache}, so pair fan-out with one. setupSteps?: CiStep[] Steps prepended to every job — checkout, tool setup, cache restore. Defaults to a single `actions/checkout` (rendered on GitHub; GitLab and Azure check out automatically). Provide `env` for `ZUKE_REMOTE_CACHE_*` here or via {@link env}. runsOn?: string The runner for every job (see {@link CiJob.runsOn}). includeUnlisted?: boolean Include targets hidden from `--list` via `.unlisted()`. Defaults to false. env?: Record Environment variables set on every job (e.g. the remote-cache config). interface FileTasksApi The shape of {@link FileTasks}. exists(path: PathLike): Promise Whether `path` exists. homeDirectory(): string The current user's home directory, read from `$HOME` (falling back to `$USERPROFILE` on Windows). Throws a clear error when neither is set or environment access is unavailable, so callers get a path or a useful failure — never an `undefined` to thread through. createDirectory(path: PathLike, options?: CreateDirectoryOptions): Promise Create the directory at `path`. Creates parents by default ({@link CreateDirectoryOptions.recursive}); a recursive create is a no-op when the directory already exists. cleanDirectory(path: PathLike): Promise Remove everything inside the directory at `path`, leaving an empty directory. A no-op if `path` does not exist (it is not created). remove(path: PathLike, options?: RemoveOptions): Promise Remove `path`, tolerating a missing target the way `rm -f` does: a `NotFound` resolves to `false` instead of throwing. Any other error (e.g. a non-empty directory removed without {@link RemoveOptions.recursive}) is rethrown. @return `true` if something was removed, `false` if `path` did not exist. copy(source: PathLike, destination: PathLike, options?: CopyOptions): Promise Copy a file or directory tree from `source` to `destination` (directories are copied recursively). move(source: PathLike, destination: PathLike): Promise Move (rename) `source` to `destination`. readText(path: PathLike): Promise Read the UTF-8 text content of the file at `path`. writeText(path: PathLike, content: string): Promise Write `content` to the file at `path`, creating or truncating it. readJson(path: PathLike): Promise Read and parse the JSON file at `path`. interface ForEachItem One materialised fan-out item: a unique label plus its pipeline stages. key: string A label unique within the fan-out, used to name the item's sub-targets. stages: Record The item's ordered pipeline stages, keyed by stage name. interface ForEachSpec The internal fan-out spec stored by {@link TargetBuilder.forEach}. Its {@link ForEachSpec.materialize} closure captures the item type, so the runtime list and factory are erased to concrete {@link ForEachItem}s the executor can run without knowing the item type. materialize: () => ForEachItem[] Produce the per-item sub-target pipelines from the runtime list. configure?: Configure Optional fan-out settings (concurrency, per-item failure isolation). interface GlobOptions Options for {@link glob}. cwd?: string Directory to resolve the pattern against (default: `Deno.cwd()`). interface HeldLease A held lease. Release it when the work it covers is over. readonly lost: AbortSignal Aborts if the lease is lost — the store reports the claim is no longer this holder's, which means something else has taken the work over. A signal rather than a callback because a holder is not always ready to receive one at the moment it acquires: a resume takes the lease before the run it will drive exists. A signal can be read late and still be true. release(): Promise Stop the heartbeat and release the claim (best-effort). interface HttpBuildRegistryOptions Configuration for an {@link HttpBuildRegistry}. url: string The base URL build endpoints are built under (any trailing slash is ignored). token?: string A bearer token sent as `Authorization: Bearer `, if set. fetch?: typeof fetch The `fetch` implementation; defaults to the global. Overridable for tests. interface HttpCacheStoreOptions Configuration for an {@link HttpCacheStore}. url: string The base URL keys are appended to (any trailing slash is ignored). token?: string A bearer token sent as `Authorization: Bearer `, if set. fetch?: typeof fetch The `fetch` implementation; defaults to the global. Overridable for tests. interface HttpOptions Options shared by the HTTP helpers. headers?: Record Extra request headers (e.g. an `Authorization` token). fetch?: typeof fetch The `fetch` implementation to use. Defaults to the global `fetch`; override it to unit-test without network access. interface HttpStateStoreOptions Configuration for an {@link HttpStateStore}. url: string The base URL run endpoints are built under (any trailing slash is ignored). token?: string A bearer token sent as `Authorization: Bearer `, if set. fetch?: typeof fetch The `fetch` implementation; defaults to the global. Overridable for tests. interface InstallNpmToolOptions Options for {@link installNpmTool}. destDir?: PathLike The root tools directory; the package installs under `/npm/@`. Defaults to {@link "./tool.ts".DEFAULT_TOOLS_DIR} (`.zuke/tools`). run?: NpmRunner The npm-install runner. Defaults to the ambient `npm`; a test seam. os?: OperatingSystem The OS whose bin-shim filename to return (`.cmd` on Windows). Defaults to the host; a test seam for the Windows shim path. interface InstallPlatform The host identity: a Zuke {@link OperatingSystem} and {@link Architecture}. os: OperatingSystem The operating system (normalised: `macos`, not `darwin`). arch: Architecture The CPU architecture. interface InstallReleaseOptions Options for {@link installRelease}. name: string The tool name; also the installed binary's filename (`.exe` on Windows). url: (platform: Platform) => string Resolve the download URL for the target {@link Platform}. destDir: PathLike The directory to install the binary into (created if missing). archive?: DownloadFormat | ((platform: Platform) => DownloadFormat) The download format. `"raw"` (default) treats the download as the binary itself; `"tar.gz"` and `"zip"` unpack it and take {@link binaryPath} from inside. Many release assets ship one or the other. Like {@link url} and {@link checksum} this accepts a resolver, because the format is routinely per-platform: a Go or Rust project typically publishes `.tar.gz` for Linux and macOS and `.zip` for Windows. Pass `(p) => p.os === "windows" ? "zip" : "tar.gz"` rather than declaring one format that is wrong on a third of the platforms. binaryPath?: string | ((platform: Platform) => string) For a `"tar.gz"` or `"zip"` archive, the binary's path within the archive. Defaults to {@link name}. Also resolver-friendly, for the same reason: the same release usually names the binary `tool` inside its Unix archive and `tool.exe` inside its Windows one, so `(p) => p.os === "windows" ? "tool.exe" : "tool"` is the common shape. (The installed filename gets its `.exe` automatically — this is the path to copy out of the archive.) platform?: InstallPlatform The platform to resolve the URL for. Defaults to {@link hostPlatform}. Override it to install a foreign binary or to unit-test URL resolution. download?: DownloadFn The download implementation. Defaults to {@link httpDownload}; override it to unit-test without network access. checksum?: string | ((platform: Platform) => string) The expected SHA-256 (hex) of the downloaded artifact — the `.tar.gz` for an archive, or the binary itself for a `"raw"` download; this is what release pages publish as the checksum. When set, the download is verified against it (a mismatch throws and nothing is installed) and the checksum doubles as a cache key: a prior install whose recorded checksum matches is reused without downloading again. Omit it and the tool is downloaded every time and not verified. Because {@link url} resolves a different artifact per platform, each has its own hash — so pass a resolver `(platform) => string` (like `url`) to pin a checksum per platform, or a plain string when a single artifact is installed. interface InstallTreeOptions Options for {@link installTree}. name: string The tool name; the extracted tree lands in `/`. url: (platform: Platform) => string Resolve the download URL for the target {@link Platform}. destDir: PathLike The directory the tree is installed under (created if missing). archive: ArchiveFormat | ((platform: Platform) => ArchiveFormat) The archive format — a multi-file runtime always ships packed. Accepts a per-platform resolver for the usual `.tar.gz` on Unix / `.zip` on Windows split (see {@link InstallReleaseOptions.archive}). strip?: number Leading path components to drop while unpacking (tar's `--strip-components`). A release tarball wraps everything in a `tool-v1.2.3/` directory, so `1` unwraps it; {@link bins} and the returned tree root are then relative to the stripped tree. Defaults to `0`. bins?: readonly string[] Paths (relative to the stripped tree root) to mark executable on POSIX — the tar reader does not preserve mode bits, so a runtime's `bin/node`, `bin/npm`, … need it. Chmod follows a symlink to its real target, so listing a symlinked bin makes the script it points at executable too. platform?: InstallPlatform The platform to resolve for. Defaults to {@link hostPlatform}. download?: DownloadFn The download implementation. Defaults to {@link httpDownload}; a test seam. checksum?: string | ((platform: Platform) => string) The expected SHA-256 (hex) of the downloaded archive — verified before anything is unpacked, and used as the cache key (see {@link InstallReleaseOptions.checksum}). Omit it and the tree is downloaded every time and not verified. interface LockHolder Who holds a lock — surfaced to the loser of a conflict so it can act. actor: string The actor that acquired the lock. runId: string The run that holds it (`zuke cancel ` releases it). since: string ISO-8601 timestamp when it was acquired. runUrl?: string A link to the holding run (e.g. its CI job), when known. interface McpIdentity A trusted caller identity, resolved per request by a {@link McpIdentityHook} (typically from an authenticating reverse proxy's header). Its {@link McpIdentity.actor} is the highest-precedence attribution — it overrides `--actor`, the environment, and the client's self-reported label for the call. actor: string The authenticated actor (e.g. an OAuth subject). via?: string How the identity was established (e.g. `"oauth-proxy"`); informational. interface McpRequestContext The per-request context a transport hands the message handler. Carries the request's headers, so a server's identity hook can authenticate the caller from a trusted proxy header. Empty on the stdio transport (no headers). readonly headers: Headers The request headers; an empty {@link Headers} on stdio. interface NpmToolSpec A specification of an npm-registry package to provision as a tool. name: string The npm package to install, e.g. `"vitest"` or `"@nestjs/cli"`. version: string The exact version to pin, e.g. `"4.1.9"` — installed as `name@version`. bin?: string The bin to resolve, when it differs from the package name — `@nestjs/cli` publishes the `nest` bin, so `{ name: "@nestjs/cli", bin: "nest" }`. Defaults to {@link name}. interface OpenCacheOptions Optional extras for {@link openCache}: a remote store and a warning sink. remote?: RemoteCacheStore A {@link RemoteCacheStore} to restore outputs from (on a local miss) and upload them to (after a successful run). Applies only to targets that declare {@link TargetBuilder.outputs}. warn?: (message: string) => void Report a non-fatal remote-cache error (a get/put failure never fails the build). interface OutputHost Filesystem effects used to archive and restore a target's outputs. readFile(path: string): Promise File contents, or `null` if the path does not exist. stat(path: string): Promise<{ isDirectory: boolean; } | null> Whether a path exists and is a directory, or `null` if it is missing. readDir(path: string): Promise The entry names within a directory. writeFile(path: string, bytes: Uint8Array): Promise Write a file, creating parent directories as needed. interface Platform extends InstallPlatform A platform with helpers to name it the way a tool's downloads do. `osLabel` and `archLabel` map the `os`/`arch` to a tool's own naming, falling back to the value itself for anything not in the alias map — so a `url` callback reads `p.osLabel({ macos: "darwin" })` (for a tool that spells macOS "darwin") instead of a hand-written `os === …` ternary. This is what the {@link InstallReleaseOptions.url} and {@link InstallReleaseOptions.checksum} callbacks receive. osLabel(aliases?: Partial>): string The OS named for downloads: `aliases[os]`, else the {@link InstallPlatform.os} itself. archLabel(aliases?: Partial>): string The arch named for downloads: `aliases[arch]`, else the {@link InstallPlatform.arch} itself. interface Plugin A lifecycle observer. Every hook is optional; implement only the ones you need. Hooks may be async — the executor awaits each before continuing. name?: string A name for diagnostics (optional). onStart?(run: RunInfo): void | Promise Called once before any target runs, with the run's {@link RunInfo}. onTargetStart?(target: string, run: RunInfo): void | Promise Called just before a target's body executes (not for skipped/cached), with the target name and the run's {@link RunInfo}. onTargetEnd?(target: string, status: TargetStatus, timing: TargetTiming): void | Promise Called after each target settles, with its final status and its {@link TargetTiming} (run id + duration). onFinish?(result: BuildResult, run: RunInfo): void | Promise Called once after the run completes (success or failure), with the result and the run's {@link RunInfo}. onRunStateChange?(record: RunRecord): void | Promise Called on each run-level durable status change — the run going `running`, `suspended`, `succeeded`, `failed`, `cancelling`, or `cancelled` — with the current {@link "./state/types.ts".RunRecord}. It carries the full record (per-target timings, waits, the audit trail), so a metrics exporter can derive spans, wait durations, and counters from a single source. Only fires when a state store is configured (the record's home); a plain build with no store never produces one, and this hook stays silent. The record is the secret-free projection: `secret()` parameters are omitted, and `ctx.state` metadata, target errors, and audit arguments are run through the redactor before they reach it — the same data already persisted to the store and shown by `zuke runs show`. It is safe to export. A run cancelled in-process (Ctrl-C / its `signal`) is observed as `running` → `cancelling` → `cancelled`. When another process cancels the run (`zuke cancel`), this process observes it through `cancelling` and stops — the canceller's process owns the final `cancelled` — so treat `cancelling` as run-ended for the owning process. interface Remediation A recovery step plugged into a target with {@link TargetBuilder.recoverWith}. It runs only after the target body fails, receives the failure, and may attempt to repair it — returning `{ retry: true }` to ask the executor to re-run the body (the real build command is the verifier). Implemented, for example, by the AI fixer in `@zuke/ai`, but any object with a `remediate` method qualifies. name?: string A name for diagnostics (optional). remediate(context: RemediationContext): RemediationResult | Promise Inspect (and optionally repair) the failure; report whether to retry. interface RemediationContext Context passed to a {@link Remediation} after a target body fails. target: string The name of the failed target. attempt: number The 1-based recovery attempt (the body has already failed `attempt` times). error: unknown The failure being remediated. When a target fails through the shell this is a `CommandError` carrying the failed command and its captured `stderr`. interface RemediationResult The outcome of one {@link Remediation} attempt. retry: boolean Re-run the target body after this remediation? `true` asks the executor to retry (the remediation changed something — e.g. applied a fix); `false` leaves the failure standing (e.g. a diagnose-only remediation that only explained the failure). summary?: string A one-line description of what was diagnosed or done, for diagnostics. interface RemoteCacheStore A content-addressed store for archived target outputs, keyed by {@link remoteCacheKey}. Both operations are best-effort from the build's point of view: the executor never fails a build because the store is unreachable — it just rebuilds and, where it can, re-uploads. get(key: string): Promise Fetch the archived outputs stored under `key`, or `null` if there are none. put(key: string, artifact: Uint8Array): Promise Store `artifact` (a gzipped tar of a target's outputs) under `key`. interface RemoveOptions Options for {@link FileTasksApi.remove}. recursive?: boolean Remove a directory and its contents recursively, like `rm -r`. interface Renderer How the executor renders a build's output. Each method is pure — it returns the lines to print rather than writing them — so a custom renderer stays unit-testable and the executor keeps control of the output streams. targetHeader(style: Style, name: string): string[] The banner that opens a target's section (a `::group::` under Actions). targetPassFooter(style: Style, name: string, ms: number): string[] The footer printed after a target body succeeds. targetFailFooter(style: Style, name: string, ms: number, error: unknown): { info: string[]; error: string[]; } The footer printed after a target body fails, split into `info` (stdout) and `error` (stderr) so the caller can fan the lines out correctly. targetDryRunFooter(style: Style, name: string): string[] The footer printed for a dry-run target that was never executed. summaryBlock(style: Style, reports: TargetReport[], totalMs: number, ok: boolean): string[] The end-of-build summary block: the aligned table and closing verdict. jobSummaryMarkdown(reports: TargetReport[], totalMs: number, ok: boolean): string The GitHub Actions job-summary Markdown mirroring the terminal summary. interface Reporter Sink for executor output, defaulting to the console. Overridable in tests. info(line: string): void Write an informational line. error(line: string): void Write an error line. interface ResolveRegistryOptions Inputs {@link resolveBuildRegistry} needs to build the default filesystem registry. readEnv: (name: string) => string | undefined Reads an environment variable (injectable for tests). host: StateHost Filesystem effects for the default/env filesystem registry. defaultDir: string Directory the default filesystem registry writes to (`/.zuke/builds`). enableDefault: boolean Fall back to the default filesystem registry when nothing else is configured. `zuke register` sets this so the command works out of the box. interface ResolveStateOptions Inputs {@link resolveStateStore} needs to build the default filesystem store. readEnv: (name: string) => string | undefined Reads an environment variable (injectable for tests). host: StateHost Filesystem effects for the default/env filesystem store. defaultDir: string Directory the default filesystem store writes to (`/.zuke/runs`). enableDefault: boolean Fall back to the default filesystem store when nothing else is configured. Set when the run opts into durable state (`--state`, or — from a later milestone — a durable feature like a lock or a wait). interface ResumeOptions Options for {@link resumeRun}. runId: string The id of the suspended run to resume. stateStore?: StateStore | false Durable store the run lives in. Defaults to the same resolution as a normal run (explicit → `stateStore()` override → env → `.zuke/runs`); resume always needs one. signal?: string Deliver a signal by this name before resuming (satisfies `externalSignal`). data?: JsonValue The signal's JSON payload (defaults to `{}`); ignored without {@link signal}. params?: Record Non-secret parameter overrides; the rest come from the record. readEnv?: (name: string) => string | undefined Reads an environment variable (secrets re-resolve from here). actor?: string Who to attribute the resumption to (stamped on the run). forceGraph?: boolean Continue even if the build graph changed since the run was suspended. resumeDegraded?: boolean Resume even though the record is {@link "./state/types.ts".RunRecord.degraded} — a state write was permanently lost, so a target that succeeded may still be recorded `running` or `pending`. The resume trusts the record as written, which means such a target runs again; passing this accepts that risk, on the grounds that the operator — not Zuke — knows whether the target is safe to repeat. silent?: boolean Suppress banner/summary output. reporter?: Reporter Custom reporter; overrides `silent`. plugins?: Plugin[] Lifecycle observers for the resumed run. Because a resume keeps the original run id, a plugin sees the continuation under the same identity — so an exporter's spans join one trace across the suspend/resume boundary. interface ResumeState The continuation state {@link resumeRun} hands to {@link execute} on a resume. record: RunRecord The run being continued (already transitioned to `running`). version: string Its current store version, for the writer to continue from. done: ReadonlySet Names of targets recorded `succeeded` — seeded as done, never re-run. lease?: HeldLease The lease the resumer took before moving the record out of `suspended`. Held by the resumer rather than acquired here, because the record must never read `running` in the store without its lease already held — that pairing is what tells a sweep the difference between a live run and an abandoned one. interface ResumeWhenOptions Options for {@link resumeWhen}. interval?: string | number How often `zuke resume --check` should re-evaluate the predicate. interface RunEvent One entry in a run's audit trail: an MCP tool call, who made it, and how it ended. Appended (never mutated) so the trail is a chronological record. The MCP server records a {@link RunEvent} for every mutating or denied tool call; `zuke runs show` prints them. at: string ISO-8601 time the call was recorded. tool: string The tool called (e.g. `run:deploy`, `signal_run`). actor: string Who made the call (a resolved actor; see {@link "./record.ts".resolveActor}). outcome: RunEventOutcome Whether the call ran, was denied by authorization, or errored. args: Record The call's arguments, redacted — secret values masked, tokens dropped. detail?: string A short, redacted human detail (e.g. a denial reason), when present. interface RunGraphNode One entry of a run's graph-shape snapshot. name: string The target's dotted name. dependsOn: string[] The dotted names of its direct dependencies. interface RunInfo Run identity passed to a plugin's lifecycle hooks, so an observer can group a run's events (e.g. under one trace id) — stable across a suspend/resume boundary, since a resumed run keeps the original id. readonly runId: string The run id, stable for every target in the run (and across a resume). readonly dryRun: boolean True when the run is a dry run (no target body executes). interface RunOptions Options for {@link run}. args?: string[] Command-line arguments. Defaults to `Deno.args`. plugins?: Plugin[] Lifecycle observers to run alongside the build's own hooks. renderer?: Renderer Renderer for the per-target banners and end-of-build summary. Defaults to Zuke's built-in look; inject `consoleRenderer` from `@zuke/console` (or a custom {@link Renderer}) to restyle a build's output. interface RunQuery Filters for {@link "./store.ts".StateStore.listRuns}; all fields are optional. status?: RunStatus Keep only runs with this status. target?: string Keep only runs whose graph contains a target with this dotted name. since?: string Keep only runs created at or after this ISO-8601 timestamp. limit?: number Return at most this many runs (the newest, since listing is newest-first). Applied server-side so a large store stays listable; `0` returns none. interface RunRecord A versioned snapshot of one run. Persisted as JSON; a store's opaque `version` (an ETag / content hash) drives compare-and-swap writes. id: string Unique run ID (matches {@link "../target.ts".TargetContext} `runId`). build: string The build class name. buildId?: string Which build instance this run belongs to — `ZUKE_BUILD_ID`, else `GITHUB_REPOSITORY`, resolved once at creation. Absent when neither was set (and on every record written before this field existed). The class name above cannot identify a build: a `zuke.ts` templated across a dozen services shares its name, its target names and its graph shape, so every shape-based check passes and one service's recovery sweep would drive another's runs with its own target bodies. This is what a recovery path compares; see {@link "../ownership.ts"}. rootTarget: string The dotted name of the requested (root) target. status: RunStatus The run's lifecycle status. actor: string Who started the run (resolved from `--actor`, `ZUKE_ACTOR`, or CI env). createdAt: string ISO-8601 timestamp when the run was created. updatedAt: string ISO-8601 timestamp of the last write. graph: RunGraphNode[] The graph shape the run planned, in declaration order. params: Record Resolved parameter values, keyed by name. Secrets are always omitted. targets: Record Per-target progress, keyed by dotted target name. signals: Record External signals received so far, keyed by name (see `.waitsFor(...)`). events: RunEvent[] Append-only audit trail of MCP tool calls against this run (see {@link RunEvent}). degraded?: boolean True when at least one state write for this run was permanently lost — a conflicting write from another process could not be re-applied within the writer's retry budget. Writes are best-effort, so the run itself carried on; the flag is how a later reader learns that a transition which really happened may be missing from the record. In particular a target that succeeded can still be recorded `running` or `pending`, so a resume would re-run it — which is why a resume refuses a degraded record unless `--resume-degraded` overrides it (see {@link "../resume.ts".ResumeOptions.resumeDegraded}) — and why a cancellation compensates every target whose success the record cannot rule out, rather than only those recorded `succeeded` (see {@link "../cancel.ts".runCompensations}). It is set by the writer when it loses a write and persisted by the next write that lands — the failing one, by definition, could not carry it. A drop that leaves the mutation in memory for a later write to re-persist does not set it. Absent (or `false`) means no write is known to be missing. deadlineAt?: string ISO-8601 wall-clock deadline for the whole run, stamped once at creation from `Build.deadline()`. Absent when the build sets none. A budget for running, not for existing. A run parked at an approval gate is not spending it — its budget there is the wait's own timeout — so only a sweep over `running` runs consults this. intendedTerminal?: RunStatus The terminal status the process that moved this run to `cancelling` means to leave it in. Absent means `cancelled`, which is what an ordinary `zuke cancel` intends and what every record written before this field existed meant. Recorded rather than inferred, because the settlement can be finished by a different process than the one that began it: a canceller that crashes leaves the run `cancelling`, and whoever recovers it has no other way to know whether an operator was cancelling the run or a sweep was failing an abandoned one. interface RunSummary A compact run listing row, returned by {@link "./store.ts".StateStore.listRuns}. id: string The run ID. build: string The build class name. rootTarget: string The dotted name of the requested (root) target. status: RunStatus The run's lifecycle status. actor: string Who started the run. createdAt: string ISO-8601 creation timestamp. updatedAt: string ISO-8601 timestamp of the last write. interface RunningService A started service the executor holds until it tears it down. readonly name: string The service's target name, for diagnostics. stop(): Promise Stop the service; never rejects (failures are the registry's concern). interface ScheduleEntry A scheduled trigger: a 5-field cron expression in an optional IANA timezone. cron: string A standard 5-field cron expression (`minute hour day-of-month month day-of-week`). tz?: string An IANA timezone (e.g. `Europe/Sofia`) the `cron` is expressed in. Omitted (or `UTC`) means the cron is already UTC and is emitted verbatim. interface SecretSource A provider that resolves a secret's value on demand. Built by {@link execSecret} or {@link fileSecret} and attached to a parameter with `.from(source)`; the framework calls {@link SecretSource.resolve} during parameter resolution. resolve(): Promise Produce the secret value, or throw {@link SecretError} on failure. interface ServiceHandle A running service — whatever {@link ServiceBuilder.start} returns. Its {@link ServiceHandle.stop} tears it down; a {@link https://jsr.io/@zuke/core SpawnedProcess} is one, so `.start(() => $\`…`.spawn())` needs no explicit stop. stop(): void | Promise Terminate the service. Called on teardown unless `.stop()` overrides it. interface SignalRecord A payload received for an external signal (see {@link RunRecord.signals}). data: JsonValue The signal's JSON payload (`{}` when none was sent). receivedAt: string ISO-8601 timestamp when the signal was recorded. interface StateHost Injected filesystem effects for {@link "./fs_store.ts".FileSystemStateStore}, so it stays unit-testable. The default implementation is {@link defaultStateHost}. readText(path: string): Promise File contents, or `null` when the file does not exist. writeText(path: string, content: string): Promise Write a file's contents, creating parent directories as needed. rename(from: string, to: string): Promise Rename a file (used to publish a temp file atomically). createExclusive(path: string): Promise Create `path` exclusively: resolve `true` if it was created, `false` if it already existed. Used as an atomic lock marker. remove(path: string): Promise Remove a file; a missing file is not an error. listDir(path: string): Promise The entry names in a directory, or `[]` when the directory is absent. mkdirp(path: string): Promise Create a directory and any missing parents. now(): number The current time in epoch milliseconds — the clock for lock expiry (injectable for tests). interface StateStore Pluggable persistence for run records. `version` is an opaque token (an ETag or content hash) used for optimistic concurrency: a write only lands if the stored version still matches the one the writer last read, so two writers racing at the same version cannot both win. getRun(id: string): Promise<{ record: RunRecord; version: string; } | null> Fetch a run and its current version, or `null` if it does not exist. putRun(record: RunRecord, expectedVersion: string | null): Promise Write `record` only if the stored version equals `expectedVersion` (`null` meaning "must not exist yet"). Returns the new version, or a conflict when the stored version has moved on — the caller re-reads and retries. listRuns(query: RunQuery): Promise List runs matching `query`, newest first (by `createdAt`, then `id`). deleteRun(id: string): Promise Delete a run permanently. A missing run is not an error (delete is idempotent). Backs `zuke runs prune`; on the HTTP backend this maps to a `DELETE /runs/:id` a server may leave unimplemented (retention there is the server's job — see `docs/state-api.md`). acquireLock(key: string, holder: LockHolder, ttlMs: number): Promise Atomically acquire the lock `key` for `holder`, expiring after `ttlMs`. An expired lock is taken over. Returns a `token` on success, or the current holder when the lock is live. renewLock(key: string, token: string, ttlMs: number): Promise Extend the lock `key` held under `token` by another `ttlMs`. Returns `false` if the token no longer owns it (expired and taken over), so a heartbeat can detect a lost lock. releaseLock(key: string, token: string): Promise Release the lock `key` if still held under `token`; a no-op otherwise. interface TarEntry A single entry within a tar archive — a regular file or a symbolic link. name: string The entry's path inside the archive (≤ 100 bytes). data: Uint8Array The file contents (empty for a symlink entry). linkname?: string For a symbolic-link entry, its target (≤ 100 bytes); absent for a regular file. Node's release tarballs, for one, ship `bin/npm`/`bin/npx` as symlinks into `lib/node_modules`, so extracting a runtime tree must preserve them. interface TargetContext The context passed to every target body. Optional to receive — an existing zero-argument `.executes(() => …)` stays valid, since a zero-argument function is assignable to this one-parameter type — but a body that wants the run's identity, a cancellation signal, or durable per-target state reads them here. readonly runId: string Unique ID of this run, stable for every target in the run. readonly target: string Dotted name of the executing target. readonly signal: AbortSignal Aborted when the run is cancelled (see {@link "./executor.ts".ExecuteOptions} `signal`). Pass it to a shell command's `.signal()` to have that command terminated on cancellation; the executor also applies it as the shell's ambient default, so a plain `$` in the body is terminated too. readonly state: TargetStateHandle Durable per-target metadata. Persisted to the run's state store when one is configured (see {@link "./state/store.ts".StateStore}), and an in-memory no-op otherwise. The carrier for state that must survive across a suspend/resume boundary — do not put secrets in it. readonly signals: ReadonlyMap Payloads of the external signals received so far, keyed by name (see `.waitsFor(...)` and {@link "./wait.ts".externalSignal}). Empty until a signal is delivered by `zuke resume --signal `. readonly dryRun: boolean True when the run is a dry run (bodies do not execute under a dry run). stateOf(target: string): TargetStateHandle The durable state handle of another target in this run — the seam a body reads a dependency's published metadata through (e.g. the result a `.waitsFor(githubWorkflow(...))` gate recorded to its state). `stateOf(this target)` is equivalent to {@link state}. It reads the run's current record, so it sees writes a dependency made earlier in the run — including across a suspend/resume, since the record is durable. outcomeOf(target: string): TargetOutcomeView | undefined What another target in this run did, or `undefined` if it has no outcome yet — it has not run, or is running now. The seam for a target that must decide on the run's results rather than merely follow them: an aggregate gate reporting one verdict for a fan of checks, some of which are allowed to fail. `.dependsOn(...)` alone cannot express that, because a failed dependency never lets its dependents run; pair this with `.always()` and `.proceedAfterFailure()` on the checks. It reads what this run has settled so far, whichever process settled it: outcomes from a previous process come back after a resume, because they are in the durable record. A sibling running concurrently has no outcome yet — depend on what you intend to read. outcomes(): ReadonlyMap Every outcome this run has settled so far, keyed by dotted target name — a snapshot, not a live view. Targets that have not settled are absent rather than present with a placeholder status. interface TargetOutcomeView What another target in this run did, as {@link TargetContext.outcomeOf} reports it. The status is the record's vocabulary, not the summary's: a target whose body ran and one served from the cache both read `"succeeded"`, because that is the distinction the durable record keeps. A body branching on this wants "did it work", which both answer the same way. readonly status: TargetRunStatus The target's status: `succeeded`, `failed`, `skipped`, `waiting`, … readonly error?: string The failure's message, when it failed. Redacted like every stored string. readonly startedAt?: string When it started, ISO-8601, if it did. readonly endedAt?: string When it settled, ISO-8601, if it has. interface TargetReport One row of the end-of-build summary. name: string The target's name. status: TargetStatus The target's terminal status. ms: number The target's wall-clock duration in milliseconds. interface TargetRunState The recorded progress of a single target. status: TargetRunStatus The target's current status within the run. meta: Record Durable metadata written via {@link "../target.ts".TargetStateHandle}. startedAt?: string ISO-8601 timestamp when the body started, if it has. endedAt?: string ISO-8601 timestamp when the target settled, if it has. error?: string The failure message when `status` is `failed`. waitingFor?: WaitState The pending wait when `status` is `waiting` (set by `.waitsFor(...)`). effects?: Record The declared effects of this target, keyed by effect name — present only once at least one has been armed. interface TargetStateHandle A target's durable, per-target metadata, surfaced on {@link TargetContext} as `state`. Writes are persisted to the run's state store (see {@link "./state/store.ts".StateStore}) and are visible to later runs — e.g. a resuming process reading what a suspended target recorded. When no store is configured, the handle is an in-memory no-op scoped to the current run. Never store a secret here — state is persisted in plain JSON and read back by later runs and by `zuke runs show`. set(patch: Record): Promise Merge a JSON patch into this target's persisted metadata (awaits the write). get(): Record Read this target's persisted metadata (from prior attempts/runs too). interface TargetTiming Timing for a settled target, passed to {@link Plugin.onTargetEnd}. readonly runId: string The run id (see {@link RunInfo}). readonly durationMs: number The target's wall-clock duration in milliseconds (0 for skipped/cached). interface ToolTasksApi The task surface of {@link ToolTasks}. install(configure: Configure): Promise Install a single release tool, configured through a {@link ToolInstallSettings} lambda, and resolve to its installed path. Defaults the install directory to `.zuke/tools`. installTree(configure: Configure): Promise Install a multi-file runtime tree (Node.js, a JDK, …) from one archive, configured through a {@link ToolInstallSettings} lambda, and resolve to the extracted tree's root {@link AbsolutePath}. Because that path is callable, `root("bin", "node")` is a binary and `root("bin")` a directory to put on `PATH`. Use `.strip(...)` and `.bins(...)`; defaults the install directory to `.zuke/tools`. See {@link installTree}; group several with {@link Toolchain.tree}. npm(spec: NpmToolSpec, options?: InstallNpmToolOptions): Promise Provision a single npm-registry package as a version-pinned, cached tool and resolve to its installed bin path. Defaults the install root to `.zuke/tools`. See {@link installNpmTool}; group several with {@link Toolchain.npm}. interface ToolchainInstallOptions Options for {@link Toolchain.install}. destDir?: PathLike Where tools without their own `destDir` install. Defaults to `.zuke/tools`. download?: DownloadFn The download implementation for every release tool (defaults per {@link installRelease}). npmRun?: NpmRunner The npm-install runner for npm-package tools (defaults to the ambient `npm`; a test seam). interface Validation A check plugged into a target with {@link TargetBuilder.validateBefore} or {@link TargetBuilder.validateAfter}. The target decides when it runs; the validation decides what it checks. Throw from {@link Validation.validate} to fail the target (and break the build). Implemented, for example, by the AI reviewers in `@zuke/ai`, but any object with a `validate` method qualifies. name?: string A name for diagnostics (optional). validate(context: ValidationContext): void | Promise Run the check; throw to fail the target. May be async. interface ValidationContext Context passed to a {@link Validation} when it runs. target: string The name of the target the validation is attached to. interface WaitContext The durable context a {@link WaitTrigger} may use while deciding whether its event has occurred. Its {@link WaitContext.state} handle is the awaiting target's persisted metadata — it survives a suspend/resume, even across processes — so a stateful trigger (e.g. "dispatch a GitHub workflow, then poll it") can remember what it started and hand a result to the target's body. The built-in triggers ignore it. readonly state: TargetStateHandle The awaiting target's durable state handle (the same one its body receives as `ctx.state`). Reads and writes here persist with the run and are visible to a later resume in another process. readonly runId: string The run id — stable across a resume, so a natural correlation key. readonly target: string The awaiting target's dotted name. interface WaitState The pending wait recorded on a suspended target (see {@link TargetRunState.waitingFor}). trigger: string A human-readable descriptor of what is awaited (e.g. `signal:approved`). deadline?: string ISO-8601 deadline after which {@link onTimeout} applies, if a timeout was set. onTimeout: WaitDisposition What happens when the deadline passes. interface WaitTrigger Decides whether the event a target waits for has occurred. `descriptor` is a short, JSON-safe label recorded on the suspended target; `isSatisfied` is evaluated against the run's received signals (and a durable {@link WaitContext}) when the target is reached and again on each resume attempt. readonly descriptor: string A short label recorded on the wait (e.g. `signal:approved`). readonly pollIntervalMs?: number Poll interval hint (ms) for predicate triggers driven by `zuke resume --check`. isSatisfied(signals: ReadonlyMap, context: WaitContext): boolean | Promise Whether the awaited event has occurred, given the run's received signals and a durable {@link WaitContext}. The context lets a trigger persist correlation state across a suspend/resume; a trigger that only inspects signals may ignore it (fewer parameters stay assignable). type AnnouncementLevel = "success" | "failure" | "warning" | "info" The outcome an announcement conveys. It drives the accent colour and the icon prepended to the message; defaults to `"info"`. type Architecture = "x86_64" | "aarch64" The CPU architectures Zuke recognises. type ArchiveFormat = "tar.gz" | "zip" A packed download format, unpacked after the checksum is verified. type BuildLocation = { kind: "module"; module: string; cwd: string; repo?: string; } | { kind: "command"; command: string[]; cwd: string; repo?: string; } Where a registered build lives, so a runner can launch it. Two forms: a `module` (the entry file `deno run` executes — the form `zuke register` writes) or an explicit `command` (a launch argv, for a build fronted by a wrapper script). Both carry the working directory and, in CI, the repository. type ChangedFilesFn = (base: string) => Promise Lists the files changed since `base` (a git revision), each path relative to the repository root. The seam behind {@link ExecuteOptions.affected}; defaults to {@link gitChangedFiles} and is overridable so the affected plan can be tested without a real git repository. type CiHost = "github" | "gitlab" | "azure" | "bitbucket" | "local" The CI host a build is running on, or `"local"` when not on CI. The names match {@link CiProvider} so they compose with CI generation and per-host integrations (e.g. posting a review to the right pull-request API). type CiInvokes = TargetBuilder | CiInvocation A target to invoke, bare when the derived job needs no adjustment. type CiPinResolver = (action: string) => CiUses Resolves an action's pinned reference by name, e.g. `"actions/checkout"`. Supplying one is what lets a workflow declare hardening and checkout by intent rather than by repeating a SHA at every use. Without it each {@link CiHardenRunner} and {@link CiCheckout} must carry its own `action`. type CiProvider = "github" | "gitlab" | "azure" | "bitbucket" The CI providers {@link generateCi} can target. type CiSyncStatus = "written" | "unchanged" | "stale" What {@link syncCiFiles} did to a file. type CiUses = string | CiActionRef A step's `uses:` value — a bare reference, or one carrying its version. type Condition = () => boolean | Promise A predicate gating whether a target runs; may be synchronous or async. type DownloadFn = (url: string, dest: PathLike) => Promise A download function: fetch `url` into the file at `dest`. type DownloadFormat = "raw" | ArchiveFormat How a downloaded artifact is treated: `"raw"` is the binary itself, an {@link ArchiveFormat} is unpacked and one path taken from inside. type EffectFn = (ctx: EffectContext) => unknown | Promise The body of a declared effect (see {@link TargetBuilder.effect}). type EffectStatus = "pending" | "done" | "failed" Where one declared effect has got to (see `.effect(...)`). `pending` is the load-bearing one: it means the intent was committed and the body may or may not have run. A process that dies mid-effect leaves exactly that, which is what tells a later resume to drive it again. type ForEachFactory = (item: Item, index: number) => Record Builds one item's ordered pipeline of sub-targets for {@link TargetBuilder.forEach}. The returned record's keys are stage names and its values are targets; each stage implicitly depends on the one declared before it, so an item's stages run in insertion order. type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue; } A JSON-serialisable value — the only thing that may be persisted in a target's {@link TargetStateHandle}, since run state is stored as JSON. type LockResult = { ok: true; token: string; } | { ok: false; holder: LockHolder; } The result of {@link StateStore.acquireLock}: a `token` proving ownership, or the current `holder` when the lock is already held. type McpIdentityHook = (ctx: McpRequestContext) => McpIdentity Resolve a trusted {@link McpIdentity} from a request's context. Invoked once per message, before any dispatch; throwing rejects the whole request with an auth error, so nothing executes and nothing is written to state — the seam a proxy in front of the server uses to inject an authenticated identity. type NpmRunner = (args: string[]) => Promise Runs `npm install ` — the injectable subprocess seam. Defaults to spawning the ambient `npm`; a test injects a fake that records the argv and plants the expected bin, so provisioning stays hermetic and network-free. type OnCancel = TargetBuilder | (() => TargetBuilder) A compensation registered with {@link TargetBuilder.onCancel}: either a sibling target directly, or a thunk returning one. The thunk form defers evaluation so a compensation declared below the target it cleans up (class fields initialise top-to-bottom) can still be referenced. type OnTimeout = () => TargetBuilder | "fail" | "cancel-run" What a timed-out wait does — resolved from {@link WaitSettings.onTimeout}. type OperatingSystem = "linux" | "macos" | "windows" The operating systems Zuke recognises — Deno's raw `Deno.build.os` values normalised to a friendly set (notably `darwin` → `macos`). Used across the ecosystem so builds branch on `"macos"` rather than the surprising `"darwin"`. type OrderingEdge = readonly [TargetBuilder, TargetBuilder] A soft ordering edge `[before, after]`: `before` must run before `after`, with no data dependency. Returned by {@link "./build.ts".Build.extraEdges} to feed a consumer's dependency graph (e.g. a monorepo's `dependency-graph.json`) into planning; an edge whose endpoints are not both in the run's execution set is ignored, and cycles are reported like any other. type ParamKind = "string" | "number" | "boolean" A parameter's runtime kind tag. type ParamValue = string | number | boolean The value kinds a parameter can hold. type PathLike = string | AbsolutePath A filesystem path accepted by Zuke APIs: either a plain string or an {@link AbsolutePath}. Anywhere a tool wrapper or build helper takes a path, it accepts a `PathLike` and coerces it to a string. type PutBuildResult = { ok: true; version: string; } | { ok: false; conflict: true; } The result of a {@link BuildRegistry.register} compare-and-swap write. type PutResult = { ok: true; version: string; } | { ok: false; conflict: true; } The result of a {@link StateStore.putRun} compare-and-swap write. type RunEventOutcome = "ok" | "denied" | "error" The outcome recorded for an audited MCP tool call (see {@link RunEvent}). type RunStatus = "running" | "suspended" | "cancelling" | "succeeded" | "failed" | "cancelled" The lifecycle status of a whole run. `cancelling` is the transient state a cancellation moves through — the run has been asked to stop and its compensations are running — before it settles as `cancelled`. type Target = TargetBuilder A configured target. Alias of {@link TargetBuilder} — the same object both builds and represents the target. Exposed as `Target` for use in signatures. type TargetFn = (ctx: TargetContext) => unknown | Promise The executable body of a target. May be synchronous or asynchronous, and any returned value is ignored — so a body can return a tool-wrapper call directly (`.executes(() => DenoTasks.lint())`, which resolves to a `CommandOutput`) without wrapping it in an `async` block just to discard the result. A single returned promise is awaited before dependents run; a returned array of promises is not (it is not a thenable), so `await Promise.all([...])` inside the body when you fan work out, rather than returning the array. type TargetRunStatus = "pending" | "running" | "waiting" | "succeeded" | "failed" | "skipped" The status of one target within a run record. `waiting` (a suspended external-event wait) is produced only from a later milestone; the executor records the others. type TargetStatus = "passed" | "failed" | "skipped" | "cached" | "waiting" The outcome of a single target, reported in the summary and lifecycle hooks. `waiting` marks a `.waitsFor(...)` gate whose event has not occurred — the run suspends there. type WaitDisposition = "fail" | "cancel-run" | { target: string; } What a timed-out wait does: fail, cancel the run, or run a compensation target. Ergonomic process execution built on `Deno.Command`, exposed as the `$` tagged template. ```ts await $`deno test -A`; // throws on non-zero exit const out = await $`git rev-parse HEAD`.text(); // trimmed stdout const code = await $`flaky-cmd`.noThrow().code(); // exit code, no throw await $`build`.env({ NODE_ENV: "prod" }).cwd("./app"); ``` Interpolated values become discrete argv entries — they are never spliced into a shell string — so there is no shell-injection surface. Arrays expand to multiple arguments. @module function $(strings: TemplateStringsArray, ...values: Interpolatable[]): Command Run an external command, ergonomically. @example `await $\`deno test -A`` function splitShellArgs(input: string): string[] Split `input` into argv the way a POSIX shell would, honouring the quoting rules only: - Unquoted runs of whitespace separate arguments; leading, trailing, and repeated whitespace produce no empty arguments. - Single quotes are fully literal — no escape sequences at all, so `'a\b'` yields `a\b`. - Inside double quotes a backslash escapes only `"`, `\`, ```, `$`, and a newline; before anything else it stays literal, so `"\d+"` yields `\d+` rather than silently losing the backslash. - Outside quotes a backslash escapes the following character, so `a\ b` is one argument. - A backslash-newline pair is a line continuation and is removed, both unquoted and inside double quotes; a backslash at the very end of the input is a dangling continuation and is dropped. - Adjacent segments concatenate (`a"b c"d` → `ab cd`) and a quoted empty string is a real, empty argument (`''` → `[""]`). Non-goals, deliberately not implemented — the input is turned into argv, never interpreted: no variable expansion (`"$HOME"` stays `$HOME`), no globbing, no tilde expansion, no command substitution, and no operator handling of any kind (`|`, `&&`, `;`, `>` are ordinary characters). A caller that needs those must split on them itself, or run a real shell. `\r` is treated as a separator alongside space, tab, and newline so a command line read from a CRLF file cannot smuggle an invisible carriage return into an argument. @param input The command string to split. @return The argv entries, in order; an empty array for blank input. @throws {ShellArgsError} If a single or double quote is never closed. function tokenize(strings: ReadonlyArray, values: ReadonlyArray): string[] Tokenise a tagged-template invocation into an argv array. Literal whitespace separates arguments; interpolated values are appended as atomic tokens (so `--flag=${x}` and `pre${x}` work), and arrays expand to one argument per element. Interpolated values are never re-split on whitespace, which is what keeps command construction injection-free. class Command implements PromiseLike A lazily-executed command. Built by the `$` tagged template. The process does not start until the command is awaited or a terminal method (`text`, `lines`, `code`) is called; the result is memoised so repeated reads are cheap. constructor(argv: string[]) Build a command from a discrete argv array (binary first). env(record: Record): this Merge additional environment variables. cwd(path: PathLike): this Set the working directory for the process. noThrow(): this Do not throw on a non-zero exit; combine with {@link code}. quiet(): this Suppress live stdout/stderr streaming to the terminal. killAfter(ms: number): this Kill the process if it runs longer than `ms` milliseconds, raising a {@link CommandTimeoutError}. Fires even under {@link noThrow}. maxCapturedBytes(bytes: number): this Cap how much of each captured stream is kept in memory, in bytes (default 8 MiB). Capture keeps the newest bytes: once the cap is reached the oldest are dropped, {@link CommandOutput.truncated} is set, and {@link CommandOutput.text} prefixes a notice. Raise it for a command whose whole output you must parse; lower it to bound a chatty one. Live streaming to the terminal is never capped — every byte still reaches it. @throws {RangeError} If `bytes` is not a positive whole number. signal(signal: AbortSignal): this Terminate the process (via `SIGTERM`) when `signal` aborts — for example when the enclosing run is cancelled. Overrides the executor's ambient run signal for this command. Composes with {@link killAfter}: either the timeout or the abort kills the process, whichever fires first. get commandLine(): string The command line, for diagnostics — argv joined by spaces, with the resolved value of every `secret` parameter of the enclosing run masked. This is the only rendered form of the command (the echo under `--dry-run`, a {@link CommandError} message), so a secret passed as an argv token cannot leak through one. The argv given to the operating system is unchanged. then(onfulfilled?: ((value: CommandOutput) => TResult1 | PromiseLike) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null): PromiseLike Await support: run the command and resolve to a {@link CommandOutput}. async text(): Promise Run and resolve to trimmed stdout — prefixed with a truncation notice if the capture cap was hit. Throws on non-zero unless `noThrow`. async lines(): Promise Run and resolve to stdout split into lines (trailing blank dropped). async code(): Promise Run and resolve to the numeric exit code. Never throws on non-zero. spawn(): SpawnedProcess Start the command as a long-lived process without waiting for it to exit, returning a {@link SpawnedProcess} handle. Use this for a service — a dev server, a database, `docker compose up` — that must keep running while other targets execute; stop it with {@link SpawnedProcess.stop}. stdout/stderr are inherited so the process's output is visible. class CommandError extends Error Raised when a command exits non-zero and throwing was not suppressed. constructor(readonly command: string, readonly code: number, readonly stderr: string) Build the error from the failed command line, exit code, and stderr. override name: string The error name. class CommandOutput The resolved result of a command, available when awaiting a {@link Command}. constructor(readonly code: number, readonly stdout: string, readonly stderr: string, readonly truncated: boolean, readonly maxCapturedBytes: number) Build the output from the process exit code and captured streams. text(): string Trimmed stdout, prefixed with a one-line notice when {@link truncated} — so a caller reading the output cannot mistake a tail for the whole of it. class CommandTimeoutError extends Error Raised when a command is killed for exceeding its {@link Command.killAfter} budget. Thrown regardless of {@link Command.noThrow}, since a timeout is a distinct, exceptional outcome from a normal non-zero exit. constructor(readonly command: string, readonly timeoutMs: number) Build the error from the command line and the elapsed-time budget. override name: string The error name. class ShellArgsError extends Error Raised when {@link splitShellArgs} reaches the end of the input with a quote still open. Names the offending quote character and the offset at which it was opened so the bad spot in a long command line is findable. constructor(readonly quote: string, readonly offset: number) Build the error from the unclosed quote character and its offset. override name: string The error name. class SpawnedProcess A long-lived process started with {@link Command.spawn} — the handle a {@link https://jsr.io/@zuke/core service} keeps alive. Unlike awaiting a {@link Command}, spawning does not wait for the process to exit; call {@link SpawnedProcess.stop} to terminate it (which is also the default service teardown). Its stdout/stderr are inherited so the process's own output is visible. constructor(child: Deno.ChildProcess | undefined, readonly commandLine: string) Wrap a spawned child process (or none, for a stub) and its command line. get pid(): number The operating-system process id (`-1` for a dry-run stub). get status(): Promise Resolves when the process exits (immediate success for a dry-run stub). stop(signal: Deno.Signal, graceMs: number): Promise Terminate the process and wait for it to exit. Sends `signal` (default `SIGTERM`); if the process has not exited within `graceMs` (default 5s), it escalates to `SIGKILL` so a process that ignores `SIGTERM` cannot hang teardown. A process that has already exited is treated as stopped. A dry-run stub (no child) is a no-op. type Interpolatable = string | number | AbsolutePath | Array A value that may be interpolated into a `$` template. Foundations for typed tool wrappers (settings-lambda task functions). A tool package (e.g. `@zuke/deno`, `@zuke/npm`) defines one settings class per subcommand by extending {@link ToolSettings}: `buildArgs()` assembles the subcommand argv purely (no I/O), while the base contributes the common fluent chainers (`env`, `cwd`, `noThrow`, `quiet`, `toolPath`, `args`) and the execution logic, which reuses {@link Command} so argv stays an array end-to-end — there is no shell string and no injection surface. ```ts class MyToolSettings extends ToolSettings { protected defaultTool() { return "mytool"; } protected buildArgs() { return ["build", "--fast"]; } } await runSettings(new MyToolSettings(), (s) => s.cwd("app")); ``` @module function defineTool(tool: string, options: DefineToolOptions): ToolTask Define a fluent task for a CLI that has no dedicated `@zuke` wrapper. Returns a task that runs the tool, configured through a {@link DynamicToolSettings} lambda — the same settings-lambda style as the built-in wrappers, with `arg`/`flag`/`option` for argv and the shared `cwd`/`env`/`noThrow`/… chainers. ```ts import { defineTool } from "jsr:@zuke/core/tooling"; const terraform = defineTool("terraform"); await terraform((s) => s.arg("plan").option("out", "plan.tfplan")); // → terraform plan --out plan.tfplan const helmUpgrade = defineTool("helm", { subcommand: "upgrade" }); await helmUpgrade((s) => s.arg("api", "./chart").flag("install")); // → helm upgrade api ./chart --install ``` function runSettings(settings: S, configure?: Configure): Promise Construct-configure-run: the shared shape of every task function. ```ts export const MyTasks = { build: (configure?: Configure) => runSettings(new MyBuildSettings(), configure), }; ``` function shimFallbackArgv(argv: ReadonlyArray, os: typeof Deno.build.os): string[] | null On Windows, wrap an argv in a `cmd /c` invocation so `.cmd`/`.bat` shims (such as npm's) become spawnable; returns `null` on other platforms. function windowsCmdShim(argv: ReadonlyArray, os: typeof Deno.build.os): string[] On Windows, spawn a resolved `.cmd`/`.bat` shim (such as npm's `node_modules` shims) through `cmd /c` — a batch shim is not a PE executable, so `Deno.Command` cannot launch it directly. Returns `argv` unchanged on other platforms or when the binary is not a batch shim. class DynamicToolSettings extends ToolSettings Fluent settings for a {@link defineTool} tool: build the argv with {@link DynamicToolSettings.arg}/{@link DynamicToolSettings.flag}/{@link DynamicToolSettings.option} (in call order), plus all the shared chainers (`cwd`, `env`, `noThrow`, `quiet`, `toolPath`, `args`). constructor(tool: string, initial: string[]) Build settings for `tool`, seeded with any `initial` subcommand tokens. override protected defaultTool(): string The configured tool binary. arg(...values: Array): this Append raw positional/argument tokens. flag(name: string): this Append a boolean flag, e.g. `flag("verbose")` → `--verbose` (or `-v`). option(name: string, value: string | number): this Append a flag and its value as two tokens, e.g. `--output dist`. override protected buildArgs(): string[] The argv assembled from the `arg`/`flag`/`option` calls, in order. abstract class SubcommandSettings extends ToolSettings Base for a wrapper over a CLI organised into subcommand groups — a command path built with {@link command} plus repeatable `--flag [value]` options built with {@link flag}. The agent and cloud wrappers (`gh`, `gcloud`, `claude`, `gemini`, `codex`) share this shape; each sets its binary via {@link ToolSettings.defaultTool} and, when needed, a fixed prefix via {@link leadingTokens} or between-command global flags via {@link middleTokens}. The argv is assembled as `[...leadingTokens(), ...command, ...middleTokens(), ...flags]`, keeping every token a discrete argv entry so command construction stays injection-free. command(...parts: Array): this Append command-path tokens — the group, verb, and operands — in order. flag(name: string, value?: string | number): this Add an arbitrary flag. With a value it renders `--name value`; without one the bare `--name`. Repeatable. protected leadingTokens(): string[] Fixed token(s) placed before the command path (e.g. a subcommand-group name). Empty by default; override to prepend a constant prefix. protected middleTokens(): string[] Token(s) placed between the command path and the trailing flags (e.g. a wrapper's common global flags). Empty by default; override to insert them. override protected buildArgs(): string[] Assemble the argv: leading tokens, command path, middle tokens, then flags. class ToolNotFoundError extends Error Raised when a tool's binary cannot be found on the system. constructor(readonly tool: string, sawNodeModules: boolean) Build the error naming the tool binary that could not be found. override name: string The error name. abstract class ToolSettings Abstract fluent base for tool settings. Subclasses provide the binary ({@link defaultTool}) and the pure subcommand argv ({@link buildArgs}); the base provides the shared chainers and {@link run}. os_: typeof Deno.build.os The platform identifier used by {@link run} to decide whether to retry a missing binary through the `cmd /c` shim path (Windows only). In production this is always `Deno.build.os`. It is exposed as a public field — rather than read from `Deno.build.os` inline — so that tests can pin a specific platform without spawning a subprocess or touching the environment: ```ts const s = new MyToolSettings(); s.os_ = "windows"; // exercise the cmd /c retry branch on any host ``` The trailing underscore signals an internal test seam: do not rely on this field in production code. abstract protected defaultTool(): string The binary to spawn when {@link toolPath} is not set. abstract protected buildArgs(): string[] The subcommand argv. Must be pure — no I/O, no environment reads. protected defaultResolution(): ToolResolution The wrapper's default binary-resolution strategy. The base returns `"path"` (bare name on `PATH`); a JS-ecosystem wrapper whose binary is almost always installed under `node_modules` overrides this to `"node_modules"`. A per-call {@link fromNodeModules}/{@link fromPath} and the ambient `ZUKE_TOOL_RESOLUTION` both take precedence over this default. env(record: Record): this Merge additional environment variables for the process. cwd(path: PathLike): this Set the working directory for the process. noThrow(): this Do not throw on a non-zero exit; inspect `code` on the output instead. get throwsOnError(): boolean Whether a failure should throw — the default, or `false` after {@link noThrow}. A task that layers its own validation on top of the subprocess (e.g. a coverage-threshold gate) reads this to decide whether a gate failure throws or is merely reported. quiet(): this Suppress live stdout/stderr streaming to the terminal. killAfter(ms: number): this Kill the tool if it runs longer than `ms` milliseconds, raising a `CommandTimeoutError`. Fires even under {@link noThrow}. maxCapturedBytes(bytes: number): this Cap how much of each captured stream the run keeps in memory, in bytes (default 8 MiB). Once the cap is reached the oldest bytes are dropped, `CommandOutput.truncated` is set, and `CommandOutput.text` prefixes a notice. Raise it for a tool whose whole output must be parsed — a coverage report, a `--json` dump — and lower it to bound a chatty one. Live streaming to the terminal is never capped. @throws {RangeError} If `bytes` is not a positive whole number. toolPath(path: PathLike): this Override the binary to run (e.g. an absolute path to the tool). fromNodeModules(): this Resolve the binary npx-style: walk up from the working directory looking for `node_modules/.bin/`, falling back to `PATH` on a miss. Overrides both the wrapper default and the ambient `ZUKE_TOOL_RESOLUTION`. Has no effect once {@link toolPath} is set (an explicit path always wins). fromPath(): this Resolve the binary from `PATH` only, ignoring any `node_modules/.bin`. args(...extra: Array): this Escape hatch: append raw arguments after all typed options. argv(): string[] The full argv (binary first). Pure — useful for tests and diagnostics. resolvedArgv(): string[] The argv {@link run} will actually spawn — like {@link argv}, but with the `node_modules/.bin` resolution applied (so it performs I/O). Useful for tests and diagnostics: it reveals whether a wrapper resolved to a local shim or fell back to the bare name on `PATH`. async run(): Promise Run the configured tool. If the binary is missing and the platform is Windows, retry once through `cmd /c` (covers `.cmd`/`.bat` shims); otherwise raise a {@link ToolNotFoundError} naming the tool. interface DefineToolOptions Options for {@link defineTool}. subcommand?: string | string[] Leading subcommand token(s) prepended to every invocation. type Configure = (settings: S) => S A lambda that configures a settings instance and returns it. type ToolResolution = "node_modules" | "path" How {@link ToolSettings.run} locates a wrapper's binary when no explicit {@link ToolSettings.toolPath} is set: - `"path"` — spawn the bare tool name and let the OS resolve it on `PATH` (the default, matching a native/global install); - `"node_modules"` — npx-style: walk up from the working directory looking for `node_modules/.bin/`, falling back to `PATH` on a miss (so a package hoisted to a monorepo root runs with no `.toolPath()`). type ToolTask = (configure?: Configure) => Promise A ready-to-run task for a {@link defineTool} tool. A conformance kit for tool-wrapper tests. Every `@zuke/*` wrapper package owes its unit test the same three checks: the settings class spawns the binary it claims to, it resolves that binary the way the wrapper intends (bare on `PATH`, or npx-style from `node_modules/.bin`), and a missing binary surfaces as a {@link "./tooling.ts".ToolNotFoundError} rather than some raw `Deno.errors.NotFound`. Hand-written per package, that is a temp-directory / `ZUKE_TOOL_RESOLUTION` save-and-restore dance copied dozens of times — and a wrapper that quietly forgets the resolution check keeps passing. {@link assertWrapperConformance} runs all three, hermetically (nothing real is ever spawned), and takes the expected resolution mode as a required argument so each wrapper asserts its default instead of remembering it: ```ts Deno.test("biome conforms", async () => { await assertWrapperConformance(() => new BiomeCheckSettings(), "biome", { resolution: "node_modules", }); }); ``` @module async function assertWrapperConformance(makeSettings: () => ToolSettings, tool: string, options: WrapperConformanceOptions): Promise Assert that a tool wrapper conforms: `makeSettings()` spawns `tool`, resolves it per `options.resolution`, and reports a missing binary as a {@link "./tooling.ts".ToolNotFoundError}. `makeSettings` is called once per check, so each check gets a pristine instance. The resolution check runs against a throwaway temp directory holding a fake `node_modules/.bin/` shim, with `ZUKE_TOOL_RESOLUTION` unset for the duration and restored afterwards; no real subprocess is ever launched. A wrapper whose `run()` resolves something at run time must have that pinned inside `makeSettings` — `() => new DockerComposeUpSettings().usePlugin()`, say — or the missing-binary check would probe the ambient host. It reports a `ToolNotFoundError` raised for any binary other than the planted one as a failure, so such a wrapper cannot pass by accident on a host that lacks the real tool. @throws {Error} naming the wrapper and the fix, on the first failed check. function missingTool(settings: S): S Point `settings` at a binary that cannot exist, so running it raises a {@link "./tooling.ts".ToolNotFoundError} without ever launching a real process — the way a wrapper test proves each of its task functions reaches execution. The platform is pinned to `linux` because on Windows a missing binary is retried through `cmd /c`, which exists, so the failure would surface as a command error instead: ```ts await assertRejects(() => BiomeTasks.check(missingTool), ToolNotFoundError); ``` interface WrapperConformanceOptions Options for {@link assertWrapperConformance}. resolution: ToolResolution The resolution strategy the wrapper must use when nothing overrides it: `"node_modules"` for a JS-ecosystem tool installed under `node_modules`, `"path"` for a natively installed one. Required, with no default: an npm-distributed wrapper that forgot to override `defaultResolution()` is exactly the bug this kit exists to catch, and a default would let that wrapper's test pass by saying nothing. Primitive terminal rendering, shared by the executor's build reporting (`./report.ts`) and the `@zuke/console` package: ANSI styling, terminal-width detection, duration formatting, and the reusable `line`/`box`/`table` primitives that draw a build's output. Everything here is pure — no I/O, no process state — so argv-free output can be unit-tested and reused without duplicating escape codes. Cells may already carry ANSI codes; width is measured on the visible text ({@link visibleWidth}) so painted content still aligns. @module function box(style: Style, content: string | readonly string[], options: BoxOptions): string[] A bordered panel around `content` (a string, split on newlines, or an array of lines). Content may carry ANSI codes; padding is measured on the visible text so the border stays flush. function detectWidth(): number Read the terminal width if available, clamped to a sane range. function formatDuration(ms: number): string Format a duration in milliseconds as `1.2s`. function isStyleName(name: string): name is StyleName Whether a string names one of the {@link SGR} styles. function line(style: Style, options: LineOptions): string A horizontal rule spanning the style's width (dimmed by default). function pad(text: string, width: number, align: "left" | "right"): string Pad `text` to `width` visible columns, aligning left (default) or right. function paint(color: boolean, codes: string, text: string): string Wrap text in ANSI codes when colour is enabled, otherwise return it as-is. function sgrCodes(names: readonly StyleName[]): string Concatenate the escape codes for `names` (an unknown name contributes none). function stripAnsi(text: string): string Strip ANSI escape sequences, leaving the visible text. function stylize(color: boolean, names: readonly StyleName[], text: string): string Paint `text` in the named styles when `color` is enabled. function table(style: Style, columns: readonly TableColumn[], rows: readonly (readonly string[])[], options: TableOptions): string[] An aligned text table: a styled header row, an optional dividing rule, then one line per row. Column widths fit the widest visible cell; cells may already carry ANSI colour. Rows shorter than the columns are padded with empty cells. function visibleWidth(text: string): number The printable width of `text`, ignoring any ANSI colour codes it carries. const SGR: { reset: string; bold: string; dim: string; italic: string; underline: string; black: string; red: string; green: string; yellow: string; blue: string; magenta: string; cyan: string; white: string; gray: string; } ANSI select-graphic-rendition codes, keyed by style name. interface BoxOptions Options for {@link box}. title?: string A title embedded in the top border. padding?: number Horizontal padding inside the border, in spaces. Defaults to `1`. width?: number Force an inner width; widened automatically to fit content and title. border?: readonly StyleName[] Styles for the border characters. Defaults to `["dim"]`. titleStyle?: readonly StyleName[] Styles for the title text. Defaults to `["bold"]`. interface LineOptions Options for {@link line}. char?: string The character to repeat. Defaults to `═`. width?: number The rule width. Defaults to the style's width. style?: readonly StyleName[] Styles applied to the whole rule. Defaults to `["dim"]`. interface Style How a run renders its output. github: boolean Wrap target output in `::group::`/`::endgroup::` and emit `::error::`. color: boolean Emit ANSI colour codes (off when piped, under `NO_COLOR`, or in CI). width: number Width of horizontal rules and boxes, in characters. interface TableColumn One column of a {@link table}. header: string The column header. align?: "left" | "right" Cell alignment. Defaults to `left`. interface TableOptions Options for {@link table}. separator?: string Column separator. Defaults to two spaces. divider?: boolean Draw a dividing rule under the header. Defaults to `true`. headerStyle?: readonly StyleName[] Styles for the header row. Defaults to `["bold"]`. dividerStyle?: readonly StyleName[] Styles for the divider rule. Defaults to `["dim"]`. type StyleName = keyof typeof SGR A style name understood by {@link sgrCodes}, {@link paint}, and markup. A backend conformance kit for the state-api (`docs/state-api.md`). A hosted {@link "./state/store.ts".StateStore} / {@link "./registry/registry.ts".BuildRegistry} backend must implement the same compare-and-swap, listing, and TTL-lock semantics the filesystem backend does — the exactly-once resume, lock takeover, and one-writer-wins guarantees the core relies on ride on them. This module extracts those semantics into store-agnostic scenarios you can point at any implementation: Zuke's own test lane runs them against the filesystem store, and a backend author runs them against a live service: ```sh deno run -A jsr:@zuke/core/conformance --url http://localhost:8080 [--token …] ``` Every scenario uses freshly-generated ids, so it is safe to run against a shared, persistent service; the lock-takeover scenario uses a short real TTL and a brief sleep, so it takes a beat of wall-clock time. A backend that passes is compatible with {@link "./state/http_store.ts".HttpStateStore} / {@link "./registry/http_registry.ts".HttpBuildRegistry}; one that violates CAS fails loudly. @module async function checkBuildRegistry(make: BuildRegistryFactory): Promise Run the build-registry conformance scenarios against the registry `make` builds. async function checkStateStore(make: StateStoreFactory, options: ConformanceOptions): Promise Run the state-store conformance scenarios against the store `make` builds. async function runConformanceCli(args: string[], deps: ConformanceCliDeps): Promise Run the conformance kit as a CLI: `--url ` (required) and `--token ` (optional) name the backend, then both suites run against it. Prints a `PASS`/`FAIL` line per scenario and resolves to a process exit code — `0` when every scenario passes, `1` when any fails or `--url` is missing. interface ConformanceCliDeps Injectable dependencies for {@link runConformanceCli} (tests override them). makeStateStore?: (url: string, token?: string) => StateStore Build the {@link StateStore} for a url/token (default {@link HttpStateStore}). makeBuildRegistry?: (url: string, token?: string) => BuildRegistry Build the {@link BuildRegistry} for a url/token (default {@link HttpBuildRegistry}). log?: (line: string) => void Emit a line of output (default `console.log`). interface ConformanceOptions Tuning options for the conformance scenarios. lockTtlMs?: number The lock TTL (ms) the takeover scenario acquires with; it then waits a bit longer than this for the lock to expire. Raise it for a slow backend. Default 200. interface ConformanceResult The outcome of one conformance scenario. readonly name: string The scenario's name. readonly ok: boolean Whether the backend satisfied it. readonly error?: string The failure detail when `ok` is false. type BuildRegistryFactory = () => BuildRegistry | Promise A `() =>` factory the kit calls once to obtain the registry under test. type StateStoreFactory = () => StateStore | Promise A `() =>` factory the kit calls once to obtain the store under test. ======================================================================== # @zuke/deno ======================================================================== `@zuke/deno` — typed `DenoTasks` wrappers for the `deno` CLI, for use in Zuke build targets. ```ts import { DenoTasks } from "jsr:@zuke/deno"; await DenoTasks.check((s) => s.paths("mod.ts")); await DenoTasks.test((s) => s.allowAll().coverage("cov_profile")); await DenoTasks.fmt((s) => s.check()); ``` @module const DenoTasks: DenoTasksApi Typed task functions for the `deno` CLI. class CoverageThresholdError extends Error Raised when measured coverage falls below a configured threshold. constructor(readonly failures: string[]) Construct the error from one message per metric that fell short. override name: string The error name, `"CoverageThresholdError"`. class DenoCacheSettings extends DenoSettings Settings for `deno cache`. reload(): this Reload remote modules instead of using the cache (`--reload`). frozen(): this Error out if the lockfile is out of date (`--frozen`). See {@link DenoPermissionSettings.frozen} for why the name mirrors the real Deno flag rather than `PnpmSettings.frozenLockfile()`'s naming. paths(...paths: PathLike[]): this The entry points to cache (at least one is required). override protected buildArgs(): string[] Assemble the `deno cache` argv. class DenoCheckSettings extends DenoSettings Settings for `deno check`. paths(...paths: PathLike[]): this The files to type-check (at least one is required). config(path: PathLike): this Type-check against a specific configuration file (`--config`) instead of the one Deno would discover by walking up from the checked files. The discovered config decides how bare specifiers resolve, so pointing at another one type-checks the same sources against a different dependency set — for example checking a workspace member against the published version of a sibling it declares, rather than the local member that workspace resolution would substitute. noLock(): this Ignore the lockfile entirely (`--no-lock`), neither reading nor writing it. Use it for a check whose resolutions are deliberately not the project's: writing them into the committed lock would corrupt it, and reading it would pin the very versions the check is trying to vary. frozen(): this Error out if the lockfile is out of date (`--frozen`). See {@link DenoPermissionSettings.frozen} for why the name mirrors the real Deno flag rather than `PnpmSettings.frozenLockfile()`'s naming. override protected buildArgs(): string[] Assemble the `deno check` argv. class DenoCoverageSettings extends DenoSettings Settings for `deno coverage`. dir(path: PathLike): this The coverage profile directory to report on. lcov(): this Emit lcov instead of the table report (`--lcov`). output(path: PathLike): this Write the report to a file (`--output=`). exclude(pattern: string): this Exclude files matching the pattern (`--exclude=`). linesThreshold(percent: number): this Fail the gate if line coverage is below `percent`. `deno coverage` has no fail-under flag, so {@link DenoTasks.coverage} enforces this after parsing the lcov report (and forces `--lcov` so a report exists to parse). branchesThreshold(percent: number): this Fail the gate if branch coverage is below `percent` (see {@link linesThreshold}). threshold(percent: number): this Fail the gate if either line or branch coverage is below `percent`. perFileThreshold(percent: number): this Fail the gate if any single instrumented file's line coverage is below `percent` — a per-file floor, so an under-tested file can't hide inside a healthy aggregate (see {@link CoverageThresholds.perFile}, which notes the `deno coverage` limit for files no test loads). get thresholds(): CoverageThresholds The configured thresholds; read by {@link DenoTasks.coverage}. get outputPath(): string | undefined The `--output` file path, if {@link output} was set; read by the task. override protected buildArgs(): string[] Assemble the `deno coverage` argv. class DenoDocSettings extends DenoSettings Settings for `deno doc`. paths(...paths: PathLike[]): this The source files (entry points) to document. json(): this Output the documentation as JSON (`--json`). frozen(): this Error out if the lockfile is out of date (`--frozen`). See {@link DenoPermissionSettings.frozen} for why the name mirrors the real Deno flag rather than `PnpmSettings.frozenLockfile()`'s naming. html(): this Generate static HTML documentation (`--html`). name(title: string): this Title for the generated HTML documentation (`--name`). output(dir: PathLike): this Output directory for HTML documentation (`--output`). private(): this Include private and internal symbols (`--private`). filter(symbol: string): this Document only the symbol at this dot-separated path (`--filter`). lint(): this Report documentation diagnostics rather than rendering docs (`--lint`). override protected buildArgs(): string[] Assemble the `deno doc` argv. class DenoFmtSettings extends DenoSettings Settings for `deno fmt`. check(): this Verify formatting without writing changes (`--check`). paths(...paths: PathLike[]): this Restrict formatting to specific files or directories. override protected buildArgs(): string[] Assemble the `deno fmt` argv. class DenoInstallSettings extends DenoPermissionSettings Settings for `deno install`. global(): this Install a global executable (`--global`/`-g`) instead of project deps. force(): this Overwrite an existing installation (`--force`/`-f`). root(path: PathLike): this Install root; the binary lands in `/bin` (`--root`). name(value: string): this Name the installed executable (`--name`/`-n`). module(spec: string): this The module to install, e.g. `npm:cspell@9` (required for a global install). moduleArgs(...args: Array): this Arguments baked into the generated launcher (after the module). override protected buildArgs(): string[] Assemble the `deno install` argv. class DenoLintSettings extends DenoSettings Settings for `deno lint`. fix(): this Apply automatic fixes (`--fix`). paths(...paths: PathLike[]): this Restrict linting to specific files or directories. override protected buildArgs(): string[] Assemble the `deno lint` argv. abstract class DenoPermissionSettings extends DenoSettings Base for subcommands that accept `--allow-*` permission flags. allowAll(): this Grant all permissions (`--allow-all`). allow(permission: DenoPermission, ...values: string[]): this Grant one permission, optionally scoped to values (`--allow-read=a,b`). frozen(): this Error out if the lockfile is out of date instead of silently updating it (`--frozen`). Use it whenever the module graph must match the committed `deno.lock` exactly — running an `npm:` tool in CI, say, so its transitive tree stays pinned to the audited integrity hashes rather than being resolved afresh. Named `frozen` — not `frozenLockfile` — to mirror the real Deno CLI flag exactly. This is a deliberate divergence from `PnpmSettings.frozenLockfile()` in `@zuke/pnpm`, which follows pnpm's own flag name instead: guideline 7 (mirror the real CLI) takes priority over cross-package naming symmetry. protected get permissionArgs(): string[] The accumulated permission flags, in declaration order. protected get frozenArgs(): string[] The `--frozen` flag, if set; read by subclasses assembling their argv. class DenoPublishSettings extends DenoSettings Settings for `deno publish`. allowDirty(): this Publish even with an uncommitted working tree (`--allow-dirty`). allowSlowTypes(): this Permit slow types in the published package (`--allow-slow-types`). noCheck(): this Skip type-checking before publishing (`--no-check`). dryRun(): this Validate without publishing (`--dry-run`). config(path: PathLike): this Use an explicit config file (`--config`). token(value: string): this Authenticate with a token instead of interactive/OIDC auth (`--token`). override protected buildArgs(): string[] Assemble the `deno publish` argv. class DenoRunSettings extends DenoPermissionSettings Settings for `deno run`. script(path: PathLike): this The script to run (required). scriptArgs(...args: Array): this Arguments passed to the script (after the script path). config(path: PathLike): this Use an explicit config file (`--config`). reload(): this Reload the module cache (`--reload`). override protected buildArgs(): string[] Assemble the `deno run` argv. abstract class DenoSettings extends ToolSettings Base for all `deno` subcommand settings: binary is the running deno. override protected defaultTool(): string Default the tool binary to the running `deno` executable. class DenoTaskSettings extends DenoSettings Settings for `deno task`. name(value: string): this The task name from deno.json (required). taskArgs(...args: Array): this Arguments forwarded to the task. frozen(): this Error out if the lockfile is out of date (`--frozen`). See {@link DenoPermissionSettings.frozen} for why the name mirrors the real Deno flag rather than `PnpmSettings.frozenLockfile()`'s naming. override protected buildArgs(): string[] Assemble the `deno task` argv. class DenoTestSettings extends DenoPermissionSettings Settings for `deno test`. paths(...paths: PathLike[]): this Restrict the run to specific test files or directories. coverage(dir: PathLike): this Collect coverage into the given profile directory (`--coverage=`). filter(pattern: string): this Only run tests whose name matches (`--filter`). parallel(): this Run test files in parallel (`--parallel`). failFast(): this Stop on the first failure (`--fail-fast`). override protected buildArgs(): string[] Assemble the `deno test` argv. interface CoverageThresholds Line and branch percentage floors; an omitted metric is not enforced. lines?: number Minimum line-coverage percentage (0–100). branches?: number Minimum branch-coverage percentage (0–100). perFile?: number Minimum per-file line-coverage percentage (0–100). Unlike {@link lines} (an aggregate over the whole report), this fails the gate when any single instrumented file falls below the floor — so an under-tested file can't hide inside a healthy repo-wide average. Files with no measurable lines are skipped. Note the coverage tool's limit: `deno coverage` only reports files that were loaded, so a source file no test imports at all is invisible to this check (as it is to every coverage metric). interface DenoTasksApi The shape of {@link DenoTasks}. run(configure?: Configure): Promise Run a script: `deno run`. test(configure?: Configure): Promise Run tests: `deno test`. check(configure?: Configure): Promise Type-check files: `deno check`. fmt(configure?: Configure): Promise Format files: `deno fmt`. lint(configure?: Configure): Promise Lint files: `deno lint`. doc(configure?: Configure): Promise Generate documentation: `deno doc`. cache(configure?: Configure): Promise Warm the module cache: `deno cache`. coverage(configure?: Configure): Promise Report coverage: `deno coverage`. install(configure?: Configure): Promise Install a script or executable: `deno install`. publish(configure?: Configure): Promise Publish a package to JSR: `deno publish`. task(configure?: Configure): Promise Run a deno.json task: `deno task`. type DenoPermission = "read" | "write" | "net" | "env" | "run" | "sys" | "ffi" | "import" A Deno permission domain, as used by `--allow-*` flags. ======================================================================== # @zuke/docs ======================================================================== `@zuke/docs` — typed tasks that turn already-generated API documentation into agent-friendly artifacts, so neither humans nor agents have to guess an API. You supply each package's documentation text (for a Deno workspace, the output of `deno doc`); this package renders it into three things: - an `llms.txt` index (the llmstxt.org convention), - a complete `llms-full.txt` reference (the whole surface in one file), - a generated `## API` block in every package README. It runs no subprocess and depends only on `@zuke/core`, so it works without `deno` on `PATH` and without the `@zuke/deno` package — pair it with whatever produces your doc text (`@zuke/deno`'s `DenoTasks.doc`, a checked-in file, …). ```ts import { DocsTasks } from "jsr:@zuke/docs"; const docs = [{ name: "@acme/core", dir: "core", doc: denoDocText }]; await DocsTasks.apiDocs(docs, { project: { title: "Acme", summary: "…" } }); // In the CI gate: const stale = await DocsTasks.checkApiDocs(docs); if (stale.length > 0) throw new Error(`Stale docs: ${stale.join(", ")}`); ``` @module const DocsTasks: DocsTasksApi Typed tasks for generating and verifying API documentation. interface ApiDocsOptions Options accepted by {@link DocsTasks.apiDocs} and {@link DocsTasks.checkApiDocs}. packagesDir?: string Directory holding the package subdirectories. Default `"packages"`. jsrBaseUrl?: string Base URL for package documentation links. Default `"https://jsr.io"`. index?: string Output path for the short index. Default `"llms.txt"`. full?: string Output path for the full reference. Default `"llms-full.txt"`. readmes?: boolean Inject a generated `## API` block into each package README. Default `true`. project?: ProjectInfo Project framing for the index. Falls back to a generic blurb. regenerateCommand?: string Command shown in "regenerate with …" notes. Default `"deno task docs"`. interface DocLintReport One package's `deno doc --lint` output plus the type names it imports from other `@zuke/*` packages, fed into {@link DocsTasksApi.checkDocLint}. The caller runs the linter and scans the package's imports, so `@zuke/docs` never runs `deno`. pkg: string The package identifier, surfaced in violations (e.g. `@zuke/kubectl`). output: string The raw `deno doc --lint` output for the package's entrypoints. crossPackageTypes: string[] The local names the package imports from another `@zuke/*` package. A `private-type-ref` to one of these is the accepted residual (guideline 4); a ref to any other type is a defect (the type is first-party and must be exported). interface DocLintViolation A documentation-lint defect, tied to the package it was found in. pkg: string The package the defect is in. kind: string The lint rule, e.g. `"missing-jsdoc"` or `"private-type-ref"`. message: string The diagnostic's headline message. interface DocsTasksApi The shape of {@link DocsTasks}. apiDocs(docs: PackageDoc[], options?: ApiDocsOptions): Promise From the supplied per-package docs, generate the index, the full reference, and (unless disabled) each package README's API block, writing only the files whose content changed. Returns the paths written. checkApiDocs(docs: PackageDoc[], options?: ApiDocsOptions): Promise Recompute every artifact and return the paths that are out of date on disk (empty when everything is current). Writes nothing. checkDocLint(reports: DocLintReport[]): DocLintViolation[] Classify `deno doc --lint` output across packages into real defects: every `missing-jsdoc`, plus every `private-type-ref` whose referenced type is not an accepted cross-package import (in the report's `crossPackageTypes`). Fails safe — any other referenced type is treated as a first-party leak. Pure: the caller runs the linter; this classifies. Empty when clean. interface PackageDoc One package's already-generated documentation, fed into the tasks. name: string The published name, e.g. `@zuke/deno`. dir: string The directory under `packagesDir` whose README receives the API block. doc: string The package's API documentation text — typically the output of `deno doc ` (machine-specific `Defined in …` lines are stripped for you). Produced by the caller, so this package never has to run `deno`. interface ProjectInfo Project framing rendered into the `llms.txt` index. title: string Heading for the index, e.g. `"Zuke"`. summary: string One-paragraph summary, rendered as the index's blockquote. example?: string An optional canonical code example, fenced under an "Example" heading. install?: string An optional install/scaffold command, shown in the "do not guess" list. guidance?: string[] Extra bullet lines appended to the "do not guess" list. cli?: string An optional pre-rendered markdown block describing the `zuke` command surface, rendered under a `## CLI` heading in the index. The caller builds it (e.g. from the build's command/flag registry) so this package stays agnostic about CLI specifics. ======================================================================== # @zuke/npm ======================================================================== `@zuke/npm` — typed `NpmTasks` wrappers for the `npm` CLI, for use in Zuke build targets (including builds that drive Node projects). ```ts import { NpmTasks } from "jsr:@zuke/npm"; await NpmTasks.ci(); await NpmTasks.run((s) => s.script("build")); ``` @module const NpmTasks: NpmTasksApi Typed task functions for the `npm` CLI. class NpmCiSettings extends NpmSettings Settings for `npm ci`. omit(type: NpmOmitType): this Skip a dependency group (`--omit=dev` etc.); repeatable. override protected buildArgs(): string[] Assemble the `npm ci` argv. class NpmExecSettings extends NpmSettings Settings for `npm exec`. command(name: string): this The command to execute (required). package(spec: string): this The package providing the command (`--package=`). yes(): this Skip the install prompt (`--yes`). execArgs(...args: Array): this Arguments forwarded to the command (after `--`). override protected buildArgs(): string[] Assemble the `npm exec` argv. class NpmInstallSettings extends NpmSettings Settings for `npm install`. packages(...specs: string[]): this Package specs to install; omit to install from package.json. saveDev(): this Save to devDependencies (`--save-dev`). saveExact(): this Pin exact versions (`--save-exact`). override protected buildArgs(): string[] Assemble the `npm install` argv. class NpmPublishSettings extends NpmSettings Settings for `npm publish`. tag(name: string): this Publish under a dist-tag (`--tag=`). access(level: NpmAccess): this Set the package access level (`--access=`). dryRun(): this Report what would be published without uploading (`--dry-run`). otp(code: string): this Provide a one-time password (`--otp=`). override protected buildArgs(): string[] Assemble the `npm publish` argv. class NpmRunSettings extends NpmSettings Settings for `npm run`. script(name: string): this The package.json script to run (required). workspace(name: string): this Run in a specific workspace (`--workspace=`). workspaces(): this Run the script in every workspace (`--workspaces`). Pair with {@link ifPresent} to skip workspaces that lack the script. Mutually exclusive with {@link workspace} — setting both is a build error. ifPresent(): this Do not fail when the script is missing (`--if-present`). scriptArgs(...args: Array): this Arguments forwarded to the script (after `--`). override protected buildArgs(): string[] Assemble the `npm run` argv. abstract class NpmSettings extends ToolSettings Base for all `npm` subcommand settings: binary is `npm` from PATH. override protected defaultTool(): string The default binary: `npm` resolved from PATH. class NpmVersionSettings extends NpmSettings Settings for `npm version`. bump(value: string): this The bump: `patch` | `minor` | `major` or an explicit semver (required). message(text: string): this Commit message; `%s` expands to the new version (`--message`). noGitTagVersion(): this Do not create a git commit and tag (`--no-git-tag-version`). override protected buildArgs(): string[] Assemble the `npm version` argv. interface NpmTasksApi The shape of {@link NpmTasks}. install(configure?: Configure): Promise Install dependencies: `npm install`. ci(configure?: Configure): Promise Clean install from the lockfile: `npm ci`. run(configure?: Configure): Promise Run a package.json script: `npm run`. exec(configure?: Configure): Promise Execute a package binary: `npm exec`. publish(configure?: Configure): Promise Publish the package: `npm publish`. version(configure?: Configure): Promise Bump the package version: `npm version`. type NpmAccess = "public" | "restricted" An access level accepted by npm's `--access` flag. type NpmOmitType = "dev" | "optional" | "peer" A dependency group accepted by npm's `--omit` flag. ======================================================================== # @zuke/npx ======================================================================== `@zuke/npx` — typed `NpxTasks` wrappers for the `npx` package runner, for use in Zuke build targets (including builds that drive Node projects). ```ts import { NpxTasks } from "jsr:@zuke/npx"; await NpxTasks.npx((s) => s.command("cowsay").yes().execArgs("hello")); ``` @module const NpxTasks: NpxTasksApi Typed task functions for the `npx` package runner. class NpxSettings extends ToolSettings Settings for the `npx` package runner. override protected defaultTool(): string The executable this settings object drives: `npx`. command(name: string): this The package binary to execute (required unless {@link call} is set). package(...specs: string[]): this Packages to load before running (`--package=`); repeatable. call(script: string): this Execute a string as if inside `npm run-script` (`--call`). yes(): this Auto-install a missing package without prompting (`--yes`). no(): this Never auto-install; fail if the package is missing (`--no`). ignoreExisting(): this Ignore binaries already present in `$PATH` (`--ignore-existing`). execArgs(...args: Array): this Arguments forwarded to the command. override protected buildArgs(): string[] Assemble the `npx ` argv from the configured settings. interface NpxTasksApi The shape of {@link NpxTasks}. npx(configure?: Configure): Promise Download and execute a package binary: `npx `. ======================================================================== # @zuke/bun ======================================================================== `@zuke/bun` — typed `BunTasks` wrappers for the `bun` CLI, for use in Zuke build targets (package management, scripts, and the built-in test runner). ```ts import { BunTasks } from "jsr:@zuke/bun"; await BunTasks.install((s) => s.frozenLockfile()); await BunTasks.run((s) => s.script("build")); ``` @module const BunTasks: BunTasksApi Typed task functions for the `bun` CLI. class BunAddSettings extends BunSettings Settings for `bun add`. packages(...specs: string[]): this Package specs to add (required). dev(): this Add to devDependencies (`--dev`). optional(): this Add to optionalDependencies (`--optional`). exact(): this Pin the exact version (`--exact`). global(): this Install globally (`--global`). override protected buildArgs(): string[] Assemble the `bun add` argv. class BunInstallSettings extends BunSettings Settings for `bun install`. production(): this Install without devDependencies (`--production`). frozenLockfile(): this Fail if the lockfile is out of date (`--frozen-lockfile`). override protected buildArgs(): string[] Assemble the `bun install` argv. class BunRemoveSettings extends BunSettings Settings for `bun remove`. packages(...names: string[]): this Package names to remove (required). override protected buildArgs(): string[] Assemble the `bun remove` argv. class BunRunSettings extends BunSettings Settings for `bun run`. script(name: string): this The package.json script to run (required). scriptArgs(...args: Array): this Arguments forwarded to the script. override protected buildArgs(): string[] Assemble the `bun run` argv. abstract class BunSettings extends ToolSettings Base for all `bun` subcommand settings: binary is `bun` from PATH. override protected defaultTool(): string The tool binary: `bun` on PATH. class BunTestSettings extends BunSettings Settings for `bun test`. paths(...patterns: string[]): this Test file or directory patterns to run; omit to run all tests. coverage(): this Collect coverage (`--coverage`). bail(): this Stop after the first failure (`--bail`). override protected buildArgs(): string[] Assemble the `bun test` argv. class BunXSettings extends BunSettings Settings for `bun x` (the `bunx` package runner). command(name: string): this The package binary to execute (required). execArgs(...args: Array): this Arguments forwarded to the command. override protected buildArgs(): string[] Assemble the `bun x` argv. interface BunTasksApi The shape of {@link BunTasks}. install(configure?: Configure): Promise Install dependencies: `bun install`. add(configure?: Configure): Promise Add dependencies: `bun add`. remove(configure?: Configure): Promise Remove dependencies: `bun remove`. run(configure?: Configure): Promise Run a package.json script: `bun run`. x(configure?: Configure): Promise Execute a package binary: `bun x` (bunx). test(configure?: Configure): Promise Run the test suite: `bun test`. ======================================================================== # @zuke/pnpm ======================================================================== `@zuke/pnpm` — typed `PnpmTasks` wrappers for the `pnpm` CLI, for use in Zuke build targets (including builds that drive Node/workspace projects). ```ts import { PnpmTasks } from "jsr:@zuke/pnpm"; await PnpmTasks.install((s) => s.frozenLockfile()); await PnpmTasks.run((s) => s.script("build").filter("app")); ``` @module const PnpmTasks: PnpmTasksApi Typed task functions for the `pnpm` CLI. class PnpmAddSettings extends PnpmSettings Settings for `pnpm add`. packages(...specs: string[]): this Package specs to add (required). saveDev(): this Save to devDependencies (`--save-dev`). saveExact(): this Pin the exact version (`--save-exact`). global(): this Install globally (`--global`). override protected buildArgs(): string[] Assemble the `pnpm add` argv. class PnpmDlxSettings extends PnpmSettings Settings for `pnpm dlx`. command(name: string): this The command to execute (required). package(spec: string): this The package providing the command (`--package=`). execArgs(...args: Array): this Arguments forwarded to the command. override protected buildArgs(): string[] Assemble the `pnpm dlx` argv. class PnpmInstallSettings extends PnpmSettings Settings for `pnpm install`. frozenLockfile(): this Fail if the lockfile is out of date (`--frozen-lockfile`). prod(): this Install without devDependencies (`--prod`). override protected buildArgs(): string[] Assemble the `pnpm install` argv. class PnpmPublishSettings extends PnpmSettings Settings for `pnpm publish`. tag(name: string): this Publish under a dist-tag (`--tag=`). access(level: PnpmAccess): this Set the package access level (`--access=`). noGitChecks(): this Skip the clean-working-tree checks (`--no-git-checks`). dryRun(): this Report what would be published without uploading (`--dry-run`). override protected buildArgs(): string[] Assemble the `pnpm publish` argv. class PnpmRemoveSettings extends PnpmSettings Settings for `pnpm remove`. packages(...names: string[]): this Package names to remove (required). override protected buildArgs(): string[] Assemble the `pnpm remove` argv. class PnpmRunSettings extends PnpmSettings Settings for `pnpm run`. script(name: string): this The package.json script to run (required). filter(pattern: string): this Restrict to matching workspace packages (`--filter`). ifPresent(): this Do not fail when the script is missing (`--if-present`). scriptArgs(...args: Array): this Arguments forwarded to the script. override protected buildArgs(): string[] Assemble the `pnpm run` argv. abstract class PnpmSettings extends ToolSettings Base for all `pnpm` subcommand settings: binary is `pnpm` from PATH. override protected defaultTool(): string The default binary: `pnpm` resolved from PATH. interface PnpmTasksApi The shape of {@link PnpmTasks}. install(configure?: Configure): Promise Install dependencies: `pnpm install`. add(configure?: Configure): Promise Add dependencies: `pnpm add`. remove(configure?: Configure): Promise Remove dependencies: `pnpm remove`. run(configure?: Configure): Promise Run a package.json script: `pnpm run`. dlx(configure?: Configure): Promise Download and execute a package binary: `pnpm dlx`. publish(configure?: Configure): Promise Publish the package: `pnpm publish`. type PnpmAccess = "public" | "restricted" An access level accepted by pnpm's `--access` flag. ======================================================================== # @zuke/yarn ======================================================================== `@zuke/yarn` — typed `YarnTasks` wrappers for the `yarn` CLI, for use in Zuke build targets (Yarn Classic v1 and Berry v2+; version-specific options are documented on each method). ```ts import { YarnTasks } from "jsr:@zuke/yarn"; await YarnTasks.install((s) => s.immutable()); await YarnTasks.run((s) => s.script("build")); ``` @module const YarnTasks: YarnTasksApi Typed task functions for the `yarn` CLI. class YarnAddSettings extends YarnSettings Settings for `yarn add`. packages(...specs: string[]): this Package specs to add (required). dev(): this Add to devDependencies (`--dev`). exact(): this Pin the exact version (`--exact`). override protected buildArgs(): string[] Assemble the `yarn add` argv. class YarnDlxSettings extends YarnSettings Settings for `yarn dlx` (Yarn Berry's one-off package runner). command(name: string): this The command to execute (required). package(spec: string): this An extra package to make available (`--package`). execArgs(...args: Array): this Arguments forwarded to the command. override protected buildArgs(): string[] Assemble the `yarn dlx` argv. class YarnInstallSettings extends YarnSettings Settings for `yarn install`. immutable(): this Fail if the lockfile would change — `--immutable` (Yarn Berry). frozenLockfile(): this Fail if the lockfile would change — `--frozen-lockfile` (Yarn Classic). override protected buildArgs(): string[] Assemble the `yarn install` argv. class YarnRemoveSettings extends YarnSettings Settings for `yarn remove`. packages(...names: string[]): this Package names to remove (required). override protected buildArgs(): string[] Assemble the `yarn remove` argv. class YarnRunSettings extends YarnSettings Settings for `yarn run`. script(name: string): this The package.json script to run (required). scriptArgs(...args: Array): this Arguments forwarded to the script. override protected buildArgs(): string[] Assemble the `yarn run` argv. abstract class YarnSettings extends ToolSettings Base for all `yarn` subcommand settings: binary is `yarn` from PATH. override protected defaultTool(): string The default binary: `yarn` resolved from PATH. interface YarnTasksApi The shape of {@link YarnTasks}. install(configure?: Configure): Promise Install dependencies: `yarn install`. add(configure?: Configure): Promise Add dependencies: `yarn add`. remove(configure?: Configure): Promise Remove dependencies: `yarn remove`. run(configure?: Configure): Promise Run a package.json script: `yarn run`. dlx(configure?: Configure): Promise Download and execute a package binary: `yarn dlx` (Berry). ======================================================================== # @zuke/cmd ======================================================================== `@zuke/cmd` — generic command execution for Zuke builds: the fallback for tools that have no dedicated wrapper package. Check the package catalogue in `llms.txt` before reaching for it. A tool with a `@zuke/` wrapper should be driven through that wrapper — running it here instead gives up typed flags and the wrapper's tool resolution, so the example below deliberately uses a tool Zuke does not wrap. ```ts import { CmdTasks } from "jsr:@zuke/cmd"; await CmdTasks.exec("shellcheck", (s) => s.args("--severity", "warning")); ``` @module const CmdTasks: CmdTasksApi Task functions for running arbitrary tools. class CmdSettings extends ToolSettings Settings for a generic command: the tool name plus raw arguments. constructor(tool: PathLike) Create settings for `tool`; the tool name is required. override protected defaultTool(): string The command to run — the tool name passed to the constructor. override protected buildArgs(): string[] No implicit arguments; the caller supplies them via `.args(...)`. interface CmdTasksApi The shape of {@link CmdTasks}. exec(tool: PathLike, configure?: Configure): Promise Run `tool` with the configured settings. ======================================================================== # @zuke/console ======================================================================== `@zuke/console` — task-shaped console output for Zuke builds, so a build never reaches for `console.log`. A levelled logger (NUKE-style), Spectre.Console-style markup and a semantic theme, and the primitives Zuke draws its own output with (`line`, `rule`, `box`, `table`, target `header`/`summary`). ```ts import { ConsoleTasks as Log } from "jsr:@zuke/console"; Log.rule("Deploy"); Log.info("pushing [bold]core@1.2.0[/]"); Log.success("published 4 packages"); ``` A build can also route the executor's own banners through this package: ```ts import { run } from "jsr:@zuke/core"; import { consoleRenderer } from "jsr:@zuke/console"; await run(MyBuild, { renderer: consoleRenderer }); ``` @module function createConsoleRenderer(theme: Theme): Renderer Build a {@link Renderer} that draws target headers with `theme`'s palette. const ConsoleTasks: ConsoleTasksApi Task-shaped console output. A single namespaced object (like `FileTasks`) rather than loose helpers: logging methods, structural primitives, and configuration all hang off `ConsoleTasks`. const consoleRenderer: Renderer The default console renderer, using {@link defaultTheme}. const defaultTheme: Theme The default palette — a conventional terminal colour scheme. interface ConsoleOptions Options accepted when reconfiguring {@link ConsoleTasks}. level?: LogLevel The minimum severity to print. sink?: Sink Where rendered lines go (default: stdout/stderr). theme?: Theme A custom colour palette. color?: boolean Force ANSI colour on or off (default: auto-detected). width?: number Force the rule/box width (default: the terminal width). github?: boolean Force GitHub Actions output formatting (default: auto-detected). interface ConsoleTasksApi The shape of {@link ConsoleTasks}. info(message: string): void Log an informational message (markup-aware). log(message: string): void Alias for {@link ConsoleTasksApi.info}. success(message: string): void Log a success/completion message. warn(message: string): void Log a warning (a `::warning::` annotation under GitHub Actions). error(message: string, options?: ErrorOptions): void Log an error, optionally appending a thrown value's message. debug(message: string): void Log a debug diagnostic (shown only at `debug`/`trace` level). trace(message: string): void Log the most verbose trace output (shown only at `trace` level). escape(text: string): string Escape `[`/`]` in `text` so it renders literally rather than as markup — for embedding arbitrary or untrusted strings in a message. line(options?: LineOptions): void Print a horizontal rule spanning the width. rule(title?: string, options?: RuleOptions): void Print a rule, optionally with a centred title. box(content: string | string[], options?: BoxOptions): void Print a bordered panel around `content` (markup-aware). table(columns: TableColumn[], rows: string[][], options?: TableOptions): void Print an aligned table; header and cell text may contain markup. header(name: string): void Print the ruled banner Zuke opens a target's section with. summary(reports: TargetReport[], totalMs: number, ok: boolean): void Print the end-of-build summary table and closing verdict. group(name: string): void Open a collapsible group; close it with {@link ConsoleTasksApi.endGroup}. endGroup(): void Close the group opened by {@link ConsoleTasksApi.group}. configure(options: ConsoleOptions): void Reconfigure logging (level, sink, theme, colour, width, Actions mode). level(): LogLevel The active minimum severity. reset(): void Reset all configuration to defaults (level re-seeded from the env). interface ErrorOptions Options for {@link ConsoleTasks.error}. error?: unknown An error whose message is appended as a dimmed detail line. interface RuleOptions extends LineOptions Options for {@link ConsoleTasks.rule}. interface Sink A destination for rendered lines. Overridable to capture output in tests. out(line: string): void Write a line to standard output. err(line: string): void Write a line to standard error. interface Theme The colour palette. Each semantic token maps to the ANSI styles applied to text (or markup) tagged with that name. info: StyleName[] Informational messages. success: StyleName[] Success/completion messages. warn: StyleName[] Warnings. error: StyleName[] Errors and failures. debug: StyleName[] Debug diagnostics. trace: StyleName[] The most verbose trace output. muted: StyleName[] De-emphasised, secondary text. type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "silent" A severity threshold. Messages below the active level are suppressed. ======================================================================== # @zuke/cli ======================================================================== `@zuke/cli` — the `zuke` command. Install it globally with ```sh deno install -A -g -n zuke jsr:@zuke/cli ``` and scaffold Zuke into any project with `zuke setup`. @module async function main(args: string[], host: SetupHost, prompter: Prompter, docRunner: DocRunner): Promise The CLI entry point. Returns a process exit code; `host`/`prompter`/`docRunner` are injectable for testing. function parseImportFlags(args: string[]): ImportFlags Parse the argument list following `zuke import`. function parseSetupFlags(args: string[]): SetupFlags Parse the argument list following `zuke setup`. function resolveDocSpec(pkg: string | undefined): string | undefined Resolve a `zuke doc` argument to a `deno doc` specifier: a bare package name (`core`) becomes `jsr:@zuke/core`, a scoped name (`@scope/pkg`) becomes `jsr:@scope/pkg`, and an explicit `jsr:`/`npm:`/`https:`/`file:`/path specifier is passed through unchanged. Returns `undefined` for no argument. const defaultPrompter: Prompter The real {@link Prompter}, backed by Deno's `prompt`/`confirm`. interface ImportFlags extends SetupFlags Flags accepted by `zuke import` — the setup flags plus `--from`. from?: ImportSource Force a source (`package.json` or `makefile`); auto-detected when unset. interface Prompter The interactive surface, injectable so the wizard is testable without a TTY. interactive(): boolean Whether prompts should be shown (i.e. stdin is a terminal). ask(question: string, fallback: string): string Ask a free-text question, returning `fallback` if unanswered. confirm(question: string): boolean Ask a yes/no question. interface SetupFlags Flags accepted by `zuke setup`. force: boolean Overwrite existing files. yes: boolean Skip prompts and accept defaults. name?: string Build class name for the starter `zuke.ts`. dir?: string Directory to scaffold into (defaults to the current directory). launcherName?: string Base name for the launcher scripts, when `zuke` is taken by a directory. interface SetupHost Injected side effects, so {@link runSetup} is unit-testable. exists(path: string): Promise Whether a path exists. isDirectory(path: string): Promise Whether a path exists and is a directory (a reserved-name collision). readText(path: string): Promise Read a file as UTF-8 text. writeText(path: string, content: string): Promise Write UTF-8 text to a file, creating or truncating it. chmod(path: string, mode: number): Promise Set a file's permission bits (may be unsupported on some platforms). log(message: string): void Emit a line of progress output. type DocRunner = (denoArgs: string[]) => Promise Runs `deno doc ` — the injectable subprocess seam for {@link commandDoc}, so the command is testable without spawning `deno`. type ImportSource = "package.json" | "Makefile" The kinds of project `zuke import` can read. ======================================================================== # @zuke/docker ======================================================================== `@zuke/docker` — typed `docker` CLI task wrappers for Zuke builds. ```ts import { DockerTasks } from "jsr:@zuke/docker"; await DockerTasks.build((s) => s.tag("app:1.0").file("Dockerfile")); await DockerTasks.push((s) => s.image("app:1.0")); ``` @module const DockerTasks: DockerTasksApi Typed task functions for the `docker` CLI. class DockerBuildSettings extends DockerSettings Settings for `docker build`. tag(reference: string): this Add an image tag (`-t`); repeatable. file(path: PathLike): this Use an explicit Dockerfile (`-f`). target(stage: string): this Build a specific stage (`--target`). platform(value: string): this Set the target platform(s) (`--platform`). buildArg(key: string, value: string): this Pass a build-time variable (`--build-arg KEY=value`); repeatable. noCache(): this Do not use the layer cache (`--no-cache`). pull(): this Always attempt to pull newer base images (`--pull`). push(): this Push the result to the registry after building (`--push`). context(path: PathLike): this The build context path or URL (default `.`). override protected buildArgs(): string[] Assemble the `docker build` argv. class DockerExecSettings extends DockerSettings Settings for `docker exec`. container(name: string): this The target container (required). interactive(): this Keep STDIN open (`-i`). tty(): this Allocate a pseudo-TTY (`-t`). envVar(key: string, value: string): this Set an environment variable for the command (`-e KEY=value`). workdir(path: PathLike): this Working directory inside the container (`-w`). commandArgs(...args: Array): this The command and arguments to execute. override protected buildArgs(): string[] Assemble the `docker exec` argv. class DockerImagesSettings extends DockerSettings Settings for `docker images`. all(): this Show all images, including intermediate layers (`-a`). quietOutput(): this Only show image IDs (`-q`). filter(expression: string): this Filter the listing (`--filter`); repeatable. repository(name: string): this Restrict to a repository (positional argument). override protected buildArgs(): string[] Assemble the `docker images` argv. class DockerLoadSettings extends DockerSettings Settings for `docker load`. input(path: PathLike): this Read from a tar archive instead of STDIN (`-i`). quietOutput(): this Suppress the load output (`-q`). override protected buildArgs(): string[] Assemble the `docker load` argv. class DockerLoginSettings extends DockerSettings Settings for `docker login`. username(value: string): this The username (`-u`). password(value: string): this The password (`-p`). This lands directly in the process argv, where it can leak through `ps`/process listings, shell history, or CI job logs — {@link passwordStdin} is the safe choice in CI (and generally), since it pipes the secret through STDIN instead of putting it on the command line. passwordStdin(): this Read the password from STDIN (`--password-stdin`). registry(server: string): this The registry server (defaults to Docker Hub). override protected buildArgs(): string[] Assemble the `docker login` argv. class DockerPsSettings extends DockerSettings Settings for `docker ps`. all(): this Show stopped containers too (`-a`). quietOutput(): this Only show container IDs (`-q`). filter(expression: string): this Filter the listing (`--filter`); repeatable. override protected buildArgs(): string[] Assemble the `docker ps` argv. class DockerPullSettings extends DockerSettings Settings for `docker pull`. image(reference: string): this The image reference to pull (required). platform(value: string): this Pull a specific platform (`--platform`). quietOutput(): this Suppress verbose output (`-q`). override protected buildArgs(): string[] Assemble the `docker pull` argv. class DockerPushSettings extends DockerSettings Settings for `docker push`. image(reference: string): this The image reference to push (required). allTags(): this Push every tag of the repository (`--all-tags`). override protected buildArgs(): string[] Assemble the `docker push` argv. class DockerRmSettings extends DockerSettings Settings for `docker rm`. containers(...names: string[]): this The containers to remove (at least one is required). force(): this Force removal of a running container (`-f`). volumes(): this Also remove anonymous volumes (`-v`). override protected buildArgs(): string[] Assemble the `docker rm` argv. class DockerRmiSettings extends DockerSettings Settings for `docker rmi`. images(...references: string[]): this The images to remove (at least one is required). force(): this Force removal (`-f`). override protected buildArgs(): string[] Assemble the `docker rmi` argv. class DockerRunSettings extends DockerSettings Settings for `docker run`. image(reference: string): this The image to run (required). name(value: string): this Assign a container name (`--name`). rm(): this Remove the container when it exits (`--rm`). detach(): this Run the container in the background (`-d`). interactive(): this Keep STDIN open (`-i`). tty(): this Allocate a pseudo-TTY (`-t`). envVar(key: string, value: string): this Set a container environment variable (`-e KEY=value`); repeatable. publish(host: string | number, container: string | number): this Publish a container port to the host (`-p host:container`). volume(source: PathLike, target: PathLike): this Bind-mount or attach a volume (`-v source:target`). network(value: string): this Connect the container to a network (`--network`). commandArgs(...args: Array): this The command and arguments to run inside the container. override protected buildArgs(): string[] Assemble the `docker run` argv. class DockerSaveSettings extends DockerSettings Settings for `docker save`. images(...references: string[]): this The images to save (at least one is required). output(path: PathLike): this Write to a file instead of STDOUT (`-o`). override protected buildArgs(): string[] Assemble the `docker save` argv. abstract class DockerSettings extends ToolSettings Base for all `docker` subcommand settings: the binary is `docker`. override protected defaultTool(): string The invoked binary is `docker`. class DockerStartSettings extends DockerSettings Settings for `docker start`. containers(...names: string[]): this The containers to start (at least one is required). attach(): this Attach STDOUT/STDERR and forward signals (`-a`). override protected buildArgs(): string[] Assemble the `docker start` argv. class DockerStopSettings extends DockerSettings Settings for `docker stop`. containers(...names: string[]): this The containers to stop (at least one is required). time(seconds: number): this Seconds to wait before killing (`-t`). override protected buildArgs(): string[] Assemble the `docker stop` argv. class DockerTagSettings extends DockerSettings Settings for `docker tag`. source(reference: string): this The existing image reference (required). target(reference: string): this The new image reference (required). override protected buildArgs(): string[] Assemble the `docker tag` argv. interface DockerTasksApi The shape of {@link DockerTasks}. build(configure?: Configure): Promise Build an image: `docker build`. run(configure?: Configure): Promise Run a container: `docker run`. exec(configure?: Configure): Promise Run a command in a container: `docker exec`. push(configure?: Configure): Promise Push an image: `docker push`. pull(configure?: Configure): Promise Pull an image: `docker pull`. tag(configure?: Configure): Promise Tag an image: `docker tag`. login(configure?: Configure): Promise Authenticate to a registry: `docker login`. images(configure?: Configure): Promise List images: `docker images`. ps(configure?: Configure): Promise List containers: `docker ps`. stop(configure?: Configure): Promise Stop containers: `docker stop`. start(configure?: Configure): Promise Start containers: `docker start`. rm(configure?: Configure): Promise Remove containers: `docker rm`. rmi(configure?: Configure): Promise Remove images: `docker rmi`. save(configure?: Configure): Promise Save images to a tar archive: `docker save`. load(configure?: Configure): Promise Load images from a tar archive: `docker load`. ======================================================================== # @zuke/docker-compose ======================================================================== `@zuke/docker-compose` — typed Docker Compose task wrappers for Zuke builds. Configure a fluent settings object in a lambda; the task builds the argv and runs it. The wrapper detects whether Compose is installed as the v2 plugin (`docker compose`) or the v1 standalone binary (`docker-compose`) at run time, so the same build works on either host. ```ts import { DockerComposeTasks } from "jsr:@zuke/docker-compose"; await DockerComposeTasks.up((s) => s.file("compose.yml").detach().build()); await DockerComposeTasks.logs((s) => s.follow().tail(100)); await DockerComposeTasks.down((s) => s.volumes()); ``` @module async function defaultComposeProbe(argv: readonly string[]): Promise The default {@link ComposeProbe}: run the candidate's `version` subcommand quietly and treat a zero exit as success. A missing binary resolves to `false` rather than throwing, so detection can fall through to the next candidate. function resetComposeInvocationCache_(): void Clear the cached Compose invocation so the next {@link resolveComposeInvocation} re-detects. Internal test seam — the trailing underscore signals it is not part of the stable public API. function resolveComposeInvocation(probe: ComposeProbe): Promise Resolve how Docker Compose is invoked on this host: `["docker", "compose"]` for the v2 plugin or `["docker-compose"]` for the v1 standalone binary. The v2 plugin is preferred; if neither is runnable a {@link ToolNotFoundError} is raised. The result is cached after the first successful detection (a failed detection is not cached, so a later call retries). Pass a custom {@link ComposeProbe} to override how candidates are tested. const DockerComposeTasks: DockerComposeTasksApi Typed task functions for Docker Compose (`docker compose`/`docker-compose`). class DockerComposeBuildSettings extends DockerComposeSettings Settings for `compose build`. noCache(): this Do not use the layer cache (`--no-cache`). pull(): this Always attempt to pull newer base images (`--pull`). buildArg(key: string, value: string): this Pass a build-time variable (`--build-arg KEY=value`); repeatable. services(...names: string[]): this Restrict to specific services (positional); optional. override protected composeArgs(): string[] Assemble the `compose build` argv. class DockerComposeConfigSettings extends DockerComposeSettings Settings for `compose config`. quietOutput(): this Only validate, printing nothing (`-q`). servicesOnly(): this Print the service names only (`--services`). volumesOnly(): this Print the volume names only (`--volumes`). format(value: string): this Output format (`--format`), e.g. `yaml` or `json`. override protected composeArgs(): string[] Assemble the `compose config` argv. class DockerComposeDownSettings extends DockerComposeSettings Settings for `compose down`. volumes(): this Also remove named and anonymous volumes (`-v`). removeOrphans(): this Remove containers for services no longer defined (`--remove-orphans`). rmi(type: string): this Remove images of the given type (`--rmi`), e.g. `all` or `local`. timeout(seconds: number): this Shutdown timeout in seconds (`-t`). override protected composeArgs(): string[] Assemble the `compose down` argv. class DockerComposeExecSettings extends DockerComposeSettings Settings for `compose exec`. service(name: string): this The service whose container to exec into (required). detach(): this Run in the background (`-d`). noTty(): this Disable pseudo-TTY allocation (`-T`). workdir(path: PathLike): this Working directory inside the container (`-w`). envVar(key: string, value: string): this Set an environment variable (`-e KEY=value`); repeatable. commandArgs(...args: Array): this The command and arguments to execute. override protected composeArgs(): string[] Assemble the `compose exec` argv. class DockerComposeLogsSettings extends DockerComposeSettings Settings for `compose logs`. follow(): this Stream new log output (`-f`). timestamps(): this Prefix each line with a timestamp (`-t`). tail(lines: number | "all"): this Show only the last N lines, or `all` (`--tail`). services(...names: string[]): this Restrict to specific services (positional); optional. override protected composeArgs(): string[] Assemble the `compose logs` argv. class DockerComposePsSettings extends DockerComposeSettings Settings for `compose ps`. all(): this Show stopped containers too (`-a`). quietOutput(): this Only show container IDs (`-q`). servicesOnly(): this Display services instead of containers (`--services`). services(...names: string[]): this Restrict to specific services (positional); optional. override protected composeArgs(): string[] Assemble the `compose ps` argv. class DockerComposePullSettings extends DockerComposeSettings Settings for `compose pull`. ignorePullFailures(): this Continue past services whose pull fails (`--ignore-pull-failures`). quietOutput(): this Pull without printing progress (`-q`). services(...names: string[]): this Restrict to specific services (positional); optional. override protected composeArgs(): string[] Assemble the `compose pull` argv. class DockerComposePushSettings extends DockerComposeSettings Settings for `compose push`. ignorePushFailures(): this Continue past services whose push fails (`--ignore-push-failures`). services(...names: string[]): this Restrict to specific services (positional); optional. override protected composeArgs(): string[] Assemble the `compose push` argv. class DockerComposeRestartSettings extends DockerComposeSettings Settings for `compose restart`. timeout(seconds: number): this Restart timeout in seconds (`-t`). services(...names: string[]): this Restrict to specific services (positional); optional. override protected composeArgs(): string[] Assemble the `compose restart` argv. class DockerComposeRmSettings extends DockerComposeSettings Settings for `compose rm`. force(): this Do not prompt for confirmation (`-f`). stop(): this Stop the containers first if needed (`-s`). volumes(): this Also remove anonymous volumes (`-v`). services(...names: string[]): this Restrict to specific services (positional); optional. override protected composeArgs(): string[] Assemble the `compose rm` argv. class DockerComposeRunSettings extends DockerComposeSettings Settings for `compose run`. service(name: string): this The service to run (required). rm(): this Remove the container after it exits (`--rm`). detach(): this Run in the background (`-d`). noDeps(): this Do not start linked services (`--no-deps`). name(value: string): this Assign a container name (`--name`). envVar(key: string, value: string): this Set an environment variable (`-e KEY=value`); repeatable. commandArgs(...args: Array): this The command and arguments to run inside the container. override protected composeArgs(): string[] Assemble the `compose run` argv. abstract class DockerComposeSettings extends ToolSettings Base for all Compose subcommand settings. Holds the invocation prefix (`docker compose` vs `docker-compose`) and the global options that precede every subcommand (`-f`, `-p`, `--profile`, …), and resolves the prefix at run time unless it was pinned with {@link usePlugin}/{@link useStandalone}. override protected defaultTool(): string The resolved binary (`docker` or `docker-compose`) for error messages. file(path: PathLike): this Add a Compose file (`-f`); repeatable, order-significant. projectName(name: string): this Set the project name (`-p`). profile(name: string): this Enable a service profile (`--profile`); repeatable. projectDirectory(path: PathLike): this Set the project working directory (`--project-directory`). envFile(path: PathLike): this Load environment from a file (`--env-file`). usePlugin(): this Force the v2 plugin form (`docker compose`) and skip detection. useStandalone(): this Force the v1 standalone form (`docker-compose`) and skip detection. abstract protected composeArgs(): string[] The subcommand argv (without global options). Must be pure — no I/O. override protected buildArgs(): string[] Assemble the global options followed by the subcommand argv. override async run(): Promise Resolve the invocation prefix (unless pinned) and run, so the same build works against either the v2 plugin or the v1 standalone binary. class DockerComposeStartSettings extends DockerComposeSettings Settings for `compose start`. services(...names: string[]): this Restrict to specific services (positional); optional. override protected composeArgs(): string[] Assemble the `compose start` argv. class DockerComposeStopSettings extends DockerComposeSettings Settings for `compose stop`. timeout(seconds: number): this Shutdown timeout in seconds (`-t`). services(...names: string[]): this Restrict to specific services (positional); optional. override protected composeArgs(): string[] Assemble the `compose stop` argv. class DockerComposeUpSettings extends DockerComposeSettings Settings for `compose up`. detach(): this Run in the background (`-d`). build(): this Build images before starting (`--build`). forceRecreate(): this Recreate containers even if unchanged (`--force-recreate`). removeOrphans(): this Remove containers for services no longer defined (`--remove-orphans`). wait(): this Wait until services are running/healthy (`--wait`). abortOnContainerExit(): this Stop all containers if any container stops (`--abort-on-container-exit`). exitCodeFrom(service: string): this Exit with this service's container's exit code (`--exit-code-from`). scale(service: string, instances: number): this Scale a service to N instances (`--scale service=N`); repeatable. services(...names: string[]): this Restrict to specific services (positional); optional. override protected composeArgs(): string[] Assemble the `compose up` argv. interface DockerComposeTasksApi The shape of {@link DockerComposeTasks}. up(configure?: Configure): Promise Create and start services: `compose up`. down(configure?: Configure): Promise Stop and remove services: `compose down`. build(configure?: Configure): Promise Build service images: `compose build`. pull(configure?: Configure): Promise Pull service images: `compose pull`. push(configure?: Configure): Promise Push service images: `compose push`. run(configure?: Configure): Promise Run a one-off command: `compose run`. exec(configure?: Configure): Promise Exec into a running service: `compose exec`. logs(configure?: Configure): Promise View service logs: `compose logs`. ps(configure?: Configure): Promise List containers: `compose ps`. config(configure?: Configure): Promise Render the resolved configuration: `compose config`. start(configure?: Configure): Promise Start existing services: `compose start`. stop(configure?: Configure): Promise Stop running services: `compose stop`. restart(configure?: Configure): Promise Restart services: `compose restart`. rm(configure?: Configure): Promise Remove stopped service containers: `compose rm`. type ComposeProbe = (argv: readonly string[]) => Promise Probes whether a candidate Compose invocation is runnable on this host. Receives the binary-and-prefix argv (`["docker", "compose"]` or `["docker-compose"]`) and resolves to `true` when it works. Injectable so detection can be unit-tested without a real Docker install. ======================================================================== # @zuke/kubectl ======================================================================== `@zuke/kubectl` — typed `kubectl` CLI task wrappers for Zuke builds, for deploying to and managing Kubernetes from a pipeline. ```ts import { KubectlTasks } from "jsr:@zuke/kubectl"; await KubectlTasks.apply((s) => s.file("k8s/").namespace("prod")); await KubectlTasks.setImage((s) => s.resource("deployment/api").image("api", "api:1.4").namespace("prod") ); await KubectlTasks.rollout((s) => s.status().resource("deployment/api").namespace("prod").timeout("120s") ); ``` @module function parseNamespaces(json: string): KubernetesNamespace[] Parse the JSON text of `kubectl get namespaces -o json` — a `List`, or a single namespace object — into {@link KubernetesNamespace} records. Items without a `metadata.name` are skipped; empty input yields `[]`. Throws if the text is non-empty and not valid JSON. const KubectlTasks: KubectlTasksApi Typed task functions for the `kubectl` CLI. class KubectlAnnotateSettings extends KubectlSettings Settings for `kubectl annotate`. resource(...tokens: string[]): this Resource tokens, e.g. `("deploy", "api")` or `("pods", "-l", "app=web")`; repeatable. annotation(key: string, value: string): this Set an annotation as a `key=value` token; repeatable. remove(key: string): this Remove an annotation, rendered as kubectl's `key-` syntax; repeatable. overwrite(): this Overwrite existing annotations (`--overwrite`). all(): this Apply to all resources of the given type (`--all`). selector(query: string): this Restrict to resources matching a label selector (`-l`). override protected buildArgs(): string[] Assemble the `kubectl annotate` argv. class KubectlApplySettings extends KubectlSettings Settings for `kubectl apply`. file(path: PathLike): this Apply a manifest file, directory, or URL (`-f`); repeatable. kustomize(dir: PathLike): this Apply a kustomization directory (`-k`). recursive(): this Recurse into directories given to `-f` (`-R`). prune(): this Prune resources not present in the applied set (`--prune`). serverSide(): this Apply server-side (`--server-side`). dryRun(mode: DryRunMode): this Preview without persisting (`--dry-run=`; defaults to `client`). selector(query: string): this Restrict to resources matching a label selector (`-l`). force(): this Force apply by delete-and-recreate when needed (`--force`). override protected buildArgs(): string[] Assemble the `kubectl apply` argv. class KubectlCreateSettings extends KubectlSettings Settings for `kubectl create`. file(path: PathLike): this Create from a manifest file, directory, or URL (`-f`); repeatable. For resource-form creation (`create secret …`), use the base `.args(...)`. recursive(): this Recurse into directories given to `-f` (`-R`). dryRun(mode: DryRunMode): this Preview without persisting (`--dry-run=`; defaults to `client`). output(format: string): this Output format, e.g. `yaml` or `json` (`-o`). saveConfig(): this Record the current resource in its annotation (`--save-config`). override protected buildArgs(): string[] Assemble the `kubectl create` argv. class KubectlDeleteSettings extends KubectlSettings Settings for `kubectl delete`. file(path: PathLike): this Delete from a manifest file or directory (`-f`); repeatable. resource(...tokens: string[]): this Resource tokens, e.g. `("pod", "web")` or `("deployment/api")`; repeatable. selector(query: string): this Restrict to resources matching a label selector (`-l`). all(): this Delete all resources of the given type (`--all`). ignoreNotFound(): this Treat "not found" as a success (`--ignore-not-found`). force(): this Force immediate deletion (`--force`). gracePeriod(seconds: number): this Seconds to wait before forceful termination (`--grace-period`). recursive(): this Recurse into directories given to `-f` (`-R`). override protected buildArgs(): string[] Assemble the `kubectl delete` argv. class KubectlDescribeSettings extends KubectlSettings Settings for `kubectl describe`. resource(...tokens: string[]): this Resource tokens, e.g. `("pod", "web")` or `("deployment/api")`; repeatable. selector(query: string): this Restrict to resources matching a label selector (`-l`). override protected buildArgs(): string[] Assemble the `kubectl describe` argv. class KubectlExecSettings extends KubectlSettings Settings for `kubectl exec`. resource(name: string): this The pod (or `type/name`) to exec into (required). container(name: string): this Target a specific container (`-c`). stdin(): this Keep STDIN open (`-i`). tty(): this Allocate a TTY (`-t`). command(...args: Array): this The command and arguments to run in the container (required). override protected buildArgs(): string[] Assemble the `kubectl exec` argv. class KubectlGetSettings extends KubectlSettings Settings for `kubectl get`. resource(...tokens: string[]): this Resource tokens, e.g. `("pods")` or `("pod", "web")`; repeatable. output(format: string): this Output format, e.g. `wide`, `yaml`, `json`, `jsonpath=…` (`-o`). selector(query: string): this Restrict to resources matching a label selector (`-l`). fieldSelector(query: string): this Restrict by field selector (`--field-selector`). allNamespaces(): this List across all namespaces (`-A`). watch(on: boolean): this Watch for changes instead of returning once (`-w`); pass `false` to disable. showLabels(): this Include resource labels as columns (`--show-labels`). override protected buildArgs(): string[] Assemble the `kubectl get` argv. class KubectlLabelSettings extends KubectlSettings Settings for `kubectl label`. resource(...tokens: string[]): this Resource tokens, e.g. `("deploy", "api")` or `("pods", "-l", "app=web")`; repeatable. label(key: string, value: string): this Set a label as a `key=value` token; repeatable. remove(key: string): this Remove a label, rendered as kubectl's `key-` syntax; repeatable. overwrite(): this Overwrite existing labels (`--overwrite`). all(): this Apply to all resources of the given type (`--all`). selector(query: string): this Restrict to resources matching a label selector (`-l`). override protected buildArgs(): string[] Assemble the `kubectl label` argv. class KubectlLogsSettings extends KubectlSettings Settings for `kubectl logs`. resource(name: string): this The pod (or `type/name`) to read logs from. container(name: string): this Read from a specific container (`-c`). selector(query: string): this Select pods by label instead of naming one (`-l`). follow(): this Stream new log output (`-f`). previous(): this Read the previous container instance's logs (`--previous`). tail(lines: number): this Show only the last N lines (`--tail`). since(duration: string): this Only logs newer than a duration, e.g. `5m` (`--since`). allContainers(): this Include all containers in the pod (`--all-containers`). timestamps(): this Prefix each line with a timestamp (`--timestamps`). override protected buildArgs(): string[] Assemble the `kubectl logs` argv. class KubectlPatchSettings extends KubectlSettings Settings for `kubectl patch`. resource(name: string): this The resource to patch, e.g. `deployment/api` (required). patch(content: string): this The patch document (`-p`, required). type(strategy: PatchType): this The patch strategy (`--type`). override protected buildArgs(): string[] Assemble the `kubectl patch` argv. class KubectlPortForwardSettings extends KubectlSettings Settings for `kubectl port-forward`. resource(name: string): this The pod or service, e.g. `svc/api` (required). port(mapping: string): this A port mapping, e.g. `8080:80` or `8080`; repeatable, at least one. address(value: string): this The local address(es) to bind (`--address`). override protected buildArgs(): string[] Assemble the `kubectl port-forward` argv. class KubectlRolloutSettings extends KubectlSettings Settings for `kubectl rollout`. status(): this Show rollout status (`rollout status`). restart(): this Restart a rollout (`rollout restart`). undo(): this Roll back to the previous revision (`rollout undo`). history(): this Show rollout history (`rollout history`). resource(name: string): this The resource, e.g. `deployment/api` (required). toRevision(revision: number): this With `undo`, the revision to roll back to (`--to-revision`). timeout(duration: string): this With `status`, how long to wait, e.g. `60s` (`--timeout`). override protected buildArgs(): string[] Assemble the `kubectl rollout ` argv. class KubectlScaleSettings extends KubectlSettings Settings for `kubectl scale`. replicas(count: number): this Desired replica count (`--replicas`, required). resource(name: string): this The resource to scale, e.g. `deployment/api`. file(path: PathLike): this Scale a resource defined in a file (`-f`). currentReplicas(count: number): this Only scale if the current replica count matches (`--current-replicas`). selector(query: string): this Restrict to resources matching a label selector (`-l`). all(): this Scale all resources of the given type (`--all`). override protected buildArgs(): string[] Assemble the `kubectl scale` argv. class KubectlSetImageSettings extends KubectlSettings Settings for `kubectl set image`. resource(name: string): this The resource to update, e.g. `deployment/api` (required). image(container: string, reference: string): this Set a container's image (`container=image`); repeatable, at least one. selector(query: string): this Restrict to resources matching a label selector (`-l`). all(): this Apply to all resources of the given type (`--all`). override protected buildArgs(): string[] Assemble the `kubectl set image` argv. abstract class KubectlSettings extends ToolSettings Base for all `kubectl` subcommand settings: the binary is `kubectl`, and the cluster-targeting flags (`--namespace`, `--context`, `--kubeconfig`) are shared by every subcommand. override protected defaultTool(): string The tool binary invoked by every subcommand: `kubectl`. namespace(name: string): this Target a namespace (`--namespace`). context(name: string): this Use a named kubeconfig context (`--context`). kubeconfig(path: PathLike): this Use an explicit kubeconfig file (`--kubeconfig`). protected globalArgs(): string[] The cluster-targeting flags shared by every subcommand. class KubectlTopSettings extends KubectlSettings Settings for `kubectl top`. pods(): this Report pod usage (`top pods`). nodes(): this Report node usage (`top nodes`). name(value: string): this Limit to a single named pod or node. selector(query: string): this Restrict to resources matching a label selector (`-l`). containers(): this Break pod usage down by container (`--containers`). allNamespaces(): this Report across all namespaces (`-A`). override protected buildArgs(): string[] Assemble the `kubectl top ` argv. class KubectlWaitSettings extends KubectlSettings Settings for `kubectl wait`. file(path: PathLike): this Wait on resources defined in a file (`-f`); repeatable. resource(...tokens: string[]): this Resource tokens, e.g. `("pod/web")` or `("pods")`; repeatable. forCondition(condition: string): this The condition to wait for, e.g. `condition=Available` or `delete`. timeout(duration: string): this How long to wait, e.g. `60s` (`--timeout`). selector(query: string): this Restrict to resources matching a label selector (`-l`). all(): this Wait on all resources of the given type (`--all`). override protected buildArgs(): string[] Assemble the `kubectl wait` argv. interface KubectlTasksApi The shape of {@link KubectlTasks}. apply(configure?: Configure): Promise Apply manifests: `kubectl apply`. create(configure?: Configure): Promise Create resources: `kubectl create`. delete(configure?: Configure): Promise Delete resources: `kubectl delete`. get(configure?: Configure): Promise List resources: `kubectl get`. getNamespaces(configure?: Configure): Promise List namespaces as typed {@link KubernetesNamespace} records: runs `kubectl get namespaces -o json` (forcing JSON output, quietly) and parses the result. Use the lambda for cluster flags or a label `.selector(...)`. describe(configure?: Configure): Promise Describe resources: `kubectl describe`. logs(configure?: Configure): Promise Read logs: `kubectl logs`. exec(configure?: Configure): Promise Exec into a container: `kubectl exec`. rollout(configure?: Configure): Promise Manage rollouts: `kubectl rollout`. scale(configure?: Configure): Promise Scale a workload: `kubectl scale`. setImage(configure?: Configure): Promise Update a container image: `kubectl set image`. annotate(configure?: Configure): Promise Annotate resources: `kubectl annotate`. label(configure?: Configure): Promise Label resources: `kubectl label`. patch(configure?: Configure): Promise Patch a resource: `kubectl patch`. portForward(configure?: Configure): Promise Forward local ports: `kubectl port-forward`. wait(configure?: Configure): Promise Wait for a condition: `kubectl wait`. top(configure?: Configure): Promise Show resource usage: `kubectl top`. interface KubernetesNamespace A Kubernetes namespace, parsed from `kubectl get namespaces -o json` — the typed result of {@link KubectlTasksApi.getNamespaces}. name: string The namespace name (`metadata.name`). status: string The lifecycle phase (`status.phase`), e.g. `"Active"` or `"Terminating"`; `""` when the field is absent. labels: Record The namespace labels (`metadata.labels`), string-valued; `{}` when none. createdAt?: string When the namespace was created (`metadata.creationTimestamp`), if present. type DryRunMode = "none" | "client" | "server" The `--dry-run` strategies kubectl accepts. type PatchType = "strategic" | "merge" | "json" A patch strategy accepted by `kubectl patch --type`. type RolloutAction = "status" | "restart" | "undo" | "history" A rollout sub-action: `kubectl rollout `. ======================================================================== # @zuke/helm ======================================================================== `@zuke/helm` — typed `HelmTasks` wrappers for the Helm (https://helm.sh) CLI, for packaging and deploying to Kubernetes from a Zuke build. ```ts import { HelmTasks } from "jsr:@zuke/helm"; await HelmTasks.upgrade((s) => s.release("api").chart("./charts/api").install().namespace("prod").wait() ); ``` @module const HelmTasks: HelmTasksApi Typed task functions for the `helm` CLI. class HelmDependencyUpdateSettings extends HelmSettings Settings for `helm dependency update`. chart(path: PathLike): this The chart path whose dependencies to update (required). override protected buildArgs(): string[] Assemble the `helm dependency update` argv. class HelmInstallSettings extends HelmValuesSettings Settings for `helm install`. release(name: string): this The release name (required). chart(ref: string): this The chart reference or path (required). createNamespace(): this Create the release namespace if absent (`--create-namespace`). wait(): this Wait until resources are ready (`--wait`). atomic(): this Roll back on failure (`--atomic`). timeout(duration: string): this Operation timeout, e.g. `5m` (`--timeout`). dryRun(): this Simulate the install (`--dry-run`). override protected buildArgs(): string[] Assemble the `helm install` argv. class HelmLintSettings extends HelmSettings Settings for `helm lint`. chart(path: PathLike): this The chart path to lint (required). values(path: PathLike): this Add a values file (`--values`); repeatable. strict(): this Treat warnings as errors (`--strict`). override protected buildArgs(): string[] Assemble the `helm lint` argv. class HelmPackageSettings extends HelmSettings Settings for `helm package`. chart(path: PathLike): this The chart path to package (required). destination(path: PathLike): this Output directory for the packaged chart (`--destination`). version(value: string): this Set the chart version (`--version`). appVersion(value: string): this Set the chart appVersion (`--app-version`). override protected buildArgs(): string[] Assemble the `helm package` argv. class HelmRepoAddSettings extends HelmSettings Settings for `helm repo add`. name(value: string): this The repository name (required). url(value: string): this The repository URL (required). override protected buildArgs(): string[] Assemble the `helm repo add` argv. abstract class HelmSettings extends ToolSettings Base for all `helm` subcommand settings: the binary is `helm`, and the cluster-targeting flags (`--namespace`, `--kube-context`, `--kubeconfig`) are shared by every subcommand. override protected defaultTool(): string The tool binary: `helm`. namespace(name: string): this Target a namespace (`--namespace`). kubeContext(name: string): this Use a named kube context (`--kube-context`). kubeconfig(path: PathLike): this Use an explicit kubeconfig file (`--kubeconfig`). protected globalArgs(): string[] The cluster-targeting flags shared by every subcommand. class HelmTemplateSettings extends HelmValuesSettings Settings for `helm template` (render manifests locally). release(name: string): this The release name (required). chart(ref: string): this The chart reference or path (required). outputDir(path: PathLike): this Write rendered manifests to a directory (`--output-dir`). override protected buildArgs(): string[] Assemble the `helm template` argv. class HelmUninstallSettings extends HelmSettings Settings for `helm uninstall`. release(name: string): this The release name to uninstall (required). keepHistory(): this Retain release history (`--keep-history`). wait(): this Wait until removal completes (`--wait`). override protected buildArgs(): string[] Assemble the `helm uninstall` argv. class HelmUpgradeSettings extends HelmValuesSettings Settings for `helm upgrade`. release(name: string): this The release name (required). chart(ref: string): this The chart reference or path (required). install(): this Install the release if it does not exist (`--install`). createNamespace(): this Create the release namespace if absent (`--create-namespace`). wait(): this Wait until resources are ready (`--wait`). atomic(): this Roll back on failure (`--atomic`). timeout(duration: string): this Operation timeout, e.g. `5m` (`--timeout`). override protected buildArgs(): string[] Assemble the `helm upgrade` argv. abstract class HelmValuesSettings extends HelmSettings Base for value-bearing commands (install/upgrade/template). values(path: PathLike): this Add a values file (`--values`/`-f`); repeatable. set(name: string, value: string): this Override a single value (`--set name=value`); repeatable. version(value: string): this Pin the chart version (`--version`). protected valueArgs(): string[] The shared value/version arguments. interface HelmTasksApi The shape of {@link HelmTasks}. install(configure?: Configure): Promise Install a chart: `helm install`. upgrade(configure?: Configure): Promise Upgrade (or install) a release: `helm upgrade`. uninstall(configure?: Configure): Promise Uninstall a release: `helm uninstall`. template(configure?: Configure): Promise Render manifests locally: `helm template`. lint(configure?: Configure): Promise Lint a chart: `helm lint`. dependencyUpdate(configure?: Configure): Promise Update chart dependencies: `helm dependency update`. repoAdd(configure?: Configure): Promise Add a chart repository: `helm repo add`. package(configure?: Configure): Promise Package a chart: `helm package`. ======================================================================== # @zuke/kustomize ======================================================================== `@zuke/kustomize` — typed `KustomizeTasks` wrappers for the Kustomize (https://kustomize.io) CLI, for use in Zuke builds. ```ts import { KustomizeTasks } from "jsr:@zuke/kustomize"; await KustomizeTasks.build((s) => s.dir("overlays/prod")); await KustomizeTasks.editSetImage((s) => s.image("api", "api:1.4")); ``` @module const KustomizeTasks: KustomizeTasksApi Typed task functions for the `kustomize` CLI. class KustomizeBuildSettings extends KustomizeSettings Settings for `kustomize build`. dir(path: PathLike): this The kustomization directory to build (defaults to the current directory). output(path: PathLike): this Write the rendered output to a file or directory (`--output`). enableHelm(): this Enable the Helm chart inflator (`--enable-helm`). loadRestrictor(mode: string): this Set the file-load restrictor, e.g. `LoadRestrictionsNone` (`--load-restrictor`). override protected buildArgs(): string[] Assemble the `kustomize build` argv. class KustomizeEditSetImageSettings extends KustomizeSettings Settings for `kustomize edit set image`. image(name: string, reference: string): this Set an image override, e.g. `("api", "api:1.4")` → `api=api:1.4`; repeatable, at least one is required. override protected buildArgs(): string[] Assemble the `kustomize edit set image` argv. abstract class KustomizeSettings extends ToolSettings Base for all `kustomize` subcommand settings: the binary is `kustomize`. override protected defaultTool(): string The binary these settings invoke: `kustomize`. interface KustomizeTasksApi The shape of {@link KustomizeTasks}. build(configure?: Configure): Promise Render a kustomization: `kustomize build`. editSetImage(configure?: Configure): Promise Update image overrides: `kustomize edit set image`. ======================================================================== # @zuke/oxlint ======================================================================== `@zuke/oxlint` — typed `oxlint` task wrappers for Zuke builds. Configure a fluent settings object in a lambda; the task builds the argv and runs it. ```ts import { OxlintTasks } from "jsr:@zuke/oxlint"; await OxlintTasks.lint((s) => s.paths("src").fix().denyWarnings()); ``` @module const OxlintTasks: OxlintTasksApi Typed task functions for the `oxlint` linter. class OxlintSettings extends ToolSettings Settings for an `oxlint` run. override protected defaultTool(): string The default executable name (`oxlint`). override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — oxlint is an npm-distributed tool. paths(...values: PathLike[]): this Files or directories to lint (positional); repeatable. config(path: PathLike): this Use an explicit config file (`-c`/`--config`). tsconfig(path: PathLike): this Point at a `tsconfig.json` for type-aware rules (`--tsconfig`). fix(): this Apply automatic fixes (`--fix`). fixSuggestions(): this Apply suggestion fixes too (`--fix-suggestions`). deny(rule: string): this Raise a rule or category to error (`-D`/`--deny`); repeatable. warn(rule: string): this Set a rule or category to warning (`-W`/`--warn`); repeatable. allow(rule: string): this Turn a rule or category off (`-A`/`--allow`); repeatable. ignorePath(path: PathLike): this Read ignore globs from a file (`--ignore-path`). ignorePattern(glob: string): this Ignore files matching a glob (`--ignore-pattern`); repeatable. maxWarnings(count: number): this Fail once this many warnings are reached (`--max-warnings`). quietWarnings(): this Report errors only, suppressing warnings (`--quiet`). denyWarnings(): this Exit non-zero if any warnings are found (`--deny-warnings`). format(value: string): this Output format, e.g. `default`, `json`, `github` (`-f`/`--format`). threads(count: number): this Number of threads to use (`--threads`). override protected buildArgs(): string[] Assemble the `oxlint` argv from the configured settings. interface OxlintTasksApi The shape of {@link OxlintTasks}. lint(configure?: Configure): Promise Lint with `oxlint`. ======================================================================== # @zuke/eslint ======================================================================== `@zuke/eslint` — typed `eslint` task wrappers for Zuke builds. Configure a fluent settings object in a lambda; the task builds the argv and runs it. ```ts import { EslintTasks } from "jsr:@zuke/eslint"; await EslintTasks.lint((s) => s.paths("src").ext(".ts", ".tsx").fix()); ``` @module const EslintTasks: EslintTasksApi Typed task functions for the `eslint` linter. class EslintSettings extends ToolSettings Settings for an `eslint` run. override protected defaultTool(): string The default executable this settings object runs (`eslint`). override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — eslint is an npm-distributed tool. paths(...values: PathLike[]): this Files, directories, or globs to lint (positional); repeatable. config(path: PathLike): this Use an explicit config file (`-c`/`--config`). ext(...extensions: string[]): this Additional file extensions to lint (`--ext`); repeatable. fix(): this Apply automatic fixes (`--fix`). fixDryRun(): this Compute fixes without writing them (`--fix-dry-run`). fixType(...types: string[]): this Restrict fixes to the given types (`--fix-type`); repeatable. quietWarnings(): this Report errors only, suppressing warnings (`--quiet`). maxWarnings(count: number): this Fail once this many warnings are reached (`--max-warnings`). format(value: string): this Output format, e.g. `stylish`, `json` (`-f`/`--format`). outputFile(path: PathLike): this Write the report to a file (`-o`/`--output-file`). cache(): this Cache results between runs (`--cache`). cacheLocation(path: PathLike): this Where to store the cache (`--cache-location`). ignorePath(path: PathLike): this Read ignore globs from a file (`--ignore-path`). ignorePattern(glob: string): this Ignore files matching a glob (`--ignore-pattern`); repeatable. noIgnore(): this Disable all ignore handling (`--no-ignore`). noConfigLookup(): this Do not search for a config file (`--no-config-lookup`). reportUnusedDisableDirectives(): this Report unused `eslint-disable` directives (`--report-unused-disable-directives`). override protected buildArgs(): string[] Assemble the `eslint` argv from the configured settings. interface EslintTasksApi The shape of {@link EslintTasks}. lint(configure?: Configure): Promise Lint with `eslint`. ======================================================================== # @zuke/cspell ======================================================================== `@zuke/cspell` — typed `cspell` task wrappers for Zuke builds. Configure a fluent settings object in a lambda; the task builds the argv and runs it. ```ts import { CspellTasks } from "jsr:@zuke/cspell"; await CspellTasks.lint((s) => s.files("**").noProgress().showSuggestions()); ``` @module const CspellTasks: CspellTasksApi Typed task functions for the `cspell` spell-checker. class CspellSettings extends ToolSettings Settings for a `cspell lint` run. override protected defaultTool(): string The default executable name (`cspell`). override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — cspell is an npm-distributed tool. files(...globs: PathLike[]): this Files or globs to check (positional); repeatable. config(path: PathLike): this Use an explicit config file (`-c`/`--config`). noProgress(): this Suppress the progress output (`--no-progress`). noSummary(): this Suppress the summary line (`--no-summary`). showSuggestions(): this Print spelling suggestions for each issue (`--show-suggestions`). showContext(): this Print the surrounding line for each issue (`--show-context`). quietOutput(): this Only emit issues, hiding informational output (`--quiet`). cache(): this Cache results between runs (`--cache`). dot(): this Include dotfiles and dot-directories (`--dot`). gitignore(): this Honour `.gitignore` files (`--gitignore`). unique(): this Report each unique issue only once (`--unique`). locale(value: string): this Restrict to a locale, e.g. `en,en-GB` (`--locale`). exclude(glob: string): this Exclude files matching a glob (`-e`/`--exclude`); repeatable. maxDuplicateProblems(count: number): this Cap the number of duplicate problems reported (`--max-duplicate-problems`). override protected buildArgs(): string[] Assemble the `cspell lint` argv. interface CspellTasksApi The shape of {@link CspellTasks}. lint(configure?: Configure): Promise Spell-check with `cspell lint`. ======================================================================== # @zuke/jest ======================================================================== `@zuke/jest` — typed `jest` task wrappers for Zuke builds. Configure a fluent settings object in a lambda; the task builds the argv and runs it. ```ts import { JestTasks } from "jsr:@zuke/jest"; await JestTasks.run((s) => s.ci().coverage().maxWorkers(2)); ``` @module const JestTasks: JestTasksApi Typed task functions for the `jest` test runner. class JestSettings extends ToolSettings Settings for a `jest` run. override protected defaultTool(): string The underlying tool binary is `jest`. override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — jest is an npm-distributed tool. paths(...values: PathLike[]): this Regex patterns matched against test paths (positional); repeatable. config(path: PathLike): this Use an explicit config file (`-c`/`--config`). coverage(): this Collect test coverage (`--coverage`). watch(): this Watch files related to changed files (`--watch`). watchAll(): this Watch all files (`--watchAll`). ci(): this Run in CI mode, failing on new snapshots (`--ci`). runInBand(): this Run all tests serially in the current process (`-i`/`--runInBand`). maxWorkers(value: string | number): this Limit worker count, e.g. `2` or `50%` (`--maxWorkers`). updateSnapshot(): this Re-record snapshots (`-u`/`--updateSnapshot`). bail(suites: number): this Stop after N failing test suites (`--bail`). verbose(): this Report each individual test (`--verbose`). silent(): this Prevent tests from printing to the console (`--silent`). testNamePattern(pattern: string): this Run only tests whose name matches the pattern (`-t`/`--testNamePattern`). onlyChanged(): this Run only tests affected by changed files (`-o`/`--onlyChanged`). passWithNoTests(): this Pass when no tests are found (`--passWithNoTests`). detectOpenHandles(): this Detect handles keeping the process open (`--detectOpenHandles`). selectProjects(...names: string[]): this Restrict to named projects (`--selectProjects`); repeatable. reporters(...names: string[]): this Use the named reporters (`--reporters`); repeatable. override protected buildArgs(): string[] Assemble the `jest` argv from the configured flags and patterns. interface JestTasksApi The shape of {@link JestTasks}. run(configure?: Configure): Promise Run tests with `jest`. ======================================================================== # @zuke/vitest ======================================================================== `@zuke/vitest` — typed `vitest` task wrappers for Zuke builds. Configure a fluent settings object in a lambda; the task builds the argv and runs it. The one-shot `run` subcommand is emitted by default; switch to watch mode with `.watch()`. ```ts import { VitestTasks } from "jsr:@zuke/vitest"; await VitestTasks.run((s) => s.coverage().reporter("dot")); ``` @module const VitestTasks: VitestTasksApi Typed task functions for the `vitest` test runner. class VitestSettings extends ToolSettings Settings for a `vitest` run. override protected defaultTool(): string The underlying tool binary (`vitest`). override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — vitest is an npm-distributed tool. filters(...values: string[]): this Filename filters matched against test files (positional); repeatable. watch(): this Use watch mode (`watch`) instead of the default one-shot `run`. config(path: PathLike): this Use an explicit config file (`-c`/`--config`). root(path: PathLike): this Project root (`--root`). dir(path: PathLike): this Restrict the scanned directory (`--dir`). coverage(): this Collect test coverage (`--coverage`). ui(): this Open the Vitest UI (`--ui`). update(): this Update snapshots (`-u`/`--update`). forceRun(): this Force one-shot mode even under watch (`--run`). pool(name: VitestPool): this Choose the worker pool implementation (`--pool`). maxWorkers(count: number): this Cap the number of parallel workers (`--maxWorkers`). minWorkers(count: number): this Set the minimum number of parallel workers (`--minWorkers`). bail(count: number): this Stop after N failed tests (`--bail`). retry(count: number): this Retry failed tests up to N times (`--retry`). shard(value: string): this Run a shard of the suite, e.g. `1/4` (`--shard`). reporter(...names: string[]): this Use the named reporters (`--reporter`); repeatable. outputFile(path: PathLike): this Write report output to a file (`--outputFile`). testNamePattern(pattern: string): this Run only tests whose name matches the pattern (`-t`/`--testNamePattern`). environment(value: string): this Test environment, e.g. `jsdom`, `node` (`--environment`). globals(): this Enable global test APIs (`--globals`). passWithNoTests(): this Pass when no tests are found (`--passWithNoTests`). silent(): this Suppress test console output (`--silent`). override protected buildArgs(): string[] Assemble the `vitest run`/`vitest watch` argv. interface VitestTasksApi The shape of {@link VitestTasks}. run(configure?: Configure): Promise Run tests with `vitest` (one-shot `run` unless {@link VitestSettings.watch}). type VitestPool = "threads" | "forks" | "vmThreads" | "vmForks" The Vitest worker pool implementation (`--pool`). ======================================================================== # @zuke/playwright ======================================================================== `@zuke/playwright` — typed `PlaywrightTasks` wrappers for the Playwright CLI, for use in Zuke build targets (end-to-end browser testing). ```ts import { PlaywrightTasks } from "jsr:@zuke/playwright"; await PlaywrightTasks.install((s) => s.withDeps()); await PlaywrightTasks.test((s) => s.project("chromium").grep("@smoke")); ``` @module const PlaywrightTasks: PlaywrightTasksApi Typed task functions for the Playwright CLI. class PlaywrightCodegenSettings extends PlaywrightSettings Settings for `playwright codegen`. url(value: string): this The URL to open for recording; omit to start blank. target(language: string): this The output language (`--target=`, e.g. `javascript`, `python`). output(path: string): this Write the generated script to a file (`--output=`). override protected buildArgs(): string[] Assemble the `playwright codegen` argv. class PlaywrightInstallSettings extends PlaywrightSettings Settings for `playwright install` (browser binaries). browsers(...names: string[]): this Browsers to install (e.g. `chromium`); omit to install all. withDeps(): this Also install the OS dependencies (`--with-deps`). override protected buildArgs(): string[] Assemble the `playwright install` argv. abstract class PlaywrightSettings extends ToolSettings Base for all Playwright subcommand settings: binary is `playwright`. override protected defaultTool(): string The tool binary invoked by all Playwright subcommands: `playwright`. override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — playwright is an npm-distributed tool. class PlaywrightShowReportSettings extends PlaywrightSettings Settings for `playwright show-report`. dir(path: string): this The report directory to open; omit for the default. override protected buildArgs(): string[] Assemble the `playwright show-report` argv. class PlaywrightTestSettings extends PlaywrightSettings Settings for `playwright test`. project(...names: string[]): this Restrict to the named project(s) (`--project=`); repeatable. grep(pattern: string): this Only run tests matching the pattern (`--grep`). headed(): this Run in headed browsers (`--headed`). ui(): this Open the interactive UI mode (`--ui`). workers(count: number): this Set the number of parallel workers (`--workers=`). reporter(name: string): this Choose the reporter (`--reporter=`). updateSnapshots(): this Update snapshots instead of failing on a mismatch (`--update-snapshots`). config(path: string): this Use a specific config file (`--config=`). paths(...filters: string[]): this Test file or directory filters to run; omit to run all tests. override protected buildArgs(): string[] Assemble the `playwright test` argv. interface PlaywrightTasksApi The shape of {@link PlaywrightTasks}. test(configure?: Configure): Promise Run the test suite: `playwright test`. install(configure?: Configure): Promise Install browser binaries: `playwright install`. showReport(configure?: Configure): Promise Open the HTML report: `playwright show-report`. codegen(configure?: Configure): Promise Record interactions into a script: `playwright codegen`. ======================================================================== # @zuke/cypress ======================================================================== `@zuke/cypress` — typed `CypressTasks` wrappers for the Cypress (https://cypress.io) CLI (end-to-end and component testing), for use in Zuke builds. ```ts import { CypressTasks } from "jsr:@zuke/cypress"; await CypressTasks.run((s) => s.e2e().browser("chrome")); ``` @module const CypressTasks: CypressTasksApi Typed task functions for the `cypress` CLI. class CypressInfoSettings extends CypressSettings Settings for `cypress info`. override protected buildArgs(): string[] Assemble the `cypress info` argv. class CypressInstallSettings extends CypressSettings Settings for `cypress install` (the bundled binary). force(): this Reinstall even if already present (`--force`). override protected buildArgs(): string[] Assemble the `cypress install` argv. class CypressOpenSettings extends CypressTestingSettings Settings for `cypress open` (interactive). override protected buildArgs(): string[] Assemble the `cypress open` argv. class CypressRunSettings extends CypressTestingSettings Settings for `cypress run` (headless). headed(): this Run in a headed browser (`--headed`). spec(pattern: string): this Glob of spec files to run (`--spec`). record(): this Record the run to Cypress Cloud (`--record`). parallel(): this Run in parallel across machines (`--parallel`). tag(value: string): this Tag the recorded run (`--tag`). port(value: number): this Override the server port (`--port`). override protected buildArgs(): string[] Assemble the `cypress run` argv. abstract class CypressSettings extends ToolSettings Base for all `cypress` subcommand settings: the binary is `cypress`. override protected defaultTool(): string The default tool binary: `cypress`. override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — cypress is an npm-distributed tool. abstract class CypressTestingSettings extends CypressSettings Base for the `run`/`open` commands, which share testing-type selection, a browser, a config file, and a project path. e2e(): this Run end-to-end tests (`--e2e`). component(): this Run component tests (`--component`). browser(name: string): this Choose the browser, e.g. `chrome` or `electron` (`--browser`). configFile(path: PathLike): this Use an explicit config file (`--config-file`). project(path: PathLike): this Run against a project at the given path (`--project`). protected sharedArgs(): string[] The testing-type/browser/config/project arguments shared by run and open. class CypressVerifySettings extends CypressSettings Settings for `cypress verify`. override protected buildArgs(): string[] Assemble the `cypress verify` argv. interface CypressTasksApi The shape of {@link CypressTasks}. run(configure?: Configure): Promise Run tests in headless mode: `cypress run`. open(configure?: Configure): Promise Open the interactive runner: `cypress open`. install(configure?: Configure): Promise Install the bundled binary: `cypress install`. verify(configure?: Configure): Promise Verify the installation: `cypress verify`. info(configure?: Configure): Promise Print environment info: `cypress info`. ======================================================================== # @zuke/biome ======================================================================== `@zuke/biome` — typed `BiomeTasks` wrappers for the Biome (https://biomejs.dev) CLI (lint + format + import organizing in one tool), for use in Zuke builds. ```ts import { BiomeTasks } from "jsr:@zuke/biome"; await BiomeTasks.ci((s) => s.paths("src")); await BiomeTasks.check((s) => s.write().paths("src")); ``` @module const BiomeTasks: BiomeTasksApi Typed task functions for the `biome` CLI. class BiomeCheckSettings extends BiomeSettings Settings for `biome check` (lint + format + organize-imports). write(): this Write safe fixes back to disk (`--write`). unsafe(): this Also apply unsafe fixes; implies writing (`--unsafe`). override protected buildArgs(): string[] Assemble the `biome check` argv. class BiomeCiSettings extends BiomeSettings Settings for `biome ci` (read-only check tuned for CI). override protected buildArgs(): string[] Assemble the `biome ci` argv. class BiomeFormatSettings extends BiomeSettings Settings for `biome format`. write(): this Write formatting changes back to disk (`--write`). override protected buildArgs(): string[] Assemble the `biome format` argv. class BiomeLintSettings extends BiomeSettings Settings for `biome lint`. write(): this Write safe lint fixes back to disk (`--write`). unsafe(): this Also apply unsafe fixes; implies writing (`--unsafe`). override protected buildArgs(): string[] Assemble the `biome lint` argv. abstract class BiomeSettings extends ToolSettings Base for all `biome` subcommand settings: the binary is `biome`, and the common filters (config path, reporter, `--staged`, `--changed`) plus the trailing path arguments are shared by every subcommand. override protected defaultTool(): string The tool binary: `biome`. override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — biome is an npm-distributed tool. paths(...paths: PathLike[]): this Files or directories to operate on; omit to use the configured includes. config(path: PathLike): this Use an explicit configuration file (`--config-path`). reporter(name: string): this Choose the diagnostics reporter, e.g. `github` or `json` (`--reporter`). staged(): this Restrict to files staged in git (`--staged`). changed(): this Restrict to files changed against the VCS base (`--changed`). protected flagArgs(): string[] The shared flag arguments (before paths). protected pathArgs(): string[] The trailing path arguments. interface BiomeTasksApi The shape of {@link BiomeTasks}. check(configure?: Configure): Promise Lint, format, and organize imports: `biome check`. format(configure?: Configure): Promise Format code: `biome format`. lint(configure?: Configure): Promise Lint code: `biome lint`. ci(configure?: Configure): Promise Read-only CI check: `biome ci`. ======================================================================== # @zuke/knip ======================================================================== `@zuke/knip` — a typed `KnipTasks` wrapper for the Knip (https://knip.dev) CLI (unused files, dependencies, and exports), for use in Zuke builds. ```ts import { KnipTasks } from "jsr:@zuke/knip"; await KnipTasks.run((s) => s.production().strict()); ``` @module const KnipTasks: KnipTasksApi Typed task functions for the `knip` CLI. class KnipRunSettings extends ToolSettings Settings for a `knip` run. override protected defaultTool(): string The underlying CLI command: `knip`. override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — knip is an npm-distributed tool. production(): this Restrict analysis to production code paths (`--production`). strict(): this Treat the production set strictly (`--strict`). fix(): this Auto-remove unused exports/dependencies where possible (`--fix`). cache(): this Enable the analysis cache (`--cache`). noExitCode(): this Always exit 0, even when issues are found (`--no-exit-code`). config(path: PathLike): this Use an explicit config file (`--config`). workspace(name: string): this Restrict to a single workspace (`--workspace`). reporter(name: string): this Choose the reporter, e.g. `json` or `compact` (`--reporter`). include(...types: string[]): this Limit to specific issue types, e.g. `files`, `dependencies` (`--include`). override protected buildArgs(): string[] Assemble the `knip ` argv. interface KnipTasksApi The shape of {@link KnipTasks}. run(configure?: Configure): Promise Find unused files, dependencies, and exports: `knip`. ======================================================================== # @zuke/dpdm ======================================================================== `@zuke/dpdm` — a typed `DpdmTasks` wrapper for the dpdm (https://github.com/acrazing/dpdm) CLI (module dependency graph and circular-import analysis), for use in Zuke builds. ```ts import { DpdmTasks } from "jsr:@zuke/dpdm"; await DpdmTasks.analyze((s) => s.noTree().noWarning().exitCode("circular:1").entries("src/index.ts") ); ``` @module const DpdmTasks: DpdmTasksApi Typed task functions for the `dpdm` CLI. class DpdmAnalyzeSettings extends ToolSettings Settings for a `dpdm` analysis run. override protected defaultTool(): string The command this settings object runs (`dpdm`). override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — dpdm is an npm-distributed tool. transform(): this Transform TypeScript modules to JavaScript before analysis (`--transform`). noTree(): this Suppress the dependency tree output (`--no-tree`). noCircular(): this Suppress the circular-dependency output (`--no-circular`). noWarning(): this Suppress warnings about unresolved/missing modules (`--no-warning`). noProgress(): this Disable the progress bar (`--no-progress`). output(path: PathLike): this Write the analysis as JSON to a file (`--output`). tsconfig(path: PathLike): this Use an explicit tsconfig for module resolution (`--tsconfig`). context(path: PathLike): this Set the context directory used to shorten printed paths (`--context`). extensions(...exts: string[]): this Extensions to resolve, e.g. `.ts`, `.tsx` (`--extensions`). js(...exts: string[]): this Extensions treated as JavaScript-like (`--js`). include(pattern: string): this Only analyze files matching this regular expression (`--include`). exclude(pattern: string): this Skip files matching this regular expression (`--exclude`). skipDynamicImports(mode: "circular" | "tree"): this Skip dynamic imports when detecting `circular` or `tree` (`--skip-dynamic-imports`). detectUnusedFilesFrom(glob: string): this Detect unused files starting from this glob (`--detect-unused-files-from`). exitCode(rule: string): this Exit with a code when a case occurs, e.g. `circular:1` (`--exit-code`). entries(...paths: PathLike[]): this The entry files or globs to analyze (appended after all options). override protected buildArgs(): string[] Assemble the `dpdm ` argv. interface DpdmTasksApi The shape of {@link DpdmTasks}. analyze(configure?: Configure): Promise Analyze dependencies and circular imports: `dpdm `. ======================================================================== # @zuke/jsr ======================================================================== `@zuke/jsr` — tools for the JSR (https://jsr.io) registry in Zuke builds: typed `JsrTasks` wrappers for the `jsr` CLI (publish, add, remove), plus read-only registry queries to check which versions are already published. ```ts import { isPublished, JsrTasks } from "jsr:@zuke/jsr"; if (!(await isPublished("@zuke/core", "0.13.0"))) { await JsrTasks.publish((s) => s.allowDirty()); } await JsrTasks.add((s) => s.packages("@std/assert")); ``` @module async function isPublished(pkg: string, version: string, options?: JsrRegistryOptions): Promise Whether `pkg@version` (e.g. `@zuke/core`, `0.13.0`) is already on JSR. async function jsrVersions(pkg: string, options: JsrRegistryOptions): Promise> The set of published versions of `pkg` (a scoped name like `@zuke/core`). Resolves to an empty set if the package is not found on JSR. function publishedVersions(meta: unknown): Set The set of version strings present in a JSR `meta.json` payload. Tolerant of malformed input: anything without a `versions` object yields an empty set. const JsrTasks: JsrTasksApi Typed task functions for the `jsr` CLI. class JsrAddSettings extends JsrSettings Settings for `jsr add` (install a JSR dependency). packages(...specs: string[]): this Package specs to add, e.g. `@std/assert` (required). dev(): this Add as a development dependency (`--save-dev`). override protected buildArgs(): string[] Assemble the `jsr add` argv. class JsrPublishSettings extends JsrSettings Settings for `jsr publish`. dryRun(): this Validate without publishing (`--dry-run`). allowSlowTypes(): this Permit slow types in the published package (`--allow-slow-types`). allowDirty(): this Publish even with an uncommitted working tree (`--allow-dirty`). noCheck(): this Skip type-checking before publishing (`--no-check`). provenance(): this Attach provenance attestation in CI (`--provenance`). token(value: string): this Authenticate with a token instead of the interactive flow (`--token`). override protected buildArgs(): string[] Assemble the `jsr publish` argv. class JsrRemoveSettings extends JsrSettings Settings for `jsr remove`. packages(...names: string[]): this Package names to remove (required). override protected buildArgs(): string[] Assemble the `jsr remove` argv. abstract class JsrSettings extends ToolSettings Base for all `jsr` subcommand settings: the binary is `jsr`. override protected defaultTool(): string The tool binary is `jsr`. interface JsrRegistryOptions Options shared by the JSR registry helpers. fetch?: typeof fetch The `fetch` implementation to use. Defaults to the global `fetch`; override it to unit-test without network access. interface JsrTasksApi The shape of {@link JsrTasks}. publish(configure?: Configure): Promise Publish the package: `jsr publish`. add(configure?: Configure): Promise Add a JSR dependency: `jsr add`. remove(configure?: Configure): Promise Remove a dependency: `jsr remove`. ======================================================================== # @zuke/vite ======================================================================== `@zuke/vite` — typed `ViteTasks` wrappers for the Vite (https://vitejs.dev) CLI, for use in Zuke builds. ```ts import { ViteTasks } from "jsr:@zuke/vite"; await ViteTasks.build((s) => s.outDir("dist").mode("production")); await ViteTasks.preview((s) => s.port(4173)); ``` @module const ViteTasks: ViteTasksApi Typed task functions for the `vite` CLI. class ViteBuildSettings extends ViteSettings Settings for `vite build`. outDir(path: PathLike): this Output directory (`--outDir`). base(path: string): this Public base path (`--base`). emptyOutDir(): this Empty the output directory before building (`--emptyOutDir`). sourcemap(): this Emit source maps (`--sourcemap`). root(path: PathLike): this The project root (positional). override protected buildArgs(): string[] Assemble the `vite build` argv. class ViteDevSettings extends ViteSettings Settings for `vite dev` (the development server). host(value: string): this Bind to a host/IP (`--host`). port(value: number): this Serve on a specific port (`--port`). open(): this Open the app in the browser on start (`--open`). override protected buildArgs(): string[] Assemble the `vite dev` argv. class VitePreviewSettings extends ViteSettings Settings for `vite preview` (serve a production build locally). host(value: string): this Bind to a host/IP (`--host`). port(value: number): this Serve on a specific port (`--port`). open(): this Open the app in the browser on start (`--open`). override protected buildArgs(): string[] Assemble the `vite preview` argv. abstract class ViteSettings extends ToolSettings Base for all `vite` subcommand settings: the binary is `vite`, with the `--config` and `--mode` options shared by every subcommand. override protected defaultTool(): string The default binary this wrapper invokes: `vite`. override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — vite is an npm-distributed tool. config(path: PathLike): this Use an explicit config file (`--config`). mode(name: string): this Set the mode, e.g. `production` or `development` (`--mode`). protected baseArgs(): string[] The shared option arguments. interface ViteTasksApi The shape of {@link ViteTasks}. dev(configure?: Configure): Promise Start the dev server: `vite dev`. build(configure?: Configure): Promise Build for production: `vite build`. preview(configure?: Configure): Promise Preview a production build: `vite preview`. ======================================================================== # @zuke/tsup ======================================================================== `@zuke/tsup` — a typed `TsupTasks` wrapper for the tsup (https://tsup.egoist.dev) bundler, for use in Zuke builds. ```ts import { TsupTasks } from "jsr:@zuke/tsup"; await TsupTasks.build((s) => s.entry("src/index.ts").format("esm", "cjs").dts().minify().clean() ); ``` @module const TsupTasks: TsupTasksApi Typed task functions for the `tsup` bundler. class TsupBuildSettings extends ToolSettings Settings for a `tsup` bundle run. override protected defaultTool(): string The executable this settings object runs: `tsup`. override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — tsup is an npm-distributed tool. entry(...paths: PathLike[]): this Entry point(s) to bundle (positional); repeatable. format(...formats: TsupFormat[]): this Output format(s), joined into `--format` (e.g. `esm,cjs`). dts(): this Emit TypeScript declaration files (`--dts`). minify(): this Minify the output (`--minify`). sourcemap(): this Emit source maps (`--sourcemap`). clean(): this Clean the output directory before building (`--clean`). watch(): this Rebuild on change (`--watch`). outDir(path: PathLike): this Output directory (`--out-dir`). target(value: string): this Compilation target, e.g. `es2022` or `node18` (`--target`). tsconfig(path: PathLike): this Path to a tsconfig file (`--tsconfig`). config(path: PathLike): this Path to a tsup config file (`--config`). override protected buildArgs(): string[] Assemble the `tsup ` argv. interface TsupTasksApi The shape of {@link TsupTasks}. build(configure?: Configure): Promise Bundle the entry points: `tsup`. type TsupFormat = "esm" | "cjs" | "iife" An output format accepted by tsup's `--format`. ======================================================================== # @zuke/turbo ======================================================================== `@zuke/turbo` — typed `TurboTasks` wrappers for the Turborepo (https://turbo.build) CLI, for use in Zuke builds. ```ts import { TurboTasks } from "jsr:@zuke/turbo"; await TurboTasks.run((s) => s.tasks("build", "test").filter("web")); ``` @module const TurboTasks: TurboTasksApi Typed task functions for the `turbo` CLI. class TurboPruneSettings extends TurboSettings Settings for `turbo prune`. package(name: string): this The package to prune the workspace down to (required). docker(): this Produce a Docker-friendly layout (`--docker`). outDir(path: PathLike): this Output directory (`--out-dir`). override protected buildArgs(): string[] Assemble the `turbo prune` argv. class TurboRunSettings extends TurboSettings Settings for `turbo run`. tasks(...names: string[]): this The package.json task(s) to run (positional; at least one required). filter(pattern: string): this Restrict to matching packages (`--filter`); repeatable. parallel(): this Run tasks in parallel, ignoring dependencies (`--parallel`). concurrency(value: string): this Limit concurrency, e.g. `10` or `50%` (`--concurrency`). force(): this Ignore cache hits and force execution (`--force`). noCache(): this Disable reading and writing the cache (`--no-cache`). continue(): this Continue running tasks even after one fails (`--continue`). dryRun(): this List what would run without executing (`--dry-run`). outputLogs(mode: string): this Output-log mode, e.g. `full`, `hash-only`, `errors-only` (`--output-logs`). override protected buildArgs(): string[] Assemble the `turbo run` argv. abstract class TurboSettings extends ToolSettings Base for all `turbo` subcommand settings: the binary is `turbo`. override protected defaultTool(): string The tool binary this settings class invokes: `turbo`. override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — turbo is an npm-distributed tool. interface TurboTasksApi The shape of {@link TurboTasks}. run(configure?: Configure): Promise Run workspace tasks: `turbo run`. prune(configure?: Configure): Promise Prune the workspace to a package: `turbo prune`. ======================================================================== # @zuke/nx ======================================================================== `@zuke/nx` — typed `NxTasks` wrappers for the Nx (https://nx.dev) CLI, for use in Zuke builds. ```ts import { NxTasks } from "jsr:@zuke/nx"; await NxTasks.affected((s) => s.target("test").base("main")); await NxTasks.runMany((s) => s.target("build").projects("web", "api")); ``` @module const NxTasks: NxTasksApi Typed task functions for the `nx` CLI. class NxAffectedSettings extends NxSettings Settings for `nx affected`. target(name: string): this The target to run on affected projects (required). base(ref: string): this The base ref to diff against (`--base`). head(ref: string): this The head ref to diff against (`--head`). configuration(name: string): this Use a named configuration (`--configuration`). parallel(count: number): this Maximum number of tasks to run in parallel (`--parallel`). override protected buildArgs(): string[] Assemble the `nx affected` argv. class NxRunManySettings extends NxSettings Settings for `nx run-many`. target(name: string): this The target to run across projects (required). projects(...names: string[]): this Limit to specific projects (`--projects`); repeatable. configuration(name: string): this Use a named configuration (`--configuration`). parallel(count: number): this Maximum number of tasks to run in parallel (`--parallel`). all(): this Run for every project (`--all`). override protected buildArgs(): string[] Assemble the `nx run-many` argv. class NxRunSettings extends NxSettings Settings for `nx run` (a single `project:target`). target(spec: string): this The `project:target` to run, e.g. `web:build` (required). configuration(name: string): this Use a named configuration (`--configuration`). override protected buildArgs(): string[] Assemble the `nx run` argv. abstract class NxSettings extends ToolSettings Base for all `nx` subcommand settings: the binary is `nx`. override protected defaultTool(): string The tool binary is `nx`. override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — nx is an npm-distributed tool. interface NxTasksApi The shape of {@link NxTasks}. run(configure?: Configure): Promise Run a single `project:target`: `nx run`. runMany(configure?: Configure): Promise Run a target across many projects: `nx run-many`. affected(configure?: Configure): Promise Run a target on affected projects: `nx affected`. ======================================================================== # @zuke/tsx ======================================================================== `@zuke/tsx` — typed `tsx` task wrappers for Zuke builds. Configure a fluent settings object in a lambda; the task builds the argv and runs it. The task names mirror the CLI: `tsx` runs an entry point and `watch` re-runs it on changes. ```ts import { TsxTasks } from "jsr:@zuke/tsx"; await TsxTasks.tsx((s) => s.script("src/main.ts").tsconfig("tsconfig.json")); ``` @module const TsxTasks: TsxTasksApi Typed task functions for the `tsx` TypeScript runner. abstract class TsxCommonSettings extends ToolSettings Options shared by every `tsx` invocation: the entry point and how to load it. override protected defaultTool(): string The underlying executable: `tsx`. override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — tsx is an npm-distributed tool. script(path: PathLike): this The entry point to execute (required). scriptArgs(...args: Array): this Arguments passed to the script (after the entry point). tsconfig(path: PathLike): this Use an explicit `tsconfig.json` (`--tsconfig`). envFile(path: PathLike): this Load environment variables from a file (`--env-file`). noCache(): this Disable the file-system transpile cache (`--no-cache`). noWarnings(): this Suppress Node warnings (`--no-warnings`). conditions(...names: string[]): this Custom export conditions to resolve (`--conditions`); repeatable. importModule(...modules: string[]): this Preload a module before the entry point (`--import`); repeatable. protected entryArgs(): string[] The option flags, then the required entry point and its arguments. class TsxSettings extends TsxCommonSettings Settings for `tsx `. override protected buildArgs(): string[] Assemble the `tsx ` argv. class TsxWatchSettings extends TsxCommonSettings Settings for `tsx watch `. noClearScreen(): this Keep prior output between reruns (`--clear-screen=false`). include(...paths: PathLike[]): this Additional paths to watch (`--include`); repeatable. exclude(...paths: PathLike[]): this Paths to ignore while watching (`--exclude`); repeatable. override protected buildArgs(): string[] Assemble the `tsx watch ` argv. interface TsxTasksApi The shape of {@link TsxTasks}. tsx(configure?: Configure): Promise Run a TypeScript entry point: `tsx `. watch(configure?: Configure): Promise Re-run an entry point on changes: `tsx watch `. ======================================================================== # @zuke/tsc ======================================================================== `@zuke/tsc` — typed `tsc` task wrappers for Zuke builds. `tsc` is the TypeScript compiler — since TypeScript 7.0 that binary is the native Go compiler, so this wrapper drives it with no change on your side. Configure a fluent settings object in a lambda; the task builds the argv and runs it. Two tasks are exposed: a standard {@link TscTasks.tsc} compile/type-check and a {@link TscTasks.build} project-references build (`tsc --build`). ```ts import { TscTasks } from "jsr:@zuke/tsc"; await TscTasks.tsc((s) => s.project("tsconfig.json").noEmit()); await TscTasks.build((s) => s.projects("packages/a", "packages/b")); ``` @module const TscTasks: TscTasksApi Typed task functions for the `tsc` TypeScript compiler. abstract class TscBaseSettings extends ToolSettings Shared base for `tsc` settings; resolves the `tsc` binary. override protected defaultTool(): string The default binary these settings invoke: `tsc`. override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — tsc is an npm-distributed tool. class TscBuildSettings extends TscBaseSettings Settings for a `tsc --build` project-references run. projects(...values: PathLike[]): this Project config files or directories to build (positional); repeatable. noEmit(): this Type-check without emitting output (`--noEmit`). `tsc --build` accepts the same compiler-option overrides as a plain compile, applied on top of each project's build; this is not inherited from {@link TscBaseSettings} — {@link TscSettings.noEmit} is a separate, unrelated field on the other subclass. clean(): this Delete the outputs of all projects (`--clean`). force(): this Build all projects, even those that appear up to date (`--force`). dry(): this Show what would be built without building it (`--dry`). watch(): this Rebuild projects on file changes (`--watch`). verbose(): this Print verbose logging about the build (`--verbose`). incremental(): this Reuse prior build information for faster rebuilds (`--incremental`). override protected buildArgs(): string[] Assemble the `tsc --build` argv from the configured options. class TscSettings extends TscBaseSettings Settings for a standard `tsc` run. paths(...values: PathLike[]): this Source files to compile (positional); repeatable. project(path: PathLike): this Compile the project at the given config or directory (`-p`/`--project`). noEmit(): this Type-check without emitting output (`--noEmit`). outDir(path: PathLike): this Directory for emitted files (`--outDir`). declaration(): this Generate `.d.ts` declaration files (`--declaration`). emitDeclarationOnly(): this Emit declarations only, no JavaScript (`--emitDeclarationOnly`). incremental(): this Reuse prior build information for faster rebuilds (`--incremental`). watch(): this Recompile on file changes (`--watch`). strict(): this Enable all strict type-checking options (`--strict`). pretty(): this Colourise and format diagnostics (`--pretty`). listFiles(): this Print the names of files included in the compilation (`--listFiles`). skipLibCheck(): this Skip type-checking of declaration files (`--skipLibCheck`). noEmitOnError(): this Do not emit output if any errors are reported (`--noEmitOnError`). target(value: string): this Target ECMAScript version, e.g. `es2022` (`--target`). module(value: string): this Module system, e.g. `esnext`, `nodenext` (`--module`). override protected buildArgs(): string[] Assemble the `tsc` argv from the configured compile options. interface TscTasksApi The shape of {@link TscTasks}. tsc(configure?: Configure): Promise Type-check (or compile) with `tsc`. build(configure?: Configure): Promise Run a project-references build with `tsc --build`. ======================================================================== # @zuke/tsc-alias ======================================================================== `@zuke/tsc-alias` — typed `tsc-alias` task wrappers for Zuke builds. `tsc-alias` rewrites TypeScript path aliases (the `paths` mapping in `tsconfig.json`) into relative imports in the compiled output, so the emitted JavaScript runs without a path resolver. Configure a fluent settings object in a lambda; the task builds the argv and runs it. ```ts import { TscAliasTasks } from "jsr:@zuke/tsc-alias"; await TscAliasTasks.run((s) => s.project("tsconfig.json").resolveFullPaths()); ``` @module const TscAliasTasks: TscAliasTasksApi Typed task functions for the `tsc-alias` path-alias rewriter. class TscAliasRunSettings extends ToolSettings Settings for a `tsc-alias` run. override protected defaultTool(): string The executable this settings object drives (`tsc-alias`). override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — tsc-alias is an npm-distributed tool. project(path: PathLike): this Path to the `tsconfig.json` to read aliases from (`-p`/`--project`). watch(): this Re-run on file changes (`--watch`). outDir(path: PathLike): this Output directory of the compiled files to rewrite (`--outDir`). declarationDir(path: PathLike): this Output directory of the emitted declaration files (`--declarationDir`). resolveFullPaths(): this Attempt to fully resolve alias paths, including extensions (`--resolveFullPaths`). resolveFullExtension(ext: string): this Extension to append when resolving full paths, e.g. `.js` (`--resolveFullExtension`). replacers(...files: PathLike[]): this Additional replacer module file(s); repeatable (`-f`/`--replacers`). dir(path: PathLike): this Base directory to resolve relative paths against (`--dir`). fileExtensions(list: string): this Comma-separated list of file extensions to process (`--fileExtensions`). verbose(): this Print verbose output (`--verbose`). debug(): this Print debug output (`--debug`). silent(): this Suppress all output (`--silent`). override protected buildArgs(): string[] Assemble the `tsc-alias` argv from the configured settings. interface TscAliasTasksApi The shape of {@link TscAliasTasks}. run(configure?: Configure): Promise Rewrite TypeScript path aliases in compiled output with `tsc-alias`. ======================================================================== # @zuke/tsdown ======================================================================== `@zuke/tsdown` — a typed `TsdownTasks` wrapper for the tsdown (https://tsdown.dev) bundler, for use in Zuke builds. ```ts import { TsdownTasks } from "jsr:@zuke/tsdown"; await TsdownTasks.build((s) => s.entry("src/index.ts").format("esm", "cjs").dts().minify().clean() ); ``` @module const TsdownTasks: TsdownTasksApi Typed task functions for the `tsdown` bundler. class TsdownBuildSettings extends ToolSettings Settings for a `tsdown` bundle run (`tsdown [entries] [flags]`). override protected defaultTool(): string The default executable to run: `tsdown`. override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — tsdown is an npm-distributed tool. entry(...paths: PathLike[]): this Entry point(s) to bundle (positional); repeatable. format(...formats: TsdownFormat[]): this Output format(s), joined into `--format` (e.g. `esm,cjs`). dts(): this Emit TypeScript declaration files (`--dts`). minify(): this Minify the output (`--minify`). sourcemap(): this Emit source maps (`--sourcemap`). clean(): this Clean the output directory before building (`--clean`). watch(): this Rebuild on change (`--watch`). outDir(path: PathLike): this Output directory (`--out-dir`). target(value: string): this Compilation target, e.g. `es2022` or `node18` (`--target`). tsconfig(path: PathLike): this Path to a tsconfig file (`--tsconfig`). config(path: PathLike): this Path to a tsdown config file (`--config`). platform(value: string): this Target platform, e.g. `node`, `browser`, or `neutral` (`--platform`). treeshake(): this Enable tree-shaking of the output (`--treeshake`). override protected buildArgs(): string[] Assemble the `tsdown [entries] [flags]` argv. class TsdownMigrateSettings extends ToolSettings Settings for a `tsdown migrate` run (`tsdown migrate [flags]`). override protected defaultTool(): string The default executable to run: `tsdown`. override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — tsdown is an npm-distributed tool. from(value: string): this The tool to migrate from, e.g. `tsup` (`--from`). dryRun(): this Preview the migration without writing any files (`--dry-run`). override protected buildArgs(): string[] Assemble the `tsdown migrate [flags]` argv. interface TsdownTasksApi The shape of {@link TsdownTasks}. build(configure?: Configure): Promise Bundle the entry points: `tsdown`. migrate(configure?: Configure): Promise Migrate an existing project to tsdown: `tsdown migrate`. type TsdownFormat = "esm" | "cjs" | "iife" | "umd" An output format accepted by tsdown's `--format`. ======================================================================== # @zuke/nest ======================================================================== `@zuke/nest` — typed NestJS CLI (`nest`) task wrappers for Zuke builds. Wraps the `@nestjs/cli` (https://docs.nestjs.com) `nest` command in the same settings-lambda style as the other Zuke tool wrappers: configure a fluent settings object in a lambda; the task builds the argv and runs it. ```ts import { NestTasks } from "jsr:@zuke/nest"; await NestTasks.generate((s) => s.schematic("service").name("users")); await NestTasks.build((s) => s.webpack()); ``` @module const NestTasks: NestTasksApi Typed task functions for the NestJS CLI (`nest`). class NestBuildSettings extends NestSettings Settings for `nest build` — compile a NestJS application. app(value: string): this The application/project to build (positional, optional). config(path: PathLike): this Path to the Nest CLI configuration file (`--config

`). path(path: PathLike): this Path to the `tsconfig` file (`--path

`). watch(): this Rebuild on file changes (`--watch`). webpack(): this Use the webpack builder (`--webpack`). tsc(): this Use the `tsc` builder (`--tsc`). builder(value: string): this Builder to use, e.g. `tsc`/`webpack`/`swc` (`--builder `). preserveWatchOutput(): this Keep prior console output between watch rebuilds (`--preserveWatchOutput`). override protected subcommandArgs(): string[] Assemble the `nest build` argv. class NestGenerateSettings extends NestSettings Settings for `nest generate` — generate code from a schematic. schematic(value: string): this The schematic to generate, e.g. `module`/`service` (positional, required). name(value: string): this The name passed to the schematic (positional, optional). project(value: string): this Target project in a monorepo (`--project `). collection(value: string): this Schematics collection to use (`--collection `). flat(): this Generate files without a dedicated directory (`--flat`). spec(): this Force generation of a spec file (`--spec`). noSpec(): this Disable generation of a spec file (`--no-spec`). skipImport(): this Skip importing the generated element into its module (`--skip-import`). dryRun(): this Report what would be generated without writing files (`--dry-run`). override protected subcommandArgs(): string[] Assemble the `nest generate` argv. class NestInfoSettings extends NestSettings Settings for `nest info` — print Nest CLI and project information. override protected subcommandArgs(): string[] Assemble the `nest info` argv. class NestNewSettings extends NestSettings Settings for `nest new` — scaffold a new NestJS application. name(value: string): this The application name (positional, required). directory(path: PathLike): this Generate into this directory (`--directory

`). skipInstall(): this Skip package installation (`--skip-install`). skipGit(): this Skip git repository initialization (`--skip-git`). strict(): this Enable TypeScript strict mode in the generated project (`--strict`). dryRun(): this Report what would be generated without writing files (`--dry-run`). packageManager(value: string): this Package manager to use, e.g. `npm`/`yarn`/`pnpm` (`--package-manager `). language(value: string): this Programming language, e.g. `ts`/`js` (`--language `). override protected subcommandArgs(): string[] Assemble the `nest new` argv. abstract class NestSettings extends ToolSettings Shared base for every `nest` subcommand: the binary and argv assembly. override protected defaultTool(): string The tool binary: `nest`. override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — nest is an npm-distributed tool. abstract protected subcommandArgs(): string[] The subcommand argv (the verb and its arguments). override protected buildArgs(): string[] Assemble the full `nest` argv from the subcommand. class NestStartSettings extends NestSettings Settings for `nest start` — build and run a NestJS application. app(value: string): this The application/project to start (positional, optional). config(path: PathLike): this Path to the Nest CLI configuration file (`--config

`). path(path: PathLike): this Path to the `tsconfig` file (`--path

`). watch(): this Rebuild and restart on file changes (`--watch`). debug(): this Start in debug mode (`--debug`). preserveWatchOutput(): this Keep prior console output between watch rebuilds (`--preserveWatchOutput`). exec(value: string): this Binary used to run the compiled output (`--exec `). builder(value: string): this Builder to use, e.g. `tsc`/`webpack`/`swc` (`--builder `). override protected subcommandArgs(): string[] Assemble the `nest start` argv. interface NestTasksApi The shape of {@link NestTasks}. new(configure?: Configure): Promise Scaffold a new application: `nest new`. generate(configure?: Configure): Promise Generate code from a schematic: `nest generate`. build(configure?: Configure): Promise Compile an application: `nest build`. start(configure?: Configure): Promise Build and run an application: `nest start`. info(configure?: Configure): Promise Print CLI and project information: `nest info`. ======================================================================== # @zuke/openapi-ts ======================================================================== `@zuke/openapi-ts` — typed `openapi-ts` task wrappers for Zuke builds. `openapi-ts` is the Hey API (https://heyapi.dev) code generator (`@hey-api/openapi-ts`): it turns an OpenAPI specification into a type-safe client. Configure a fluent settings object in a lambda; the task builds the argv and runs it. ```ts import { OpenapiTsTasks } from "jsr:@zuke/openapi-ts"; await OpenapiTsTasks.generate((s) => s.input("openapi.yaml").output("src/client") ); ``` @module const OpenapiTsTasks: OpenapiTsTasksApi Typed task functions for the Hey API `openapi-ts` code generator. class OpenapiTsGenerateSettings extends ToolSettings Settings for an `openapi-ts` generation run. override protected defaultTool(): string The tool binary this settings object invokes (`openapi-ts`). override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — openapi-ts is an npm-distributed tool. input(value: PathLike): this OpenAPI specification to read — a file path or URL (`--input`). output(value: PathLike): this Directory the generated client is written to (`--output`). client(value: string): this HTTP client to generate for, e.g. `@hey-api/client-fetch` (`--client`). file(value: PathLike): this Configuration file to load settings from (`--file`). dryRun(): this Print the planned output without writing any files (`--dry-run`). watch(): this Regenerate on changes to the specification (`--watch`). silent(): this Suppress informational logging (`--silent`). override protected buildArgs(): string[] Assemble the `openapi-ts` argv from the configured flags. interface OpenapiTsTasksApi The shape of {@link OpenapiTsTasks}. generate(configure?: Configure): Promise Generate a type-safe API client from an OpenAPI spec with `openapi-ts`. ======================================================================== # @zuke/orval ======================================================================== `@zuke/orval` — typed `orval` task wrappers for Zuke builds. `orval` is an OpenAPI client and mock generator (https://orval.dev). It reads an OpenAPI specification and generates a type-safe TypeScript client and optional mocks. Configure a fluent settings object in a lambda; the task builds the argv and runs it. ```ts import { OrvalTasks } from "jsr:@zuke/orval"; await OrvalTasks.generate((s) => s.config("orval.config.ts").clean()); ``` @module const OrvalTasks: OrvalTasksApi Typed task functions for the `orval` OpenAPI client and mock generator. class OrvalGenerateSettings extends ToolSettings Settings for an `orval` generation run. override protected defaultTool(): string The executable this settings object runs: `orval`. override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — orval is an npm-distributed tool. config(value: PathLike): this Configuration file to load settings from (`-c`/`--config`). project(value: string): this Run only the named project from the config (`-p`/`--project`). input(value: PathLike): this OpenAPI specification to read — a file path or URL (`-i`/`--input`). output(value: PathLike): this Directory the generated client is written to (`-o`/`--output`). watch(): this Regenerate on changes to the specification (`-w`/`--watch`). clean(): this Remove previously generated files before writing (`--clean`). prettier(): this Format the generated output with Prettier (`--prettier`). biome(): this Format the generated output with Biome (`--biome`). mock(): this Generate mocks alongside the client (`--mock`). override protected buildArgs(): string[] Assemble the `orval` argv from the configured flags. interface OrvalTasksApi The shape of {@link OrvalTasks}. generate(configure?: Configure): Promise Generate a TypeScript API client and mocks from an OpenAPI spec with `orval`. ======================================================================== # @zuke/husky ======================================================================== `@zuke/husky` — typed `husky` task wrappers for Zuke builds. `husky` (https://typicode.github.io/husky) manages Git hooks. Configure a fluent settings object in a lambda; the task builds the argv and runs it. ```ts import { HuskyTasks } from "jsr:@zuke/husky"; await HuskyTasks.init(); await HuskyTasks.install(); ``` @module const HuskyTasks: HuskyTasksApi Typed task functions for the `husky` Git-hooks tool. class HuskyInitSettings extends HuskySettings Settings for `husky init [dir]` — scaffold husky in a project: create the hooks directory, add a sample `pre-commit` hook, and wire up the `prepare` script. This is the canonical husky v9 setup command. dir(path: PathLike): this The hooks directory to initialise (positional; defaults to `.husky`). override protected subcommandArgs(): string[] Assemble the `husky init [dir]` subcommand argv. class HuskyInstallSettings extends HuskySettings Settings for installing Git hooks by invoking `husky [dir]` bare. husky v9 removed the old `install` subcommand: running `husky` with no subcommand is what installs the hooks (an optional directory may follow). This task therefore emits the bare `husky` invocation — its default argv is just `["husky"]`, not `["husky", "install"]`. dir(path: PathLike): this The hooks directory to install into (positional; defaults to `.husky`). override protected subcommandArgs(): string[] Assemble the bare `husky [dir]` invocation argv (no subcommand). abstract class HuskySettings extends ToolSettings Shared base for every `husky` invocation: the binary and argv assembly. override protected defaultTool(): string The tool binary is `husky`. override protected defaultResolution(): ToolResolution Resolve the binary from `node_modules/.bin` by default — husky is an npm-distributed tool. abstract protected subcommandArgs(): string[] The subcommand argv (everything after the binary). override protected buildArgs(): string[] Assemble the full `husky` argv from the subcommand argv. interface HuskyTasksApi The shape of {@link HuskyTasks}. init(configure?: Configure): Promise Scaffold husky in a project: `husky init [dir]`. install(configure?: Configure): Promise Install Git hooks via the bare `husky [dir]` invocation (husky v9 removed the `install` subcommand). ======================================================================== # @zuke/node ======================================================================== `@zuke/node` — typed Node.js task wrappers for Zuke builds. Configure a fluent settings object in a lambda; the task builds the argv and runs it. The task names mirror common `node` invocations: `run` executes a script, `eval` evaluates inline code, and `test` runs the built-in test runner. ```ts import { NodeTasks } from "jsr:@zuke/node"; await NodeTasks.run((s) => s.script("server.js").enableSourceMaps()); ``` @module const NodeTasks: NodeTasksApi Typed task functions for the Node.js runtime `node`. class NodeEvalSettings extends NodeSettings Settings for `node [options] --eval `. code(source: string): this The JavaScript source to evaluate (required). requireModule(...modules: string[]): this Preload a CommonJS module before evaluating (`--require `); repeatable. importModule(...modules: string[]): this Preload an ES module before evaluating (`--import `); repeatable. print(): this Print the result of the evaluated code (`--print` instead of `--eval`). override protected buildArgs(): string[] Assemble the `node --eval ` (or `--print`) argv. class NodeRunSettings extends NodeSettings Settings for `node [options]