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

@marxlo/hivemind

v0.1.0

Published

Run a team of scoped Claude Code agents over one repository

Readme

hivemind

Run a team of scoped Claude Code agents over one repository. One agent per lane, one git worktree per agent, a leader that owns the spec and the trunk, and a message bus between them.

hivemind init          # write a starter hivemind.yaml
hivemind start         # worktrees, hooks, bus, tmux — one window per agent
tmux attach -t hive-<project>

Are you an agent? docs/agent-guide.md is the whole tool on one page — commands, config, the bus HTTP API, and what every error message means — written to be read instead of searched for. Every generated agent prompt points at it.

Working on hivemind itself? CLAUDE.md is the working model, docs/design-log.md is why each thing is the way it is (including every bug and what it taught), docs/owed.md is what is honestly missing, and npm test covers the parts that have tests.

Why it is shaped like this

Everything here is a post-mortem, not a hypothesis. It was written after running three agents by hand over one repository for a week. That week produced exactly two data-losing incidents and about twenty long, useful messages — so the coordination was never the problem.

The problem was shared mutable state. One working tree, one main, one index.

  • One agent ran git add -A and swept another's half-written file into an unrelated commit. The commit message described half of what the commit contained.
  • One agent ran git checkout -B main origin/main from a second worktree. -B force-moves a shared ref, and four commits stopped being reachable from main. Nothing was destroyed, but only because someone noticed within the hour.

Both were committed by the agent that had written the rule against them, in the project's own AGENTS.md, earlier the same day. Advisory rules do not survive contact with a busy agent. So hivemind enforces the ones that matter with git hooks and refuses the configurations that make them likely.

hivemind.yaml

project: neon
trunk: main

# Run by every agent's pre-push hook.
verify: npm run ci

defaults:
  enforce: hard          # hard | soft | off

agents:
  - name: spec
    role: leader         # exactly one
    owns: ["**"]
    model: opus
    brief: |
      You define and update the spec, hand out work, and merge the others' branches.

  - name: android
    owns: [android-shell/]
    denies: ["**/generated/"]
    enforce: hard
    todo:
      - Audit the test harness for assertions nothing checks

  - name: sdk
    owns: [miniapp-sdk/]
    denies: ["**/generated/"]
    enforce: soft

| Key | | |---|---| | owns | Path prefixes this agent may commit. Required. | | denies | Carve-outs from owns — generated directories usually belong to the leader. | | enforce | hard refuses out-of-lane commits, soft warns, off does nothing. Per agent. | | role: leader | Owns the spec, merges branches, and is the only agent allowed to push to trunk. | | verify | One command, run by every agent before push. | | todo | Seeded into the agent's opening prompt. | | model, effort | Passed through to claude. | | worktreeDir | Where worktrees go. Default .hivemind/worktrees. | | autostart | false declares a lane without running it — it still claims its scope. | | permissionMode | Passed to the agent's settings. Declared, never inferred. |

verify is checked before anything launches: the runner must match the repo's packageManager, and every <runner> run <script> must exist in package.json. A verify that cannot run is worse than none — a gate everyone believes in and nobody executes — so start refuses rather than warning.

Two workers owning overlapping paths is a config error, rejected at load. It is decidable from the file alone, so it should never be discovered by two agents editing one file.

What start actually does

For each agent: creates .hivemind/worktrees/<name> as its own worktree on hive/<name> (reusing the branch if it exists — that is where unmerged work lives), installs its hooks, renders its system prompt, and opens a tmux window running claude there.

It also starts the message bus, and fails the whole run if the bus does not come up. Agents with no bus cannot coordinate, and a send that goes nowhere is worse than a refusal.

Worktrees live under .hivemind/ rather than in a sibling directory, so a project stays one directory rather than two. start makes sure .hivemind/ is gitignored before creating anything — unignored, every agent's full checkout shows up as untracked in the main tree and one git add -A there stages the entire hive. Override the location with worktreeDir:.

Changing worktreeDir on an existing hive moves the worktrees rather than failing — git worktree move, so uncommitted work comes with them. Hook paths are absolute and live outside the worktree, so enforcement survives the move.

Nesting has one consequence worth knowing: hivemind.yaml is normally tracked, so each worktree carries its own copy. hivemind asks git for the main worktree (--git-common-dir) before walking up, so running a command from inside an agent's tree resolves the real config rather than the copy beside it. Without that it reported the bus down and no agent having a tree.

Advancing the trunk

hivemind integrate <agent> — catch the leader up to trunk, merge the agent's branch, run verify, publish. hivemind integrate does every worker in turn.

start defines a remote named trunk (the real origin URL, or . when there is none) and sets receive.denyCurrentBranch=updateInstead, so integration is one command in both topologies and the primary worktree updates in place. Two consequences worth knowing:

  • The gate actually fires. verify runs from a pre-push hook, so on a repo with no remote nobody ever pushed and the mechanism every brief calls "the only thing that catches two agents drifting apart" was inert. Pushing to trunk is a real push.
  • A dirty primary worktree refuses the publish rather than overwriting it. That is the point of updateInstead; the merge is kept, so committing there and re-running finishes it.

Never advance the trunk by hand. git update-ref moves the ref without touching the primary worktree's index, after which git status there reports the whole repo as deleted.

Auto-polling

Agents do not poll. start writes a Stop hook into each worktree's .claude/settings.local.json that checks the bus whenever the agent would otherwise go idle; unread messages come back as decision: "block" with the text, so work wakes the agent instead of waiting to be noticed. Nothing is on a timer and no session sits blocked. Any failure in the hook exits 0, so a down bus can never wedge an agent.

hivemind send --to <agent> addresses a message; inbox and the hook filter on it. Without --to it is a broadcast, and a broadcast is nobody's job.

Sessions

Each launcher resumes that worktree's own conversation with claude --continue when one exists, so an agent does not re-derive what it already worked out. Claude Code compacts its own context, so a long-lived session is the cheaper of the two.

Enforcement

Scope — a pre-commit hook checks staged paths against owns/denies and names the agent that owns anything foreign. Override deliberately with HIVE_CROSS_LANE=1, which asks you to say why in the commit message.

Trunk — a pre-push hook stops non-leader agents pushing to trunk. Push your branch and ask the leader to merge.

Verify — the same pre-push hook runs verify. The same command for every agent, deliberately: it is the one mechanism that catches two agents drifting apart, and it only works if all of them run it. HIVE_SKIP_VERIFY=1 if you must.

Per-agent hooks require per-worktree core.hooksPath, which hivemind sets, because linked worktrees otherwise share $GIT_COMMON_DIR/hooks. Writing each agent's hook to git rev-parse --git-path hooks puts all of them at one path and the last writer wins — every agent then silently runs whichever policy was installed last. This was found during testing, when a hard-enforced agent was let through by a soft-enforced agent's hook.

Alive is not working

status used to print "running" for anything with a live tmux window. An agent parked on an interactive prompt satisfies that and does nothing, indefinitely, while the table says it is fine — a process that is alive but not working, which is worse than a crash because a crash is visible.

It now reads the pane and reports BLOCKED with the reason. The signatures are deliberately narrow: a false "blocked" is noise, but a missed one is the exact lie the check exists to catch, so anything ambiguous reports as running.

doctor checks the other half — whether each worktree is a trusted folder. Claude Code asks "Is this a project you created or one you trust?" for an untrusted directory and waits, so an agent launched into one blocks before reading a single instruction. Trust is recorded per absolute path in ~/.claude.json and inherited from a trusted ancestor, which is the only reason the default .hivemind/worktrees layout launches cleanly: it sits under the repo root you already trusted. Point worktreeDir somewhere else and every agent hangs at once.

Unblocking, and the line this does not cross

Exactly one of those prompts is removed, and it is removed by preventing it rather than by answering it.

start records the worktree as a trusted folder — but only ever extending trust the repo root already has. hivemind created that directory, from a repository you already trusted, inside that repository. If the root is not trusted, neither is the worktree, and the agent gets the prompt it should get; the refusal says so by name. It keeps one backup of ~/.claude.json and writes through a temp file.

Permission prompts are not auto-answered and must not be. "Do you want to proceed?" is your decision about what an agent may do to your machine. A tool that clicks yes on your behalf has not unblocked the agent — it has removed the control and kept the appearance of it. An agent that should not need to ask gets an explicit permissionMode: in hivemind.yaml, declared by a human, once, in a file you can read. That is a different act from a tool deciding case by case in the dark.

  - name: web
    permissionMode: acceptEdits     # default | acceptEdits | plan | dontAsk | bypassPermissions

hivemind doctor

Every check is something that actually happened:

  • the same branch checked out in two worktrees — git normally refuses, checkout -B does not
  • an index holding blobs from an older commit — the signature of a stale index, where committing would silently revert whatever landed in between
  • staged paths belonging to another agent
  • a detached HEAD, or a worktree on the wrong branch
  • unpushed commits, and branches with no remote
  • a local trunk ahead of its origin — one push away from racing someone else's

Messaging

hivemind send  --from android "the CSP permits wss: — three specs say otherwise"
hivemind inbox --agent spec
hivemind inbox --agent spec --wait 25     # long-poll

Rooms, append-only history in .hivemind/bus/<room>.jsonl, token auth, long-polling. The bus binds the configured port, or an ephemeral one if it is taken — it will never fall back to talking to whatever else holds that port, which is a mistake this made once during testing and now cannot make.

It binds loopback by default. The token is plaintext on disk and the port is the whole credential, so reaching it from another machine is opt-in — bus.host: 0.0.0.0 — and start says so on the line where that takes effect.

A chat log is not documentation. The agent prompts say so: if a message describes a shape, a schema, or a rule, it belongs in the repo, and the leader should put it there before anyone builds against it. A contract that lives only in a message diverges the moment the second reader sees a different message.

What this does not do

No scheduler, no task queue, no automatic work assignment. The leader is a Claude session you talk to, and it hands out work in messages. Agents are interactive sessions you can type into — which mattered repeatedly during the week this came from.

It also does not make agents correct. The thing that kept two independent implementations honest in the project this came from was a shared conformance suite both of them ran, not the chat. verify is where that goes. Without it you get well-coordinated divergence.