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

warpline

v0.3.4

Published

Deterministic plugin runtime with LLM-judgment dispatch and side-effect approval gates

Readme

Warpline

A deterministic plugin runtime where the LLM is a step you dispatch, not a capability the code carries around.

npm CI Secret scan License

Warpline runs the recurring work that keeps a business going, on a schedule. Outbound sequencing, market research pulls, content pipelines, competitor monitoring, lead qualification, report generation.

A plugin that declares a side effect (sending email, creating issues, writing to a database, calling external APIs, modifying files) doesn't run without explicit human session approval. That includes at autonomous, because the autonomy level is dispatch autonomy. It decides whether the scheduler can start a plugin without asking. It never decides whether that plugin can act on the world without asking.

Blanket approval exists and it's deliberate. warpline approve --all writes a wildcard grant. What it covers, what it prints before writing anything, when it expires, and why a run can't widen its own scope: Can the gate be bypassed?.

Published docs: warplinehq.github.io/warpline.

warpline plan — preview only; nothing was executed.

Grant: none — plugins with side effects would be SKIPPED this run
Plugins: /tmp/warpline-demo/plugins

Due (3):

  anomaly-watch (level 0)
    (no declared side effects)
  feed-triage (level 0)
    (no declared side effects)
  metrics-rollup (level 0)
    (no declared side effects)

Not due (3):

  feed-monitor — skipped (unapproved): side effects require session approval
    external_api: ⚠ unapproved — would be SKIPPED this run
  github-poll — skipped (unapproved): side effects require session approval
    external_api: ⚠ unapproved — would be SKIPPED this run
  anomaly-issue — skipped (unapproved): side effects require session approval
    creates_issue: ⚠ unapproved — would be SKIPPED this run
    external_api: ⚠ unapproved — would be SKIPPED this run

Quickstart

npm i warpline          # or: bun add warpline
npx warpline --help

Runs on Node 22.18+ or 23.6+ (engines.node excludes 23.0–23.5), or Bun ≥ 1.3. Node alone is enough. You don't need Bun to use warpline. v0.1 supports POSIX systems (macOS, Linux). Windows is untested and unclaimed.

Every file warpline reads or writes lives under one home directory: the WARPLINE_HOME env var, else the nearest ancestor .warpline/ directory, else <cwd>/.warpline.

What you get

  • Plugin runtime — Zod-validated manifests; per-attempt timeouts; bounded retries with exponential backoff + jitter; AbortSignal threaded into your I/O; per-run artifacts (runs/<id>.json + captured log with attempt delimiters).
  • Side-effect approval gate — a closed enum of side-effect types declared per plugin; declared effects gate execution behind warpline approve-style session approval, regardless of autonomy level.
  • Engine — TTL freshness (skip work that is still fresh), dependency topological ordering, quiet hours, review gate, and idle-based degradation tiers (normal → degraded → extended → suspended).
  • Event board — append-only events.jsonl + acknowledgements; tasks with ack / defer / complete states and severity-FIFO ordering.
  • The [needs-llm] contract — plugins emit judgment work as a typed handoff; a Claude Code companion skill picks it up. Deterministic work costs nothing to run; judgment work uses your existing Claude subscription. See docs/needs-llm-contract.md.

Writing a plugin

A plugin is a directory under <home>/plugins/<name>/ with two files:

my-plugin/
  manifest.ts   # export const manifest = PluginManifestSchema.parse({...})
  handler.ts    # export const handler: HandlerFn = async (manifest, args, signal) => SkillResult

The manifest declares what the plugin is allowed to do (side effects, schedule, TTL, timeout, retries, minimum degradation tier). The handler does the work and returns a structured SkillResult. Invalid manifests are a hard-stop at load, so a misconfigured plugin never silently runs.

Worked examples in examples/plugins/:

| Example | Demonstrates | | --- | --- | | anomaly-watch | A pure deterministic check — the baseline shape | | github-poll | external_api side effect gating an autonomous plugin | | feed-monitor | Deterministic fetch/parse that emits the handoff — the producer half of the feed chain | | feed-triage | The on_run consumer half — per-entry judgment handed off via [needs-llm], no declared side effects | | metrics-rollup | daily schedule with retained state — append-only rows, a retention window, weekly rollups; writes only under the home | | anomaly-issue | dependencies ordering after anomaly-watch, supervised autonomy, and a creates_issue side effect through the gate — irreversible, so the result says how to undo it |

Authoring guide: docs/plugin-authoring.md.

# Scaffold a plugin — also prepares the home directory
npx warpline scaffold my-plugin

# Preview what the next engine advance would do. Executes nothing.
npx warpline plan

# Invoke one plugin handler directly
npx warpline run my-plugin default

# Answer whichever gate is waiting — record a parked result, or grant a
# side-effecting plugin permission to run for this session
npx warpline approve my-plugin

# Say no to what a plugin proposed. The answer is bound to the proposal, so
# the question comes back if what it proposes changes.
npx warpline deny my-plugin

# Clear the session approval
npx warpline revoke

Those six subcommands are the whole CLI surface. Running everything that's due on a schedule is a library call, not a command. It's runAdvance() from the package root:

import { runAdvance } from 'warpline'

const result = await runAdvance()

Where the LLM fits

If you can write an if/else for it, it's code. If it needs understanding or judgment, it's an LLM task, and the plugin hands it off instead of calling a model.

Read the full doctrine: docs/doctrine.md.

Nowhere in this repo. That's the point. Plugins that reach a judgment step return a [needs-llm] handoff (mapped to the delegated run status, never retried). An orchestrating Claude Code session consumes those handoffs via companion skills, and a template lives in skills/needs-llm-template/. That directory is deliberately not shipped in the package, so the link is absolute. It resolves the same from npm, from GitHub, and from node_modules. Side effects that follow from judgment work still go through the approval gate.

FAQ

Can the gate be bypassed?

Only deliberately, and only by a human at a keyboard. warpline approve --all is the one route to a wildcard scopes: '*' grant, and it refuses to run if you also name plugins, so no plugin name, glob or shell expansion can widen a grant past what you typed. It prints the coverage it's about to grant before it writes anything. The grant is session-scoped and it expires. See the session approval file for the default lifetime and the ceiling from first grant. And nothing inside a run can widen its own scope. The grant helpers have no caller on the advance path, so a run can only ever spend approval a human already gave.

Why not just let the plugin call a model?

Because a plugin that calls a model has quietly made every future rerun an experiment. The deterministic half stops being reproducible, the judgment half stops being reviewable, and you find out which was which when they disagree with each other. If you can write an if/else for it, it's code. If it needs understanding, it's a handoff. Keep the boundary in the manifest and you can read a plugin and know which one you're looking at.

Do I need Bun / a Claude subscription?

No to both, in different ways. Node 22.18+ or 23.6+ is enough to install and run warpline. 23.0–23.5 is excluded by engines.node, and npm reports EBADENGINE there (a hard failure wherever engine-strict is set). Bun is the development runtime for this repository's own test suite, not a user requirement. The [needs-llm] half is a handoff, not an API call. It uses whatever Claude Code session you already have, and if nobody ever picks a handoff up, the deterministic work carries on running without it.

Docs

From source

Cloning gets you the test suite and the board, neither of which ships in the package:

git clone https://github.com/warplinehq/warpline
cd warpline
bun install
bun run test                  # builds, then runs the full suite

Requires bun ≥ 1.3. This is the one place it's genuinely required, because the suite is written against bun:test.

# The board — a repo-only surface at 0.1, not wired into the published bin
bun run src/cli/board-cli.ts status
bun run src/cli/board-cli.ts tasks

Provenance

Warpline was extracted in August 2026 from the private automation engine that's run one company's marketing operations since early 2026. The domain plugins stayed behind. The runtime, gates, board, and doctrine are what generalised.

License

Apache-2.0