@zuke/core

← API reference

Zuke — a code-first, strongly-typed build automation system for Deno.

Symbols

# $ function
function $(strings: TemplateStringsArray, ...values: Interpolatable[]): Command

Run an external command, ergonomically.

# absolutePath function
function absolutePath(first: string, ...rest: string[]): AbsolutePath

Build an 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.

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"
# AbsolutePath interface
interface AbsolutePath

An immutable, absolute filesystem path with a fluent API.

Build one with absolutePath. The value itself is callablepath(...segments) returns a new path with those segments appended — and the equivalent 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().

MemberSignatureDoc
join join(...segments: string[]): AbsolutePath Append path segments, returning a new path.
parent parent(): AbsolutePath The parent directory; a root is its own parent.
relativeTo relativeTo(base: AbsolutePath | string): string This path expressed relative to base (e.g. "src/main.ts", "../lib").
equals equals(other: AbsolutePath | string): boolean Whether other resolves to the same normalised path.
toString toString(): string The normalised path string.
path path: string The normalised path string (forward slashes, ./.. resolved).
name name: string The final segment, e.g. "main.ts" (or "" for a root).
stem stem: string The final segment without its extension, e.g. "main" (".gitignore" has none).
extension extension: string The extension including the dot, e.g. ".ts" (or "" if none).
isRoot isRoot: boolean Whether this path is a filesystem root ("/", "C:/").
# AffectedOptions interface
interface AffectedOptions

Configure ExecuteOptions.affected: the base revision and diff seam.

MemberSignatureDoc
base? base?: string The git revision to diff against. Defaults to HEAD (uncommitted changes).
changedFiles? changedFiles?: ChangedFilesFn How to list changed files. Defaults to gitChangedFiles.
# affectedTargets function
function affectedTargets(order: unknown, changed: unknown): Set<TargetBuilder>

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 plan/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.

# AlreadyResumedError class
class AlreadyResumedError extends Error

Raised when a run has already been resumed by another process.

MemberSignatureDoc
name name: string The error name.
# AnnounceError class
class AnnounceError extends Error

Raised when an announcement is run before it is fully configured.

MemberSignatureDoc
name name: string The error name.
# Announcement interface
interface Announcement

A structured announcement assembled by an AnnouncementSettings.

MemberSignatureDoc
text text: string The main message body.
title? title?: string An optional heading rendered above the message.
level level: AnnouncementLevel The outcome level driving the accent colour and icon.
fields? fields?: AnnouncementField[] Labelled details rendered beside the message.
link? link?: AnnouncementLink A clickable action rendered with the announcement.
# AnnouncementField interface
interface AnnouncementField

A labelled detail rendered beside the message (e.g. a version or environment).

MemberSignatureDoc
name name: string The field's label.
value value: string The field's value.
# AnnouncementLevel type
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".

# AnnouncementSettings class
class AnnouncementSettings

Fluent settings shared by every announcement: the message content (a body, an optional title, a 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.

MemberSignatureDoc
text text(text: string): this Set the main message body.
title title(title: string): this Set an optional heading shown above the body.
level level(level: AnnouncementLevel): this Set the outcome the message conveys (default "info").
success success(): this Shorthand for .level("success").
failure failure(): this Shorthand for .level("failure").
warning warning(): this Shorthand for .level("warning").
info info(): this Shorthand for .level("info").
field field(name: string, value: string): this Add a labelled detail rendered beside the body. Repeatable.
link link(text: string, url: string): this Set an action link rendered with the message.
username 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 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 fetch(impl: fetch): this The fetch implementation to use. Defaults to the global fetch; override it to unit-test without network access.
bot bot(): this Post through the platform's API with a bot/access token instead of an incoming webhook. Pair with token and channel.
token token(token: string): this Set the bot/access token for 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 bot.
channel channel(channel: string): this Set the channel (id or name) to post to in bot mode.
send send(): Promise<void> Send the announcement: through the platform's API when bot mode was requested, otherwise by posting the payload to the webhook.
# AnnounceTasks const
const AnnounceTasks: AnnounceTasksApi

Announcement task functions for posting build status to chat platforms.

# AnnounceTasksApi interface
interface AnnounceTasksApi

The shape of AnnounceTasks.

MemberSignatureDoc
slack slack(configure?: Configure<SlackAnnouncementSettings>): Promise<void> Announce to Slack. Configure a SlackAnnouncementSettings: set a .webhook(url) (or .bot().token(t).channel(c) for the Web API) and the message content.
teams teams(configure?: Configure<TeamsAnnouncementSettings>): Promise<void> Announce to Microsoft Teams. Configure a TeamsAnnouncementSettings: set a .webhook(url) (or .bot().token(t).team(id).channel(c) to post through Microsoft Graph) and the message content.
discord discord(configure?: Configure<DiscordAnnouncementSettings>): Promise<void> Announce to Discord. Configure a 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.
# AnyParameter interface
interface AnyParameter

The non-generic view of a parameter, used by discovery and resolution.

MemberSignatureDoc
resolve_ resolve_(raw: string | undefined): void Resolve from a raw input (or undefined when none was supplied).
isSet_ isSet_(): boolean Whether the parameter resolved to a defined value (used by .requires()).
stringValue_ stringValue_(): string | undefined The resolved value as a string, or undefined if unset (for masking).
name_? name_?: string Property name, assigned during discovery. Undefined until then.
description_? description_?: string Human-readable description shown in --help/--list.
kind_ kind_: ParamKind The runtime value kind.
required_ required_: boolean Whether a value must be supplied (no default).
options_? options_?: unknown The allowed string choices, if restricted with Parameter.options.
envName_? envName_?: string An explicit environment variable name override.
hasFallback_ hasFallback_: boolean Whether the parameter has a declared default value.
secret_ secret_: boolean Whether the value is sensitive and should be masked in CI output.
array_ array_: boolean Whether the value is a comma-separated / repeatable list (.array()).
source_? source_?: SecretSource A provider that resolves the value when no flag/env supplied one.
default_? 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.
# Architecture type
type Architecture = x86_64 | aarch64

The CPU architectures Zuke recognises.

# archiveOutputs function
async function archiveOutputs(outputs: unknown, host: OutputHost): Promise<Uint8Array>

Archive a target's outputs into a gzipped tar of their current contents.

# assert function
function assert(condition: unknown, message?: string): asserts condition

Assert that condition is truthy, narrowing it for the rest of the scope. Throws an AssertionError with message otherwise.

# assertDirectoryExists function
async function assertDirectoryExists(path: PathLike): Promise<void>

Assert that path exists and is a directory. Async (stats the filesystem).

# assertExists function
function assertExists(value: T, message?: string): NonNullable<T>

Assert that value is neither null nor undefined, returning it narrowed to its non-nullable type so it can be used inline.

const token = assertExists(Deno.env.get("TOKEN"), "TOKEN is required");
# assertFileExists function
async function assertFileExists(path: PathLike): Promise<void>

Assert that path exists and is a file. Async (stats the filesystem).

# AssertionError class
class AssertionError extends Error

Raised by the assertion helpers when an expectation fails.

MemberSignatureDoc
name name: string The error name.
# assertSafeEntryName function
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.

# assertSafeLinkTarget function
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 assertSafeEntryName; a symlink adds a second escape vector (its target), so a poisoned tarball can't plant bin/x -> ../../etc.

# assertWrapperConformance function
async function assertWrapperConformance(makeSettings: unknown, tool: string, options: WrapperConformanceOptions): Promise<void>

Assert that a tool wrapper conforms: makeSettings() spawns tool, resolves it per options.resolution, and reports a missing binary as a "./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/<tool> 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.

# box function
function box(style: Style, content: string | unknown, 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.

# BoxOptions interface
interface BoxOptions

Options for box.

MemberSignatureDoc
title? title?: string A title embedded in the top border.
padding? padding?: number Horizontal padding inside the border, in spaces. Defaults to 1.
width? width?: number Force an inner width; widened automatically to fit content and title.
border? border?: unknown Styles for the border characters. Defaults to ["dim"].
titleStyle? titleStyle?: unknown Styles for the title text. Defaults to ["bold"].
# Build class
class Build

Base class for user-defined builds. Provides no targets of its own; subclasses declare targets as properties. Optionally override the lifecycle hooks.

MemberSignatureDoc
onStart onStart(): void | Promise<void> Called once before any target runs.
onFinish onFinish(_result: BuildResult): void | Promise<void> Called once after the run completes (success or failure).
onTargetStart onTargetStart(_name: string): void | Promise<void> Called just before a target's body executes (not for skipped/cached).
onTargetEnd onTargetEnd(_name: string, _status: TargetStatus): void | Promise<void> Called after each target settles, with its final status.
recoverWith recoverWith(): Remediation[] Remediations applied to every target, running after each target's own "./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 remoteCache(): RemoteCacheStore | undefined The "./remote_cache.ts".RemoteCacheStore that shares target "./target.ts".TargetBuilder.outputs across machines. Override to declare one in code; the default is none, and — unless overridden — the executor falls back to "./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(): StateStore | undefined The "./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 <root>/.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" }); }); } ``
extraEdges extraEdges(_targets: Map<string, TargetBuilder>): 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<string, Target>) { // 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 orderWith(_targets: Map<string, TargetBuilder>): OrderingEdge[] | Promise<OrderingEdge[]> A lazy, per-run provider of soft ordering edges, merged with 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<string, Target>): Promise<OrderingEdge[]> { 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 registry(): BuildRegistry | undefined The "./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 <root>/.zuke/builds. Kept a separate concern from 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 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" }; }; } } ``
# BuildCache interface
interface BuildCache

The incremental cache used by the executor to skip up-to-date targets.

MemberSignatureDoc
upToDate upToDate(target: TargetBuilder): Promise<boolean> Whether target is up-to-date: it declares inputs, their fingerprint matches the last successful run, and every declared output still exists.
record record(target: TargetBuilder): Promise<void> Record target's current fingerprint after a successful run.
save save(): Promise<void> Persist the store if anything changed.
# BuildDescriptor interface
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.

MemberSignatureDoc
id id: string Stable id of the build (its class name, unless overridden).
name name: string Human-facing build name (the build class name).
location location: BuildLocation Where the build lives, so a runner can launch it.
surface surface: CliDescription The build's CLI surface, exactly as "../describe.ts".describeCli produces it.
actor actor: string Who registered the build (a resolved actor; secrets never appear here).
createdAt createdAt: string ISO-8601 timestamp when the build was first registered.
updatedAt updatedAt: string ISO-8601 timestamp of the last registration write.
# BuildLocation type
type BuildLocation = unknown | unknown

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.

# BuildQuery interface
interface BuildQuery

Filters for "./registry.ts".BuildRegistry.listBuilds; all fields optional.

MemberSignatureDoc
name? name?: string Keep only builds whose name equals this.
since? since?: string Keep only builds registered at or after this ISO-8601 timestamp.
# BuildRegistry interface
interface BuildRegistry

Pluggable persistence for BuildDescriptors. 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.

MemberSignatureDoc
getBuild getBuild(id: string): Promise<unknown | null> Fetch a build and its current version, or null if it is not registered.
register register(descriptor: BuildDescriptor, expectedVersion: string | null): Promise<PutBuildResult> 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 deregister(id: string): Promise<void> Remove a registered build by id; a missing build is not an error.
listBuilds listBuilds(query: BuildQuery): Promise<BuildSummary[]> List registered builds matching query, newest first (by createdAt, then id).
# BuildRegistryFactory type
type BuildRegistryFactory = unknown

A () => factory the kit calls once to obtain the registry under test.

# BuildResult interface
interface BuildResult

Result passed to the Build.onFinish lifecycle hook.

MemberSignatureDoc
ok ok: boolean Whether every executed target succeeded (also true for a suspended run).
executed executed: string[] Names of the targets that ran, in execution order.
error? error?: unknown The error that aborted the run, if any.
suspended? 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? 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? runId?: string The run's id, when a run identity was established (always, in practice — every "./executor.ts".execute generates one). Lets the caller point a follow-up (zuke runs show, zuke cancel) at this run.
# BuildSummary interface
interface BuildSummary

A compact registry listing row, returned by "./registry.ts".BuildRegistry.listBuilds.

MemberSignatureDoc
id id: string The build id.
name name: string The build name.
actor actor: string Who last registered the build.
createdAt createdAt: string ISO-8601 first-registration timestamp.
updatedAt updatedAt: string ISO-8601 timestamp of the last registration write.
# CancelOptions interface
interface CancelOptions

Options for cancelRun.

MemberSignatureDoc
runId runId: string The id of the run to cancel.
stateStore? 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? actor?: string Who to attribute the cancellation to in the audit trail.
readEnv? readEnv?: unknown Reads an environment variable (secrets re-resolve from here for compensations).
silent? silent?: boolean Suppress progress output.
reporter? reporter?: Reporter Custom reporter; overrides silent.
also? also?: string[] Extra compensation target names to run first (a timed-out wait whose onTimeout names a specific compensation target routes through here).
# CancelResult interface
interface CancelResult

The outcome of cancelRun.

MemberSignatureDoc
runId runId: string The run that was cancelled.
status status: RunStatus The run's status after cancelling (cancelled, or the terminal status on a no-op).
noop noop: boolean True when the run was already terminal and nothing was done.
compensated compensated: string[] Names of compensation targets whose bodies ran.
failures failures: CompensationFailure[] Compensations that threw (recorded, non-fatal).
# cancelRun function
async function cancelRun(build: Build, options: CancelOptions): Promise<CancelResult>

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.

# ChangedFilesFn type
type ChangedFilesFn = unknown

Lists the files changed since base (a git revision), each path relative to the repository root. The seam behind ExecuteOptions.affected; defaults to gitChangedFiles and is overridable so the affected plan can be tested without a real git repository.

# checkBuildRegistry function
async function checkBuildRegistry(make: BuildRegistryFactory): Promise<ConformanceResult[]>

Run the build-registry conformance scenarios against the registry make builds.

# checkStateStore function
async function checkStateStore(make: StateStoreFactory, options?: ConformanceOptions): Promise<ConformanceResult[]>

Run the state-store conformance scenarios against the store make builds.

# cicd function
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.

class MyBuild extends Build {
  ci = cicd({ provider: "github" }); // sensible default workflow
  // …or customise:
  gitlab = cicd({ provider: "gitlab", pipeline: { jobs: [{ steps: [...] }] } });
}
# CiConcurrency interface
interface CiConcurrency

A concurrency group: at most one run per group, optionally cancelling the prior one.

MemberSignatureDoc
group group: string The group key (often interpolated, e.g. ci-${{ github.ref }}).
cancelInProgress? cancelInProgress?: boolean Cancel an in-progress run in the same group when a new one starts.
# CiFile class
class CiFile

A declared CI file. Assign one (via cicd) to a build field and Zuke keeps the file on disk in sync with the definition when the build runs.

MemberSignatureDoc
pipelineFor pipelineFor(targets: Map<string, TargetBuilder>): CiPipeline The pipeline this file renders. With fan-out, the build's targets are expanded into one job per target; otherwise the declared pipeline.
render render(): string Render the file's YAML content (the base pipeline; fan-out is resolved at discovery).
provider provider: CiProvider The provider this file renders for.
path path: string The output path.
pipeline pipeline: CiPipeline The base pipeline (pipeline-level fields, and the jobs unless fanning out).
fanOut? fanOut?: FanOutOptions Fan-out options, when this file expands the build's targets into jobs.
# CiFileSpec interface
interface CiFileSpec

A CI configuration file declared on a build: a pipeline bound to a path.

MemberSignatureDoc
provider provider: CiProvider The provider to render for — the one field you must choose.
path? path?: string The output path (relative to the working directory). Defaults to the provider's conventional location (.github/workflows/ci.yml, .gitlab-ci.yml, or azure-pipelines.yml).
pipeline? pipeline?: CiPipeline The pipeline to render. Defaults to a single build job that runs the build.
fanOut? fanOut?: boolean | FanOutOptions Fan the build's targets out into one CI job per target, wired by their dependencies (see fanOutPipeline). true uses the defaults; pass FanOutOptions to customise. When set, pipeline supplies the pipeline-level fields (name, triggers, …) and its jobs are ignored.
# ciHost function
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 detectCiHost for new code: its values match CiProvider. This function is kept for compatibility and uses longer, host-specific names.

# CiHost type
type CiHost = github | gitlab | azure | bitbucket | local

The CI host a build is running on, or "local" when not on CI. The names match CiProvider so they compose with CI generation and per-host integrations (e.g. posting a review to the right pull-request API).

# CiJob interface
interface CiJob

A job: a named unit of work with steps, optionally fanned out by a matrix.

MemberSignatureDoc
id? id?: string Stable identifier, used as the job key and as a dependency target. Defaults to "build".
name? name?: string Human-readable job name.
runsOn? 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? needs?: string[] Other jobs (by id) that must finish before this one.
matrix? matrix?: Record<string, Array<string | number>> A build matrix: each key fans out over its values.
env? env?: Record<string, string> Environment variables for the job.
if? 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? timeoutMinutes?: number Fail the job if it runs longer than this many minutes.
steps? steps?: CiStep[] The steps to run, in order. Defaults to a single step that runs the build.
# CiPipeline interface
interface CiPipeline

A complete, provider-agnostic CI pipeline.

MemberSignatureDoc
name? name?: string The pipeline name. Defaults to "CI".
triggers? 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? permissions?: Record<string, string> Workflow-level token permissions (GitHub only), e.g. { contents: "read", "pull-requests": "write" }. Ignored elsewhere.
concurrency? concurrency?: CiConcurrency Limit concurrent runs (GitHub only). Ignored elsewhere.
jobs? jobs?: CiJob[] The jobs to run. Defaults to a single build job that runs the build.
# CiProvider type
type CiProvider = github | gitlab | azure | bitbucket

The CI providers generateCi can target.

# CiStep interface
interface CiStep

A single step in a job.

MemberSignatureDoc
name? name?: string Human-readable step name.
run? run?: string A shell command to run. Portable across all providers.
uses? uses?: string A GitHub Action reference (e.g. actions/checkout@v4). Rendered only for GitHub; skipped for GitLab and Azure.
with? with?: Record<string, string> Inputs for a uses Action (GitHub only).
env? env?: Record<string, string> 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).
# CiTriggers interface
interface CiTriggers

When the pipeline runs.

MemberSignatureDoc
push? 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? 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.
manual? manual?: boolean Allow manual runs (workflow dispatch / web).
schedule? 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 "./ci_schedule.ts".
# CliCommandInfo interface
interface CliCommandInfo

A reserved command (graph, generate-ci, completions).

MemberSignatureDoc
name name: string The command word.
description description: string One-line summary.
# CliDescription interface
interface CliDescription

A build's full CLI surface, suitable for JSON serialization.

MemberSignatureDoc
commands commands: CliCommandInfo[] The reserved positional commands.
flags flags: CliFlagInfo[] The built-in option flags.
targets targets: CliTargetInfo[] The build's targets, in declaration order.
parameters parameters: CliParameterInfo[] The build's declared parameters, in declaration order.
# CliFlagInfo interface
interface CliFlagInfo

A built-in option flag.

MemberSignatureDoc
name name: string The flag, with leading dashes.
description description: string One-line summary.
# CliParameterInfo interface
interface CliParameterInfo

A parameter declared on the build.

MemberSignatureDoc
name name: string The parameter's property name — the key an MCP tool call and execute's params map use (e.g. skipE2e). Distinct from flag, which is its kebab-case form.
flag flag: string The CLI flag (without leading dashes), e.g. skip-e2e.
description description: string The parameter's description, or "" when none was set.
required required: boolean Whether a value is required.
kind kind: string | number | boolean The parameter's value kind.
boolean boolean: boolean Whether the flag is a value-less boolean.
array array: boolean Whether repeated flags accumulate into a list.
options options: string[] The allowed values, when the parameter is constrained to a set.
default? default?: string The declared default rendered as a string, when the parameter has one.
# CliTargetInfo interface
interface CliTargetInfo

A target declared on the build.

MemberSignatureDoc
name name: string The target's name (its field name on the build).
description description: string The target's description, or "" when none was set.
dependsOn dependsOn: string[] The names of its direct dependencies, in declaration order.
default default: boolean Whether this is the conventional default target.
unlisted unlisted: boolean Whether the target is hidden from --list (still runnable by name).
# Command class
class Command

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.

MemberSignatureDoc
env env(record: Record<string, string>): this Merge additional environment variables.
cwd cwd(path: PathLike): this Set the working directory for the process.
noThrow noThrow(): this Do not throw on a non-zero exit; combine with code.
quiet quiet(): this Suppress live stdout/stderr streaming to the terminal.
killAfter killAfter(ms: number): this Kill the process if it runs longer than ms milliseconds, raising a CommandTimeoutError. Fires even under noThrow.
maxCapturedBytes 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, CommandOutput.truncated is set, and 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.
signal 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 killAfter: either the timeout or the abort kills the process, whichever fires first.
commandLine 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 CommandError message), so a secret passed as an argv token cannot leak through one. The argv given to the operating system is unchanged.
then then(onfulfilled?: unknown | null, onrejected?: unknown | null): PromiseLike<TResult1 | TResult2> Await support: run the command and resolve to a CommandOutput.
text text(): Promise<string> Run and resolve to trimmed stdout — prefixed with a truncation notice if the capture cap was hit. Throws on non-zero unless noThrow.
lines lines(): Promise<string[]> Run and resolve to stdout split into lines (trailing blank dropped).
code code(): Promise<number> Run and resolve to the numeric exit code. Never throws on non-zero.
spawn spawn(): SpawnedProcess Start the command as a long-lived process without waiting for it to exit, returning a 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 SpawnedProcess.stop. stdout/stderr are inherited so the process's output is visible.
# CommandError class
class CommandError extends Error

Raised when a command exits non-zero and throwing was not suppressed.

MemberSignatureDoc
name name: string The error name.
# CommandOutput class
class CommandOutput

The resolved result of a command, available when awaiting a Command.

MemberSignatureDoc
text text(): string Trimmed stdout, prefixed with a one-line notice when truncated — so a caller reading the output cannot mistake a tail for the whole of it.
# CommandTimeoutError class
class CommandTimeoutError extends Error

Raised when a command is killed for exceeding its Command.killAfter budget. Thrown regardless of Command.noThrow, since a timeout is a distinct, exceptional outcome from a normal non-zero exit.

MemberSignatureDoc
name name: string The error name.
# CompensationFailure interface
interface CompensationFailure

A compensation that threw during the cancel walk (recorded, non-fatal).

MemberSignatureDoc
target target: string The compensation target that failed.
forTarget forTarget: string The original target whose compensation this was.
error error: string The failure message.
# Condition type
type Condition = unknown

A predicate gating whether a target runs; may be synchronous or async.

# CONFIG_FILE const
const CONFIG_FILE: zuke.json

The Zuke config file name; its presence marks a repository root.

# Configure type
type Configure = unknown

A lambda that configures a settings instance and returns it.

# ConformanceCliDeps interface
interface ConformanceCliDeps

Injectable dependencies for runConformanceCli (tests override them).

MemberSignatureDoc
makeStateStore? makeStateStore?: unknown Build the StateStore for a url/token (default HttpStateStore).
makeBuildRegistry? makeBuildRegistry?: unknown Build the BuildRegistry for a url/token (default HttpBuildRegistry).
log? log?: unknown Emit a line of output (default console.log).
# ConformanceOptions interface
interface ConformanceOptions

Tuning options for the conformance scenarios.

MemberSignatureDoc
lockTtlMs? 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.
# ConformanceResult interface
interface ConformanceResult

The outcome of one conformance scenario.

MemberSignatureDoc
name name: string The scenario's name.
ok ok: boolean Whether the backend satisfied it.
error? error?: string The failure detail when ok is false.
# CopyOptions interface
interface CopyOptions

Options for FileTasksApi.copy.

MemberSignatureDoc
overwrite? overwrite?: boolean Overwrite an existing destination file (default true).
# CreateDirectoryOptions interface
interface CreateDirectoryOptions

Options for FileTasksApi.createDirectory.

MemberSignatureDoc
recursive? recursive?: boolean Create parent directories as needed (default true).
# createTarGzip function
async function createTarGzip(files: PathLike[], dest: PathLike, options?: unknown): Promise<void>

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.

# DEFAULT_POLL_INTERVAL_MS const
const DEFAULT_POLL_INTERVAL_MS: 200

How often ServiceBuilder.readyWhen is polled while waiting.

# DEFAULT_READY_TIMEOUT_MS const
const DEFAULT_READY_TIMEOUT_MS: 30000

The default time a service is given to become ready before it fails.

# DEFAULT_TOOLS_DIR const
const DEFAULT_TOOLS_DIR: .zuke/tools

The default directory a Toolchain (and ToolTasks) installs into.

# defaultRenderer const
const defaultRenderer: Renderer

The built-in renderer: Zuke's ruled headers and summary table.

# defaultStateHost const
const defaultStateHost: StateHost

The real, Deno-backed StateHost.

# defineTool function
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 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.

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
# DefineToolOptions interface
interface DefineToolOptions

Options for defineTool.

MemberSignatureDoc
subcommand? subcommand?: string | string[] Leading subcommand token(s) prepended to every invocation.
# describeCli function
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.

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).

# DescribeCliOptions interface
interface DescribeCliOptions

Options for describeCli.

MemberSignatureDoc
omitSecrets? omitSecrets?: boolean Drop .secret() parameters from the surface (used for registry descriptors).
# detectCiHost function
function detectCiHost(env?: unknown): 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.

# detectWidth function
function detectWidth(): number

Read the terminal width if available, clamped to a sane range.

# DiscordAnnouncementSettings class
class DiscordAnnouncementSettings extends AnnouncementSettings

Fluent settings for AnnounceTasksApi.discord. Bot mode (.bot().token(t).channel(c)) posts through the REST API with a bot token.

# discoverGroups function
function discoverGroups(build: Build): Map<string, Group>

Discover all parallel 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.

# discoverParameters function
function discoverParameters(build: object): Map<string, AnyParameter>

Discover all parameters declared on a build instance: scan its fields (recursing into plain-object component bundles) for Parameter values, bind each its dotted property path, and return a name → parameter map preserving declaration order.

# discoverTargets function
function discoverTargets(build: Build): Map<string, TargetBuilder>

Discover all targets declared on a build instance.

Scans the instance's fields (recursing into plain-object component bundles) for TargetBuilder values, assigns each its dotted property path, and returns a name → target map preserving declaration order.

# DownloadFn type
type DownloadFn = unknown

A download function: fetch url into the file at dest.

# DynamicToolSettings class
class DynamicToolSettings extends ToolSettings

Fluent settings for a defineTool tool: build the argv with DynamicToolSettings.arg/DynamicToolSettings.flag/DynamicToolSettings.option (in call order), plus all the shared chainers (cwd, env, noThrow, quiet, toolPath, args).

MemberSignatureDoc
arg arg(...values: Array<string | number>): this Append raw positional/argument tokens.
flag flag(name: string): this Append a boolean flag, e.g. flag("verbose")--verbose (or -v).
option option(name: string, value: string | number): this Append a flag and its value as two tokens, e.g. --output dist.
# envBuildRegistry function
function envBuildRegistry(readEnv: unknown, host: StateHost): BuildRegistry | undefined

Resolve a BuildRegistry from the environment, or undefined when none is configured. ZUKE_REGISTRY_URL (with an optional ZUKE_REGISTRY_TOKEN) selects an HttpBuildRegistry; otherwise ZUKE_REGISTRY_DIR selects a FileSystemBuildRegistry.

# envCacheStore function
function envCacheStore(readEnv: unknown): RemoteCacheStore | undefined

Resolve a RemoteCacheStore from the environment, or undefined when none is configured. ZUKE_REMOTE_CACHE_URL (with an optional ZUKE_REMOTE_CACHE_TOKEN) selects an HttpCacheStore; otherwise ZUKE_REMOTE_CACHE_DIR selects a FileSystemCacheStore.

# envStateStore function
function envStateStore(readEnv: unknown, host: StateHost): StateStore | undefined

Resolve a StateStore from the environment, or undefined when none is configured. ZUKE_STATE_URL (with an optional ZUKE_STATE_TOKEN) selects an HttpStateStore; otherwise ZUKE_STATE_DIR selects a FileSystemStateStore.

# envVarName function
function envVarName(name: string): string

The environment variable for a parameter: its path in SCREAMING_SNAKE_CASE.

# execSecret function
function execSecret(configure: Configure<ExecSecretSettings>): SecretSource

A SecretSource that runs a command and takes its standard output as the secret value. Configure it through an ExecSecretSettings lambda.

parameter("Vault token").secret().from(
  execSecret((s) => s.command("vault").arg("kv", "get", "-field=token", "secret/ci")),
);
# ExecSecretSettings class
class ExecSecretSettings

Fluent settings for execSecret: a command whose standard output is the secret. Configure the binary with ExecSecretSettings.command, arguments with ExecSecretSettings.arg, and optionally the environment and working directory. Output is trimmed of surrounding whitespace unless ExecSecretSettings.trim is turned off (some values are whitespace-sensitive).

MemberSignatureDoc
command command(binary: PathLike): this The binary to run (e.g. op, vault, gcloud). Required.
arg arg(...values: Array<string | number | AbsolutePath>): this Append one or more arguments to the command.
env env(record: Record<string, string>): this Merge additional environment variables for the process.
cwd cwd(path: PathLike): this Set the working directory for the process.
trim trim(on?: boolean): this Whether to trim surrounding whitespace from stdout (default true).
resolve_ resolve_(): Promise<string> 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 SecretError naming the command.
# execute function
async function execute(build: Build, root: TargetBuilder, options?: ExecuteOptions): Promise<BuildResult>

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.

# ExecuteOptions interface
interface ExecuteOptions

Options for execute.

MemberSignatureDoc
silent? silent?: boolean Suppress all banner/summary output (used by tests).
reporter? reporter?: Reporter Custom reporter; overrides silent.
plugins? 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? skip?: string[] Target names to skip even if they appear in the plan (CLI --skip).
parallel? 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? cache?: boolean | BuildCache Incremental caching: skip targets whose declared 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 BuildCache may be supplied directly (used in tests).
remoteCache? remoteCache?: RemoteCacheStore | false A RemoteCacheStore that shares target 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 BuildCache or is false.
params? params?: Record<string, string> Raw parameter values from the command line, keyed by parameter (property) name. Each declared Parameter is resolved from this map, then the environment, then its declared default before any target runs.
readEnv? readEnv?: unknown 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? prompt?: unknown 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? 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? affected?: AffectedOptions Restrict the run to the targets affected by files changed since a base git revision (CLI --affected[=<base>]). A target is affected when a changed file falls inside its declared 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? github?: boolean Force GitHub Actions output formatting on or off. Auto-detected from the GITHUB_ACTIONS environment variable when omitted.
color? 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 Renderer for the per-target banners and the end-of-build summary. Defaults to Zuke's built-in "./renderer.ts".defaultRenderer; @zuke/console exports an alternative a build can inject to restyle its output.
signal? 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 "./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 "./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?: StateStore | false Durable run state (see "./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 state is set — a filesystem store under <root>/.zuke/runs.
state? 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 stateStore, the build, or the environment.
actor? 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? resume?: ResumeState Continue a suspended run instead of starting a fresh one. Set by "./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.
# executionSet function
function executionSet(root: TargetBuilder): Set<TargetBuilder>

Compute the execution set for a requested target: the target plus the transitive closure of its hard dependencies.

# externalSignal function
function externalSignal(name: string): WaitTrigger

A trigger satisfied when a signal named name has been delivered to the run (via zuke resume <id> --signal <name>). The signal's payload is exposed to target bodies through "./target.ts".TargetContext signals.

# ExtractOptions interface
interface ExtractOptions

Options common to extractTarGzip and extractZip.

MemberSignatureDoc
strip? 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.
# extractTarGzip function
async function extractTarGzip(src: PathLike, destDir: PathLike, options?: ExtractOptions): Promise<void>

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 ExtractOptions.strip to drop leading path components.

# extractZip function
async function extractZip(src: PathLike, destDir: PathLike, options?: ExtractOptions): Promise<void>

Read the .zip at src, unpack it, and write each entry under destDir (creating parent directories as needed) — the zip counterpart of extractTarGzip. Entry names are validated so a malicious archive cannot escape destDir.

# fail function
function fail(message: string): never

Throw an AssertionError with message. Never returns.

# FanOutOptions interface
interface FanOutOptions

Options for fanOutPipeline: how a build's targets become parallel CI jobs.

MemberSignatureDoc
command? command?: unknown The command a job runs for its target, given the target name. Defaults to the ./zuke <target> launcher (which bootstraps Deno). Each job runs only its own target; its dependencies run in their own jobs and are shared via the remote cache, so pair fan-out with one.
setupSteps? 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 env.
runsOn? runsOn?: string The runner for every job (see CiJob.runsOn).
includeUnlisted? includeUnlisted?: boolean Include targets hidden from --list via .unlisted(). Defaults to false.
env? env?: Record<string, string> Environment variables set on every job (e.g. the remote-cache config).
# fanOutPipeline function
function fanOutPipeline(targets: Map<string, TargetBuilder>, 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 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 FanOutOptions.includeUnlisted) unlisted targets, are omitted, and needs edges to omitted targets are dropped.

# fileSecret function
function fileSecret(configure: Configure<FileSecretSettings>): SecretSource

A 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 FileSecretSettings lambda.

parameter("Registry password").secret().from(
  fileSecret((s) => s.path("/run/secrets/registry_password")),
);
# FileSecretSettings class
class FileSecretSettings

Fluent settings for fileSecret: read a secret from a file. Set the path with FileSecretSettings.path; the content is trimmed of surrounding whitespace unless FileSecretSettings.trim is turned off.

MemberSignatureDoc
path path(path: PathLike): this The file to read the secret from. Required.
trim trim(on?: boolean): this Whether to trim surrounding whitespace from the content (default true).
resolve_ resolve_(): Promise<string> Read the file and return its content as the secret. A missing or unreadable file throws a SecretError naming the path.
# FileSystemBuildRegistry class
class FileSystemBuildRegistry

A BuildRegistry that writes one <id>.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 "../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.

MemberSignatureDoc
getBuild getBuild(id: string): Promise<unknown | null> Fetch a build and the content-hash version of its stored file.
register register(descriptor: BuildDescriptor, expectedVersion: string | null): Promise<PutBuildResult> Publish descriptor under an exclusive lock, guarding the expected version.
deregister deregister(id: string): Promise<void> Remove a registered build under an exclusive lock; a missing file is a no-op.
listBuilds listBuilds(query: BuildQuery): Promise<BuildSummary[]> List builds matching query, newest first. Unreadable files are skipped.
# FileSystemCacheStore class
class FileSystemCacheStore

A RemoteCacheStore backed by a shared or mounted directory.

MemberSignatureDoc
get get(key: string): Promise<Uint8Array | null> Fetch the archived outputs stored under key, or null if there are none.
put put(key: string, artifact: Uint8Array): Promise<void> Store artifact (a gzipped tar of a target's outputs) under key.
# FileSystemStateStore class
class FileSystemStateStore

A StateStore that writes one <id>.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 "../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.

MemberSignatureDoc
getRun getRun(id: string): Promise<unknown | null> Fetch a run and the content-hash version of its stored file.
putRun putRun(record: RunRecord, expectedVersion: string | null): Promise<PutResult> Publish record under an exclusive lock, guarding the expected version.
listRuns listRuns(query: RunQuery): Promise<RunSummary[]> List runs matching query, newest first. Unreadable files are skipped.
deleteRun deleteRun(id: string): Promise<void> Delete a run's file (under its lock); a missing run is a no-op.
acquireLock acquireLock(key: string, holder: LockHolder, ttlMs: number): Promise<LockResult> Atomically acquire the lock key for holder, taking over if expired.
renewLock renewLock(key: string, token: string, ttlMs: number): Promise<boolean> Extend the lock key held under token; false if the token lost it.
releaseLock releaseLock(key: string, token: string): Promise<void> Release the lock key if still held under token; a no-op otherwise.
# FileTasks const
const FileTasks: FileTasksApi

Filesystem task functions for build scripts.

# FileTasksApi interface
interface FileTasksApi

The shape of FileTasks.

MemberSignatureDoc
exists exists(path: PathLike): Promise<boolean> Whether path exists.
homeDirectory 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 createDirectory(path: PathLike, options?: CreateDirectoryOptions): Promise<void> Create the directory at path. Creates parents by default (CreateDirectoryOptions.recursive); a recursive create is a no-op when the directory already exists.
cleanDirectory cleanDirectory(path: PathLike): Promise<void> Remove everything inside the directory at path, leaving an empty directory. A no-op if path does not exist (it is *not* created).
remove remove(path: PathLike, options?: RemoveOptions): Promise<boolean> 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 RemoveOptions.recursive) is rethrown.
copy copy(source: PathLike, destination: PathLike, options?: CopyOptions): Promise<void> Copy a file or directory tree from source to destination (directories are copied recursively).
move move(source: PathLike, destination: PathLike): Promise<void> Move (rename) source to destination.
readText readText(path: PathLike): Promise<string> Read the UTF-8 text content of the file at path.
writeText writeText(path: PathLike, content: string): Promise<void> Write content to the file at path, creating or truncating it.
readJson readJson(path: PathLike): Promise<T> Read and parse the JSON file at path.
# findCycle function
function findCycle(targets: Map<string, TargetBuilder>): string[] | null

Detect a cycle in the hard-dependency (dependsOn) graph across all targets.

# ForEachFactory type
type ForEachFactory = unknown

Builds one item's ordered pipeline of sub-targets for 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.

# ForEachItem interface
interface ForEachItem

One materialised fan-out item: a unique label plus its pipeline stages.

MemberSignatureDoc
key key: string A label unique within the fan-out, used to name the item's sub-targets.
stages stages: Record<string, TargetBuilder> The item's ordered pipeline stages, keyed by stage name.
# ForEachSettings class
class ForEachSettings

Fluent configuration for TargetBuilder.forEach, in the settings-lambda style: .forEach(items, factory, (s) => s.concurrency(3).continueOnItemFailure()). Sets the concurrency cap and whether one item's failure isolates it or stops the whole batch.

MemberSignatureDoc
concurrency 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 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.
concurrency_? concurrency_?: number Max item pipelines in flight at once; set by concurrency.
continueOnItemFailure_ continueOnItemFailure_: boolean Isolate a failed item from its siblings; set by continueOnItemFailure.
# ForEachSpec interface
interface ForEachSpec

The internal fan-out spec stored by TargetBuilder.forEach. Its ForEachSpec.materialize closure captures the item type, so the runtime list and factory are erased to concrete ForEachItems the executor can run without knowing the item type.

MemberSignatureDoc
materialize materialize: unknown Produce the per-item sub-target pipelines from the runtime list.
configure? configure?: Configure<ForEachSettings> Optional fan-out settings (concurrency, per-item failure isolation).
# formatDuration function
function formatDuration(ms: number): string

Format a duration in milliseconds as 1.2s.

# generateCi function
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.

# gitChangedFiles function
async function gitChangedFiles(base?: string, run?: unknown): Promise<string[]>

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.

# glob function
async function glob(pattern: string, options?: GlobOptions): Promise<string[]>

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.

# GlobOptions interface
interface GlobOptions

Options for glob.

MemberSignatureDoc
cwd? cwd?: string Directory to resolve the pattern against (default: Deno.cwd()).
# globToRegExp function
function globToRegExp(pattern: string): RegExp

Compile a glob pattern into an anchored RegExp that matches a full path. Exposed (and pure) for testing and custom matching.

# GraphError class
class GraphError extends Error

Raised when the build graph is invalid (cycle or unknown dependency).

MemberSignatureDoc
name name: string The error name.
# group function
function group(): Group

Create a parallel Group. Targets join it with TargetBuilder.partOf, and a downstream target can depend on the whole batch by passing the group to TargetBuilder.dependsOn.

checks = group();
lint = target().partOf(this.checks).executes(...);
format = target().partOf(this.checks).executes(...);
deploy = target().dependsOn(this.checks).executes(...);
# Group class
class Group

A parallel batch of targets, created with group. Targets join it via 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 TargetBuilder.dependsOn depends on every member at once.

MemberSignatureDoc
members_ members_: TargetBuilder[] Members that declared themselves part of this group, in declaration order.
name_? name_?: string Property name, assigned during discovery. Undefined until then.
# gunzip function
async function gunzip(data: Uint8Array): Promise<Uint8Array>

Gunzip-decompress data using the platform DecompressionStream.

# gzip function
async function gzip(data: Uint8Array): Promise<Uint8Array>

Gzip-compress data using the platform CompressionStream.

# hostPlatform function
function hostPlatform(): Platform

The current host's Platform (from Deno.build, with the OS normalised) — the analogue of "./host.ts".isCI for "what machine am I running on". Its os is a Zuke OperatingSystem (macos, not darwin); use the osLabel/archLabel helpers to name it for a download URL.

const p = hostPlatform();
p.os;                                          // "linux" | "macos" | "windows"
const cpu = p.archLabel({ x86_64: "amd64", aarch64: "arm64" });
# HttpBuildRegistry class
class HttpBuildRegistry

A 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.

MemberSignatureDoc
getBuild getBuild(id: string): Promise<unknown | null> GET /builds/:id → descriptor + ETag; a 404 is a miss.
register register(descriptor: BuildDescriptor, expectedVersion: string | null): Promise<PutBuildResult> PUT /builds/:id guarded by If-Match / If-None-Match; 412 → conflict.
deregister deregister(id: string): Promise<void> DELETE /builds/:id; a missing build (404) is not an error.
listBuilds listBuilds(query: BuildQuery): Promise<BuildSummary[]> GET /builds?name=&since= → an array of BuildSummary.
# HttpBuildRegistryOptions interface
interface HttpBuildRegistryOptions

Configuration for an HttpBuildRegistry.

MemberSignatureDoc
url url: string The base URL build endpoints are built under (any trailing slash is ignored).
token? token?: string A bearer token sent as Authorization: Bearer <token>, if set.
fetch? fetch?: fetch The fetch implementation; defaults to the global. Overridable for tests.
# HttpCacheStore class
class HttpCacheStore

A RemoteCacheStore backed by HTTP: GET <url>/<key> fetches an artifact (a 404 means a miss) and PUT <url>/<key> 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 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 restoreOutputs), so a poisoned store cannot write outside it.

MemberSignatureDoc
get get(key: string): Promise<Uint8Array | null> Fetch the archived outputs stored under key, or null if there are none.
put put(key: string, artifact: Uint8Array): Promise<void> Store artifact (a gzipped tar of a target's outputs) under key.
# HttpCacheStoreOptions interface
interface HttpCacheStoreOptions

Configuration for an HttpCacheStore.

MemberSignatureDoc
url url: string The base URL keys are appended to (any trailing slash is ignored).
token? token?: string A bearer token sent as Authorization: Bearer <token>, if set.
fetch? fetch?: fetch The fetch implementation; defaults to the global. Overridable for tests.
# httpDownload function
async function httpDownload(url: string, dest: PathLike, options?: HttpOptions): Promise<void>

Download url to dest, streaming the response body to the file. Creates or truncates dest. Throws HttpError on a non-2xx status.

# HttpError class
class HttpError extends Error

Raised when an HTTP request returns a non-2xx status. The URL appears in the message and on url, so it is passed through redactUrl first — userinfo and credential query params never reach a log.

MemberSignatureDoc
name name: string The error name.
status status: number The HTTP status code of the failing response.
url url: string The requested URL, with any credentials redacted.
# httpJson function
async function httpJson(url: string, options?: HttpOptions): Promise<T>

Fetch url and parse its body as JSON. Throws HttpError on non-2xx.

# HttpOptions interface
interface HttpOptions

Options shared by the HTTP helpers.

MemberSignatureDoc
headers? headers?: Record<string, string> Extra request headers (e.g. an Authorization token).
fetch? fetch?: fetch The fetch implementation to use. Defaults to the global fetch; override it to unit-test without network access.
# HttpStateStore class
class HttpStateStore

A 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 secret parameter or environment variable over a hard-coded value.

MemberSignatureDoc
getRun getRun(id: string): Promise<unknown | null> GET /runs/:id → record + ETag; a 404 is a miss.
putRun putRun(record: RunRecord, expectedVersion: string | null): Promise<PutResult> PUT /runs/:id guarded by If-Match / If-None-Match; 412 → conflict.
listRuns listRuns(query: RunQuery): Promise<RunSummary[]> GET /runs?status=&target=&since= → an array of RunSummary.
deleteRun deleteRun(id: string): Promise<void> DELETE /runs/:id; a missing run (404) is not an error.
acquireLock acquireLock(key: string, holder: LockHolder, ttlMs: number): Promise<LockResult> POST /locks/:key201 { token }, or 409 with the current holder.
renewLock renewLock(key: string, token: string, ttlMs: number): Promise<boolean> PUT /locks/:key renews; a 409/404 means the token lost the lock.
releaseLock releaseLock(key: string, token: string): Promise<void> DELETE /locks/:key releases; a missing lock (404) is not an error.
# HttpStateStoreOptions interface
interface HttpStateStoreOptions

Configuration for an HttpStateStore.

MemberSignatureDoc
url url: string The base URL run endpoints are built under (any trailing slash is ignored).
token? token?: string A bearer token sent as Authorization: Bearer <token>, if set.
fetch? fetch?: fetch The fetch implementation; defaults to the global. Overridable for tests.
# httpText function
async function httpText(url: string, options?: HttpOptions): Promise<string>

Fetch url and return its body as text. Throws HttpError on non-2xx.

# installNpmTool function
async function installNpmTool(spec: NpmToolSpec, options?: InstallNpmToolOptions): Promise<AbsolutePath>

Provision an npm-registry package as a version-pinned, cached tool and return the installed bin's AbsolutePath — hand it straight to a wrapper's .toolPath(...).

The package installs under <destDir>/npm/<name>@<version> via npm install --prefix <dir> --no-save <name>@<version>; 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).

# InstallNpmToolOptions interface
interface InstallNpmToolOptions

Options for installNpmTool.

MemberSignatureDoc
destDir? destDir?: PathLike The root tools directory; the package installs under <destDir>/npm/<name>@<version>. Defaults to "./tool.ts".DEFAULT_TOOLS_DIR (.zuke/tools).
run? run?: NpmRunner The npm-install runner. Defaults to the ambient npm; a test seam.
os? 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.
# InstallPlatform interface
interface InstallPlatform

The host identity: a Zuke OperatingSystem and Architecture.

MemberSignatureDoc
os os: OperatingSystem The operating system (normalised: macos, not darwin).
arch arch: Architecture The CPU architecture.
# installRelease function
async function installRelease(options: InstallReleaseOptions): Promise<AbsolutePath>

Download and install a release binary, returning its AbsolutePath. The path is ready to hand to a wrapper's .toolPath(...) (or CmdTasks).

With a 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.

# InstallReleaseOptions interface
interface InstallReleaseOptions

Options for installRelease.

MemberSignatureDoc
name name: string The tool name; also the installed binary's filename (.exe on Windows).
url url: unknown Resolve the download URL for the target Platform.
destDir destDir: PathLike The directory to install the binary into (created if missing).
archive? archive?: raw | tar.gz | zip The download format. "raw" (default) treats the download as the binary itself; "tar.gz" and "zip" unpack it and take binaryPath from inside. Many release assets ship one or the other.
binaryPath? binaryPath?: string For a "tar.gz" or "zip" archive, the binary's path within the archive. Defaults to name.
platform? platform?: InstallPlatform The platform to resolve the URL for. Defaults to hostPlatform. Override it to install a foreign binary or to unit-test URL resolution.
download? download?: DownloadFn The download implementation. Defaults to httpDownload; override it to unit-test without network access.
checksum? checksum?: string | unknown 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 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.
# installTree function
async function installTree(options: InstallTreeOptions): Promise<AbsolutePath>

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 AbsolutePath of its (stripped) root. installRelease extracts a single binary; installTree keeps the entire directory, symlinks included.

Because 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 InstallTreeOptions.bins are marked executable on POSIX. With a InstallTreeOptions.checksum the archive is verified before unpacking and a matching prior install is reused.

# InstallTreeOptions interface
interface InstallTreeOptions

Options for installTree.

MemberSignatureDoc
name name: string The tool name; the extracted tree lands in <destDir>/<name>.
url url: unknown Resolve the download URL for the target Platform.
destDir destDir: PathLike The directory the tree is installed under (created if missing).
archive archive: tar.gz | zip The archive format — a multi-file runtime always ships packed.
strip? 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; bins and the returned tree root are then relative to the stripped tree. Defaults to 0.
bins? bins?: unknown 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? platform?: InstallPlatform The platform to resolve for. Defaults to hostPlatform.
download? download?: DownloadFn The download implementation. Defaults to httpDownload; a test seam.
checksum? checksum?: string | unknown The expected SHA-256 (hex) of the downloaded archive — verified before anything is unpacked, and used as the cache key (see InstallReleaseOptions.checksum). Omit it and the tree is downloaded every time and not verified.
# Interpolatable type
type Interpolatable = string | number | AbsolutePath | Array<string | number | AbsolutePath>

A value that may be interpolated into a $ template.

# isCI function
function isCI(): boolean

Whether the build appears to be running in a CI environment.

# isStyleName function
function isStyleName(name: string): name is StyleName

Whether a string names one of the SGR styles.

# JsonValue type
type JsonValue = string | number | boolean | null | JsonValue[] | unknown

A JSON-serialisable value — the only thing that may be persisted in a target's TargetStateHandle, since run state is stored as JSON.

# line function
function line(style: Style, options?: LineOptions): string

A horizontal rule spanning the style's width (dimmed by default).

# LineOptions interface
interface LineOptions

Options for line.

MemberSignatureDoc
char? char?: string The character to repeat. Defaults to .
width? width?: number The rule width. Defaults to the style's width.
style? style?: unknown Styles applied to the whole rule. Defaults to ["dim"].
# LockConflictError class
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).

MemberSignatureDoc
name name: string The error name.
# LockHolder interface
interface LockHolder

Who holds a lock — surfaced to the loser of a conflict so it can act.

MemberSignatureDoc
actor actor: string The actor that acquired the lock.
runId runId: string The run that holds it (zuke cancel <runId> releases it).
since since: string ISO-8601 timestamp when it was acquired.
runUrl? runUrl?: string A link to the holding run (e.g. its CI job), when known.
# lockKey function
function lockKey(...parts: Array<string | number>): 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.

# LockResult type
type LockResult = unknown | unknown

The result of StateStore.acquireLock: a token proving ownership, or the current holder when the lock is already held.

# LockSettings class
class LockSettings

Fluent configuration for TargetBuilder.lock, in the settings-lambda style: .lock((s) => s.lockKey("deploy", repo).withTtl("4h")). Set the key (composed from sanitised parts with LockSettings.lockKey, or directly with LockSettings.key), the TTL, and an optional LockSettings.onConflict message. The lambda runs after parameters resolve, so the key may read this.<param>.value.

MemberSignatureDoc
lockKey lockKey(...parts: Array<string | number>): this Set the lock key from parts, sanitised and joined via "./state/lock.ts".lockKey — e.g. s.lockKey("deploy", repo).
key key(key: string): this Set the lock key directly (must be filename-safe; prefer lockKey).
withTtl 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 onConflict(render: unknown): this Render the guidance shown to a run that loses the lock. Receives the current "./state/lock.ts".LockHolder; the returned string becomes the failure message. Defaults to a generic "held by … then retry" line.
key_? key_?: string The resolved lock key; set by key or lockKey.
ttl_? ttl_?: string | number The TTL (a duration string or milliseconds); set by withTtl.
onConflict_? onConflict_?: unknown The conflict-guidance renderer; set by onConflict.
# McpIdentity interface
interface McpIdentity

A trusted caller identity, resolved per request by a McpIdentityHook (typically from an authenticating reverse proxy's header). Its McpIdentity.actor is the highest-precedence attribution — it overrides --actor, the environment, and the client's self-reported label for the call.

MemberSignatureDoc
actor actor: string The authenticated actor (e.g. an OAuth subject).
via? via?: string How the identity was established (e.g. "oauth-proxy"); informational.
# McpIdentityHook type
type McpIdentityHook = unknown

Resolve a trusted 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.

# McpRequestContext interface
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).

MemberSignatureDoc
headers headers: Headers The request headers; an empty Headers on stdio.
# missingTool function
function missingTool(settings: S): S

Point settings at a binary that cannot exist, so running it raises a "./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:

await assertRejects(() => BiomeTasks.check(missingTool), ToolNotFoundError);
# NpmRunner type
type NpmRunner = unknown

Runs npm install <args> — 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.

# NpmToolSpec interface
interface NpmToolSpec

A specification of an npm-registry package to provision as a tool.

MemberSignatureDoc
name name: string The npm package to install, e.g. "vitest" or "@nestjs/cli".
version version: string The exact version to pin, e.g. "4.1.9" — installed as name@version.
bin? 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 name.
# OnCancel type
type OnCancel = TargetBuilder | unknown

A compensation registered with 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.

# OnTimeout type
type OnTimeout = unknown

What a timed-out wait does — resolved from WaitSettings.onTimeout.

# OpenCacheOptions interface
interface OpenCacheOptions

Optional extras for openCache: a remote store and a warning sink.

MemberSignatureDoc
remote? remote?: RemoteCacheStore A RemoteCacheStore to restore outputs from (on a local miss) and upload them to (after a successful run). Applies only to targets that declare TargetBuilder.outputs.
warn? warn?: unknown Report a non-fatal remote-cache error (a get/put failure never fails the build).
# operatingSystem function
function operatingSystem(os?: Deno.build.os): OperatingSystem

The operating system as a Zuke 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 isCI.

import { operatingSystem } from "jsr:@zuke/core";
if (operatingSystem() === "macos") { ... }
# OperatingSystem type
type OperatingSystem = linux | macos | windows

The operating systems Zuke recognises — Deno's raw Deno.build.os values normalised to a friendly set (notably darwinmacos). Used across the ecosystem so builds branch on "macos" rather than the surprising "darwin".

# OrderingEdge type
type OrderingEdge = unknown

A soft ordering edge [before, after]: before must run before after, with no data dependency. Returned by "./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.

# OutputHost interface
interface OutputHost

Filesystem effects used to archive and restore a target's outputs.

MemberSignatureDoc
readFile readFile(path: string): Promise<Uint8Array | null> File contents, or null if the path does not exist.
stat stat(path: string): Promise<unknown | null> Whether a path exists and is a directory, or null if it is missing.
readDir readDir(path: string): Promise<string[]> The entry names within a directory.
writeFile writeFile(path: string, bytes: Uint8Array): Promise<void> Write a file, creating parent directories as needed.
# pad function
function pad(text: string, width: number, align?: left | right): string

Pad text to width visible columns, aligning left (default) or right.

# paint function
function paint(color: boolean, codes: string, text: string): string

Wrap text in ANSI codes when colour is enabled, otherwise return it as-is.

# parameter function
function parameter(description?: string): Parameter<string, string | undefined>

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.

# Parameter class
class Parameter

A typed build parameter. Declare one with 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.

MemberSignatureDoc
value value(): T The resolved value. Throws if read before the build resolves parameters.
isSet_ isSet_(): boolean Whether the parameter resolved to a defined value (used by .requires()).
stringValue_ stringValue_(): string | undefined The resolved value as a string, or undefined if unset (for masking).
secret secret(): Parameter<K, T> Mark the value as sensitive: it is masked in CI output (::add-mask::) and redacted from all of Zuke's reporter output. Pair with Parameter.from to resolve the value from a secret manager rather than the environment.
from from(source: SecretSource): Parameter<K, T> Resolve the value from a SecretSource (see execSecret / 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 Parameter.secret so the resolved value is redacted.
number number(this: Parameter<string, string | undefined>): Parameter<number, number | undefined> Parse the value as a number (e.g. --workers 4).
boolean boolean(this: Parameter<string, string | undefined>): Parameter<boolean, boolean> Treat the parameter as a boolean flag (e.g. --verbose); defaults to false.
options options(this: Parameter<string, string | undefined>, ...values: string[]): Parameter<string, string | undefined> Restrict a string parameter to a fixed set of choices.
default default(this: Parameter<K, K | undefined>, value: K): Parameter<K, K> Provide a default, making value non-optional (K).
required required(this: Parameter<K, K | undefined>): Parameter<K, K> Require a value, making value non-optional (K); errors if unsupplied.
env env(name: string): Parameter<K, T> Override the environment variable read as a fallback for this parameter.
array array(this: Parameter<E, E | undefined>): Parameter<E, E[]> 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_ resolve_(raw: string | undefined): void Resolve from a raw input (or undefined when none was supplied).
name_? name_?: string Property name, assigned during discovery. Undefined until then.
description_? description_?: string Human-readable description shown in --help/--list.
kind_ kind_: ParamKind The runtime value kind.
required_ required_: boolean Whether a value must be supplied (no default).
options_? options_?: unknown The allowed string choices, if restricted with Parameter.options.
envName_? envName_?: string An explicit environment variable name override.
hasFallback_ hasFallback_: boolean Whether the parameter has a declared default value.
secret_ secret_: boolean Whether the value is sensitive and should be masked in CI output.
array_ array_: boolean Whether the value is a comma-separated / repeatable list (.array()).
source_? source_?: SecretSource A provider that resolves the value when no flag/env supplied one.
default_? 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.
# ParameterError class
class ParameterError extends Error

Raised when a parameter value is invalid or read before resolution.

MemberSignatureDoc
name name: string The error name.
# ParamKind type
type ParamKind = string | number | boolean

A parameter's runtime kind tag.

# ParamValue type
type ParamValue = string | number | boolean

The value kinds a parameter can hold.

# parseDuration function
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.

# PathLike type
type PathLike = string | AbsolutePath

A filesystem path accepted by Zuke APIs: either a plain string or an AbsolutePath. Anywhere a tool wrapper or build helper takes a path, it accepts a PathLike and coerces it to a string.

# plan function
function plan(root: TargetBuilder, extra?: unknown): 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).

# Platform interface
interface Platform

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 InstallReleaseOptions.url and InstallReleaseOptions.checksum callbacks receive.

MemberSignatureDoc
osLabel osLabel(aliases?: Partial<Record<OperatingSystem, string>>): string The OS named for downloads: aliases[os], else the InstallPlatform.os itself.
archLabel archLabel(aliases?: Partial<Record<Architecture, string>>): string The arch named for downloads: aliases[arch], else the InstallPlatform.arch itself.
# Plugin interface
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.

MemberSignatureDoc
onStart? onStart?(run: RunInfo): void | Promise<void> Called once before any target runs, with the run's RunInfo.
onTargetStart? onTargetStart?(target: string, run: RunInfo): void | Promise<void> Called just before a target's body executes (not for skipped/cached), with the target name and the run's RunInfo.
onTargetEnd? onTargetEnd?(target: string, status: TargetStatus, timing: TargetTiming): void | Promise<void> Called after each target settles, with its final status and its TargetTiming (run id + duration).
onFinish? onFinish?(result: BuildResult, run: RunInfo): void | Promise<void> Called once after the run completes (success or failure), with the result and the run's RunInfo.
onRunStateChange? onRunStateChange?(record: RunRecord): void | Promise<void> Called on each run-level durable status change — the run going running, suspended, succeeded, failed, cancelling, or cancelled — with the current "./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 runningcancellingcancelled. 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.
name? name?: string A name for diagnostics (optional).
# prependPath function
function prependPath(dir: PathLike, os?: 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 "./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).

# PutBuildResult type
type PutBuildResult = unknown | unknown

The result of a BuildRegistry.register compare-and-swap write.

# PutResult type
type PutResult = unknown | unknown

The result of a StateStore.putRun compare-and-swap write.

# REDACTED const
const REDACTED: [redacted]

The placeholder a Redactor substitutes for each secret value.

# Redactor class
class Redactor

Collects secret values and masks them in text. Register a value with Redactor.add and rewrite a line with 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.

MemberSignatureDoc
add add(value: string): void Register a secret value to mask. Ignores empty strings and duplicates.
redact redact(line: string): string Replace every registered secret in line with REDACTED.
size size(): number The number of distinct secret values registered.
# Remediation interface
interface Remediation

A recovery step plugged into a target with 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.

MemberSignatureDoc
remediate remediate(context: RemediationContext): RemediationResult | Promise<RemediationResult> Inspect (and optionally repair) the failure; report whether to retry.
name? name?: string A name for diagnostics (optional).
# RemediationContext interface
interface RemediationContext

Context passed to a Remediation after a target body fails.

MemberSignatureDoc
target target: string The name of the failed target.
attempt attempt: number The 1-based recovery attempt (the body has already failed attempt times).
error 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.
# RemediationResult interface
interface RemediationResult

The outcome of one Remediation attempt.

MemberSignatureDoc
retry 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? summary?: string A one-line description of what was diagnosed or done, for diagnostics.
# remoteCacheKey function
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.

# RemoteCacheStore interface
interface RemoteCacheStore

A content-addressed store for archived target outputs, keyed by 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.

MemberSignatureDoc
get get(key: string): Promise<Uint8Array | null> Fetch the archived outputs stored under key, or null if there are none.
put put(key: string, artifact: Uint8Array): Promise<void> Store artifact (a gzipped tar of a target's outputs) under key.
# RemoveOptions interface
interface RemoveOptions

Options for FileTasksApi.remove.

MemberSignatureDoc
recursive? recursive?: boolean Remove a directory and its contents recursively, like rm -r.
# Renderer interface
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.

MemberSignatureDoc
targetHeader targetHeader(style: Style, name: string): string[] The banner that opens a target's section (a ::group:: under Actions).
targetPassFooter targetPassFooter(style: Style, name: string, ms: number): string[] The footer printed after a target body succeeds.
targetFailFooter targetFailFooter(style: Style, name: string, ms: number, error: unknown): unknown 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 targetDryRunFooter(style: Style, name: string): string[] The footer printed for a dry-run target that was never executed.
summaryBlock summaryBlock(style: Style, reports: TargetReport[], totalMs: number, ok: boolean): string[] The end-of-build summary block: the aligned table and closing verdict.
jobSummaryMarkdown jobSummaryMarkdown(reports: TargetReport[], totalMs: number, ok: boolean): string The GitHub Actions job-summary Markdown mirroring the terminal summary.
# repoRoot function
function repoRoot(...segments: string[]): AbsolutePath

The absolute path of the repository root — the directory containing CONFIG_FILE — with any segments appended. The returned value is an AbsolutePath, so it is itself callable for further joining.

repoRoot();                  // <root>
repoRoot("src", "main.ts");  // <root>/src/main.ts
repoRoot().join("dist");     // <root>/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.

# Reporter interface
interface Reporter

Sink for executor output, defaulting to the console. Overridable in tests.

MemberSignatureDoc
info info(line: string): void Write an informational line.
error error(line: string): void Write an error line.
# resolveBuildRegistry function
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 envBuildRegistry environment fallback, then — only when ResolveRegistryOptions.enableDefault — a filesystem registry under <root>/.zuke/builds.

# ResolveRegistryOptions interface
interface ResolveRegistryOptions

Inputs resolveBuildRegistry needs to build the default filesystem registry.

MemberSignatureDoc
readEnv readEnv: unknown Reads an environment variable (injectable for tests).
host host: StateHost Filesystem effects for the default/env filesystem registry.
defaultDir defaultDir: string Directory the default filesystem registry writes to (<root>/.zuke/builds).
enableDefault 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.
# resolveRemoteStore function
function resolveRemoteStore(option: RemoteCacheStore | false | undefined, declared: RemoteCacheStore | undefined, readEnv: unknown): 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 envCacheStore environment fallback.

# ResolveStateOptions interface
interface ResolveStateOptions

Inputs resolveStateStore needs to build the default filesystem store.

MemberSignatureDoc
readEnv readEnv: unknown Reads an environment variable (injectable for tests).
host host: StateHost Filesystem effects for the default/env filesystem store.
defaultDir defaultDir: string Directory the default filesystem store writes to (<root>/.zuke/runs).
enableDefault 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).
# resolveStateStore function
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 envStateStore environment fallback, then — only when ResolveStateOptions.enableDefault — a filesystem store under <root>/.zuke/runs. A plain build with no durable feature and no configuration gets undefined, so it carries zero overhead.

# restoreOutputs function
async function restoreOutputs(artifact: Uint8Array, host: OutputHost): Promise<string[]>

Restore the files in artifact (a gzipped tar produced by archiveOutputs) to disk, returning the paths written. Entry names are validated first: an absolute path or one escaping the workspace (..) is rejected before anything is written, so a malicious archive can't plant files outside the current directory.

# resumeCheck function
async function resumeCheck(build: Build, options: Omit<ResumeOptions, runId | signal | data> & unknown): Promise<unknown>

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 "./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 ResumeOptions.resumeDegraded still picks it up.

# ResumeOptions interface
interface ResumeOptions

Options for resumeRun.

MemberSignatureDoc
runId runId: string The id of the suspended run to resume.
stateStore? 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? signal?: string Deliver a signal by this name before resuming (satisfies externalSignal).
data? data?: JsonValue The signal's JSON payload (defaults to {}); ignored without signal.
params? params?: Record<string, string> Non-secret parameter overrides; the rest come from the record.
readEnv? readEnv?: unknown Reads an environment variable (secrets re-resolve from here).
actor? actor?: string Who to attribute the resumption to (stamped on the run).
forceGraph? forceGraph?: boolean Continue even if the build graph changed since the run was suspended.
resumeDegraded? resumeDegraded?: boolean Resume even though the record is "./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? silent?: boolean Suppress banner/summary output.
reporter? reporter?: Reporter Custom reporter; overrides silent.
plugins? 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.
# resumeRun function
async function resumeRun(build: Build, options: ResumeOptions): Promise<BuildResult>

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 "./executor.ts".execute, re-running only the not-yet-succeeded targets.

# ResumeState interface
interface ResumeState

The continuation state resumeRun hands to execute on a resume.

MemberSignatureDoc
record record: RunRecord The run being continued (already transitioned to running).
version version: string Its current store version, for the writer to continue from.
done done: ReadonlySet<string> Names of targets recorded succeeded — seeded as done, never re-run.
# resumeWhen function
function resumeWhen(check: unknown, 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 <id> --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).

# ResumeWhenOptions interface
interface ResumeWhenOptions

Options for resumeWhen.

MemberSignatureDoc
interval? interval?: string | number How often zuke resume --check should re-evaluate the predicate.
# run function
async function run(BuildClass: unknown, options?: RunOptions): Promise<void>

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.

await run(MyBuild);
// …with plugins:
await run(MyBuild, { plugins: [timing] });
# runConformanceCli function
async function runConformanceCli(args: string[], deps?: ConformanceCliDeps): Promise<number>

Run the conformance kit as a CLI: --url <base> (required) and --token <bearer> (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.

# RunEvent interface
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 RunEvent for every mutating or denied tool call; zuke runs show prints them.

MemberSignatureDoc
at at: string ISO-8601 time the call was recorded.
tool tool: string The tool called (e.g. run:deploy, signal_run).
actor actor: string Who made the call (a resolved actor; see "./record.ts".resolveActor).
outcome outcome: RunEventOutcome Whether the call ran, was denied by authorization, or errored.
args args: Record<string, string> The call's arguments, redacted — secret values masked, tokens dropped.
detail? detail?: string A short, redacted human detail (e.g. a denial reason), when present.
# RunEventOutcome type
type RunEventOutcome = ok | denied | error

The outcome recorded for an audited MCP tool call (see RunEvent).

# RunGraphNode interface
interface RunGraphNode

One entry of a run's graph-shape snapshot.

MemberSignatureDoc
name name: string The target's dotted name.
dependsOn dependsOn: string[] The dotted names of its direct dependencies.
# RunInfo interface
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.

MemberSignatureDoc
runId runId: string The run id, stable for every target in the run (and across a resume).
dryRun dryRun: boolean True when the run is a dry run (no target body executes).
# RunningService interface
interface RunningService

A started service the executor holds until it tears it down.

MemberSignatureDoc
stop stop(): Promise<void> Stop the service; never rejects (failures are the registry's concern).
name name: string The service's target name, for diagnostics.
# RunOptions interface
interface RunOptions

Options for run.

MemberSignatureDoc
args? args?: string[] Command-line arguments. Defaults to Deno.args.
plugins? plugins?: Plugin[] Lifecycle observers to run alongside the build's own hooks.
renderer? 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 Renderer) to restyle a build's output.
# RunQuery interface
interface RunQuery

Filters for "./store.ts".StateStore.listRuns; all fields are optional.

MemberSignatureDoc
status? status?: RunStatus Keep only runs with this status.
target? target?: string Keep only runs whose graph contains a target with this dotted name.
since? since?: string Keep only runs created at or after this ISO-8601 timestamp.
limit? 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.
# RunRecord interface
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.

MemberSignatureDoc
id id: string Unique run ID (matches "../target.ts".TargetContext runId).
build build: string The build class name.
rootTarget rootTarget: string The dotted name of the requested (root) target.
status status: RunStatus The run's lifecycle status.
actor actor: string Who started the run (resolved from --actor, ZUKE_ACTOR, or CI env).
createdAt createdAt: string ISO-8601 timestamp when the run was created.
updatedAt updatedAt: string ISO-8601 timestamp of the last write.
graph graph: RunGraphNode[] The graph shape the run planned, in declaration order.
params params: Record<string, string> Resolved parameter values, keyed by name. Secrets are always omitted.
targets targets: Record<string, TargetRunState> Per-target progress, keyed by dotted target name.
signals signals: Record<string, SignalRecord> External signals received so far, keyed by name (see .waitsFor(...)).
events events: RunEvent[] Append-only audit trail of MCP tool calls against this run (see RunEvent).
degraded? 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 "../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 "../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.
# runSettings function
function runSettings(settings: S, configure?: Configure<S>): Promise<CommandOutput>

Construct-configure-run: the shared shape of every task function.

export const MyTasks = {
  build: (configure?: Configure<MyBuildSettings>) =>
    runSettings(new MyBuildSettings(), configure),
};
# RunStatus type
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.

# RunSummary interface
interface RunSummary

A compact run listing row, returned by "./store.ts".StateStore.listRuns.

MemberSignatureDoc
id id: string The run ID.
build build: string The build class name.
rootTarget rootTarget: string The dotted name of the requested (root) target.
status status: RunStatus The run's lifecycle status.
actor actor: string Who started the run.
createdAt createdAt: string ISO-8601 creation timestamp.
updatedAt updatedAt: string ISO-8601 timestamp of the last write.
# ScheduleEntry interface
interface ScheduleEntry

A scheduled trigger: a 5-field cron expression in an optional IANA timezone.

MemberSignatureDoc
cron cron: string A standard 5-field cron expression (minute hour day-of-month month day-of-week).
tz? 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.
# SecretError class
class SecretError extends Error

Raised when a SecretSource cannot produce a value.

MemberSignatureDoc
name name: string The error name.
# SecretSource interface
interface SecretSource

A provider that resolves a secret's value on demand. Built by execSecret or fileSecret and attached to a parameter with .from(source); the framework calls SecretSource.resolve during parameter resolution.

MemberSignatureDoc
resolve resolve(): Promise<string> Produce the secret value, or throw SecretError on failure.
# service function
function service(): ServiceBuilder

Create a service target — a long-lived process kept running while its dependents execute. Configure it with ServiceBuilder.start / ServiceBuilder.readyWhen and depend on it from a target.

# ServiceBuilder class
class ServiceBuilder extends TargetBuilder

A long-lived target. Configure how it starts (ServiceBuilder.start), how to tell it is ready (ServiceBuilder.readyWhen), and — when the started handle is not self-stopping — how it stops (ServiceBuilder.stop). It inherits the ordering methods (dependsOn, before, after, description) from TargetBuilder; a service has no .executes body.

MemberSignatureDoc
start start(fn: unknown): this How to start the process. Return a ServiceHandle (e.g. $\…\.spawn()) so the service can be stopped on teardown; provide a custom ServiceBuilder.stop if the handle is not self-stopping.
readyWhen readyWhen(fn: unknown): 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 tcpReachable for the common "is the port accepting connections?".
readyTimeout readyTimeout(ms: number): this Override how long to wait for ServiceBuilder.readyWhen (default 30s).
stop stop(fn: unknown): this Custom teardown, given the handle ServiceBuilder.start returned.
launch_ launch_(name: string): Promise<RunningService> INTERNAL: start the service and wait until it is ready, returning a handle the executor stops on teardown. Throws 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).
# ServiceError class
class ServiceError extends Error

Raised when a service cannot start or does not become ready in time.

MemberSignatureDoc
name name: string The error name.
# ServiceHandle interface
interface ServiceHandle

A running service — whatever ServiceBuilder.start returns. Its ServiceHandle.stop tears it down; a {@link https://jsr.io/@zuke/core SpawnedProcess} is one, so .start(() => $\…\.spawn()) needs no explicit stop.

MemberSignatureDoc
stop stop(): void | Promise<void> Terminate the service. Called on teardown unless .stop() overrides it.
# ServiceRegistry class
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.

MemberSignatureDoc
register register(running: RunningService): void Record a started service to stop later.
size size(): number The number of services currently held.
stopAll stopAll(report: unknown): Promise<void> Stop every registered service, newest first, reporting each outcome.
# SGR const
const SGR: unknown

ANSI select-graphic-rendition codes, keyed by style name.

# sgrCodes function
function sgrCodes(names: unknown): string

Concatenate the escape codes for names (an unknown name contributes none).

# ShellArgsError class
class ShellArgsError extends Error

Raised when 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.

MemberSignatureDoc
name name: string The error name.
# shimFallbackArgv function
function shimFallbackArgv(argv: ReadonlyArray<string>, os: 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.

# SignalRecord interface
interface SignalRecord

A payload received for an external signal (see RunRecord.signals).

MemberSignatureDoc
data data: JsonValue The signal's JSON payload ({} when none was sent).
receivedAt receivedAt: string ISO-8601 timestamp when the signal was recorded.
# SlackAnnouncementSettings class
class SlackAnnouncementSettings extends AnnouncementSettings

Fluent settings for AnnounceTasksApi.slack. Bot mode (.bot().token(t).channel(c)) posts through the Web API (chat.postMessage).

# SlackApiError class
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).

MemberSignatureDoc
name name: string The error name.
# SpawnedProcess class
class SpawnedProcess

A long-lived process started with Command.spawn — the handle a {@link https://jsr.io/@zuke/core service} keeps alive. Unlike awaiting a Command, spawning does not wait for the process to exit; call 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.

MemberSignatureDoc
pid pid(): number The operating-system process id (-1 for a dry-run stub).
status status(): Promise<Deno.CommandStatus> Resolves when the process exits (immediate success for a dry-run stub).
stop stop(signal?: Deno.Signal, graceMs?: number): Promise<void> 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.
# splitShellArgs function
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"dab 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.

# StateHost interface
interface StateHost

Injected filesystem effects for "./fs_store.ts".FileSystemStateStore, so it stays unit-testable. The default implementation is defaultStateHost.

MemberSignatureDoc
readText readText(path: string): Promise<string | null> File contents, or null when the file does not exist.
writeText writeText(path: string, content: string): Promise<void> Write a file's contents, creating parent directories as needed.
rename rename(from: string, to: string): Promise<void> Rename a file (used to publish a temp file atomically).
createExclusive createExclusive(path: string): Promise<boolean> Create path exclusively: resolve true if it was created, false if it already existed. Used as an atomic lock marker.
remove remove(path: string): Promise<void> Remove a file; a missing file is not an error.
listDir listDir(path: string): Promise<string[]> The entry names in a directory, or [] when the directory is absent.
mkdirp mkdirp(path: string): Promise<void> Create a directory and any missing parents.
now now(): number The current time in epoch milliseconds — the clock for lock expiry (injectable for tests).
# StateStore interface
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.

MemberSignatureDoc
getRun getRun(id: string): Promise<unknown | null> Fetch a run and its current version, or null if it does not exist.
putRun putRun(record: RunRecord, expectedVersion: string | null): Promise<PutResult> 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 listRuns(query: RunQuery): Promise<RunSummary[]> List runs matching query, newest first (by createdAt, then id).
deleteRun deleteRun(id: string): Promise<void> 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 acquireLock(key: string, holder: LockHolder, ttlMs: number): Promise<LockResult> 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 renewLock(key: string, token: string, ttlMs: number): Promise<boolean> 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 releaseLock(key: string, token: string): Promise<void> Release the lock key if still held under token; a no-op otherwise.
# StateStoreFactory type
type StateStoreFactory = unknown

A () => factory the kit calls once to obtain the store under test.

# stripAnsi function
function stripAnsi(text: string): string

Strip ANSI escape sequences, leaving the visible text.

# Style re-export
Style
# StyleName type
type StyleName = unknown

A style name understood by sgrCodes, paint, and markup.

# stylize function
function stylize(color: boolean, names: unknown, text: string): string

Paint text in the named styles when color is enabled.

# SubcommandSettings class
class SubcommandSettings extends ToolSettings

Base for a wrapper over a CLI organised into subcommand groups — a command path built with command plus repeatable --flag [value] options built with flag. The agent and cloud wrappers (gh, gcloud, claude, gemini, codex) share this shape; each sets its binary via ToolSettings.defaultTool and, when needed, a fixed prefix via leadingTokens or between-command global flags via middleTokens.

The argv is assembled as [...leadingTokens(), ...command, ...middleTokens(), ...flags], keeping every token a discrete argv entry so command construction stays injection-free.

MemberSignatureDoc
command command(...parts: Array<string | number>): this Append command-path tokens — the group, verb, and operands — in order.
flag flag(name: string, value?: string | number): this Add an arbitrary flag. With a value it renders --name value; without one the bare --name. Repeatable.
# table function
function table(style: Style, columns: unknown, rows: unknown, 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.

# TableColumn interface
interface TableColumn

One column of a table.

MemberSignatureDoc
header header: string The column header.
align? align?: left | right Cell alignment. Defaults to left.
# TableOptions interface
interface TableOptions

Options for table.

MemberSignatureDoc
separator? separator?: string Column separator. Defaults to two spaces.
divider? divider?: boolean Draw a dividing rule under the header. Defaults to true.
headerStyle? headerStyle?: unknown Styles for the header row. Defaults to ["bold"].
dividerStyle? dividerStyle?: unknown Styles for the divider rule. Defaults to ["dim"].
# tar function
function tar(entries: TarEntry[]): Uint8Array

Create a ustar archive from the given entries (in order).

# TarEntry interface
interface TarEntry

A single entry within a tar archive — a regular file or a symbolic link.

MemberSignatureDoc
name name: string The entry's path inside the archive (≤ 100 bytes).
data data: Uint8Array The file contents (empty for a symlink entry).
linkname? 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.
# target function
function target(): TargetBuilder

Create a new, empty target builder.

# Target type
type Target = TargetBuilder

A configured target. Alias of TargetBuilder — the same object both builds and represents the target. Exposed as Target for use in signatures.

# TargetBuilder class
class TargetBuilder

The fluent builder returned by target. All configuration methods are chainable and return this. A body (via TargetBuilder.executes) is required before a target can be executed.

MemberSignatureDoc
description description(text: string): this Set the human-readable description shown in zuke --list.
dependsOn dependsOn(...targets: Array<TargetBuilder | Group>): this Declare hard prerequisites. References sibling targets via this.x, or a group (which expands to every member that has joined it).
partOf partOf(group: Group): this Join a parallel 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 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 outputs still exist. Repeatable.
outputs 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 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(...); ``
executes executes(fn: TargetFn): this Set the target body. May be async.
before before(...targets: TargetBuilder[]): this Run before the listed targets if both are in the plan (soft ordering).
after after(...targets: TargetBuilder[]): this Run after the listed targets if both are in the plan (soft ordering).
triggers triggers(...targets: TargetBuilder[]): this Pull the listed targets into the plan and run them *after* this one. The inverse of dependsOn: running this target triggers the others.
dependentFor dependentFor(...targets: TargetBuilder[]): this Declare this target as a prerequisite of the listed targets — the reverse of dependsOn: each listed target gains this one as a dependency, so this runs before them. Declare the listed targets above this one.
requires 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 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 unlisted(): this Hide this target from --list and --help (it can still be run by name).
readOnly 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 always(): this Run this target even after the build has failed — for cleanup/teardown that must happen regardless. It still waits for its own dependencies to complete; the build's overall result is unchanged. Repeatable conditions/inputs apply.
dryRunnable 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 $/"./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 "./executor.ts".TargetContext dryRun flag rather than trust the echoed result.
cacheKey cacheKey(fn: unknown): 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 produces(...paths: PathLike[]): this Declare artifact files/directories this target produces (metadata).
consumes consumes(...targets: Array<TargetBuilder | Group>): this Depend on the listed targets and consume their artifacts: equivalent to dependsOn for ordering, expressing that this target uses what they produces.
whenSkipped whenSkipped(behavior: run-dependencies | skip-dependencies): this When this target is skipped by an 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 timeout(ms: number): this Fail the target if its body runs longer than ms milliseconds (per attempt).
retry retry(times: number, delayMs?: number): this Retry the target body up to times more attempts on failure, optionally pausing delayMs between attempts. Combined with timeout, each attempt is bounded by the timeout.
validateBefore validateBefore(...validations: Validation[]): this Run one or more Validations *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 validateAfter(...validations: Validation[]): this Run one or more Validations *after* the target body completes successfully. Each runs in declaration order; the first to throw fails the target. Repeatable.
recoverWith recoverWith(...remediations: Remediation[]): this Attach one or more Remediations 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 recoverAttempts(times: number): this The maximum number of fix-then-rerun cycles attempted when the body fails and 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 lock(configure: Configure<LockSettings>): 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 "./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.<param>.value; compose composite keys with "./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 waitsFor(configure: Configure<WaitSettings>): 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 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 onCancel(compensation: OnCancel): this Register a compensation target that undoes this target's effect when the run is later cancelled (via zuke cancel <run-id>, 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 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 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 forEach(items: unknown, factory: ForEachFactory<Item>, configure?: Configure<ForEachSettings>): 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.<param>.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 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(), ); ``
description_? description_?: string Human-readable summary shown in --list.
dependsOn_ dependsOn_: TargetBuilder[] Hard prerequisites: these run (transitively) before this target.
before_ before_: TargetBuilder[] Soft ordering: this runs before the listed targets if both are planned.
after_ after_: TargetBuilder[] Soft ordering: this runs after the listed targets if both are planned.
fn_? fn_?: TargetFn The target body.
name_? name_?: string Property name, assigned during discovery. Undefined until then.
group_? group_?: Group The parallel batch this target belongs to, if any (set by partOf).
inputs_ inputs_: string[] Input files/directories whose contents key the cache (set by inputs).
outputs_ outputs_: string[] Output files/directories that must exist for a cache hit (set by outputs).
onlyWhen_ onlyWhen_: Condition[] Conditions gating execution; all must hold or the target is skipped.
triggers_ triggers_: TargetBuilder[] Targets pulled in and run after this one (set by triggers).
requires_ requires_: AnyParameter[] Parameters that must be set for this target (set by requires).
proceedAfterFailure_ proceedAfterFailure_: boolean Continue the build if this target fails (set by proceedAfterFailure).
always_ always_: boolean Run even after the build has failed (set by always).
unlisted_ unlisted_: boolean Hide this target from --list/--help (set by unlisted).
readOnly_ readOnly_: boolean Advertise this target as query-only over MCP (set by readOnly).
dryRunnable_ dryRunnable_: boolean Run this target's body under --dry-run with $ echoed (set by dryRunnable).
cacheKeys_ cacheKeys_: Array<unknown> Extra cache-key contributors beyond input files (set by cacheKey).
produces_ produces_: string[] Artifact paths this target produces (set by produces).
skipDependencies_ skipDependencies_: boolean When skipped by a condition, also skip dependencies (set by whenSkipped).
timeout_? timeout_?: number Per-attempt timeout in milliseconds, if set by timeout.
retries_ retries_: number Number of extra attempts on failure, set by retry.
retryDelay_ retryDelay_: number Delay between retry attempts in milliseconds.
validateBefore_ validateBefore_: Validation[] Validations run before the body (set by validateBefore).
validateAfter_ validateAfter_: Validation[] Validations run after the body (set by validateAfter).
recoverWith_ recoverWith_: Remediation[] Remediations run after the body fails (set by recoverWith).
recoverAttempts_ recoverAttempts_: number Max fix-then-rerun cycles when the body fails (set by recoverAttempts).
lock_? lock_?: Configure<LockSettings> Cross-run lock settings lambda, set by lock and run after params resolve.
waitsFor_? waitsFor_?: Configure<WaitSettings> External-event wait settings lambda, set by waitsFor and run when reached.
forEach_? forEach_?: ForEachSpec Fan-out spec, set by forEach: materialises per-item sub-target pipelines.
onCancel_? onCancel_?: unknown Compensation thunk, set by onCancel: runs on cancel iff this target succeeded.
# TargetContext interface
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.

MemberSignatureDoc
stateOf 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 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.
runId runId: string Unique ID of this run, stable for every target in the run.
target target: string Dotted name of the executing target.
signal signal: AbortSignal Aborted when the run is cancelled (see "./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.
state state: TargetStateHandle Durable per-target metadata. Persisted to the run's state store when one is configured (see "./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.
signals signals: ReadonlyMap<string, SignalRecord> Payloads of the external signals received so far, keyed by name (see .waitsFor(...) and "./wait.ts".externalSignal). Empty until a signal is delivered by zuke resume <id> --signal <name>.
dryRun dryRun: boolean True when the run is a dry run (bodies do not execute under a dry run).
# TargetFn type
type TargetFn = unknown

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.

# TargetReport interface
interface TargetReport

One row of the end-of-build summary.

MemberSignatureDoc
name name: string The target's name.
status status: TargetStatus The target's terminal status.
ms ms: number The target's wall-clock duration in milliseconds.
# TargetRunState interface
interface TargetRunState

The recorded progress of a single target.

MemberSignatureDoc
status status: TargetRunStatus The target's current status within the run.
meta meta: Record<string, JsonValue> Durable metadata written via "../target.ts".TargetStateHandle.
startedAt? startedAt?: string ISO-8601 timestamp when the body started, if it has.
endedAt? endedAt?: string ISO-8601 timestamp when the target settled, if it has.
error? error?: string The failure message when status is failed.
waitingFor? waitingFor?: WaitState The pending wait when status is waiting (set by .waitsFor(...)).
# TargetRunStatus type
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.

# TargetStateHandle interface
interface TargetStateHandle

A target's durable, per-target metadata, surfaced on TargetContext as state. Writes are persisted to the run's state store (see "./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.

MemberSignatureDoc
set set(patch: Record<string, JsonValue>): Promise<void> Merge a JSON patch into this target's persisted metadata (awaits the write).
get get(): Record<string, JsonValue> Read this target's persisted metadata (from prior attempts/runs too).
# TargetStatus type
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.

# TargetTiming interface
interface TargetTiming

Timing for a settled target, passed to Plugin.onTargetEnd.

MemberSignatureDoc
runId runId: string The run id (see RunInfo).
durationMs durationMs: number The target's wall-clock duration in milliseconds (0 for skipped/cached).
# tcpReachable function
async function tcpReachable(address: string): Promise<boolean>

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 ServiceBuilder.readyWhen.

.readyWhen(() => tcpReachable("localhost:5432"))
# TeamsAnnouncementSettings class
class TeamsAnnouncementSettings extends AnnouncementSettings

Fluent settings for AnnounceTasksApi.teams. Bot mode (.bot().token(t).team(id).channel(c)) posts through Microsoft Graph with a bearer token.

MemberSignatureDoc
team team(team: string): this Set the Teams team (group) id to post to in bot mode (Microsoft Graph).
# tokenize function
function tokenize(strings: ReadonlyArray<string>, values: ReadonlyArray<Interpolatable>): 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.

# toolchain function
function toolchain(configure?: unknown): Toolchain

Create a Toolchain. Configure it inline with a callback, or chain Toolchain.tool on the returned instance.

const tools = toolchain((t) =>
  t.tool((s) => s.name("helm").url(helmUrl))
   .tool((s) => s.name("kubectl").url(kubectlUrl))
);
# Toolchain class
class Toolchain

A declared set of external tools. Add tools with Toolchain.tool (a ToolInstallSettings lambda) and fetch them all with Toolchain.install. Build one with toolchain.

MemberSignatureDoc
tool tool(configure: Configure<ToolInstallSettings>): this Add a release tool, configured through a settings-lambda. Chainable.
tree tree(configure: Configure<ToolInstallSettings>): this Add a multi-file runtime tree (see ToolTasksApi.installTree), configured through a settings-lambda with .strip(...)/.bins(...). In install's result its entry is the extracted tree's root — a callable AbsolutePath, so root("bin") is the directory to put on PATH. Chainable.
npm npm(spec: NpmToolSpec): this Add an npm-registry package to provision as a version-pinned tool — installed under <destDir>/npm/<name>@<version> and keyed in install's result by its NpmToolSpec.name. See installNpmTool. Chainable.
tools tools(): unknown The configured release tools, in declaration order.
trees trees(): unknown The configured runtime trees, in declaration order.
npmTools npmTools(): unknown The configured npm-package tools, in declaration order.
install install(options?: ToolchainInstallOptions): Promise<Map<string, AbsolutePath>> 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 AbsolutePath. A tree's entry is its extracted root directory.
# ToolchainInstallOptions interface
interface ToolchainInstallOptions

Options for Toolchain.install.

MemberSignatureDoc
destDir? destDir?: PathLike Where tools without their own destDir install. Defaults to .zuke/tools.
download? download?: DownloadFn The download implementation for every release tool (defaults per installRelease).
npmRun? npmRun?: NpmRunner The npm-install runner for npm-package tools (defaults to the ambient npm; a test seam).
# ToolInstallSettings class
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 InstallReleaseOptions.

MemberSignatureDoc
name name(name: string): this The tool name; also the installed binary's filename (.exe on Windows).
url url(resolve: unknown): this Resolve the download URL for the target Platform.
destDir destDir(dir: PathLike): this The directory to install the binary into (created if missing).
archive archive(format: raw | tar.gz | zip): this Treat the download as a "tar.gz" or "zip" to unpack (default "raw", the bare binary). Pair with binaryPath for the binary inside.
binaryPath binaryPath(path: string): this For an archive, the binary's path within it (defaults to the name).
strip strip(components: number): this For a tree install (ToolTasksApi.installTree / 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 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 checksum(sha256: string | unknown): 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 InstallReleaseOptions.checksum).
platform platform(platform: InstallPlatform): this Resolve for a specific platform instead of the host (a foreign install).
download download(fn: DownloadFn): this Override the downloader (defaults to an HTTPS download; a test seam).
options_ options_(fallbackDestDir: PathLike): InstallReleaseOptions Build the InstallReleaseOptions, using fallbackDestDir when no destDir was set. Throws if a required field is missing.
treeOptions_ treeOptions_(fallbackDestDir: PathLike): InstallTreeOptions Build the InstallTreeOptions for a tree install, using fallbackDestDir when no 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.
name_? name_?: string The tool name, and the installed filename. Set by name.
url_? url_?: unknown Resolves the per-platform download URL. Set by url.
destDir_? destDir_?: PathLike Install directory (overrides the toolchain's). Set by destDir.
archive_? archive_?: raw | tar.gz | zip Download format. Set by archive.
binaryPath_? binaryPath_?: string The binary's path within a tar.gz. Set by binaryPath.
strip_? strip_?: number Leading path components to strip on a tree install. Set by strip.
bins_? bins_?: string[] Executable bins within a tree install. Set by bins.
checksum_? checksum_?: string | unknown Expected SHA-256 (or a per-platform resolver). Set by checksum.
platform_? platform_?: InstallPlatform The platform to resolve for. Set by platform.
download_? download_?: DownloadFn The download implementation. Set by download.
# ToolNotFoundError class
class ToolNotFoundError extends Error

Raised when a tool's binary cannot be found on the system.

MemberSignatureDoc
name name: string The error name.
# ToolResolution type
type ToolResolution = node_modules | path

How ToolSettings.run locates a wrapper's binary when no explicit 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/<tool>, falling back to PATH on a miss (so a package hoisted to a monorepo root runs with no .toolPath()).

# ToolSettings class
class ToolSettings

Abstract fluent base for tool settings. Subclasses provide the binary (defaultTool) and the pure subcommand argv (buildArgs); the base provides the shared chainers and run.

MemberSignatureDoc
env env(record: Record<string, string>): this Merge additional environment variables for the process.
cwd cwd(path: PathLike): this Set the working directory for the process.
noThrow noThrow(): this Do not throw on a non-zero exit; inspect code on the output instead.
throwsOnError throwsOnError(): boolean Whether a failure should throw — the default, or false after 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 quiet(): this Suppress live stdout/stderr streaming to the terminal.
killAfter killAfter(ms: number): this Kill the tool if it runs longer than ms milliseconds, raising a CommandTimeoutError. Fires even under noThrow.
maxCapturedBytes 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.
toolPath toolPath(path: PathLike): this Override the binary to run (e.g. an absolute path to the tool).
fromNodeModules fromNodeModules(): this Resolve the binary npx-style: walk up from the working directory looking for node_modules/.bin/<tool>, falling back to PATH on a miss. Overrides both the wrapper default and the ambient ZUKE_TOOL_RESOLUTION. Has no effect once toolPath is set (an explicit path always wins).
fromPath fromPath(): this Resolve the binary from PATH only, ignoring any node_modules/.bin.
args args(...extra: Array<string | number | AbsolutePath>): this Escape hatch: append raw arguments after all typed options.
argv argv(): string[] The full argv (binary first). Pure — useful for tests and diagnostics.
resolvedArgv resolvedArgv(): string[] The argv run will actually spawn — like 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.
run run(): Promise<CommandOutput> 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 ToolNotFoundError naming the tool.
os_ os_: Deno.build.os The platform identifier used by 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.
# ToolTask type
type ToolTask = unknown

A ready-to-run task for a defineTool tool.

# ToolTasks const
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 toolchain.

# ToolTasksApi interface
interface ToolTasksApi

The task surface of ToolTasks.

MemberSignatureDoc
install install(configure: Configure<ToolInstallSettings>): Promise<AbsolutePath> Install a single release tool, configured through a ToolInstallSettings lambda, and resolve to its installed path. Defaults the install directory to .zuke/tools.
installTree installTree(configure: Configure<ToolInstallSettings>): Promise<AbsolutePath> Install a multi-file runtime tree (Node.js, a JDK, …) from one archive, configured through a ToolInstallSettings lambda, and resolve to the extracted tree's root 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 installTree; group several with Toolchain.tree.
npm npm(spec: NpmToolSpec, options?: InstallNpmToolOptions): Promise<AbsolutePath> 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 installNpmTool; group several with Toolchain.npm.
# untar function
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.

# unzip function
async function unzip(archive: Uint8Array): Promise<TarEntry[]>

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.

# validateGraph function
function validateGraph(targets: Map<string, TargetBuilder>): void

Validate the whole graph: unknown references first, then cycles.

# Validation interface
interface Validation

A check plugged into a target with TargetBuilder.validateBefore or TargetBuilder.validateAfter. The target decides *when* it runs; the validation decides *what* it checks. Throw from 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.

MemberSignatureDoc
validate validate(context: ValidationContext): void | Promise<void> Run the check; throw to fail the target. May be async.
name? name?: string A name for diagnostics (optional).
# ValidationContext interface
interface ValidationContext

Context passed to a Validation when it runs.

MemberSignatureDoc
target target: string The name of the target the validation is attached to.
# visibleWidth function
function visibleWidth(text: string): number

The printable width of text, ignoring any ANSI colour codes it carries.

# WaitContext interface
interface WaitContext

The durable context a WaitTrigger may use while deciding whether its event has occurred. Its 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.

MemberSignatureDoc
state 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.
runId runId: string The run id — stable across a resume, so a natural correlation key.
target target: string The awaiting target's dotted name.
# WaitDisposition type
type WaitDisposition = fail | cancel-run | unknown

What a timed-out wait does: fail, cancel the run, or run a compensation target.

# WaitSettings class
class WaitSettings

Fluent configuration for TargetBuilder.waitsFor: .waitsFor((s) => s.on(externalSignal("approved")).timeout("72h")). Set the trigger, an optional WaitSettings.timeout, and an optional WaitSettings.onTimeout disposition. The lambda runs when the target is reached, so the trigger may read this.<param>.value.

MemberSignatureDoc
on on(trigger: WaitTrigger): this Set the "./wait.ts".WaitTrigger the wait is satisfied by.
timeout timeout(duration: string | number): this Give the wait a deadline (a duration like "72h" or milliseconds).
onTimeout 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".
trigger_? trigger_?: WaitTrigger The trigger deciding when the wait is satisfied; set by on.
timeout_? timeout_?: string | number The deadline duration (string or ms); set by timeout.
onTimeout_? onTimeout_?: OnTimeout The timeout disposition thunk; set by onTimeout.
# WaitState interface
interface WaitState

The pending wait recorded on a suspended target (see TargetRunState.waitingFor).

MemberSignatureDoc
trigger trigger: string A human-readable descriptor of what is awaited (e.g. signal:approved).
deadline? deadline?: string ISO-8601 deadline after which onTimeout applies, if a timeout was set.
onTimeout onTimeout: WaitDisposition What happens when the deadline passes.
# WaitTrigger interface
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 WaitContext) when the target is reached and again on each resume attempt.

MemberSignatureDoc
isSatisfied isSatisfied(signals: ReadonlyMap<string, SignalRecord>, context: WaitContext): boolean | Promise<boolean> Whether the awaited event has occurred, given the run's received signals and a durable 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).
descriptor descriptor: string A short label recorded on the wait (e.g. signal:approved).
pollIntervalMs? pollIntervalMs?: number Poll interval hint (ms) for predicate triggers driven by zuke resume --check.
# windowsCmdShim function
function windowsCmdShim(argv: ReadonlyArray<string>, os: 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.

# WrapperConformanceOptions interface
interface WrapperConformanceOptions

Options for assertWrapperConformance.

MemberSignatureDoc
resolution 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.