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

@codependence/cli

v0.4.3

Published

Ask your other Claude Code sessions questions. Runs on the machine where your sessions live and answers on their behalf.

Readme

The machine bridge

The bridge is a daemon that runs on your laptop. It is the piece that makes a real Claude Code session answer questions from the outside.

What it actually does

  YOUR SESSION (project A)        CLOUD SERVICE              PEER MACHINE (this bridge)
 ┌─────────────────────┐       ┌──────────────────┐       ┌────────────────────────────┐
 │ Claude Code         │  ask  │ Worker + AgentDO │ poll  │ bridge.mjs                 │
 │ talking to /mcp     │──────▶│ queue + D1       │◀──────│ long-polls for work        │
 │                     │◀──────│                  │──────▶│                            │
 │ gets a thread_id    │ticket │                  │message│      │ tmux send-keys      │
 └─────────────────────┘       └──────────────────┘       │      ▼                     │
           │                            ▲                 │ Claude Code in tmux        │
           │  check_answer              │  reply          │ (the live session, with    │
           └────────────────────────────┴─────────────────│  all of its context)       │
                                                           └────────────────────────────┘

Asking from a project

cd ~/the-project-that-asks
codependence connect

Mints a client token and registers the MCP server in that directory. The token is never displayed -- it goes straight from the service into your Claude Code config, which is the only handling of it that cannot end up in a terminal scrollback or a chat window.

Restart that session afterwards; MCP servers are read at startup. Then ask in English: ask alice/billing why the webhook retries twice.

To see who you can ask:

codependence peers

Publishing a peer

Stand in the repo you want answerable and run:

cd ~/src/billing
node ~/src/codependence.ai/bridge/bridge.mjs add

It takes the path, the name and the session from where you are standing, so ~/src/billing becomes <your-handle>/billing. Pass a name to override it: add billing-api.

Then restart the bridge to connect it. To stop publishing one:

node bridge/bridge.mjs remove billing

Both edit bridge/config.json for you. Editing that file by hand still works and does the same thing -- add exists so you do not have to know its shape.

Worth doing afterwards: give the peer some capability_tags in the config. They are what an asking agent reads to choose who to ask, so they are written for the agent doing the picking rather than for you.

Delivery modes

headless (default, recommended)

Shells out to claude -p --resume <session> --fork-session, with the question on stdin. That single command does everything the tmux dance was working around:

  • --resume carries the peer session's accumulated conversation -- the reasoning that never landed in a commit message, which is the entire reason to ask a peer instead of reading its repo yourself.
  • --fork-session means answering does not touch the live session's history. Nobody's work gets interrupted.
  • -p means the process exiting is the completion signal. No screen to scrape, no answer file to wait for. Its stdout is the answer.
  • --allowedTools restricts the run to reading (Read,Grep,Glob by default). The question is text from another machine and must not reach a tool that changes anything.
  • It works anywhere the claude CLI runs, which includes Windows.

Which session gets forked: session_id if you set one, otherwise the most recently active session for that repo_path. If several sessions run in the same repo, "most recent" may not be the one you want -- pin it. --doctor prints which session each agent will use.

If there is no prior session at all, the run still happens: it just answers from CLAUDE.md, project memory and the repo, without conversation history.

tmux (legacy)

Types one line into a live Claude Code session telling it to read a question file, whose instructions tell it to write an answer file, which the bridge waits for.

This exists because you cannot tell from a TUI's rendered output when Claude has finished thinking, so "detect when a TUI is done" had to become "wait for a file". It works, and it is the only mode that reaches a session you are actively sitting in -- but it needs tmux, it types into your live session, and that session runs with whatever tool permissions you gave it. Prefer headless.

echo

Answers automatically with a canned reply. No Claude, no tmux. Use it first: it proves the whole loop, so a failure afterwards is never the plumbing's fault.

Safety: a question is text from another machine

Be clear-eyed about this. A question written by an agent elsewhere is read by a Claude Code session that has tools.

In headless mode the fork is restricted to read-only tools, which is a real boundary rather than a polite request. In tmux mode it is injected into your live session with whatever permissions that session already has, and the only defense is the wrapper telling it to treat the text as data and not act on it -- a mitigation, not a guarantee.

Either way the peer can read its repo and put what it finds in the answer, so only put agents on the bus whose askers you trust. Today that means your own machines.

Install

npm install -g @codependence/cli
codependence login

Node 18 or newer. Node 22 has a WebSocket built in; on older versions the CLI uses a bundled fallback, so there is nothing to configure either way.

You also need the claude CLI signed in on the same machine -- that is what actually answers questions, so the bridge is useless without it.

One thing that will catch you: if you use nvm and switch Node versions later, global packages are kept per version, so codependence will be missing until you install it again under the new one. That is nvm, not this.

Setup

1. Run the service

npm install
npx wrangler d1 migrations apply codependence --local
npm run dev

2. Sign in and mint a bridge token

Tokens belong to you and are minted while signed in. Sign in at /auth/github, choose a handle if you have not already, then:

curl -sS -X POST http://localhost:8787/v1/me/tokens \
  -H 'Content-Type: application/json' -b cookies.txt \
  -d '{"label":"my-laptop","kind":"bridge"}'

It looks like cdp_<your-handle>_<random>. The handle is in the token because tokens live in their owner's Durable Object, so verifying one is a parse rather than a lookup in a global table -- and there is no cross-owner index to leak.

Shown once, stored only as a SHA-256 hash. One per machine, so a single laptop can be revoked without killing the rest.

3. Write the config

cp bridge/config.example.json bridge/config.json

Edit it: paste the token, and list the agents this machine hosts. config.json is gitignored.

4. Check everything before you trust it

node bridge/bridge.mjs --doctor

It verifies the service is reachable, the token is accepted, tmux is installed, each tmux_target pane actually exists, and each repo_path is a real directory. Fix whatever it flags.

5. Run it

codependence start

This holds the terminal, which is what you want the first time: you watch it register, connect and answer, and you learn what it does.

6. Keep it running

start dies with the shell that launched it. On a machine you reach over SSH that means the peer goes offline the moment you disconnect.

codependence service install

That writes a user service — ~/.config/systemd/user/codependence.service on Linux, ~/Library/LaunchAgents/ai.codependence.bridge.plist on macOS — and starts it. It runs as you, not as root, because the bridge needs your home, your claude credentials and your repos.

codependence service status
codependence service logs -f
codependence service uninstall

Two details that decide whether this actually survives:

  • Lingering. systemd tears your user manager down when your last session ends, so without loginctl enable-linger <you> the service stops when you log out — exactly the problem it was installed to solve. service install enables it, falling back to sudo -n and telling you the command if both are refused.
  • PATH is baked in at install time. The bridge shells out to claude, and a service inherits almost nothing. The unit pins the absolute node that ran the install and the PATH that could find claude at that moment. If you later change Node versions with nvm, re-run service install.

Asking from a project

cd ~/the-project-that-asks
codependence connect

Mints a client token and registers the MCP server in that directory. The token is never displayed -- it goes straight from the service into your Claude Code config, which is the only handling of it that cannot end up in a terminal scrollback or a chat window.

Restart that session afterwards; MCP servers are read at startup. Then ask in English: ask alice/billing why the webhook retries twice.

To see who you can ask:

codependence peers

Publishing a peer

Stand in the repo you want answerable and run:

cd ~/src/billing
node ~/src/codependence.ai/bridge/bridge.mjs add

It takes the path, the name and the session from where you are standing, so ~/src/billing becomes <your-handle>/billing. Pass a name to override it: add billing-api.

Then restart the bridge to connect it. To stop publishing one:

node bridge/bridge.mjs remove billing

Both edit bridge/config.json for you. Editing that file by hand still works and does the same thing -- add exists so you do not have to know its shape.

Worth doing afterwards: give the peer some capability_tags in the config. They are what an asking agent reads to choose who to ask, so they are written for the agent doing the picking rather than for you.

Delivery modes

"delivery": "echo" answers automatically with a canned reply and needs no tmux at all. Use it first. It proves the whole loop — ask, queue, poll, deliver, reply, collect — so that when you switch to a real session you know any problem is the session's, not the plumbing's.

"delivery": "tmux" hands the question to a live Claude Code session. Find your pane address with:

tmux list-panes -a -F "#{session_name}:#{window_index}.#{pane_index}"

Walking through a test

Test 1 — the plumbing, with no tmux

Config one agent with "delivery": "echo". Start the bridge, then ask it something from another terminal:

CLIENT=$(curl -sS -X POST http://localhost:8787/v1/admin/tokens \
  -H 'Content-Type: application/json' -H 'X-Admin-Secret: local-dev-admin-secret' \
  -d '{"label":"asker","kind":"client"}' | jq -r .token)

curl -sS -X POST http://localhost:8787/v1/ask \
  -H "Authorization: Bearer $CLIENT" -H 'Content-Type: application/json' -d '{
    "to": "john/echo-peer",
    "question": "Does the round trip work?",
    "symptom": "I have never seen this system answer anything",
    "what_i_tried": "Reading the code",
    "relevant_code": "none -- this is a design question, not a bug",
    "wait_ms": 15000
  }' | jq

You should get "status": "answered" back, and see the bridge log the delivery. If you do, every moving part except tmux is working.

Test 2 — a real Claude Code session

  1. Start a session in the repo you want to be the peer:
    tmux new -s peer -c /path/to/that/repo
    claude
  2. Get the pane address and put it in tmux_target.
  3. Set that agent to "delivery": "tmux" and restart the bridge.
  4. Ask it a question that genuinely requires reading that repo.
  5. Watch the peer pane: a line appears, the session reads the inbox file, works, and writes the outbox file.
  6. Your ask will almost certainly return "status": "pending" with a thread_idthat is the expected outcome, not a failure. Collect it:
    curl -sS "http://localhost:8787/v1/threads/$THREAD_ID" \
      -H "Authorization: Bearer $CLIENT" | jq -r '.thread.answer'

Test 3 — from inside Claude Code, as an MCP server

This is the real thing: one session asking another with no curl involved.

claude mcp add --transport http codependence http://localhost:8787/mcp \
  --header "Authorization: Bearer $CLIENT"

Then in that session: "ask john/echo-peer whether the round trip works". It will call list_agents, then ask, get a ticket, and — because the tool description tells it to — carry on with other work and call check_answer later rather than reporting a failure.

Things that will happen to you

Superseded. One bridge per agent. If you leave a second running in another terminal, the older connection is sent a superseded message explaining why and then closed, and that bridge exits with status 1 rather than lingering as a process that keeps agents marked online while listening to nothing.

Restarting is instant: the new connection displaces the old one.

How work arrives. The bridge holds a WebSocket per agent and is pushed questions as they arrive. It does not poll. An earlier version long-polled over HTTP, which held each agent's Durable Object awake for the whole wait window and was billed by wall-clock time -- roughly 11,000 GB-s per agent per day against a 13,000 GB-s daily free tier, for agents doing nothing at all. A hibernated WebSocket costs nothing while idle.

GET /v1/agents/:id/peek still exists for a single non-blocking look at the queue, but it will not wait, and asking it to will tell you why.

Which bridge is authoritative? Do not read logs across terminals. Ask:

curl -sS "http://localhost:8787/v1/admin/agents/john%2Fyour-agent/poller" \
  -H "X-Admin-Secret: $ADMIN_SECRET" | jq

It tells you which machine holds the poll and since when, or says plainly that nobody is polling and questions are piling up.

A question that never gets answered. If the session is busy or the answer file never appears, the bridge gives up after answer_timeout_ms (default 8 minutes) and marks the thread failed with a reason -- not answered. An asking agent reading status answered should never find failure text there. Keep answer_timeout_ms below the server's LEASE_MS (default 10 minutes).

A question is only ever handed to a bridge three times. A bridge that crashes on the same question every time would otherwise requeue it forever, leaving the asker polling a thread that can never resolve; after the third attempt it is marked failed saying so.

Ctrl-c is clean. The bridge reports any question it was mid-way through as failed before exiting, so the asking agent finds out immediately instead of waiting out the ten minute lease.

A dead tmux pane. If the target pane does not exist when a question arrives, the bridge replies immediately saying so rather than swallowing the question.