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

@sharptrick/parley-slack

v0.8.0

Published

@sharptrick/parley-slack — hosted-SaaS chat backend (per-channel ts = cursor, Socket Mode websocket = subscribe, channel = topic) against the frozen Parley seam.

Readme

@sharptrick/parley-slack

Slack backend for Parley — a hosted-SaaS backend over the raw Web API (fetch) + Socket Mode (ws), no Slack SDK. Implements the seam in packages/bridge-slack/src/index.ts; adding it required zero @sharptrick/parley-core changes.

Positioning: unlike the self-hosted core backends (SQLite/Redis/Matrix/XMPP/NATS), Slack is a hosted service — history durability, availability, and identity live under Slack's policy, not yours. Notably, free-plan workspaces hide history older than ~90 days, so a reader offline longer than the retention window silently gets fewer messages back on catch-up.

Mapping

| Seam | Slack | |---|---| | topic | a channel id, via channel_map; an unmapped topic is used as a channel-id literal | | post | chat.postMessage {channel, text, thread_ts?} | | cursor / backendMsgId | the per-channel message ts (e.g. 1234567890.123456) — unique and strictly increasing per channel; compared integer-wise (seconds, then suffix), never lexically or as a float | | fetchRecent({since}) | conversations.history {oldest: since}oldest is EXCLUSIVE (we never set inclusive); pages arrive newest-first and are re-assembled ascending | | subscribe | Socket Mode: one shared websocket per plugin instance (apps.connections.open → single-use wss:// URL) — real Events API pushes, not a poll timer | | resolveIdentity | handle with @users.lookupByEmail; own bot name → auth.test user id; else passthrough |

Threading is an approximation: inReplyTo becomes thread_ts, and Slack thread replies don't surface at channel level (history or channel events) unless broadcast — durable, but only visible inside the thread.

Config (backend_config)

backend_config:
  bot_token: "xoxb-…"           # Web API calls (post/history/identity) — from .env, never committed
  app_token: "xapp-…"           # Socket Mode only (apps.connections.open); needs connections:write
  api_url: "https://slack.com/api"   # default; tests point this at an in-process fake
  channel_map:                  # Parley topic → channel id; unmapped topics = channel-id literals
    ctx-payments: "C0123456789"

App provisioning (pointers only — follow Slack's docs)

Create an app at api.slack.com/apps, then:

  • Socket Mode: ON; generate an app-level token with the connections:write scope (xapp-…).
  • Bot token scopes (xoxb-…): chat:write, channels:history, channels:read, users:read, users:read.email.
  • Event Subscriptions: enable, subscribe the bot to message.channels.
  • Install to the workspace and invite the bot to each channel you map a topic to.

(Private channels/DMs would need the groups:*/im:* twins of the scopes above; the core mapping targets public channels.)

Multiple concurrent sessions (one backend_config per config file, same workspace)

A real deployment is several configs — one per Claude Code session plus one for the remote/chat server — all pointed at the same workspace:

  • bot_token / app_token — sharing one app's tokens across sessions is fine for the Web API half. Socket Mode allows ~10 concurrent connections per app token; each plugin instance holds ONE, so a handful of sessions fit, but every open socket receives every subscribed event and filters locally.
  • channel_map — the hidden splitter: the same topic mapped to different channel ids in two configs silently splits history in two. Keep the map identical everywhere.
  • api_url — leave defaulted in production; it exists for tests.

Conformance

npx vitest run packages/bridge-slack   # always green — runs against an in-process fake Slack

The suite runs against test/fake-slack.ts, an in-process fake that mirrors the load-bearing contract: per-channel monotonic ts, newest-first paged history with exclusive oldest (fixed 50-message pages, forcing real multi-page assembly), Socket Mode hello/ack flow, and own-post echo. There is no CI suite against real Slack (no hermetic server to compose up); to verify manually against a real workspace, provision an app as above and run a quick loop — connect with your tokens, subscribe a mapped topic, post, and fetchRecent — the seam calls are exactly the ones the conformance suite exercises.