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

@halecraft/verify

v1.2.0

Published

Hierarchical verification runner with parallel execution and terse output

Readme

@halecraft/verify

Quickly check if your nodejs project is in an OK state.

Or, more technically--verify is a hierarchical verification runner with parallel execution and terse output.

Installation

pnpm add -D @halecraft/verify
# or
npm install -D @halecraft/verify
# or
yarn add -D @halecraft/verify

Quick Start

Initialize a Config

The easiest way to get started is to use the --init flag:

# Interactive mode - select which tasks to include
npx @halecraft/verify --init

The init command will:

  1. Scan your package.json for verification-related scripts (lint, test, typecheck, build, etc.)
  2. Present an interactive checkbox UI to select which tasks to include
  3. Generate a verify.config.ts file with your selections

Manual Configuration

Create a verify.config.ts file in your project root:

import { defineConfig } from "@halecraft/verify";

export default defineConfig({
  tasks: [
    { key: "format", run: "biome check ." },
    { key: "types", run: "tsc --noEmit" },
    { key: "test", run: "vitest run" },
  ],
});

Note: Commands automatically have access to binaries in node_modules/.bin directories. You can write run: "biome check ." instead of run: "./node_modules/.bin/biome check .". This works in monorepos too—verify walks up the directory tree to find all node_modules/.bin directories, just like npm/pnpm/yarn do when running package.json scripts.

Run Verification

# Run all tasks
pnpm exec verify

# Run specific task
pnpm exec verify format

# Run nested task with full path
pnpm exec verify types:tsc

# Run nested task with shortcut (if unambiguous)
pnpm exec verify tsc
# → Resolving "tsc" to "types:tsc"

# Pass arguments to underlying command
pnpm exec verify logic -- -t "specific test name"

# Run with verbose output
pnpm exec verify --verbose

# Output JSON (for CI)
pnpm exec verify --json

Or you can add "verify": "verify" to package.json scripts and run:

# Run all tasks
pnpm verify

Configuration

Task Definition

Each task in verify.config.ts can have the following properties:

interface VerificationNode {
  // Unique key for this task (used in CLI filtering)
  key: string;

  // Human-readable name (optional)
  name?: string;

  // Command to run (leaf nodes only)
  // Supports: string, object with cmd/args/cwd/env/timeout
  run?:
    | string
    | {
        cmd: string;
        args: string[];
        cwd?: string;
        env?: Record<string, string | null>;
        timeout?: number;
      };

  // Child tasks (for grouping)
  children?: VerificationNode[];

  // Execution strategy for children: 'parallel' | 'sequential' | 'fail-fast'
  strategy?: ExecutionStrategy;

  // Parser ID for output parsing (auto-detected if not specified)
  parser?: string;

  // Tasks that must pass for this task's failure to be reported
  reportingDependsOn?: string[];

  // Timeout in milliseconds (for string commands)
  timeout?: number;

  // Environment variables for this task and its children
  // Set to null to unset an inherited variable
  env?: Record<string, string | null>;

  // Custom success message template (optional)
  successLabel?: string;

  // Custom failure message template (optional)
  failureLabel?: string;
}

Smart Output Suppression with reportingDependsOn

When a syntax error occurs, multiple tools often report the same underlying issue (Biome, tsc, esbuild all complaining about the same missing comma). The reportingDependsOn option reduces this noise by suppressing redundant failure output.

import { defineConfig } from "@halecraft/verify";

export default defineConfig({
  tasks: [
    { key: "format", run: "biome check ." },
    { key: "types", run: "tsc --noEmit", reportingDependsOn: ["format"] },
    { key: "logic", run: "vitest run", reportingDependsOn: ["format"] },
    { key: "build", run: "tsup", reportingDependsOn: ["format"] },
  ],
});

How it works:

  • All tasks still execute in parallel (no speed regression)
  • When a dependency fails (e.g., format), dependent tasks are terminated early for faster feedback
  • Dependent tasks that also fail are marked as "suppressed"
  • Only the root cause failure shows detailed logs
  • Suppressed tasks show ⊘ suppressed instead of ✗ failed

Before (noisy):

✗ format (syntax error at line 14)
✗ types (syntax error at line 14)
✗ logic (syntax error at line 14)
✗ build (syntax error at line 14)

==== FORMAT FAIL ====
[50 lines of biome output]

==== TYPES FAIL ====
[20 lines of tsc output]

==== LOGIC FAIL ====
[30 lines of vitest output]

==== BUILD FAIL ====
[30 lines of tsup output]

After (clean):

✗ format (syntax error at line 14)
⊘ types (suppressed - format failed)
⊘ logic (suppressed - format failed)
⊘ build (suppressed - format failed)

==== FORMAT FAIL ====
[50 lines of biome output]

== verification: Failed ==

Note: When using verify --init, the generated config automatically adds reportingDependsOn: ["format"] to types, logic, and build tasks when a format task is detected.

Nested Tasks

Group related tasks together:

import { defineConfig } from "@halecraft/verify";

export default defineConfig({
  tasks: [
    { key: "format", run: "pnpm lint" },
    { key: "types", run: "pnpm typecheck" },
    {
      key: "logic",
      children: [
        { key: "unit", run: "vitest run" },
        { key: "e2e", run: "playwright test" },
      ],
    },
  ],
});

Run nested tasks with colon notation:

npx verify logic:unit

Execution Strategies

Control how child tasks are executed:

{
  key: 'tests',
  strategy: 'fail-fast', // Stop on first failure
  children: [
    { key: 'unit', run: 'vitest run' },
    { key: 'integration', run: 'pnpm test:integration' },
  ],
}
  • parallel (default): Run all tasks simultaneously
  • sequential: Run tasks one after another
  • fail-fast: Run sequentially, stop on first failure

Command Timeouts

Prevent hung processes by setting a timeout (in milliseconds):

import { defineConfig } from "@halecraft/verify";

export default defineConfig({
  tasks: [
    // String command with timeout
    { key: "test", run: "vitest run", timeout: 60000 }, // 60 seconds

    // Object command with timeout
    {
      key: "build",
      run: {
        cmd: "tsup",
        args: [],
        timeout: 120000, // 2 minutes
      },
    },
  ],
});

When a command exceeds its timeout:

  • The process is killed with SIGTERM (including child processes)
  • The task is marked as failed with timedOut: true
  • The summary shows: task: timed out after 60000ms

Note: For object commands, the timeout on the command takes precedence over the node-level timeout.

Environment Variables

Set environment variables at the config level (applies to all tasks) or at the task level (inherits to children):

import { defineConfig } from "@halecraft/verify";

export default defineConfig({
  // Global env vars - applied to all tasks
  env: {
    NO_COLOR: "1", // Recommended: disable colors for cleaner output parsing
    CI: "true",
  },
  tasks: [
    { key: "format", run: "biome check ." },
    {
      key: "test",
      // Enable colors for test output by unsetting NO_COLOR
      env: { NO_COLOR: null },
      children: [
        { key: "unit", run: "vitest run" },
        {
          key: "e2e",
          run: "playwright test",
          // E2E-specific env (still inherits CI: "true")
          env: { PLAYWRIGHT_BROWSERS_PATH: "0" },
        },
      ],
    },
  ],
});

Environment merge order (most specific wins):

  1. process.env - System environment
  2. config.env - Global config-level
  3. Parent task env - Inherited from parent tasks
  4. Node env - Current task
  5. Command env - VerificationCommand object only

Unsetting variables: Set a value to null to explicitly unset an inherited variable:

{
  key: "test",
  env: { NO_COLOR: null }, // Re-enables colors for this task
  run: "vitest run",
}

Note: Generated configs (via --init) include env: { NO_COLOR: "1" } by default to ensure consistent output parsing.

CLI Options

Usage:
  verify [flags...] [task] [--] [passthrough...]

Flags:
  --json              Output results as JSON
  --verbose, -v       Show all task output
  --quiet, -q         Show only final result
  --top-level, -t     Show only top-level tasks (hide descendants)
  --no-tty            Force sequential output (disable live dashboard)
  --logs=MODE         Log verbosity: all, failed, none (default: failed)
  --config, -c PATH   Path to config file (or output path for --init)
  --init              Initialize a new verify.config.ts file
  --force             Overwrite existing config file (with --init)
  --yes, -y           Skip interactive prompts, auto-accept detected tasks
  --help, -h          Show this help message

Passthrough Arguments

You can pass arguments directly to the underlying command using -- (double-dash):

# Run a specific vitest test
verify logic -- -t "should handle edge case"

# Run with coverage
verify logic -- --coverage

# Multiple passthrough args
verify logic -- -t "foo" --reporter=verbose

# Combine with verify flags
verify logic --verbose -- -t "foo"

Requirements:

  • Passthrough arguments require exactly one task filter
  • The task must be a leaf node (has a run command)
  • Arguments are appended to the command string

How it works:

  • For string commands: args are shell-escaped and appended to the command
  • For object commands: args are appended to the args array

Exit Codes

  • 0 - All tasks passed
  • 1 - Some tasks failed
  • 2 - Configuration/usage error (invalid task name, missing config)

Task Name Validation

Verify validates task names before running any tasks. If you specify a task that doesn't exist, you'll get a helpful error:

$ verify test
Error: Task "test" not found.

Did you mean "types:tsc"?

Available tasks:
  format
  logic
  types
  types:tsc
  types:tsgo
  build

Child task shortcuts: You can use just the child key if it's unambiguous:

$ verify tsc
→ Resolving "tsc" to "types:tsc"
✓ verified types:tsc

If the shortcut is ambiguous (multiple tasks have the same child key), you'll get an error listing the options:

$ verify test  # if both unit:test and e2e:test exist
Error: Task "test" is ambiguous.

Matches multiple tasks:
  unit:test
  e2e:test

Programmatic API

import { verify, defineConfig } from "@halecraft/verify";

const config = defineConfig({
  tasks: [{ key: "test", run: "vitest run" }],
  // Optional: set default options for this config
  options: {
    logs: "failed",
  },
});

const result = await verify(config, {
  // All options (CLI options can override config defaults)
  logs: "failed", // "all" | "failed" | "none"
  format: "human", // "human" | "json"
  filter: ["test"], // Filter to specific task paths
  cwd: process.cwd(), // Working directory
  noColor: false, // Disable colors
  topLevelOnly: false, // Show only top-level tasks
  noTty: false, // Force sequential output
});

console.log(result.ok ? "All passed!" : "Some failed");

VerifyResult

The verify() function returns a VerifyResult object:

interface VerifyResult {
  ok: boolean; // Whether all tasks passed
  startedAt: string; // ISO timestamp when run started
  finishedAt: string; // ISO timestamp when run finished
  durationMs: number; // Total duration in milliseconds
  tasks: TaskResult[]; // Individual task results
}

interface TaskResult {
  key: string; // Task key
  path: string; // Full path (e.g., "logic:unit")
  ok: boolean; // Whether the task passed
  code: number; // Exit code
  durationMs: number; // Duration in milliseconds
  output: string; // Raw output
  summaryLine: string; // Parsed summary
  suppressed?: boolean; // True if output was suppressed
  suppressedBy?: string; // Path of dependency that caused suppression
  timedOut?: boolean; // True if task exceeded its timeout
  children?: TaskResult[]; // Child results (for group nodes)
}

Output Parsers

Built-in parsers for common tools:

  • vitest - Vitest/Jest test runner
  • tsc - TypeScript compiler (tsc/tsgo)
  • biome - Biome/ESLint linter/formatter
  • gotest - Go test runner
  • generic - Fallback for unknown tools

Parsers automatically extract metrics (passed/failed counts, duration) and provide concise summaries.

Parser ID Constants

Use parsers for type-safe parser references instead of magic strings:

import { defineConfig, parsers } from "@halecraft/verify";

export default defineConfig({
  tasks: [
    { key: "test", run: "vitest run", parser: parsers.vitest },
    { key: "types", run: "tsc --noEmit", parser: parsers.tsc },
    { key: "lint", run: "biome check .", parser: parsers.biome },
  ],
});

Available constants:

  • parsers.vitest - "vitest"
  • parsers.tsc - "tsc"
  • parsers.biome - "biome"
  • parsers.gotest - "gotest"
  • parsers.generic - "generic"

License

MIT