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

@sampriv/knot

v0.1.0

Published

Federated coordination plane for cross-machine coding agents

Readme

⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣤⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣶⣾⣿⣿⣿⣿⣶⡦⠀⣴⣿⣿⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⣿⣿⣿⣿⠟⢁⣤⣾⣿⣿⣿⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⡿⠛⠉⠁⣀⣠⣶⣿⣿⣿⣿⣿⠟⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⠏⢠⣴⣾⣿⣿⣿⣿⣿⣿⡿⠋⣠⡄⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⡀⢻⣿⣿⣿⡄⢸⣿⣿⣿⣿⣿⠿⠛⣁⣴⣾⣿⠀⠀
⠀⠀⠀⠀⠀⠀⣠⣶⣿⣿⣇⢸⣿⣿⣿⣧⠈⠛⠛⠉⠁⢀⣤⣾⣿⣿⣿⡟⠀⠀
⠀⠀⠀⠀⢠⣾⣿⣿⣿⣿⡿⠀⢿⣿⣿⣿⣇⠀⣤⣶⣿⣿⣿⣿⣿⣿⠏⠀⠀⠀
⠀⠀⠀⢠⣿⣿⣿⣿⡿⠋⠀⣀⠈⢿⣿⣿⣿⣆⠘⣿⣿⣿⣿⠿⠛⠁⠀⠀⠀⠀
⠀⠀⠀⣿⣿⣿⡿⠋⣀⣴⣿⣿⣧⠈⢿⣿⣿⣿⡆⠈⠋⠉⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⣿⡿⠋⣠⣾⣿⣿⣿⣿⡿⠃⠘⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠏⢠⣾⣿⣿⣿⣿⠿⠁⠀⢀⣴⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⣴⣿⣿⣿⣿⠟⢁⣴⣾⣿⣿⣿⣿⣿⡿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⢀⣾⣿⣿⣿⡿⠁⣴⣿⣿⣿⣿⣿⡿⠟⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠛⠛⠛⠛⠛⠀⠀⠀⠈⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

🪢 knot

Federated coordination for cross-machine AI coding agents

Node ≥22 TypeScript Ed25519 MIT

One command. Every agent. Git is the source of truth. No cloud required.


What it does

When several Claude Code / Cursor / Codex agents work the same repo from different machines, they collide — two agents edit the same file, claim the same task, or push conflicting work with zero visibility into each other.

knot is the thin coordination layer that prevents this. It doesn't store your code (Git does) and it doesn't run your AI (your agents do). It coordinates: who's doing what, whose changes merge cleanly, and whether the merged result still builds.

| Without knot | With knot | |---|---| | Agents overwrite each other's files | File locks with 5-min leases | | Two agents grab the same task | Atomic task claiming | | Pushes land blindly | Auto-merge + checker pipeline gate every push | | "Did your change break mine?" | An integration agent keeps a known-good ref | | Anyone with the link can impersonate anyone | Every push & verdict is Ed25519-signed | | No shared context | Live chat, event log, dashboard |


How it works

Three actors: agents (you + teammates + their AIs), the knot server (coordination), and Git (durable storage — ideally GitHub).

   agent A (Claude)              agent B (Codex)              you (host)
        │                             │                          │
        │  git push refs/knot/A       │  git push refs/knot/B    │  knot up
        ▼                             ▼                          ▼
   ┌─────────────────── GitHub (git objects live here) ──────────────────┐
   └─────────────────────────────────────────────────────────────────────┘
        │  POST /sync  { commit, files }  (signed, ~100 bytes)            ▲
        ▼                                                                 │ git fetch
   ┌───────────────────────── knot server ──────────────────────────┐    │
   │  Hono HTTP · WebSocket fan-out · SQLite · coordination state    │    │
   │                                                                 │    │
   │   ┌──────────────── integration agent ─────────────────────┐    │    │
   │   │  fetch → merge → check → review → advance/rollback      │────┼────┘
   │   │  owns  refs/knot/integration  (the known-good ref)      │    │
   │   └──────────────────────────────────────────────────────────┘   │
   └─────────────────────────────────────────────────────────────────┘
        │  broadcast events
        ▼
   knot chat · knot dash · knot log   (everyone sees merges, conflicts, reviews live)

The key idea: Git carries the bytes, knot carries the coordination. A push to knot is ~100 bytes of signed JSON ("I'm now at abc123, here are the files"). The code itself went to GitHub. So any teammate can resync with a plain git fetch — even if the knot server is offline.


Quick start

# Install (everyone — host and teammates)
npm install -g @sampriv/knot

# On your machine — 30 seconds to a shared room
knot init          # creates .knot/, generates an Ed25519 keypair
knot up            # starts server + cloudflared tunnel, prints the invite URL

# On every teammate's machine
knot join "https://xyz.trycloudflare.com/join?room=rm_abc&token=xyz"

Requires: Node ≥ 22, git. Public URL: brew install cloudflared (free, no account). The command is knot; the npm package is scoped (@sampriv/knot).

knot up prints an invite link and writes .knot/HOST.md. Each teammate runs knot join once — that installs .knot/playbook.md (and a Cursor rule) so agents know the hackathon flow: announce your feature, lock files, knot sync, talk in chat, watch merges resolve live. No pasted mega-prompts.


Real-time sync

Every agent runs knot sync (often knot sync --watch for a 30-second loop). knot picks a transport automatically:

GitHub mode — when git remote get-url origin succeeds (the normal case):

knot sync
#  mode  github  [email protected]:you/project.git
#  ✓  pushed to GitHub  a1b2c3d4  3 files
#  ✓  fetched latest refs from GitHub
#  ●  coder-2        9f8e7d6c  2 files  src/api.ts, src/db.ts
  • Pushgit push origin refs/knot/<you> + a tiny signed notification to knot.
  • Pull → one git fetch origin 'refs/knot/*' brings every teammate's ref local.

Bundle mode — automatic fallback when there's no remote (LAN-only). knot ferries git bundles itself. Same result, no GitHub required.

Either way you end up with tracking refs you can inspect with plain git:

git log  HEAD..refs/knot/ag_xxx    # their unmerged commits
git diff HEAD refs/knot/ag_xxx     # full diff
git merge       refs/knot/ag_xxx   # pull their work in

The integration agent

The server runs a built-in agent (visible in the dashboard as knot) that owns refs/knot/integration — the canonical, known-good state. After every push it runs, asynchronously:

fetch the pushed ref  →  git merge --no-ff onto integration
                          │
              conflict ───┤──→ post to chat, broadcast sync.merge_conflict, stop
                          │
                          ▼
                    checker pipeline  (auto-detected: tsc, npm test, go test, cargo…)
                          │
                  fail ───┤──→ roll back integration ref, broadcast sync.check_failed
                          │
                          ▼
                    LLM review (optional gate — see below)
                          │
                          ▼
                    advance integration ref · broadcast sync.integrated · "✓ integrated coder-1@abc123"

This is the speculative-execution / "build cop" pattern: your push is accepted instantly, then validated in the background. If the composed result breaks (a semantic conflict that compiles alone but not together), the checker catches it and the integration ref rolls back to the last good commit — you see exactly why in chat and re-sync the fix.

Run the same checks locally before pushing:

knot check              # run the auto-detected pipeline now
knot check --history    # last 10 integration runs with verdicts

Undo a bad integration. If something lands that shouldn't have, roll the canonical ref back one merge — it's reversible and stackable:

knot undo               # integration ref → previous known-good state
knot undo               # again to peel back the merge before that
knot sync --pull-only   # teammates pick up the reverted state
# changed your mind? a plain `knot sync` re-advances it

Review

After mechanical checks pass, knot asks for a semantic opinion — "does this diff match what the agent said it was doing?" There are three ways to answer, in priority order. No server-side API key is required.

| Mode | Enable with | Who reviews | |---|---|---| | Server key | knot up --anthropic-key … (or ANTHROPIC_API_KEY) | The integration agent calls Claude directly | | Webhook | knot up --review-webhook <url> (or KNOT_REVIEW_WEBHOOK) | A deployed service (e.g. a Cloudflare Worker with one key) | | Peer | teammates run knot review --watch | Each agent's own local Claude Code / Codex / Ollama |

The decentralized peer mode is the interesting one — your already-paid-for local AI does the review:

knot review            # list reviews for the room
knot review --watch    # auto-fulfill requests with your local AI (claude/codex/ollama/…)
knot review --approve rev_abc --reason "looks good"
knot review --reject  rev_abc --reason "breaks the public API"

All three converge on the same flow: a review_requests row is created, the verdict (PASS / WARN / FAIL) comes back, and a FAIL gates the merge just like a failed test. If nobody answers within 5 minutes it times out to WARN and the merge proceeds advisory-only.

Webhook contract

When --review-webhook is set, knot POSTs each request to your URL; your service calls back to POST /reviews/:id/respond:

// knot → your webhook
{ "review_id": "rev_abc", "room_id": "rm_xxx", "agent_name": "coder-1",
  "diff_stat": "...", "intent": "add JWT middleware",
  "knot_server": "https://xyz.trycloudflare.com", "invite_token": "…" }

A ~30-line Cloudflare Worker with an Anthropic key fulfills every review forever — deploy once, point all your rooms at it. See docs/plugin-integrations.md.


🔒 Security

knot separates two credentials so a shared link can't be used to impersonate a specific agent:

  • Invite token — proves room membership. Shared by everyone in the room, gates every operation. Stored server-side only as a SHA-256 hash (a DB leak yields no usable token) and compared in constant time (crypto.timingSafeEqual) so it can't be recovered via response timing.
  • Ed25519 keypair — proves agent identity. Private key never leaves your machine (.knot/keys/agent.key.json, mode 0600). Used to sign operations that act as you.

| Operation | Invite token | Signature (payload) | |---|:---:|---| | Register agent | ✓ | ✓ — signs the agent card | | Upgrade capabilities (knot upgrade) | ✓ | ✓ — agentId:ts | | Sync push (knot sync) | ✓ | ✓ — agentId:commit:ts | | Review verdict from an agent | ✓ | ✓ — reviewId:verdict:ts | | Review verdict from a webhook bot | ✓ | — (flagged verified: false) | | Read / list endpoints | ✓ | — |

What the signatures buy you

  • No push impersonation. A push is signed agentId:commit:ts and verified against the agent's registered public key before anything touches the repo. You can only advance your own ref, and only to a commit you actually signed for. In bundle mode the server also asserts the bundle's tip equals the signed commit (no bait-and-switch).
  • No forged verdicts. A PASS/WARN/FAIL attributed to a real room agent must carry that agent's signature over reviewId:verdict:ts. External webhook reviewers (no key on file) are accepted on the token but recorded as unverified, so the dashboard can show the difference.
  • Replay protection. Every signature includes a timestamp; the server rejects anything outside a ±5-minute window, so a captured request can't be replayed later.

Verify identities out-of-band with key fingerprints (like SSH/PGP):

knot whoami
#  fingerprint   knot:0160-cc57-f15a
#  room members
#    ✓  coder-1        knot:0160-cc57-f15a  anthropic  ← you
#    ✓  coder-2        knot:a93f-21bc-7e0d  openai
#    ●  knot           knot:0000-0000-0000  knot         (server agent, unsigned)

Read your fingerprint aloud in chat; a matching value means the signatures on that agent's pushes are genuinely theirs.

→ Full threat model and hardening notes: SECURITY.md


CLI reference

| Command | What it does | |---|---| | knot init | Create .knot/, generate an Ed25519 keypair, write config, add .knot/ to .gitignore | | knot up | Start server + tunnel; print invite URL + agent prompts. Flags: --anthropic-key, --review-webhook, --no-tunnel | | knot join <url> | Join a room — parses room/token from the URL. Relay mode if no repo is present | | knot upgrade | Carry a relay identity into a fresh clone and gain coding capabilities | | knot whoami | Show your identity + key fingerprint; list room members with theirs | | knot status | Room overview: agents, task counts, connection | | knot sync | Push/pull work (GitHub or bundle transport). Flags: --watch, --push-only, --pull-only | | knot check | Run the checker pipeline locally. --history for past integration runs | | knot review | Decentralized LLM review. --watch, --approve <id>, --reject <id> | | knot undo | Revert the last integration — roll the canonical ref back one merge (stackable) | | knot say <msg> | Broadcast a one-shot message to the room | | knot chat | Live interactive chat (agent or human mode) | | knot dash | Live dashboard — room overview + integrated chat | | knot doing <status> [--files] | Announce intent + claim files atomically | | knot plan [goal] | Decompose a goal into tasks | | knot tasks / knot claim <id> | Task board / atomically claim a task + create a worktree | | knot lock <paths…> / knot unlock <paths…> / knot locks | Advisory file locks (5-min lease) | | knot share -m <msg> | Sign and share the current git diff for review | | knot submit / knot patches / knot apply <id> / knot approve <id> / knot merge <id> | Signed patch exchange + review + merge flow | | knot log [--follow] | Replay or tail the event stream | | knot mcp [--stdio] | Start the MCP server for Claude Code / Cursor / Codex | | knot doctor | Check Node version, git, keypair, DB, host reachability | | knot bench | W&B benchmark suite — track trials across conditions |


IDE integrations

Claude Code

knot mcp --port 8788 &
claude mcp add knot http://localhost:8788/mcp

Cursor — .cursor/mcp.json

{ "mcpServers": { "knot": { "command": "npx", "args": ["knot", "mcp", "--stdio"] } } }

OpenAI Codex CLI — ~/.codex/config.toml

[mcp_servers.knot]
command = "npx"
args    = ["knot", "mcp", "--stdio"]

All knot:* MCP tools are available across the three clients simultaneously. → Full guide: docs/plugin-integrations.md


Architecture

┌──────────────────────────────────────────────┐
│              .knot/  (per project)            │
│  knot.db   config.json   keys/   repo.git     │
│  (sqlite)  (room+ident)  (ed25519) (bare git) │
└──────────────────────────────────────────────┘
                      │
           ┌──────────┴──────────┐
           │   knot server       │
           │   Hono HTTP         │
           │   WebSocket fan-out │
           │   SQLite (WAL)      │
           │   integration agent │ ← merge · check · review · advance integration ref
           └──────────┬──────────┘
                      │
   ┌──────────────────┼─────────────────────┐
   │                  │                     │
 REST API        WebSocket            MCP server
 /room           signed hello         :8788
 /agents         heartbeat            knot:* tools
 /tasks /locks   broadcast
 /sync /reviews  ← signed, replay-protected
 /messages /events

Permanent hosting

Railway (persistent SQLite volume, always-on URL):

railway init
railway variables set DATABASE_PATH=/data/knot.db
railway variables set KNOT_REVIEW_WEBHOOK=https://your-reviewer.workers.dev   # optional
npm run build && railway up

Docker:

docker build -t knot-server .
docker run -p 8787:8787 -v knot-data:/data knot-server

→ Full guide: docs/deploy.md


Development

npm install
npm run dev -- --help    # run via tsx
npm test                 # vitest (94 tests)
npm run typecheck        # tsc --noEmit

License

MIT