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

@jesuso/agenthook

v0.2.0

Published

Event-driven agentic development. Webhook in, coding agent out. No polling loops.

Readme

agenthook

CI npm

Event-driven agentic development. Move a task into a board section → a coding agent picks it up the instant it lands, works that stage in an isolated git worktree, and (for the coding stage) opens a draft PR. The agent reports a verdict and the receiver moves the task — forward to the next section (which fires the next stage), back a stage for rework, into a hold lane for a human answer, or to a failure lane. You define the pipeline of stages (e.g. triage → code → review).

No polling loop. The tracker already knows the moment a task moves — so it pushes a webhook and the matching stage starts. Latency is bounded by the network, not by a poll interval, and nothing spins while you're idle.

Event-first, poll only to reconcile. See docs/architecture.md for the honest tradeoffs (push delivery isn't free — agenthook ships a targeted replay for the gaps).

Two swappable axes, engine blind to both: a tracker (where work comes from) and an ingress (how the receiver is reachable). Ships with Asana, Jira, and two GitHub trackers — GitHub Issues (labels-as-sections) and GitHub Projects v2 (board columns) — plus ngrok + hosted ingress; adding another section/stage tracker or tunnel is one adapter file (docs/providers.md).

 move to a section       webhook POST            route to step        headless `claude -p`
 on your board    ─────▶  receiver (verify)  ──▶  dedup + queue   ──▶  branch + draft PR
                                                                        → advance to next section

[!WARNING] agenthook turns a webhook into code execution on your host. With fullAuto enabled it runs claude -p --dangerously-skip-permissions — a verified webhook leads straight to unsandboxed command execution, gated only by the HMAC signature and a non-guessable URL. fullAuto is off by default (agents prompt for permission). Turn it on only on a trusted host with a scoped token, ideally inside the sandboxed container (the blessed fullAuto path — only the repo mounted). Read the full threat model in docs/architecture.md#security-posture and report issues per SECURITY.md before you point this at anything real.

Install

Requires Node ≥ 20, the claude CLI, git, and — for the ngrok ingress — ngrok. Plus a tracker API token.

npm i -g @jesuso/agenthook   # installs the `agenthook` command; or run ad-hoc with `npx @jesuso/agenthook <cmd>`

Quickstart

New here? Follow the Getting Started guide — it walks the full path end to end, including the two manual steps below (finding section gids, writing the instruction files) that this overview compresses.

agenthook is a tool you run inside the project you want agents to work on — its config lives there like a tsconfig.json, while runtime state lives centrally in ~/.agenthook/<name>.

cd ~/my-project

agenthook init            # interactive: pick tracker + ingress, fetches your
                          # workspace/project so you choose from a list
                          # → writes ./agenthook.config.json (with TODO_* section gids)

$EDITOR .env              # add your ASANA_TOKEN or JIRA_API_TOKEN (init prints which vars)

# Fill in the pipeline — replace the TODO_* section gids and write the per-step
# instruction files. THIS step is required; doctor won't catch missing gids.
$EDITOR agenthook.config.json      # see Getting Started §4
cp INSTRUCTIONS.example.md INSTRUCTIONS_CODE.md

agenthook doctor          # preflight: token resolves, repo is git, port free, …
agenthook start           # ingress up → register webhook → serve

init offers an optional ah shortcut (a symlink beside the agenthook bin) so you can type ah start, ah agents, … — add or remove it later with agenthook alias [--remove]. It's opt-in and never overwrites an existing ah on your PATH.

Move an item you're assigned into your pipeline's first stage — a section (Asana), status (Jira), label (GitHub Issues), or Status column (GitHub Projects v2) → a run appears under ~/.agenthook/<name>/logs/. Watch it live with agenthook follow. Stop with agenthook stop. If nothing fires, the troubleshooting guide is symptom-first.

init writes secrets as ${ENV} references, never literal values, so the config is safe to commit or share — the actual tokens stay in .env (gitignored) or your shell.

Documentation

Profiles & parallel runs

A profile is one config = one process = one isolated state dir. Run as many as you like side by side; nothing is shared.

agenthook start --config ~/proj-a/agenthook.config.json   # port 4123
agenthook start --config ~/proj-b/agenthook.config.json   # port 4124 (set in its config)

agenthook ls              # every profile + live status
# NAME    UP  PORT  TRACKER  INGRESS  AGENTS  QUEUE  LAST EVENT
# proj-a  *   4123  asana    ngrok    1       0      2m ago
# proj-b  *   4124  asana    hosted   0       0      1h ago

agenthook status proj-a   # one profile in detail (url, queue, recent runs)

Each command auto-discovers ./agenthook.config.json (walking up from the cwd); --config selects one explicitly.

Ingress (how the webhook reaches you)

Set by ingress.type in the config; the server owns its lifecycle (brings the tunnel up on start, tears it down on stop).

  • ngrok — managed tunnel, URL rotates each boot (so agenthook scrubs + re-registers the webhook on every start). A reserved domain makes it stable. Needs NGROK_AUTHTOKEN.
  • hosted (alias manual) — you front the receiver (127.0.0.1:<port>) with anything giving a stable HTTPS URL (Caddy, Cloudflare Tunnel, a load balancer) and set ingress.url. Stable URL → no re-register churn. Best for parallel/production.

Configuration

agenthook.config.json holds non-secret wiring + ${ENV} secret refs. State (dedup set, handshake secrets, pid, logs, heartbeat) lives centrally in ~/.agenthook/<name>/.

| Field | Meaning | |-------|---------| | name | Profile name; keys the state dir. Must be unique across running profiles. | | repoPath | The repo agents work in (worktrees are siblings). Relative paths resolve against the config. | | port | Local receiver port. Distinct per parallel profile. | | trigger | Comment prefix reserved for agent-authored comments (default @agent). | | maxConcurrent | How many agents run at once (each in its own worktree). | | fullAuto | Off by default. true adds --dangerously-skip-permissions to claude -p (unsandboxed code exec from a webhook — see the warning above). false = agents prompt for permission. | | tracker | { type, token, …, pipeline: [...] }type is asana, jira, github (labels), or github-projects (Projects v2 board columns); pipeline is the ordered steps (required). | | ingress | { type, … }ngrok / hosted; type-specific options. |

See agenthook.config.example.json for a fully-commented template and .env.example for the env vars each tracker/ingress needs.

Starting vs replaying work

A step's source stage — its label (GitHub), section (Asana), or status (Jira) — is its inbox. Forward motion is event-driven: an item entering a source stage fires that step. Nothing in agenthook moves an item into an inbox on its own — catchup/reconcile only replay items already resting in one. To start new work, you put it in the inbox.

| Action | What it does | When you reach for it | |--------|--------------|-----------------------| | trigger (live) | a label/section/status move into a source stage fires that step | the hot path — you, or a prior step's advance, move an item in | | run <ref> | inject a new item: assign it to you + move it into a step's source stage | start a backlog item that has never entered the pipeline (#11) | | reconcile | replay every item currently resting in a source stage (the one explicit poll) | recover items that entered while the server was down | | catchup <ref> | replay one such resting item | recover a single missed item |

reconcile/catchup are downtime replay only: they re-fire the step a resting item already maps to — they never move an item into a stage. If an item isn't in any source stage there's nothing to replay; use run (or move it in by hand) to start it.

Start a new item. There's no event for a backlog item until it enters a step's source stage. run assigns it to you (fail-closed scoping) and moves it in; the live webhook then fires the step normally:

agenthook run <ref>             # assign + enter the FIRST step's source stage (alias: kick)
agenthook run <ref> review      # target a named step's source stage
agenthook run <ref> --no-assign # skip the assign (only if it's already assigned to you)

If no server is up, the item just rests in the stage; agenthook reconcile picks it up once it's running.

Replay a missed item. Webhooks are push-only and fire on a transition (an item moving into a stage), not a state — so a move missed while the receiver was down can't be recovered by polling alone. Replay it explicitly through the running server:

agenthook catchup <ref>           # forge + POST the exact signed event for one resting item
agenthook catchup <ref> --force   # re-run even if already handled
agenthook reconcile               # re-fire every item resting in a source stage (the one explicit poll)

Operating running agents

Each run is a plain claude -p OS process working in its own git worktree.

agenthook agents                  # list running agents (pid, runtime, ref, live token tally)
agenthook follow [session-id]     # tail a live agent read-only (no second process)
agenthook usage                   # per-run token & cost table (--ref <n>, --day, --week)
agenthook cleanup                 # dry run: which worktrees are done and safe to remove
agenthook cleanup --apply         #   remove them (add --force for dirty ones)

Every claude -p run's token counts and cost are captured to usage.jsonl and surfaced by agenthook usage (with --day/--week rollups) plus token/cost columns on agents, status, and ls. See Token & cost tracking.

Agents never remove their own worktrees (INSTRUCTIONS §7); cleanup is the one place that does, and only once the PR is merged/closed or the tracker item is completed.

Safety

agenthook ships locked down: fullAuto is off by default, so agents run a permission-gated claude -p and prompt before acting. Enabling fullAuto opts into claude -p --dangerously-skip-permissions — then a verified webhook leads straight to code execution on your host, gated only by the HMAC signature + a non-guessable URL, and it is not sandboxed. Even with fullAuto on, agents branch off the default branch, open draft PRs, and ask rather than guess. Run on a trusted host, scope the token, stop the tunnel when idle, and prefer the sandboxed container with only the repo mounted. Full posture in docs/architecture.md; disclosure process in SECURITY.md.

How it works

  • Two blind axes. The engine names neither tracker nor tunnel; src/trackers/* and src/ingress/* adapters own all platform specifics behind one interface each.
  • Server owns ingress. start brings the tunnel up, registers the webhook (scrubbing stale hooks when the URL is ephemeral), serves, then tears down on exit.
  • Fast ACK, async work. Verify synchronously, ACK in <10s (providers retry otherwise), then dispatch off the response path.
  • Dedup. Providers deliver at-least-once; a per-event seen set keeps one event → one run.
  • Worktree isolation. Parallel agents never collide; each gets its own worktree.
  • Verdicts, not exit codes. Each agent writes a verdict (advance/hold/changes/fail) the receiver reads to route the task. The changes rework loop (e.g. review → code) is capped so it can't spin forever; a crash always means fail.

Details: docs/architecture.md · docs/providers.md · docs/agenthook-v2.md

Contributing & community

Issues, ideas, and PRs all welcome — agenthook is dependency-light and built to be hacked on.

  • 🛠 CONTRIBUTING.md — dev setup, the local CI gate, and a step-by-step guide to writing a new tracker/ingress adapter (the most common contribution).
  • 💬 DiscussionsQ&A for setup help, Ideas for features.
  • 🐛 Issues — reproducible bugs (start with good first issue).
  • Sponsor — if agenthook saves you time.

By participating you agree to the Code of Conduct.

License

MIT