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

@mandible-ai/mandible

v0.3.12

Published

Universal stigmergy framework for autonomous agent coordination — like ant colonies using pheromone trails

Readme

Mandible

CI License: MIT Node

A universal stigmergy framework for autonomous agent coordination.

Instead of wiring agents together with message passing, Mandible agents coordinate by depositing and sensing signals in a shared environment — the same way ant colonies self-organize through pheromone trails. No orchestrator. No message routing. Complex behavior emerges from simple rules.

mandible.dev

Why stigmergy over message passing?

Most multi-agent frameworks coordinate agents through direct messaging. This reimplements distributed systems problems — service discovery, routing, consensus, backpressure — but for LLMs.

Stigmergy sidesteps all of that. The environment carries the state. Agents are stateless reactive workers. You never need to answer "who should I tell about this?" — you just modify the environment, and whoever cares will notice.

What you get:

  • Observability for free — the environment is the log. ls the signals directory and see the full system state.
  • Fault tolerance — an agent dies, the signal remains, another agent picks it up. No lost messages.
  • Zero coupling — add or remove colony types without touching any existing colony's configuration.
  • Natural load balancing — spin up more instances of any colony type. They self-organize around available work.
  • Provenance built in — every signal is signed by the colony that produced it. Bridges attest transfers. Trust is verifiable.

Quick start

npm install @mandible-ai/mandible
import { mandible, FilesystemEnvironment } from '@mandible-ai/mandible';

const env = new FilesystemEnvironment({ root: './.mandible/signals' });

const host = await mandible('code-review')
  .environment(env)
  .colony('shaper', c => c
    .sense('task:ready', { unclaimed: true })
    .do('shape-code', async (signal, ctx) => {
      const result = await shapeCode(signal.payload);
      await ctx.deposit('artifact:shaped', result, { causedBy: [signal.id] });
      await ctx.withdraw(signal.id);
    })
    .concurrency(2)
    .claim('lease', 30_000)
  )
  .colony('critic', c => c
    .sense('artifact:shaped', { unclaimed: true })
    .do('review-code', async (signal, ctx) => {
      const review = await reviewCode(signal.payload);
      await ctx.deposit('review:approved', review, { causedBy: [signal.id] });
      await ctx.withdraw(signal.id);
    })
    .claim('exclusive')
  )
  .start();

No colony references any other colony. They coordinate entirely through signals in the environment.

Hosting models

The environment (where signals live) is orthogonal to the host (where colony code runs). Colony definitions stay the same across all hosts — only the .host() call changes.

Local (default)

Runs colonies as Node runtimes in the current process. This is the default when .host() is omitted:

import { mandible, FilesystemEnvironment } from '@mandible-ai/mandible';

const env = new FilesystemEnvironment({ root: './.mandible/signals' });

const host = await mandible('code-pipeline')
  .environment(env)
  .colony('shaper', shaper)
  .colony('critic', critic)
  .colony('keeper', keeper)
  .start();

await host.stop();

Docker

Runs each colony in a Docker container. Same colony definitions, but the runtime boundary is containers instead of running in-process:

import { mandible, FilesystemEnvironment, docker } from '@mandible-ai/mandible';

const env = new FilesystemEnvironment({ root: './.mandible/signals' });

const host = await mandible('code-pipeline')
  .environment(env)
  .host(docker({ image: 'mandible-colony:latest' }))
  .colony('shaper', shaper)
  .colony('critic', critic)
  .colony('keeper', keeper)
  .start();

await host.dashboard(); // signal snapshots + colony names from containers
await host.stop();

Cloud (microVMs)

For production workloads, run colonies in isolated zones via Mandible Cloud:

import { mandible, FilesystemEnvironment } from '@mandible-ai/mandible';
import { cloud } from '@mandible-ai/cloud';

const env = new FilesystemEnvironment({ root: './.mandible/signals' });

const host = await mandible('code-pipeline')
  .environment(env)
  .host(cloud({ apiKey: process.env.MANDIBLE_API_KEY!, project: 'code-review' }))
  .colony('shaper', shaper)
  .colony('critic', critic)
  .colony('keeper', keeper)
  .start();

await host.stop();

Same colonies, same environment, different host.

Run with the dashboard

The fastest way to see colonies in action is the CLI:

mandible dev examples/repo-maintenance/mandible.config.ts

This starts all colonies and opens the live dashboard at localhost:4040. See the Dashboard section for details.

A ready-made demo is available:

npm run demo:repo-maintenance

Dashboard

mandible dev <config> runs your colonies and opens a live dashboard in the browser.

  • Real-time signal flow — watch signals appear, get claimed, and cascade through colonies
  • Colony status cards — running state, concurrency, claim counts, heartbeat health
  • WebSocket streaming — updates push instantly, no polling
mandible dev mandible.config.ts              # default: localhost:4040
mandible dev mandible.config.ts --port 8080  # custom port
mandible dev mandible.config.ts --no-open    # skip auto-opening browser

Dashboard

Architecture

Mandible architecture

Core concepts

Every concept maps to a biological analogy:

| Mandible | Biology | Description | |----------|---------|-------------| | Signal | Pheromone | A typed marker deposited in the environment with a payload, concentration, and TTL. | | Environment | Substrate | The shared medium agents read from and write to. Filesystem, GitHub, Dolt. | | Colony | Ant caste | A group of identical agents with shared sensors, rules, and claim strategy. | | Sensor | Antennae | How a colony perceives signals. A query pattern like task:ready or review:*. | | Rule | Instinct | A stimulus→response mapping: "when I sense X, do Y and deposit Z." | | Concentration | Pheromone strength | Signal priority (1.0 → 0.0). Agents prioritize stronger signals. | | Decay | Evaporation | Signals weaken over time, preventing stale work from accumulating. | | Colony Identity | Colony scent | Ed25519 keypair. Every signal is signed by the colony that produced it. | | Attestation | Trail markers | Bridges sign transfers, creating a verifiable chain of custody across environments. | | Sentinel | Guard ant | Monitors an environment for signals that fail provenance verification. |

The stigmergy loop

Every colony runtime executes the same loop:

sense → match rules → claim → execute action → deposit → (others sense)
  1. Sense — poll or watch the environment for signals matching the colony's sensor queries.
  2. Match — evaluate rules against sensed signals, ordered by priority.
  3. Claim — attempt to claim the signal (prevents duplicate work across concurrent agents).
  4. Act — execute the matched rule's action (LLM call, shell command, custom function).
  5. Deposit — leave new signed signals in the environment as output.

Other colonies sense those deposited signals and the cycle continues. Complex workflows emerge from simple local rules.

Mandible DSL

The mandible() function is the top-level entry point for defining and starting multi-colony systems:

const host = await mandible('my-swarm')
  .environment(env)                               // where colonies operate
  .colony('name', c => c                          // define a colony inline
    .sense('type:pattern', { unclaimed: true })   // what to watch for
    .do('action-name', handler)                   // what to do
    .concurrency(3)                               // max parallel agents
    .claim('lease', 30_000)                       // claim strategy
  )
  .start();                                       // start everything

start() delegates to the host — local() starts Node runtimes in the current process, docker() launches containers, cloud() launches Edera microVMs. Returns the host for lifecycle control (host.stop(), host.dashboard()).

Colony builder

Colony definitions are typically written as standalone configurator functions that return a ColonyBuilder callback. This keeps colony logic in its own module, reusable across hosts:

// colonies/worker.ts
import type { ColonyBuilder } from '@mandible-ai/mandible';

export function configureWorker() {
  return (c: ColonyBuilder) => c
    .sense('task:ready', { unclaimed: true })
    .do('process', async (signal, ctx) => {
      ctx.log(`processing ${signal.id}`);
      await ctx.deposit('task:done', signal.payload, {
        causedBy: [signal.id],
      });
      await ctx.withdraw(signal.id);
    })
    .concurrency(1)
    .claim('exclusive');
}

Then wire it into a mandible system:

import { configureWorker } from './colonies/worker.js';

const host = await mandible('my-system')
  .environment(env)
  .colony('worker', configureWorker())
  .start();

The builder supports the full range of colony configuration:

(c: ColonyBuilder) => c
  .sense('type:pattern', { unclaimed: true })     // what to watch for
  .when(signal => signal.payload.priority > 0)    // optional guard
  .do('shape', handler)                           // action handler
  .concurrency(3)                                 // max parallel agents
  .claim('lease', 30_000)                         // claim strategy
  .poll(2000)                                     // sensor poll interval (ms)
  .heartbeat(10_000)                              // periodic alive signals
  .autoWithdraw()                                 // auto-remove processed signals
  .timeout(60_000)                                // action timeout
  .retry(3, 1000)                                 // retry with backoff

Claim strategies:

| Strategy | Behavior | |----------|----------| | exclusive | Strict claim-before-work. Only one agent processes each signal. | | lease | Claim with TTL. Auto-releases if the agent dies or times out. | | optimistic | Let multiple agents start, reconcile after. | | none | No claiming. Multiple agents may process the same signal. |

Action providers

Action providers wrap external capabilities into a standard interface for colony rules.

| Provider | Use case | Backed by | |----------|----------|-----------| | withClaudeCode | Coding agents, complex reasoning | Claude Code SDK (live) | | withStructuredOutput | Classification, review, decisions | Anthropic, OpenAI, Vercel AI SDK | | withBash | Build commands, test runners, linters | Shell execution |

withClaudeCode is fully wired to the Claude Code SDK — colonies spawn real agent sessions that read files, write code, and run commands. It supports AWS Bedrock routing via the bedrock config option for enterprise deployments.

The provider assembles context by walking signal lineage (caused_by chains), giving the agent full awareness of the work pipeline state.

See Action Providers Guide for full configuration reference, output mapping, and context assembly.

Signal types

Signal types use a domain:state convention and support glob patterns for sensing:

'task:ready'        // exact match
'task:*'            // any task signal
'*:ready'           // anything in the ready state
'review:*'          // any review signal

Trust and attestation

Mandible provides cryptographic provenance for signals using @noble/ed25519:

  • Colony signing — each colony generates an Ed25519 keypair and signs every signal it deposits. Signatures cover the semantic content (type, payload, lineage) but not mutable state (concentration, timestamps).
  • Bridge attestation — when a signal crosses environments via a bridge, the bridge appends a signed attestation. Each attestation signs over the previous, creating a linked chain of custody.
  • Trust levels — signals are classified as verified (valid signature + chain), attested (bridge chain valid, origin unsigned), unverified (no provenance), or rejected (verification failed).
  • Sentinel colonies — monitor an environment for trust violations and deposit report signals that other colonies can react to.

Environment adapters

Any shared substrate that supports observe/deposit/withdraw/claim/watch can be a Mandible environment.

Filesystem (implemented)

Signals are JSON files. Claims use atomic file operations. History lives in a withdrawn/ directory.

import { FilesystemEnvironment } from '@mandible-ai/mandible';

const env = new FilesystemEnvironment({
  root: './.mandible/signals',
  name: 'local',
});

GitHub (implemented)

Issues, pull requests, comments, and labels mapped as signals. Colonies can sense repository activity and deposit responses.

import { GitHubEnvironment } from '@mandible-ai/mandible';

const env = new GitHubEnvironment({
  owner: 'mandible-ai',
  repo: 'mandible',
  token: process.env.GITHUB_TOKEN,
});

Dolt (stubbed)

Dolt is a SQL database with Git-like versioning. Signals become rows, branching enables parallel work, and dolt_history provides queryable time travel for the full signal history.

Writing your own

Implement the Environment interface (see Custom Environment Guide for a full walkthrough):

interface Environment {
  name: string;
  observe(query: SignalQuery): Promise<Signal[]>;
  deposit(signal): Promise<Signal>;
  withdraw(signalId: string): Promise<void>;
  claim(signalId: string, claimant: string, leaseDuration?: number): Promise<boolean>;
  release(signalId: string): Promise<void>;
  watch(query: SignalQuery, callback: (signal: Signal) => void): Subscription;
  history(query: SignalQuery): Promise<Signal[]>;
  decay(): Promise<DecayResult>;
  snapshot(): Promise<Signal[]>;
}

Hosts are orthogonal to Environments. To run colonies somewhere other than the local process, implement the Host interface:

interface Host {
  name: string;
  start(colonies: ColonyDefinition[]): Promise<void>;
  stop(): Promise<void>;
  dashboard(options?: DashboardOptions): Promise<void>;
  metadata: HostMetadata;
  colonies: Array<{ name: string; state: string }>;
  environments: Environment[];
}

Built-in hosts: local() (in-process), docker() (containers). Cloud hosts live in @mandible-ai/cloud.

Patterns

Reusable coordination patterns built on top of the core primitives. See Bridging Signals and Monitoring Trust for detailed usage.

SignalBridge

Cross-environment signal mirroring with attestation chains. Bridges watch for signals in one environment and mirror them to another, appending a signed attestation to preserve provenance across boundaries.

import { createBridge } from '@mandible-ai/mandible';

const bridge = createBridge({
  name: 'local-to-github',
  identity: bridgeIdentity,
  source: localEnv,
  target: githubEnv,
  signalTypes: ['fix:proposed'],
});
await bridge.start();

DebugBridge

One-way gate from a signal server into a local environment. Enables ad-hoc testing from the cloud console — deposit a signal in the console and it flows through the WebSocket into the colony's real environment.

import { createDebugBridge } from '@mandible-ai/mandible';

const bridge = createDebugBridge({
  url: 'wss://signals.mandible.cloud/ws',
  apiKey: 'mnd_...',
  project: 'my-project',
  environment: localEnv,
});
await bridge.start();

Sentinel

Trust monitoring colony that watches an environment for signals with invalid or missing provenance. When violations are detected, the sentinel deposits sentinel:flagged report signals that other colonies can react to.

import { createSentinel } from '@mandible-ai/mandible';

const sentinel = createSentinel({
  name: 'trust-guard',
  environment: env,
  policy: { name: 'strict', defaultTrust: 'unverified', minimumTrust: 'verified' },
});
await sentinel.start();

Project structure

src/
  cli/
    index.ts            CLI entry point — `mandible dev`
    server.ts           Dashboard HTTP + WebSocket server
    dashboard.html      Live dashboard UI
  cloud/
    index.ts            Cloud client for deploy + bundle upload
  core/
    types.ts            Core type system (Signal, Environment, Colony, Trust)
    signal.ts           Signal creation, matching, decay, priority sorting
    runtime.ts          Colony runtime — the stigmergy loop engine
    attestation.ts      Ed25519 signing & verification (@noble/ed25519)
  dsl/
    builder.ts          Fluent colony definition DSL
    mandible.ts         mandible() — multi-colony orchestration + start
  environments/
    filesystem/         Filesystem adapter (JSON files + atomic claims)
    github/             GitHub adapter (issues, PRs, comments, labels as signals)
    dolt/               Dolt adapter (stub)
  hosts/
    local.ts            LocalHost — runs colonies in current process
    docker.ts           DockerHost — runs colonies as Docker containers
  providers/
    claude-code.ts      withClaudeCode — Claude Code SDK (live)
    structured-output.ts withStructuredOutput — multi-model
    bash.ts             withBash — shell commands
    context.ts          Context assembly from signal lineage
  patterns/
    bridge.ts           SignalBridge — cross-environment mirroring with attestation
    debug-bridge.ts     DebugBridge — signal server → environment gate
    sentinel.ts         Sentinel — trust monitoring and violation reporting

tests/
  cli/                  Dashboard server, resolveEnvironments tests
  core/                 Signal, runtime, attestation tests
  environments/         Filesystem, GitHub adapter tests
  dsl/                  DSL and mandible() builder tests
  providers/            Agent, structured output, bash provider tests
  colonies/             Integration tests for colony workflows

docs/
  how-to/
    bridge-signals.md   SignalBridge + DebugBridge usage guide
    action-providers.md withClaudeCode, withStructuredOutput, withBash reference
    monitor-trust.md    Sentinel pattern + trust policies
    custom-environment.md Implementing the Environment interface

examples/
  code-pipeline/
    colonies.ts         Shared colony definitions (shaper, critic, keeper)
    index.ts            Local host — runs in current process
    docker.ts           Docker host — runs as containers
    with-providers.ts   Real LLM providers (Claude Code, Anthropic, Bash)
  repo-maintenance/     Scout + Fixer repo maintenance demo

Examples

Code pipeline

Three colonies coordinate through a shared filesystem environment:

  • Shaper (concurrency: 2) — picks up task:ready signals, produces artifact:shaped
  • Critic (concurrency: 2) — reviews shaped artifacts, deposits review:approved or review:changes-needed
  • Keeper (concurrency: 1) — merges approved work, deposits artifact:merged

Colony definitions live in colonies.ts and are shared across all hosting modes:

# Local host (default)
npx tsx examples/code-pipeline/index.ts

# Docker host
export MANDIBLE_API_URL=http://localhost:9091
export MANDIBLE_API_KEY=your-key
npx tsx examples/code-pipeline/docker.ts

# With real LLM providers
export ANTHROPIC_API_KEY=sk-ant-...
npx tsx examples/code-pipeline/with-providers.ts

Repo maintenance

Scout + Fixer colony pair that maintain a repository. Run it against any repo:

  • Scout — scans the repository for issues, deposits issue:detected signals (one per finding, categorized by severity)
  • Fixer — claims issue:detected signals, applies fixes, deposits fix:proposed or fix:failed
npm run demo:repo-maintenance

Both colonies are wired to real Claude agents via withClaudeCode. The dashboard shows signal flow in real time.

Roadmap

  • [x] mandible dev CLI + live dashboard
  • [x] withClaudeCode wired to Claude Code SDK
  • [x] Test suite (473 tests, 95%+ coverage)
  • [x] GitHub environment adapter
  • [x] mandible() DSL with Host/Environment separation
  • [x] local() and docker() host implementations
  • [x] @mandible-ai/cloud — run colonies in isolation using microVMs via Mandible Cloud
  • [ ] create-mandible starter template
  • [ ] Dashboard GIF + landing page
  • [ ] Dolt full implementation
  • [ ] CloudEvents bridge adapter
  • [ ] Colony scaler
  • [ ] Trust enforcement
  • [ ] Hosted observability platform

License

MIT