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

@avee1234/handover

v0.2.1

Published

The open format for handing off an in-progress agent task. A portable, harness-neutral JSON packet capturing everything a fresh agent needs to RESUME a task mid-flight — goal, context, progress, working state, next steps, open questions, and artifacts — s

Readme

handover

The open format for handing off an in-progress agent task. When an agent has to stop mid-flight — context window full, session ending, a better-suited model or harness needed, a human stepping away — it writes a handover packet: a single portable JSON document capturing everything a fresh agent needs to resume the work exactly where it stopped. The goal, the constraints, what's been done, the live working state, what's next, what's still unknown, and the artifacts in play. So an in-progress task can move between agents or harnesses without losing its state. Zero dependencies.

Working name — see vision.md. Grounded in the mid-2026 state of long-running agent tasks.

Long-running agent tasks routinely outlive a single agent. A coding job spans more context than one window holds; a session hits its limit; the work would go faster on a different model; a human hands the thread to a teammate's agent overnight. Coding agents — Claude Code, Codex, Cursor, and Google Antigravity — all hit this wall. Today, when that handoff happens, the working state evaporates. The next agent gets a cold transcript (if anything) and re-derives the plan, re-reads the files, re-discovers the decisions already made — or silently drops a half-finished thread. git blame doesn't hold it; a chat transcript is lossy and harness-specific; every harness that gestures at "resume" or "session export" does it in its own private, non-portable shape.

A2A standardizes how one agent invokes another. Nothing standardizes the working state an agent hands over when it stops mid-task — so every resume starts from scratch.

handover is the missing layer: an open format for the working state handed over between two agents, not another orchestrator, memory store, or runtime.

npx @avee1234/handover pack --goal "add PKCE to login" --agent me   # capture the current handoff
npx @avee1234/handover completeness .handover/packet.json           # is this good enough to resume from?
npx @avee1234/handover resume .handover/packet.json                 # render the briefing for a fresh agent
npx @avee1234/handover diff old.json new.json                       # what did one checkpoint advance over another?
npx @avee1234/handover from claude-code transcript.jsonl            # draft a packet from a native session (any harness)

Why it's different: content-addressed, so a packet is self-identifying — its id is the sha256 of its content, so any edit produces a new identity and a resumed packet is provably the one that was handed off. It's a single living document, not a ledger — no registry to fold, no server to run. Harness-neutral: Claude Code, Codex, Cursor, Google Antigravity, or a factory worker — anything that can run a CLI or import a function.

Same open-format playbook as opentrajectory (traces), provenant (provenance), and worklease (coordination) — the standard for the one thing a mid-task agent handoff currently lacks: a portable working-state document.

The packet format

A handover packet is one JSON document. id is the sha256 content hash of the record itself (its own id excluded), so a record's identity is its content. goal and provenance are the required spine; every other section is optional but type-checked when present.

{
  "id": "19483d7ee3c50e5f4ee2507643f205e9c6f28bc6f972e04bece928519b4a3374",
  "version": 1,
  "goal": "add PKCE to the OAuth login flow",
  "context": "Zero new deps. The auth module must stay framework-agnostic.",
  "progress": [
    "wrote the PKCE verifier/challenge helpers",
    "wired them into the /authorize handler"
  ],
  "state": {
    "cursor": "src/auth/login.ts:142",
    "approach": "S256 challenge",
    "key_files": ["src/auth/login.ts", "src/auth/pkce.ts"]
  },
  "next_steps": [
    "handle the token-exchange callback",
    "add tests for the verifier"
  ],
  "open_questions": ["should we fall back to plain challenge for legacy clients?"],
  "artifacts": [{ "path": "src/auth/pkce.ts", "note": "new helper module" }],
  "provenance": {
    "handed_off_by": "claude-opus-4-8/claude-code",
    "created": "2026-07-11T12:00:00Z",
    "from_session": "sess-9f21"
  }
}
  • goalthe task being handed off (required, non-empty).
  • context — constraints, background, and decisions the resumer must respect.
  • progress — what's already been done (array of notes).
  • state — the live working state (free-form object); an optional key_files array names the files to open first.
  • next_steps — what to do next.
  • open_questions — what's still unresolved.
  • artifacts{ path, hash?, note? } for the files produced or touched; hash (if present) is the sha256 of the file's bytes.
  • provenancewho handed off (handed_off_by), when (created, ISO-8601-UTC, …Z; offsets and impossible calendar dates are rejected), and optionally the originating from_session.
  • version — the checkpoint number, incremented by revise.

Library API

Zero-dependency ESM. import { … } from "@avee1234/handover". Every function is pure and clock-injected (no I/O except the packet store), so the whole core is deterministic and unit-testable.

Schema & validation — never throw; each returns { valid, errors } collecting every violation.

  • validatePacket(obj) / validateArtifact(obj)
  • isSha256Hex(s), isIso8601Utc(s) — the two format primitives
  • PACKET_FIELDS, REQUIRED_SECTIONS, ERROR_CODES

Construct — pure packet constructors (throw on bad input rather than emit a malformed packet).

  • pack(input) → a validated packet with a content-hash id and all section defaults applied. input is { goal, agent, created, context?, progress?, state?, next_steps?, open_questions?, artifacts?, from_session?, version? }; created is injected (no clock inside).
  • revise(packet, patch) → a NEW checkpoint: version incremented, array sections appended, scalar sections (goal, context) replaced when present, state shallow-merged, provenance refreshed (patch.created required — a revision is a fresh handoff).

Hash & id — the content-address primitives.

  • computeId(record) → the sha256 content hash of a record (its own id excluded)
  • canonicalize(record) → the deterministic hash pre-image (sorted keys, recursive)
  • computeHash(content) → the sha256 hex of a string/Buffer (an artifact fingerprint for artifacts[].hash)

Assess & render — pure, total, over a single packet.

  • completeness(packet){ score, total, present, missing, warnings } — how much of the handoff a fresh agent has to work with, over the seven REQUIRED_SECTIONS, plus plain-language warnings about gaps that strand a resumer.
  • resume(packet) → the Markdown briefing a fresh agent can be handed verbatim (goal, context, what's done, live state + key files, next steps, open questions, artifacts, and a provenance footer).
  • resumeInto(packet, harness) → the same briefing in a harness's opening-context shape: 'system-prompt' (a system-prompt string), 'user-turn' (a first-user-message string), or 'mcp-resource' ({ uri, mimeType: 'text/markdown', text }). The Markdown body is the real resume() output in every shape; an unknown shape throws (the supported shapes are in RESUME_SHAPES).
  • summarize(packet) → a one-line status: "<goal> — N done, M next, K open".
  • diffPackets(a, b) → what checkpoint b advanced over a: { goal_changed, version_delta, progress_added/removed, next_steps_added/removed, questions_opened/closed, artifacts_added/removed, state_keys_changed } (set semantics on the string arrays — reordering reads as no change).

Packet store — the single-document I/O layer.

  • savePacket(path, packet) → write the packet as pretty JSON (creating its parent dir); overwrites in place — a packet is one living document, not an append log.
  • loadPacket(path) → the parsed packet (clear throw on a missing file or malformed JSON).
  • defaultPacketPath(cwd)HANDOVER_PACKET, else .handover/packet.json.

Adapters — seed a draft packet from a harness's native session artifact so writing one is cheap. Every adapter shares one contract: (raw, opts) → draftPacket — latest user message → goal, last assistant turn → context, assistant bullet/numbered lines → progress. All are pure and tolerant of malformed input, and all return a PARTIAL draft (no id, no created) — not a validated packet. Refine it, then pack(). opts is { agent?, from_session?, max_progress? }.

  • fromClaudeCode(rawJsonlTranscript, opts) → draft from a Claude Code .jsonl session transcript.
  • fromCodex(rawJsonlRollout, opts) → draft from an OpenAI Codex CLI .jsonl rollout (unwraps the payload envelope; reads input_text / output_text blocks).
  • fromCursor(rawSession, opts) → draft from a Cursor chat export (whole-document JSON, .jsonl, User:/Assistant: prose, or a marker-less scratchpad).
  • fromAntigravity(rawSession, opts) → draft from a Google Antigravity session (JSON / .jsonl / prose) or an AGENTS.md-style task brief (headings → goal, bullets → progress).
  • ADAPTERS, getAdapter(name) — the name→builder registry keyed claude-code / codex / cursor / antigravity (add new harnesses here).

CLI

handover pack [--file <in.json>] [--agent <id>] [--goal "<task>"] [--out <path>] [--json]
handover show <file> [--json]
handover validate <file> [--json]
handover completeness <file> [--json]
handover resume <file>
handover diff <a> <b> [--json]
handover from <harness> <file> [--agent <id>] [--json]
handover from-<harness> <file> [--agent <id>] [--json]
  • pack — read a JSON object (from --file or stdin), fill section defaults, stamp the handoff (agent + timestamp), validate, and write the packet. --goal / --agent override the input; the clock is read only here. Writes to --out (default: HANDOVER_PACKET, else .handover/packet.json).
  • show — pretty-print a packet (--json), or a one-line summary without it.
  • validate — validate a packet against the schema. Exit 0 if valid, 1 otherwise (errors listed with their paths and codes).
  • completeness — score how much of the handoff a fresh agent has to work with, and warn about the gaps that strand a resumer.
  • resume — render the Markdown briefing a fresh agent can be handed verbatim.
  • diff — show what checkpoint <b> advanced over checkpoint <a>.
  • from — resolve a harness adapter from the registry (claude-code, codex, cursor, antigravity) and parse its native session artifact into a DRAFT packet to refine and pipe back into handover pack. from-<harness> (e.g. from-claude-code) is the shorthand form.

Common flags: --agent <id> (or HANDOVER_AGENT), --out <path> (or HANDOVER_PACKET, default .handover/packet.json), --json for machine-readable output.

Install

npm install @avee1234/handover      # library
npx @avee1234/handover pack …       # CLI, no install

Requires Node ≥ 18. Run the test suite with node --test.

Status: v0.2 — multi-harness adapters (Claude Code, Codex, Cursor, Google Antigravity) + resumeInto. See roadmap.md. MIT · zero dependencies · harness-neutral.