npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nlindstedt/zig-workflow

v0.9.0

Published

TypeScript SDK for zig — workflow orchestration engine for AI coding agents

Downloads

1,030

Readme

Zig TypeScript Binding

TypeScript binding for zig — a workflow orchestration engine for AI coding agents.

Prerequisites

  • Node.js 18+
  • The zig CLI binary installed and on your PATH (or set via ZIG_BIN env var)
  • At least one AI agent CLI (claude, codex, gemini, copilot, ollama) for workflow execution

Installation

npm install @nlindstedt/zig-workflow

Development setup

To work with the binding from source:

cd bindings/typescript
npm install
npm run build

Quick start

import { ZigBuilder } from "@nlindstedt/zig-workflow";

// Run a workflow
const output = await new ZigBuilder()
  .run("deploy-pipeline");

console.log(output);

Running workflows

import { ZigBuilder } from "@nlindstedt/zig-workflow";

// Non-interactive — capture stdout
const output = await new ZigBuilder()
  .run("my-workflow", "additional context");

// Interactive — inherits terminal stdio
await new ZigBuilder()
  .runInteractive("my-workflow");

// Stream output lines as they arrive
for await (const line of new ZigBuilder().stream("my-workflow")) {
  console.log(line);
}

Bidirectional streaming sessions

runStreaming() returns a StreamingSession with piped stdin for sending input mid-flight. Call .close({ timeout }) when you are done to shut the session down gracefully:

const session = new ZigBuilder()
  .autoCleanup()
  .runStreaming("interactive-workflow");

for await (const line of session.lines()) {
  console.log(line);
}

await session.close({ timeout: "5s" });

Automatic orphan cleanup

Long-running Node servers can leak agent subprocesses if the parent process dies unexpectedly. Opt in to .autoCleanup() on the builder to install process-wide shutdown handlers that SIGTERM every tracked live session:

const session = new ZigBuilder()
  .autoCleanup()
  .runStreaming("my-workflow");

Off by default so the SDK imposes no global side effects on consumers that don't need them.

Validating workflows

import { ZigBuilder, ZigError } from "@nlindstedt/zig-workflow";

try {
  const msg = await new ZigBuilder().validate("deploy.zwf");
  console.log(msg); // "workflow 'deploy' is valid (3 steps)"
} catch (err) {
  if (err instanceof ZigError) {
    console.error("Validation failed:", err.stderr);
  }
}

Managing workflows

import { ZigBuilder } from "@nlindstedt/zig-workflow";

const zig = new ZigBuilder();

// List available workflows
const listing = await zig.workflowList();
console.log(listing);

// Show workflow details
const details = await zig.workflowShow("deploy");
console.log(details);

// Delete a workflow
await zig.workflowDelete("old-workflow");

// Create a workflow interactively
await zig.workflowCreate({
  name: "new-workflow",
  pattern: "fan-out",
});

Parsing .zwf files

The SDK includes a lightweight TOML parser for reading .zwf workflow files directly from Node.js without spawning the CLI:

import { parseWorkflow, parseWorkflowFile } from "@nlindstedt/zig-workflow";

// Parse from a string
const workflow = parseWorkflow(`
[workflow]
name = "example"
description = "An example workflow"

[[step]]
name = "greet"
prompt = "Say hello"
provider = "claude"
model = "sonnet"
`);

console.log(workflow.workflow.name);     // "example"
console.log(workflow.steps[0].provider); // "claude"

// Parse from a file
const wf = await parseWorkflowFile("./deploy.zwf");
console.log(wf.steps.length);

Builder methods

| Method | Description | |--------|-------------| | .bin(path) | Override the zig binary path (default: ZIG_BIN env or "zig") | | .debug() | Enable debug logging | | .quiet() | Suppress all output except errors | | .autoCleanup(enabled?) | Install process-wide shutdown handlers for orphan cleanup |

Terminal methods

| Method | Returns | Description | |--------|---------|-------------| | .run(workflow, prompt?) | Promise<string> | Run a workflow non-interactively, return stdout | | .runInteractive(workflow, prompt?) | Promise<void> | Run a workflow interactively (inherits stdio) | | .stream(workflow, prompt?) | AsyncGenerator<string> | Stream stdout lines as they arrive | | .runStreaming(workflow, prompt?) | StreamingSession | Bidirectional streaming with piped stdin/stdout | | .validate(workflow) | Promise<string> | Validate a .zwf file | | .workflowList() | Promise<string> | List available workflows | | .workflowShow(workflow) | Promise<string> | Show workflow details | | .workflowDelete(workflow) | Promise<string> | Delete a workflow | | .workflowCreate(options?) | Promise<void> | Create a workflow interactively | | .listen(options?) | Promise<void> | Tail a running/completed session | | .workflowPack(path, output?) | Promise<string> | Pack a workflow directory into a .zwfz zip archive | | .man(topic?) | Promise<string> | Show a manual page topic |

Utility functions

| Function | Returns | Description | |----------|---------|-------------| | parseWorkflow(content) | Workflow | Parse a TOML .zwf string into a typed Workflow object | | parseWorkflowFile(path) | Promise<Workflow> | Read and parse a .zwf file from disk | | zagSessionName(workflow, step) | string | Compute the zag session name for a single step (zig-{workflow}-{step}) | | zagSessionNames(workflow) | Record<string, string> | Extract all zag session names from a parsed workflow |

Workflow types

The SDK exports TypeScript types that mirror the Rust data model:

import type {
  Workflow,
  WorkflowMeta,
  Role,
  Variable,
  VarType,
  Step,
  FailurePolicy,
  StepCommand,
  Pattern,
} from "@nlindstedt/zig-workflow";

Orchestration patterns

The Pattern type covers the seven orchestration patterns supported by zig:

| Pattern | Description | |---------|-------------| | "sequential" | Steps run in order, each feeding the next | | "fan-out" | Parallel independent steps, then synthesize | | "generator-critic" | Generate, evaluate, iterate until quality threshold | | "coordinator-dispatcher" | Classify input, route to specialized handlers | | "hierarchical-decomposition" | Break down into sub-tasks, delegate, synthesize | | "human-in-the-loop" | Automated steps with human approval gates | | "inter-agent-communication" | Agents collaborate via shared variables |

Bridging to zag-agent

Zig names each zag session deterministically as zig-{workflowName}-{stepName}. The SDK exposes helpers to compute these names so you can use @nlindstedt/zag-agent to control individual agent sessions spawned by a workflow:

import { parseWorkflowFile, zagSessionName, zagSessionNames } from "@nlindstedt/zig-workflow";
import { ZagBuilder } from "@nlindstedt/zag-agent";

// Single step session name
const session = zagSessionName("deploy", "lint");
// "zig-deploy-lint"

// All session names from a workflow file
const wf = await parseWorkflowFile("deploy.zwf");
const sessions = zagSessionNames(wf);
// { lint: "zig-deploy-lint", test: "zig-deploy-test", deploy: "zig-deploy-deploy" }

// Use with zag-agent to control the agent session
const output = await new ZagBuilder()
  .session(sessions.lint)
  .continueLast();

Error handling

import { ZigBuilder, ZigError, ZigVersionError } from "@nlindstedt/zig-workflow";

try {
  await new ZigBuilder().run("my-workflow");
} catch (err) {
  if (err instanceof ZigVersionError) {
    console.error(`Requires zig >= ${err.requiredVersion}, have ${err.installedVersion}`);
  } else if (err instanceof ZigError) {
    console.error("Process failed:");
    console.error("  Exit code:", err.exitCode);
    console.error("  Stderr:", err.stderr);
  } else {
    throw err;
  }
}

How it works

The SDK spawns the zig CLI as a subprocess and captures stdout/stderr. Zero external runtime dependencies — only Node.js built-ins.

Testing

npm run build && npm test

See also

License

MIT