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

channelayer

v0.0.2

Published

CLI for AI Inbox — the same tools as the MCP server, plus login.

Readme

channelayer

CLI for AI Inbox. Same tools as the live MCP server (/api/mcp), same arguments and descriptions, plus login for OAuth.

npx channelayer --help
pnpm channelayer --help          # after building this package

Install

# one-shot
npx channelayer login
npx channelayer list-threads

# or add the package
npm install -g channelayer
channelayer login

From this monorepo:

pnpm install
pnpm --filter channelayer build
pnpm --filter channelayer channelayer -- --help

Command names

MCP tools are snake_case (list_threads). The CLI uses kebab-case (list-threads) and keeps the snake_case name as an alias, so either works:

channelayer list-threads
channelayer list_threads

Adding a tool: put it in @repo/shared inboxTools (name, description, Zod schema, /api/v1 binding). The MCP server registers it from that catalog; this CLI generates the subcommand from the same list. No second command file.

The only CLI-only command is login.

Auth

channelayer login

This does not use a localhost callback.

  1. The CLI POSTs /api/cli/auth/sessions and gets an authorize URL plus a poll token.
  2. Your browser opens Supabase OAuth (consent at /oauth/consent if you are signed in).
  3. After approve, Supabase redirects to the hosted page /oauth/cli/callback on the AI Inbox origin.
  4. That page stores tokens on the pending session.
  5. The CLI polls GET /api/cli/auth/sessions/:id until they are ready, then writes them to disk.

Token storage

| Platform | Path | | ----------- | ------------------------------------------------------------------------------------------- | | Linux / XDG | $XDG_CONFIG_HOME/channelayer/credentials.json or ~/.config/channelayer/credentials.json | | macOS | ~/Library/Application Support/channelayer/credentials.json | | Windows | %APPDATA%\channelayer\credentials.json |

Override the directory with CHANNELAYER_CONFIG_DIR. The file is mode 0600. Refresh tokens are stored when Supabase issues them; the CLI refreshes via POST /api/cli/auth/refresh when the access token is near expiry.

CHANNELAYER_TOKEN skips the file and is sent as the bearer token.

OAuth dashboard (Logan)

Create a public (native) OAuth client in Supabase → Authentication → OAuth Server → Add client:

| Field | Value | | ------------------- | ------------------------------------------------- | | Name | Channelayer CLI | | Client type | Public (PKCE, no secret) | | Token endpoint auth | none | | Redirect URLs | https://<AI_INBOX_ORIGIN>/oauth/cli/callback | | | Local: http://localhost:5173/oauth/cli/callback |

Copy the client id. Set it on the API (not a secret):

# env var name
CHANNELAYER_OAUTH_CLIENT_ID=<the public client id>

Optional override for the exact redirect URL the authorize request sends (must be listed on the client):

CHANNELAYER_OAUTH_REDIRECT_URI=https://<AI_INBOX_ORIGIN>/oauth/cli/callback

If unset, the API uses {PUBLIC_ORIGIN or request origin}/oauth/cli/callback.

Until that client exists, channelayer login fails with a 503 that names this env var.

Authorization Path in the same dashboard stays /oauth/consent (already used by MCP).

Config

| Variable | What it does | | ------------------------ | -------------------------------------------------------------------------------------------------------------------------- | | CHANNELAYER_API_URL | API origin. Default https://ai-inbox.demos.cool. Local: http://localhost:8787 (or the web origin that proxies /api). | | CHANNELAYER_TOKEN | Bearer token; skips login storage. | | CHANNELAYER_CONFIG_DIR | Where credentials.json is written. | | --api-url / -u | Same as CHANNELAYER_API_URL for one invocation. | | --json | JSON on stdout (tool commands always print JSON). |

Examples

channelayer login
channelayer list-mailboxes
channelayer list-threads --channel email
channelayer get-thread --thread-id <uuid>
channelayer send-email --to [email protected] --subject Hello --body "Hi Ada"
channelayer send-sms --to +15551234567 --body Hello
channelayer create-contact --name Ada --email [email protected]

Every tool command prints JSON (the /api/v1 response). Errors go to stderr with a non-zero exit.

channelayer list-threads --help

Help text is the MCP tool description plus generated flags from the same Zod / JSON Schema the server advertises.

Publishing

Published to npm as channelayer. Publish with pnpm, not npm: zod uses the catalog: protocol, which pnpm publish rewrites to a real version range and npm publish does not.

npm login                          # once
pnpm install
pnpm --filter channelayer test
pnpm --filter channelayer build

cd packages/cli
pnpm version patch                 # or minor / major; skip for the first 0.1.0 release
pnpm publish --dry-run             # expect dist/cli.js, README.md, package.json
pnpm publish

@repo/shared is inlined into dist/cli.js by vite.config.ts, so it stays a private dev dependency. publishConfig.access is already public.

Before announcing a release, make sure the production API has CHANNELAYER_OAUTH_CLIENT_ID set (see OAuth dashboard), or channelayer login returns 503.