Sign In

@taskflow-corp/cli

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install
This package has malicious versions linked to the ongoing "Mini Shai-Hulud" supply chain attack.

Affected versions:

0.1.240.1.250.1.26
+3 more
View campaign page

@taskflow-corp/cli

Multi-agent orchestration harness for AI coding agents (claude-code, codex, cursor, opencode, pi). Async-await TypeScript API; lifecycle hooks; auto-todos with verify-loop.

latest
Source
npmnpm
Version
0.1.23
Version published
Weekly downloads
20
Maintainers
1
Weekly downloads
 
Created
Source

@taskflow-corp/cli

npm version CI Release License: MIT Node

Multi-agent orchestration harness for AI coding agents (claude-code, codex, cursor, opencode, pi). Async-await TypeScript API; lifecycle hooks; auto-todos with verify-loop.

Install

npm install @taskflow-corp/cli

Quick start

import { taskflow } from '@taskflow-corp/cli';

await taskflow('hello').run(async ({ phase, session }) => {
  await phase('greet', async () => {
    await session('say-hi', { with: 'claude-code', task: 'Print hello world' });
  });
});

Install harnesses from anywhere — taskflow add

Shadcn-style distribution: drop any harness into any project with a single command. You never need to install the package locally — npx @taskflow-corp/cli@latest <command> works from any directory and always pulls the newest version.

Source formats (every form accepted by add)

# 1. Bare name — built-in @taskflow registry
#    resolves against TASKFLOW_REGISTRY_URL (default https://taskflow.sh/r/{name}.json)
npx @taskflow-corp/cli@latest add example-hello

# 2. Namespaced — @ns/name, looked up in taskflow.json `registries` map
npx @taskflow-corp/cli@latest add @acme/e2e-video-tests
npx @taskflow-corp/cli@latest add @acme/e2e-video-tests@^1.2.0        # optional semver tail

# 3. Raw URL — any server returning a valid registry-item.json
npx @taskflow-corp/cli@latest add https://example.com/r/harness.json
npx @taskflow-corp/cli@latest add https://raw.githubusercontent.com/you/repo/main/r/x.json

# 4. Local file — absolute, relative, or ~/-prefixed
npx @taskflow-corp/cli@latest add ./my-harness.json
npx @taskflow-corp/cli@latest add /abs/path/harness.json
npx @taskflow-corp/cli@latest add ~/shared/harness.json

# 5. Bare GitHub shortcut (degit-style) — defaults to github.com
npx @taskflow-corp/cli@latest add user/repo
npx @taskflow-corp/cli@latest add user/repo/path/to/item.json         # subpath
npx @taskflow-corp/cli@latest add user/repo/path/to/item.json#v1.2.0  # branch | tag | sha

# 6. Explicit host shortcut — github: / gitlab: / bitbucket:
npx @taskflow-corp/cli@latest add github:user/repo/items/foo.json#main
npx @taskflow-corp/cli@latest add gitlab:user/repo/items/foo.json#v1
npx @taskflow-corp/cli@latest add bitbucket:user/repo/items/foo.json

# 7. Fully qualified (Terraform grammar, for private SSH, integrity pinning, etc.)
#    Format: <type>::<url>[//<subpath>][?ref=<ref>&sha256=<hex>&depth=<n>]
npx @taskflow-corp/cli@latest add git::https://host/org/repo.git//items/foo.json?ref=v1
npx @taskflow-corp/cli@latest add git::ssh://git@github.com/you/priv.git//items/foo.json?ref=main
npx @taskflow-corp/cli@latest add https::https://example.com/bundle.json?sha256=abc123
npx @taskflow-corp/cli@latest add file::./local/harness.json

Detection order (first match wins, mirrors shadcn's resolver):

  • ends with .json and not a URL → local file
  • git:: / https:: / file:: prefix → fully qualified
  • github: / gitlab: / bitbucket: prefix → host shortcut
  • parses as a URL → raw URL
  • @ns/namenamespace lookup
  • user/repo[/subpath][#ref]bare GitHub shortcut
  • otherwise → bare name (built-in @taskflow registry)

Every form resolves to: fetch → validate (Zod) → write files → patch .agents/taskflow/config.ts (ts-morph AST merge) → merge .env.local → upsert taskflow.lock.

Multiple sources in one call

npx @taskflow-corp/cli@latest add example-hello @acme/video-tests ./local.json

registryDependencies from each item are resolved transitively (BFS + Kahn topo sort with cycle tolerance), so one command can pull a whole dependency graph.

Lifecycle commands

CommandPurpose
taskflow initScaffold taskflow.json + .agents/taskflow/config.ts + harness/rules dirs (auto-invoked by add on first use)
taskflow add <source...>Install one or more harnesses
taskflow view <source>Print the resolved registry-item JSON (no write, no install)
taskflow listList installed harnesses from taskflow.lock
taskflow search <query>Fuzzy-match local registries + auto-discover taskflow harnesses on GitHub
taskflow update [name...]Re-resolve; rewrite files + lockfile (--all implied if no names)
taskflow remove <name>Delete installed files + lockfile entry
taskflow apply <preset>add --overwrite alias (shadcn-style re-skin)
taskflow build [input]Publisher: inline source file contents, emit r/*.json + r/registry.json
taskflow mcpStart MCP server over stdio (tools: list_harnesses, search, install)
taskflow run <harness.ts>Execute an installed harness (TUI if TTY else JSONL)
taskflow watch <harness.ts>Alias for run
taskflow plan <harness.ts>Static AST preview — no LLM calls

Flag reference for add

FlagDefaultEffect
-y, --yesfalseSkip all confirmation prompts. On existing-file conflicts, skips the file (does NOT auto-overwrite — use --overwrite for that).
-o, --overwritefalseReplace existing files without prompt. Orthogonal to --yes.
--dry-runfalseResolve + validate, print what would change, do not write.
--difffalseLike --dry-run with a diff. Implies --dry-run.
--viewfalseResolve and print the registry-item JSON to stdout. Do not write, do not preflight.
-p, --path <dir>harnessDir from taskflow.jsonOverride install directory for this run.
-c, --cwd <dir>process.cwd()Run as if invoked from <dir>.
-s, --silentfalseMute all @clack/prompts output. On conflicts, skips like --yes.
--frozenfalseCI mode: error if resolved items don't match taskflow.lock.
--skip-adapter-checkfalseSkip the requiredAdapters preflight check.

Getting started in any project (30 seconds)

# From any repo on your machine:
cd /path/to/some/project

# First add auto-scaffolds taskflow.json + .agents/taskflow/config.ts + dirs
npx @taskflow-corp/cli@latest add <your-source> -y --skip-adapter-check

# See what was installed
npx @taskflow-corp/cli@latest list

# Run it
npx @taskflow-corp/cli@latest run .agents/taskflow/harness/<name>.ts

File layout after init + add

project/
├── taskflow.json                     # config + registries map
├── taskflow.lock                     # content-addressed install manifest
├── .env.local                        # auto-loaded; ${VAR} expansion for registries
└── .agents/
    └── taskflow/
        ├── config.ts                 # hooks, plugins, scope
        ├── harness/<name>.ts         # installed harness files
        ├── harness/plugins/<name>.ts # installed plugins
        ├── harness/utils/<name>.ts   # installed utilities
        ├── harness/examples/<name>.ts
        └── rules/<name>.md           # installed rules files

Private registries with auth

taskflow.json:

{
  "$schema": "https://taskflow.sh/schema/taskflow.json",
  "version": "1",
  "registries": {
    // simple form — string URL template
    "@acme": "https://registry.acme.com/r/{name}.json",

    // advanced form — per-registry headers and query params
    "@private": {
      "url": "https://api.corp.com/taskflow/{name}.json",
      "headers": { "Authorization": "Bearer ${TASKFLOW_TOKEN}" },
      "params":  { "v": "latest" }
    }
  }
}
  • {name} placeholder is mandatory; {style} is reserved for future use.
  • ${VAR_NAME} (braces required, no $VAR form) interpolates from process.env.
  • .env and .env.local are auto-loaded before resolution.
  • Missing env vars fail pre-flight with a clear RegistryMissingEnvironmentVariablesError.
  • HTTP 401/403/404/410 map to specific typed errors with actionable hints.

Publishing your own registry

  • Author registry/registry.json:
    {
      "$schema": "https://taskflow.sh/schema/registry.json",
      "name": "@yourname",
      "homepage": "https://yourname.dev",
      "items": [
        {
          "$schema": "https://taskflow.sh/schema/registry-item.json",
          "name": "my-harness",
          "type": "taskflow:harness",
          "files": [
            { "path": "items/my-harness.ts", "type": "taskflow:harness" }
          ]
        }
      ]
    }
    
  • Write the source .ts files referenced by files[].path.
  • Run npx @taskflow-corp/cli@latest build -c ./registry --output ./registry/r.
  • Host the emitted r/ directory (GitHub Pages, S3, your CDN).
  • Consumers then:
    npx @taskflow-corp/cli@latest add https://<your-host>/r/my-harness.json
    

See registry/ in this repo for a worked example.

Auto-discovery — zero-config installs from any GitHub repo

Typing taskflow add <user>/<repo> with no subpath and no registry-item.json at the repo root now triggers auto-discovery: the CLI searches the target repo for files that look like taskflow harnesses (i.e. import @taskflow-corp/cli / taskflow-cli / taskflowjs / taskflow-sdk and top-level-call taskflow(...).run(...)), then prompts a multi-select so you pick exactly which harnesses to install.

$ npx @taskflow-corp/cli@latest add AbhiShake1/taskflow

◇  Discovered 4 taskflow harnesses in AbhiShake1/taskflow:

◇  Select harnesses to install: (space to toggle, enter to confirm)
   ◼  examples/ui-plan.ts        (matched: import from '@taskflow-corp/cli')
   ◻  examples/ui-execute.ts
   ◼  examples/ui-harness-trio/index.ts
   ◻  harness/self-evolve.ts

◇  Installing 2 harnesses…
   ✔ .agents/taskflow/harness/ui-plan.ts
   ✔ .agents/taskflow/harness/index.ts
✔  Done. 2 written, 0 skipped, 0 overwritten.

Rules:

  • 0 matches → error with a clear message ("no taskflow harnesses found in <repo>").
  • 1 match → auto-install, no prompt.
  • >1 matches → interactive @clack/prompts multiselect. Default nothing selected; pick what you want.
  • --yes with >1 matcheserrors ("multiple harnesses found; re-run without --yes, or pass the full path e.g. user/repo/path/file.ts to target one file"). Auto-discovery never silently installs everything just because --yes was passed.

If the target repo ships a registry-item.json at HEAD on the default branch, the original Tier 2 shortcut behaviour wins (fetch the registry item directly) and discovery is skipped. If you type the full path (user/repo/sub/path.ts), the tarball-fetch path is used and discovery is also skipped.

How it works. The CLI hits a small Cloudflare Pages Function (/api/discover) which calls the official GitHub Code Search REST API. Results are cached 10 minutes in Workers KV. Sub-second end-to-end, no headless browsers, no cookie juggling — just a plain server-to-server fetch. Set TASKFLOW_DISCOVER_URL to point the CLI at a private proxy (useful for enterprise mirrors or local wrangler pages dev):

TASKFLOW_DISCOVER_URL=https://my-proxy.example.com/api/discover \
  npx @taskflow-corp/cli@latest add AbhiShake1/taskflow

taskflow search uses discovery too. Results from a taskflow search <query> now fold GitHub-wide discovery hits in alongside the configured-registry fuzzy-matches, so you can grep the whole GitHub index for a harness by keyword without targeting a specific repo.

Full design notes for discovery live in docs/add-command-plan.md §15.

Item types (registry-item.jsontype)

TypeDefault destinationNotes
taskflow:harness<harnessDir>/<basename>Main .ts the user runs
taskflow:plugin<harnessDir>/plugins/<basename>Imported from config.ts
taskflow:utils<harnessDir>/utils/<basename>Shared TS
taskflow:example<harnessDir>/examples/<basename>Sample invocation
taskflow:rules<rulesDir>/<basename> or targetMarkdown rules
taskflow:config-patchMerged into config.ts via ts-morph ASTNot a file
taskflow:filetarget (required)Arbitrary path incl. ~/

MCP integration (Claude Code / Cursor / Codex)

npx @taskflow-corp/cli@latest mcp

Exposes three tools over stdio:

  • list_harnesses — return installed harnesses from taskflow.lock
  • search — fuzzy-match local registries + GitHub-wide auto-discovery
  • install — delegate to runAdd

Wire it into your MCP client config and the model can discover and install harnesses autonomously.

CI usage

# Reproducible — errors on lockfile drift
npx @taskflow-corp/cli@latest add <source> --yes --silent --frozen

Full design notes: docs/add-command-plan.md.

Hooks via .agents/taskflow/config.ts

import { defineConfig } from '@taskflow-corp/cli/config';

export default defineConfig({
  events: {
    afterTaskDone: async (ctx, { spec, result }) => {
      // post-task hook
    },
  },
  todos: { autoExtract: true, maxRetries: 3 },
});

Structured output

Sessions with a zod schema return typed results. claude-code uses native tool-use. codex (on gpt-5 / gpt-5.4 models) uses --output-schema; gpt-5-codex variants fall back to prompt-engineered JSON pending openai/codex#4181. Other adapters (cursor, opencode, pi) use prompt-engineered JSON. Override codex behavior with HARNESS_CODEX_SCHEMA=0|1.

import { z } from 'zod';

const result = await session('summary', {
  with: 'codex:gpt-5.4',
  task: 'Summarize the repo',
  schema: z.object({ title: z.string(), bullets: z.array(z.string()) }),
});
// result is typed: { title: string; bullets: string[] }

Plugins

A plugin contributes hooks, a ctx.plugins.<name> namespace, and optional config fragments:

import type { Plugin } from '@taskflow-corp/cli/core';

export const myPlugin: Plugin = () => ({
  name: 'my-plugin',
  events: {
    afterTaskDone: async (ctx, { spec }) => { /* ... */ },
  },
  ctx: () => ({ hello: () => 'world' }),
});

To get typed access to ctx.plugins.myPlugin.hello() in downstream hooks, module-augment the plugin namespace registry:

declare module '@taskflow-corp/cli/core' {
  interface PluginNamespaces {
    'my-plugin': { hello: () => string };
  }
}

Examples

Single-file harnesses live in examples/. Install the SDK globally first (npm i -g @taskflow-corp/sdk), then run any file directly with tsx:

  • examples/ui-plan.ts — scans a project, injects missing data-testids, emits a YAML test plan.
  • examples/ui-execute.ts — consumes the YAML and generates a standalone Playwright project.
  • examples/ui-execute.test.ts — unit tests for the YAML → Playwright codegen.
  • examples/ui-content.ts — stitches media into a video, generates narratives, and publishes to YouTube / Facebook / Instagram / LinkedIn / Twitter / Medium / Reddit (stubs — swap in real OAuth before production).

Each is ~400–600 LOC with zero build step: tsx examples/ui-plan.ts.

Environment variables

VarPurpose
ANTHROPIC_API_KEYRequired for claude-code sessions and pi:anthropic/*.
OPENAI_API_KEY, GROQ_API_KEY, CEREBRAS_API_KEY, GEMINI_API_KEYRequired per-session for the respective providers.
HARNESS_PI_BINOverride the pi binary name (default pi). Use omp with @oh-my-pi/pi-coding-agent.
HARNESS_CODEX_SCHEMA0 forces prompt-engineered JSON for codex; 1 forces native --output-schema.
HARNESS_ADAPTER_OVERRIDE=mockSwap every agent for the mock adapter — smoke runs with zero token cost.
HARNESS_NO_TTY=1Force headless JSONL output even when a TTY is attached.
HARNESS_RUNS_DIR=...Override the runs archive directory (default data/runs).
HARNESS_REAL_TESTS=1Enable integration tests that make real LLM calls (default-skipped).

Docs

See .claude/skills/taskflow/SKILL.md for the authoring guide.

Keywords

ai

FAQs

Package last updated on 19 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts