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

@pinet/slack-bridge

v0.2.6

Published

Pi package for Pinet Slack assistant integration — multi-agent broker, thread routing, and inbox tools

Readme

slack-bridge (Pinet)

Connect pi coding agents to Slack. Pinet provides multi-agent coordination, thread routing, and inbox tools through Socket Mode.

Install Pinet

Install the latest version:

pi install npm:@pinet/slack-bridge

Pin a specific version:

pi install npm:@pinet/[email protected]

For direct npm installation:

npm install @pinet/slack-bridge

What you need

  • a Slack workspace where you can install apps
  • Node.js 22 or later
  • pi installed on your system

Set up your Slack app

Create the app

  1. Go to api.slack.com/apps
  2. Select 'Create New App'
  3. Choose 'From a manifest'
  4. Select your workspace
  5. Paste the contents of manifest.yaml
  6. If you want a different Slack command, change features.slash_commands[0].command before creating and set slackCommandName or slackCommandNames in settings.json
  7. Select 'Create'

The manifest configures Socket Mode, the assistant view, bot scopes, event subscriptions, and slash commands automatically.

Get your tokens

Generate two tokens:

| Token | Where to find it | Format | | --------------- | ------------------------------------------------------------------------------- | ------------ | | App-Level Token | Basic Information → App-Level Tokens → Generate (add connections:write scope) | xapp-1-... | | Bot Token | OAuth & Permissions → Install to Workspace → Bot User OAuth Token | xoxb-... |

Required bot scopes

The manifest includes these scopes:

app_mentions:read    assistant:write      bookmarks:read
bookmarks:write      canvases:read        canvases:write
channels:history     channels:read        chat:write
commands             files:read           files:write
groups:history       groups:read          im:history
im:read              im:write             pins:read
pins:write           reactions:read       reactions:write
users:read

The commands scope enables slash commands. The files:read scope is needed because Slack uses files.info for canvas comment pagination.

Configure Pinet

Add tokens, runtime mode, and access rules to ~/.pi/agent/settings.json:

{
  "slack-bridge": {
    "botToken": "xoxb-your-bot-token",
    "appToken": "xapp-your-app-token",
    "runtimeMode": "single",
    "allowedUsers": ["U_YOUR_USER_ID"]
  }
}

Pinet stays off unless you set runtimeMode, autoConnect, or autoFollow. Start pi after you configure access.

Use environment variables instead

export SLACK_BOT_TOKEN="xoxb-..."
export SLACK_APP_TOKEN="xapp-..."

Settings in settings.json override environment variables.

Control who can use Pinet

Slack access is default-deny. Configure one of these:

  • allowedUsers: list specific Slack user IDs
  • allowAllWorkspaceUsers: true: allow everyone in the workspace

Example with specific users:

{
  "slack-bridge": {
    "botToken": "xoxb-...",
    "appToken": "xapp-...",
    "allowedUsers": ["U_USER_ID_1", "U_USER_ID_2"]
  }
}

Find user IDs by selecting a user's profile in Slack and choosing 'Copy member ID'.

Optional settings

Mesh authentication

Shared-secret authentication is optional. Configure it with settings or environment variables:

Settings:

{
  "slack-bridge": {
    "meshSecret": "your-shared-secret"
  }
}

Or use a file:

{
  "slack-bridge": {
    "meshSecretPath": "/path/to/secret.txt"
  }
}

Environment variables:

export PINET_MESH_SECRET="your-shared-secret"
# or
export PINET_MESH_SECRET_PATH="/path/to/secret.txt"

How it works:

  • settings override environment variables
  • inline secrets override file paths
  • if nothing is set, mesh auth is disabled
  • brokers create the secret file if it does not exist
  • followers need an existing file or will show an error

Require mentions in channels

Make Pinet respond only when mentioned in specific channels:

{
  "slack-bridge": {
    "ingressGuard": {
      "requireMention": {
        "channels": ["C_CHANNEL_ID"],
        "mixedParticipantThreads": {
          "enabled": true,
          "trustedUsers": ["U_TRUSTED_USER"]
        }
      }
    }
  }
}

This is separate from allowedUsers. Authorization decides who can use Pinet. The guard decides when a mention is needed.

All configuration options

{
  "slack-bridge": {
    "botToken": "xoxb-...",
    "appToken": "xapp-...",
    "runtimeMode": "single",
    "allowedUsers": ["U_USER_ID"],
    "allowAllWorkspaceUsers": false,
    "ingressGuard": {
      "requireMention": {
        "channels": ["C_CHANNEL_ID"],
        "mixedParticipantThreads": {
          "enabled": true,
          "trustedUsers": ["U_USER_ID"]
        }
      }
    },
    "defaultChannel": "C_CHANNEL_ID",
    "logChannel": "#pinet-logs",
    "logLevel": "actions",
    "autoConnect": false,
    "autoFollow": false,
    "ralphLoopIntervalMs": 300000,
    "ralphSnoozeAfterEmptyCycles": 0,
    "ralphSnoozeDurationMs": 1800000,
    "meshSecretPath": "/path/to/secret",
    "suggestedPrompts": [
      {
        "title": "Status",
        "message": "What are you working on?"
      }
    ],
    "security": {
      "readOnly": false,
      "requireConfirmation": ["slack:create_channel"],
      "blockedTools": []
    }
  }
}

| Setting | Description | Default | | ------------------------ | ------------------------------------------------------ | -------------------- | | botToken | Bot User OAuth Token (required) | none | | appToken | App-Level Token for Socket Mode (required) | none | | runtimeMode | How Pinet runs (off, single, broker, follower) | off | | allowedUsers | Slack user IDs who can use Pinet | none | | allowAllWorkspaceUsers | Allow all workspace members | false | | defaultChannel | Where to post updates | none | | logChannel | Where to post logs | none | | logLevel | What to log (errors, actions, verbose) | actions | | autoConnect | Start as a single instance when runtimeMode is unset | false | | autoFollow | Start as follower if broker exists | false | | ralphLoopIntervalMs | How often to check for stalls (milliseconds) | 300000 (5 minutes) | | meshSecret | Shared secret for mesh auth | none | | meshSecretPath | File containing shared secret | none |

Using Pinet

In Slack

Talk to Pinet:

  • Direct message: open a DM with Pinet
  • In channels: mention @pinet (or your app name)
  • Slack slash command: type /pinet agents list or /pinet agents list all

Pi commands

Run these inside pi.

Main commands:

  • /pinet - show available commands
  • /pinet status - show current Pinet status
  • /pinet logs - show recent broker activity logs
  • /pinet rename [name] - rename this agent
  • /pinet free - mark this agent idle

Coordinator commands:

  • /pinet start or /pinet broker - become the broker
  • /pinet start replace - take over a stale or stranded broker (graceful shutdown first, then a fenced SIGTERM fallback)
  • /pinet follow - become a follower
  • /pinet unfollow - disconnect from broker
  • /pinet reload <agent> - ask another agent to reload
  • /pinet exit <agent> - ask another agent to exit
  • /pinet snooze [duration|off|status] - quiet empty RALPH cycles
  • /pinet subtree [start|status|spawn|stop] - manage subtree broker mode

From pi

Use the Pinet dispatcher for agent coordination:

{
  "action": "send",
  "args": {
    "to": "@worker",
    "message": "Please review PR #123"
  }
}

Common actions:

  • send - send a message to an agent or broker-only channel
  • read - read this agent's inbox
  • schedule - schedule a future wake-up
  • free - mark this agent idle
  • help - discover actions and schemas

Use slack_send for hot-path Slack replies. Use the slack dispatcher for uploads, canvases, pins, bookmarks, and other Slack actions.

Architecture

Broker and followers

Pinet can run as:

  • single - one instance handles everything
  • broker - coordinates and routes messages
  • follower - receives work from the broker

The broker:

  • watches Slack for messages
  • assigns work to agents
  • tracks who owns what
  • syncs state across followers

Followers:

  • connect to the broker
  • receive assigned work
  • stay in sync automatically

RALPH maintenance loop

RALPH keeps broker state healthy. It:

  • runs every 5 minutes by default
  • checks worker presence
  • releases stale claims held by unavailable workers
  • observes pending backlog while broker maintenance handles assignment
  • triggers wake-ups

Configure RALPH:

{
  "slack-bridge": {
    "ralphLoopIntervalMs": 120000,
    "ralphSnoozeAfterEmptyCycles": 3,
    "ralphSnoozeDurationMs": 1800000
  }
}

Inbox and threading

Pinet maintains an inbox for each agent. Messages are:

  • routed based on thread ownership
  • queued when agents are busy
  • marked read when processed
  • preserved across restarts

Thread ownership ensures continuity. Once an agent owns a thread, it keeps receiving those messages.

Troubleshooting

Socket Mode connection issues

If you see 'WebSocket error' or connection failures:

  1. Check your app token is valid
  2. Verify Socket Mode is enabled in your Slack app
  3. Check network connectivity
  4. Look for rate limiting (Slack allows 10 connections per app)

Permission errors

If Pinet cannot perform actions:

  1. Check the bot is in the channel (invite with /invite @pinet)
  2. Verify bot scopes match the manifest
  3. Reinstall the app to update permissions
  4. Check allowedUsers includes the right user IDs

Messages not received

If Pinet does not respond:

  1. Check Socket Mode shows 'Connected' in Slack app settings
  2. Verify event subscriptions are enabled
  3. Check allowedUsers or allowAllWorkspaceUsers
  4. Look in the log channel for errors
  5. Try /pinet status to check if Pinet is running

Stranded broker (lock held, controlling session lost)

If /pinet start reports that another broker is already running but you no longer have that broker's Pi session (crash, laptop restart, stalled process):

  1. Run /pinet status from any session — it reports machine-wide broker lock ownership and socket health even while disconnected.
  2. If the broker is healthy and you just want to participate, run /pinet follow.
  3. If the broker is stranded (or you need the broker in this session), run /pinet start replace. It asks the current broker to shut down gracefully over the socket, falls back to a verified SIGTERM against the recorded lock owner, and never escalates to SIGKILL.

Two cases intentionally refuse automatic termination:

  • Legacy locks (written by older builds, PID-only): there is no recorded process start identity, so a SIGTERM could hit an unrelated process that reused the PID. Inspect the process manually (ps -p <pid>), terminate it yourself if it is truly the stranded broker, then run /pinet start.
  • Rejected shutdown: a broker that responds but rejects the shutdown request (usually a mesh secret mismatch) is alive, not stranded. Fix the mesh secret configuration or stop that broker from its own session.

Stalled agents

If work gets stuck:

  1. Check /pinet status for current state.
  2. Check /pinet logs for repeated failures.
  3. Wait for RALPH to run automatically.
  4. Reduce ralphLoopIntervalMs for faster recovery if needed.

Package information

Publishing metadata

The package declares pi metadata in package.json:

  • keywords includes pi-package for gallery discovery
  • pi.extensions points to ./dist/index.js
  • pi.skills points to bundled skills
  • No preview assets yet

Check the package contents:

cd slack-bridge
npm pack --dry-run

Development

Build the package:

cd slack-bridge
pnpm build

Run tests:

pnpm test

Deploy the Slack manifest:

pnpm deploy:slack

Security

Default-deny access

Pinet requires explicit configuration to allow users. Without allowedUsers or allowAllWorkspaceUsers, nobody can use it.

Token safety

  • Never commit tokens to git
  • Use environment variables in production
  • Rotate tokens regularly
  • Use separate apps for development and production

Confirmation for dangerous actions

Configure confirmation for sensitive operations:

{
  "slack-bridge": {
    "security": {
      "requireConfirmation": ["slack:create_channel", "slack:upload", "slack:delete"]
    }
  }
}

Read-only mode

Prevent all modifications:

{
  "slack-bridge": {
    "security": {
      "readOnly": true
    }
  }
}

Support