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

@archangel-tools/agent-worker

v0.2.2

Published

Unattended executor for agent-context organizations: scheduler + spawner + contract-verifier around headless Claude Code sessions. Org knowledge arrives at runtime from the layer and the backend.

Readme

agent-worker

An unattended executor: a THIN daemon — scheduler + spawner + contract-verifier — around headless Claude Code sessions riding an operator's subscription OAuth (~/.claude). All task intelligence lives in the workplace's compiled layer (the execute-task skill); the worker only polls the release gate, claims, spawns, and enforces the runtime contract (CONTRACTS.md). ANTHROPIC_API_KEY is deleted from every child environment.

Deployment model

The worker is thin on purpose: one instance per identity+host, serving exactly the orgs that identity holds credentials for. The package knows nothing about any organization's content — org knowledge arrives at runtime from the org's layer (_schema.md bindings) and the backend it points at. Jobs are deployment config, not package content: point jobs_dir at your own job files; the packaged jobs.example/ is a template to copy from. Architecture decision: https://app.notion.com/p/3b7bfb5a7adc8165ace9e582b95a8454

Three credentials never live in a repo; every deployment supplies its own:

  1. a Notion token, scoped to that org's teamspace, in the env var the config names (notion_token_env, default NOTION_TOKEN);
  2. git access to that org's repos;
  3. a Claude login (claude CLI logged in, credentials in ~/.claude).

Prerequisites

  • Node >= 22.5
  • claude CLI installed and logged in
  • a Notion integration whose token can read and write the org's tracker, anchor, and activity-log collections

Runbook A — the vendor cockpit (this checkout)

The vendor runs one worker over every org, from the workspace root that holds all the repos side by side:

# clone the workspace root, then fill it
./bootstrap.sh                             # every repo, from repos.txt

cd archangel-tools/agent-worker
npm install && npm run build               # build from source

mkdir -p ~/.config/agent-worker
cp config.example.yaml ~/.config/agent-worker/config.yaml
# then edit: constellation_root = the workspace root,
#            agent_ctx_bin = <root>/archangel-tools/agent-ctx/bin/agent-ctx,
#            jobs_dir = <root>/archangel-tools/agent-worker/jobs,
#            one org entry per org (default NOTION_TOKEN env)

export NOTION_TOKEN=...                    # never config, never logged
npx -y @archangel-tools/agent-ctx@latest mirror <org>/agent-context   # mirror init

node bin/agent-worker doctor               # exit 1 on a hard failure
node bin/agent-worker once --dry-run       # what WOULD be claimed/fired; zero writes
scripts/start.sh                           # nohup + pidfile in ~/.local/state/agent-worker
scripts/stop.sh                            # SIGTERM; finishes the current run, then exits

Runbook B — a single-org deployment

A client org needs no vendor git access at all — the worker installs from public npm, and the only repos on disk are the org's own:

npm i -g @archangel-tools/agent-worker

# ONLY your org, under one root:
mkdir -p ~/agents && cd ~/agents
git clone <your-git-host>/<org>/agent-context
git clone <your-git-host>/<org>/<workplace>   # each workplace the tracker claims

mkdir -p ~/.config/agent-worker
# config: constellation_root: /home/you/agents, orgs: [yours] with your
# notion_token_env — see the packaged config.example.yaml
export NOTION_TOKEN=...                    # or the var your config names

# YOUR Claude subscription login: `claude` installed and logged in

agent-worker doctor
agent-worker once --dry-run
agent-worker run                           # foreground; supervise however you like

Optional jobs: copy the packaged jobs.example/ somewhere, replace <org>, and point jobs_dir at it.

Run

run loops every poll_seconds: due jobs first (jobs_dir/*.yaml — daily at: or every_minutes:), then ONE task cycle per org — query the org tracker's Ready gate, resolve the workplace through task → project → solution → Repos, claim to In progress, spawn claude -p with agent-ctx recall output injected first and the output discipline appended last, and hand back to Review. One session at a time, sequential by design.

The prompt a run gets

Every prompt the daemon builds — task or job — is three parts in one fixed order: the recall block (or the marked <!-- no memory available --> line), then the body (the task instruction, or a job's own prompt verbatim), then a closing <output-discipline> block, the same bytes on every run.

That block tells an unattended session to skip preamble and postamble, never to restate code, file contents, diffs or tool output already in the conversation, to continue without narrating a tool call that succeeded, and to spend the words on the journal entry and the final report instead — those are the parts a human actually reads. Everything else is prose written into a log file nobody opens, and it is billed at output rates, several times input on these models.

Two properties of the block are load-bearing:

  • It is at the tail. The memory block and the task body ahead of it stay a reusable prompt prefix; the discipline is appended after them, not woven in.
  • It is byte-stable. Editing a byte is a cache-busting change across every job and every task, not a copy tweak. OUTPUT_DISCIPLINE in src/runner.ts is the text; reword it deliberately or not at all.

It governs prose only, and it says so in its own last sentence — it never licenses doing less of the work, skipping a check, or leaving the journal entry thin. A session told to be brief will otherwise hear "be brief about the work".

What a run costs

claude -p --output-format json already prices every run it finishes. The runner keeps what it reports — total_cost_usd, num_turns and the usage token breakdown, on RunOutcome.cost — and logs one line per run, to stdout and to the worker log in the state dir:

cost: $0.4213 turns=12 in=900 out=300 cache_read=41000

There is no ledger. Nothing aggregates those lines, nothing budgets against them, and nothing declines a run for being expensive. This is only the part that was free and that stopped being recoverable the moment the child process exited: the number existed, the runner was discarding it, and the sole way back to it afterwards is re-reading megabytes of transcript. A CLI old enough to report none of these fields leaves the run unpriced — no line, no cost on the outcome — rather than failing it.

Jobs

A job is one YAML file in jobs_dir, loaded in filename order:

  • name — required; the key its last-run timestamp is stored under.
  • at: "HH:MM" (daily, local) or every_minutes: <n> — exactly one of them.
  • kind: claude | command — a claude job goes through the same runner as a task; a command job is a plain spawn.
  • cwd — path under constellation_root; defaults to the root itself.
  • prompt — required for kind: claude; used as the prompt body, verbatim.
  • argv — required, non-empty, for kind: command.
  • allowed_tools — the --allowedTools list; empty by default.
  • add_dirs--add-dir entries; a leading ~/ is expanded at run time.
  • permission_modeacceptEdits by default.
  • max_turns100 by default.

Last-run state lives in jobs.json in the state dir. A daily job fires once at has passed today and the last run predates it; the attempt is recorded even when it fails, so a broken job does not re-fire on every poll. A claude-kind job runs against the first configured org's bindings and token, and journals itself through its own skill — a missing entry is logged, never backfilled (only task runs get a backfill).

Pin the spec in any job argv that runs the engine. mirror-refresh shipped as npx -y @archangel-tools/agent-ctx with no version, so npx served whatever its cache already held — a build predating the mirror command. The job failed nightly with "unknown command", the mirror was never refreshed, and every job and task after it ran with <!-- no memory available -->: a silent no-op that cost the whole deployment its memory. The argv now says @archangel-tools/agent-ctx@latest, which is what src/runner.ts already did for recall.

This checkout's own jobs/ holds three, and their order is deliberate:

  • nightly-sweep (03:17, claude) — the sweep-activity-log skill over the last 7 days: diff local session transcripts against the Activity Log by session: token and backfill missing sessions as Draft entries.
  • mine-session-waste (03:27, claude) — after the sweep, so every session in the window is already journalled. It reads this org's session transcripts, canonicalizes each tool call so pagination and truncation differences collapse into one signature, and reports loops of three or more occurrences (error loops and re-fetch loops counted differently). Each distinct signature is filed as a Task in the un-released stage (Not started, never Ready), titled with the guardrail rather than the symptom; an existing open task for the same signature is updated instead of twinned. At most 20 items per run, and it journals itself only if something was filed. It may never write Knowledge, author a decision, or move a task to Ready — that is invariant 11 of the event-sourcing pattern, and the reason its output is a proposal a human releases. Look for what it found in the Tasks database, un-released stage. It reads transcripts rather than the mirror, so its slot is about the sweep having finished, not about memory.
  • mirror-refresh (03:47, command) — agent-ctx mirror for the org's layer, so the next day's recall has current memory.

jobs/ is this deployment's config and is not packaged. Only nightly-sweep and mirror-refresh ship as templates, in jobs.example/: copy them, replace <org>, and point jobs_dir at the copies.

The contract it enforces

  • Recall before the task — fail-soft; a missing mirror degrades to a marked "no memory available" line, never blocks the run.
  • Journal after the task — the runner verifies one activity-log entry carrying the run's session:<id> token; a task session that did not journal itself gets a Draft entry backfilled by the runner and the run exits flagged. Jobs journal themselves per their own skills; a gap is logged, not backfilled.

Boundaries (from CONTRACTS.md)

  • The worker never commits, tags, or pushes; it stops where agent-ctx stops.
  • One organization per run: a run binds to one org's layer, mirror, and journal; nothing crosses orgs inside a run.