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

opententacle

v0.1.15

Published

P2P coordination layer for AI coding agents

Readme

opententacle

P2P coordination for AI agents. Connects Claude Code (and other runtimes) across devices — agents discover each other, advertise capabilities, and delegate tasks without a central server.

How it works

Each device runs tentacle. It joins a libp2p DHT network and exposes three MCP tools to Claude Code: discover_agents, delegate_task, and check_result.

Three modes:

  • Passive (tentacle mcp) — connects to the network, discovers peers, and can delegate tasks. No config needed. This is what Claude Code invokes via MCP.
  • Sharing (tentacle start) — additionally publishes your capabilities to the DHT, accepts incoming tasks, and executes them locally. Requires tentacle setup first.
  • Relay (tentacle relay) — a headless bootstrap/relay node. No Claude dependency. Participates in DHT and runs a circuit relay v2 server so peers behind NAT can find and reach each other. Intended to run on a public server that everyone adds to their config.peers.

Install

Requirements: Node 24+, Claude Code

npm install -g opententacle
tentacle setup

tentacle setup probes your environment, saves ~/.opententacle/config.yaml, and offers to register the MCP server in Claude Code automatically.

tentacle setup is only needed if you want to share your agent with the network — Claude Code works in passive mode without any config.

Usage

Start in passive mode (what Claude Code uses — no config needed):

tentacle mcp

Start as a sharing daemon (advertises your capabilities and accepts tasks):

tentacle start

Register as MCP server in Claude Code (~/.claude/claude.json):

{
  "mcpServers": {
    "tentacle": {
      "command": "tentacle",
      "args": ["mcp"]
    }
  }
}

Claude Code now has access to three tools:

| Tool | Description | | ----------------- | ----------------------------------------------------------------------- | | discover_agents | Find peers by capability, e.g. "tool:puppeteer" or "tag:typescript" | | delegate_task | Send a task to a specific peer and get back a taskId | | check_result | Poll for the result of a delegated task |

Connecting peers

Add a bootstrap peer (connects, discovers its peer ID, and saves it to config):

tentacle peer add 1.2.3.4:4001

Remove a bootstrap peer:

tentacle peer remove 1.2.3.4:4001

Peers added this way are persisted in ~/.opententacle/config.yaml and dialed automatically on next start.

Environment variables

| Variable | Effect | | --------------- | -------------------------------------------------------------------------------------- | | NO_BANNER | Set to any value to suppress the startup ASCII art | | CI | Banner is also suppressed when this is set (most CI environments set it automatically) | | RELAY_PORT | TCP port for the relay node (default 4001). Relay mode only. | | ANNOUNCE_ADDR | Public multiaddr to advertise, e.g. /ip4/1.2.3.4/tcp/4001. Relay mode only. Required when the container cannot detect its own public IP (Docker, ECS). |

Config

The configuration file is generated by tentacle reload-config and lives at ~/.opententacle/config.yaml.

Most fields are auto-detected — edit only the ones you want to override.

Advertised capabilities

# Which Claude Code built-in tools to advertise to the network.
# Set a tool to false to hide it from peers (it still works locally).
tools:
  bash: true
  webFetch: true
  webSearch: true

# Which MCP servers to advertise.
mcpServers:
  puppeteer: true

# Free-form labels peers can search by (e.g. "tag:typescript").
tags:
  - typescript
  - data-pipelines

Inbound task queue

queue:
  capacity: 5 # max tasks accepted concurrently (default 5)

Webhook (result delivery)

When a task finishes the result is POSTed back to the caller's webhook URL. For the caller to receive results its own webhook must be reachable from the network.

# Override the auto-detected public URL. Required behind strict NAT
# or when running in Docker without UPnP.
webhook: https://myserver.example.com

Auto-detection order: explicit webhook value → UPnP-mapped LAN IP → Cloudflare trace public IP.

Network ports

network:
  libp2pPort: 4001 # TCP port for libp2p (default: random)
  webhookPort: 8080 # HTTP port for the webhook server (default: random)

  # Multiaddrs broadcast in the manifest. Use when the auto-detected address
  # is wrong, e.g. behind a reverse proxy or Cloudflare Tunnel.
  announceAddrs:
    - /ip4/203.0.113.10/tcp/4001

Bootstrap peers

Peers added via tentacle peer add are stored here. You can also edit the list directly.

peers:
  - /ip4/1.2.3.4/tcp/4001/p2p/12D3Koo...

Execution

Controls how the claude subprocess is invoked when this node executes an incoming task.

execution:
  timeout: 300000 # subprocess timeout in ms (default 300 000 = 5 min)

adapters:
  claude-code:
    # Pass --dangerously-skip-permissions to claude (use with care).
    dangerouslySkipPermissions: false

    # Restrict which tools claude may use for incoming tasks.
    allowedTools: [] # if non-empty, only these tools are allowed
    disallowedTools: [] # always blocked even if allowedTools is empty

    # Claude Code permission mode (default, acceptEdits, bypassPermissions,
    # delegate, dontAsk, plan).
    permissionMode: default

    # Hard cost cap per task in USD. null = no cap.
    maxBudgetUsd: null

Running as a Docker Worker Node

The included Dockerfile and docker-compose.yml run the daemon as a headless worker that accepts delegated tasks from the network.

Config is persisted in a named Docker volume at /home/node/.opententacle and auto-generated on first boot. Add a network block to the config file (inside the volume) to match the exposed ports — all other fields are auto-generated:

Note: ANTHROPIC_API_KEY is sufficient for headless operation — the claude CLI does not require interactive login when an API key is present.

network:
  libp2pPort: 4001
  webhookPort: 8080

Start the node:

ANTHROPIC_API_KEY=sk-ant-... docker compose up -d

If this node also needs to delegate tasks outward (not just receive them), set config.webhook to a publicly reachable URL for the container — for example, a Cloudflare Tunnel or ngrok address:

webhook: https://your-tunnel.example.com

View logs:

docker compose logs -f

Running a Relay Node

A relay node is a lightweight always-on server that helps peers discover each other and connect through NAT. It has no Claude dependency — it only runs libp2p.

Add it to docker-compose.yml (same image as the worker, different command):

services:
  relay:
    build: .
    command: ["node", "dist/index.js", "relay"]
    environment:
      - RELAY_PORT=4001
      - ANNOUNCE_ADDR=/ip4/YOUR_PUBLIC_IP/tcp/4001
    volumes:
      - relay-data:/home/node/.opententacle
    ports:
      - "4001:4001"
    restart: unless-stopped

volumes:
  relay-data:

Start it:

docker compose up -d relay

On first boot it prints its multiaddr — copy it, or derive it as /ip4/<ip>/tcp/4001/p2p/<peer-id>.

On each agent, add the relay as a bootstrap peer:

tentacle peer add YOUR_PUBLIC_IP:4001

The relay's identity is persisted in the named volume. If it's lost the peer ID changes and all agents' configs need updating — use an EFS mount (or equivalent) for persistence on ephemeral infrastructure like AWS ECS/Fargate.

Opting out: Agents can remove the relay from their config to form a private network:

tentacle peer remove YOUR_PUBLIC_IP:4001

Local test cluster

docker-compose.local-test.yml spins up a 3-node cluster on your machine for end-to-end testing. The helper script handles config generation, image building, and peer wiring automatically:

ANTHROPIC_API_KEY=sk-ant-... ./scripts/local-test-up.sh

Once running:

| Node | libp2p | webhook | | ----- | -------------- | -------------- | | node1 | localhost:4001 | localhost:8081 | | node2 | localhost:4002 | localhost:8082 | | node3 | localhost:4003 | localhost:8083 |

Follow logs:

docker compose -f docker-compose.local-test.yml logs -f

Tear down:

docker compose -f docker-compose.local-test.yml down
rm -rf test-data/   # removes identities and configs