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

@zapier/connectors-dev

v0.16.1

Published

Standard dev tooling and validator for connectors: validate (with --fix), stage, and scaffold-connector.

Readme

@zapier/connectors-dev

Standard dev tooling and validator for connectors built with @zapier/connectors-sdk. Provides a unified connectors-dev CLI and a programmatic API:

| Command | What it does | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | validate | Validate connectors against agentskills.io rules (via skills-ref) plus the connector contract (package.json, index.ts, cli.ts, scripts/*.ts, evals/evals.json). With --fix, apply every fixable rule instead of reporting: shared assets, index.ts wiring, and package.json fundamentals. Vendor-specific policy (e.g. NOTICE / legal fragments / LICENSE) lives in an extends config package such as @zapier/connectors-dev-config. | | scaffold-connector | Bootstrap a new connector shell: package.json, connections.ts, SKILL.md, index.ts, and placeholder directories. | | stage | Copy a connector into a clean tmp directory (git-tracked files only) for standalone install testing — mirrors what an agentskills.io client receives. | | render-doc | Print the canonical body of one doc (SKILL.md or README.md) a connector should match (the body scaffold-connector would generate now), for diffing against the live doc when migrating to updated templates. The file to render is a required argument: render-doc <dir> SKILL.md or render-doc <dir> README.md. |

CLI

# Validate a single connector
connectors-dev validate ./apps/my-connector
# Validate every connector under apps/
# (a path that isn't itself a connector is treated as a folder of connectors)
connectors-dev validate apps

# Apply every fixable rule (shared assets, index.ts, package.json, + any config rules)
connectors-dev validate apps/my-connector --fix
# Fix every connector under apps/
connectors-dev validate apps --fix

# Bootstrap a new connector
connectors-dev scaffold-connector ./apps/my-connector --slug my-connector
connectors-dev scaffold-connector ./apps/my-connector --slug my-connector --license Elastic-2.0

# Stage a connector for standalone testing
connectors-dev stage apps/notion
# → prints path to tmp dir; capture it: path=$(connectors-dev stage apps/notion)
# Stage and also produce a ZIP
connectors-dev stage apps/notion --zip
# Vendor the local SDK source into the staging dir (test SDK changes before publishing)
connectors-dev stage apps/notion --local-sdk packages/connectors-sdk

# Print the canonical doc a connector should match (for migrating to updated templates)
connectors-dev render-doc apps/notion SKILL.md
connectors-dev render-doc apps/notion README.md

Run connectors-dev with no arguments for the full option reference.

Programmatic API

import {
  scaffoldConnector,
  validate,
  formatIssues,
  evalsJsonSchema,
  describeEvalsIssue,
} from "@zapier/connectors-dev";

// Validate connectors and format any issues. The rule set and package-name
// pattern come from connectors-dev.config.ts (loaded from the cwd).
const results = await validate(["./apps/my-connector"]);
for (const [connectorPath, issues] of results) {
  console.error(formatIssues(connectorPath, issues));
}

// Scaffold a new connector. The rule set and package-name pattern come from
// connectors-dev.config.ts too (loaded from `cwd`, defaulting to process.cwd()).
const { connectorDir, filesWritten } = await scaffoldConnector({
  slug: "my-connector",
  license: "Elastic-2.0",
  out: "./apps/my-connector",
});

// Parse/validate evals.json against the same schema the validator uses
const parsed = evalsJsonSchema.safeParse(rawEvals);
if (!parsed.success) {
  for (const issue of parsed.error.issues)
    console.error(describeEvalsIssue(issue));
}

Validation

connectors-dev validate <path>... composes two layers:

  1. agentskills.io skills-refSKILL.md frontmatter and skill-folder rules.
  2. Connector contractpackage.json, bundle index.ts / cli.ts, scripts/*.ts (defineTool + handleIfScriptMain), evals/evals.json, and SKILL.md extensions (metadata.api-docs, compatibility, metadata.source).

Vendor-specific policy (e.g. a scoped package name, LICENSE / NOTICE, legal fragments) is not built in — it arrives through an extends config package such as @zapier/connectors-dev-config. A connector copied out of the monorepo runs with no config and is therefore only held to the brand-neutral contract above.

Each path is auto-detected: a directory with a package.json is a single connector, otherwise its immediate subdirectories with a package.json are validated (a folder of connectors).

Check and --fix report identically — each issue is one <icon> path [rule] message line, where the icon is its status: ✅ fixed, 🤖 fixable (rerun with --fix), ⛔️ non-fixable (fix by hand). A trailing summary tallies Fixed / Fixable / Non-fixable. Exit code is 0 only when nothing blocks: a check run passes when there are no issues, a --fix run passes when nothing non-fixable remains (✅-fixed issues don't fail it). Blocking runs print to stderr and exit 1.

Options

| Flag | Purpose | | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | --fix | Apply every fixable rule instead of reporting (shared assets, index.ts, package.json, plus any config-supplied rules) | | --ignore-rule <rule> | Ignore a rule for this run only (repeatable: --ignore-rule foo --ignore-rule bar). Unioned with the config's ignoreRules — never modifies the config file itself. |

The rule set and package.json name policy come from connectors-dev.config.ts (or the built-in defaults) — there is no per-run name-pattern flag.

What it checks

| Layer | Rule tag | Method | | ---------------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | | SKILL.md | agentskills | Upstream skills-ref validate() | | SKILL.md metadata.api-docs | api-docs | HTTPS URL presence — agents need it to look up endpoints and auth schemes | | SKILL.md compatibility | compatibility | Required field with pinned value — harnesses read it to decide if they can run the connector | | SKILL.md metadata.source | source | Present + valid https:// URL (the exact canonical URL is a vendor policy, enforced by an extends config) | | scripts/, package.json, evals/evals.json | scripts-dir, package.json, evals.json | JSON + filesystem (scripts-dir fixably creates a missing scripts/) | | index.ts, scripts/*.ts | index.ts, scripts | TypeScript compiler API (AST) | | scripts/*.ts runtime shape | scripts | Dynamic import + getToolDefinitionShapeIssues | | cli.js, cli.ts, tsup.config.ts | cli.js, cli.ts, tsup.config.ts | Byte-identical sync to the canonical assets/ copy |

Rules & fixing

validate and validate --fix are the same pass over the same rule set — the only difference is the fix flag on the context. A ConnectorRule is a single function that inspects one connector, reports findings via ctx.report, and repairs what it can when ctx.fix is set:

interface RuleContext {
  connectorDir: string;
  packageNamePattern: string;
  fix: boolean;
  report(finding: {
    message: string;
    file?: string;
    line?: number;
    fixStatus?: "fixable" | "fixed";
  }): void;
}

type ConnectorRule = (ctx: RuleContext) => void | Promise<void>;

interface RuleEntry {
  name: string;
  rule: ConnectorRule;
}

A rule never names itself: the name lives on the registry RuleEntry, and the runner stamps it onto every reported finding. Findings carry an optional fixStatus"fixable" in a check run, "fixed" after a fix run — so the CLI can report how many issues a --fix repaired and which still need hand-editing.

runRule(entry, base) runs a single rule against one connector and returns the stamped findings; the base context's fix flag is the only thing that makes it a check run versus a fix run. It's the unit-test entry point for a rule. Rules get no special treatment — a builtin rule is the same shape a downstream config/policy package would provide, so a rule can move out of this package unchanged.

Configuration

validate, validate --fix, and scaffold-connector read an optional connectors-dev.config.{ts,js,mjs} from the working directory (loaded with c12, so extends layers and a sibling .env work). A connector copied out of the monorepo has no config and falls back to the built-in defaults, which is correct for a standalone install.

import { defineConnectorsDevConfig } from "@zapier/connectors-dev";

export default defineConnectorsDevConfig({
  // Pull in a shared policy package (resolved + merged first).
  extends: "@zapier/connectors-dev-config",
  // package.json name pattern; {name} = connector slug. Default "{name}-connector".
  packageNamePattern: "@zapier/{name}-connector",
  // Drop builtin rules by name…
  ignoreRules: ["legal"],
  // …and append your own (same RuleEntry shape as a builtin).
  rules: [{ name: "house-style", rule: (ctx) => {} }],
});

| Field | Default | Purpose | | -------------------- | -------------------- | ----------------------------------------------------------------------------------- | | packageNamePattern | "{name}-connector" | package.json name pattern; {name} is the connector slug (directory basename). | | extends | (none) | Local path(s) or package(s) to inherit and deep-merge (a later layer wins). | | ignoreRules | [] | Builtin rule names to drop from the run. | | rules | [] | Extra RuleEntry objects appended after the builtins. |

A config-supplied rule runs through the exact same path as a builtin — there is no builtin-vs-external branch — so a rule can migrate to a downstream policy package (dropped here via ignoreRules, added there via rules) with no engine change. packageNamePattern is config-only: there is no --naming flag, so validate and scaffold-connector always agree on the package name a connector should carry.

Assets

The package ships canonical connector asset files under assets/:

| File | Purpose | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | cli.js | Plain-JS connector CLI proxy — runs dist/cli.js when present (npm install route) or falls back to cli.ts (Node 22.18+). Ports the old preflight readiness checks: bails with actionable guidance when node_modules is missing or the .ts source can't run on this Node. | | cli.ts | TypeScript connector CLI entry point (no shebang; executed via cli.js). | | tsup.config.ts | tsup build config shared by all connectors. |

Each asset is enforced by its own byte-identical rule (createAssetRule): content equality is the whole contract, so no separate shebang / AST / exec-bit check is needed. These files are the source of truth — edit here; run connectors-dev validate <dir> --fix (or the monorepo's pnpm run validate:fix) to propagate changes to every connector.

scaffold-connector options

Invoked as scaffold-connector <dir> --slug <slug> [options] — the output directory is the one positional, the slug is a required named option.

| Option | Default | Notes | | ---------------------- | ----------------- | ------------------------------------------------------------------ | | --slug <slug> | (required) | Connector slug (lowercase, digits, hyphens; starts with a letter) | | --title <name> | titleCase(slug) | Human-readable app display name | | --license <spdx> | (none) | SPDX license identifier written into package.json and SKILL.md | | --description <text> | auto | One-sentence description for package.json and SKILL.md | | --api-docs <url> | (placeholder) | Vendor API docs URL for SKILL.md frontmatter | | --force | false | Overwrite an existing directory |

The package name follows the packageNamePattern from connectors-dev.config.ts (default {name}-connector), so a scaffolded connector passes validate without a separate scope flag.