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

@ajmarquez99/discord-cli

v0.3.1

Published

Discord CLI for coding agents — post, read, react, reply, and manage threads via the Discord REST API, with a fail-closed channel allowlist. Ships an MCP server too.

Readme

discord-cli

npm version CI License: MIT

A Discord CLI for coding agents — the gh/gmail/gsc sibling. Post messages, read channel history, react, reply, and create threads via the Discord REST API. All channel content access (reads, reactions, writes) is gated by a fail-closed allowlist.

Install

Global (recommended)

npm install -g @ajmarquez99/discord-cli
discord --version

This installs both the discord CLI and the discord-mcp MCP server.

From source

git clone https://github.com/AJMarquez99/discord-cli.git
cd discord-cli && npm install && npm install -g .

Discord setup

  1. Create an application + bot at https://discord.com/developers/applications.
  2. Enable the Message Content privileged intent (Bot → Privileged Gateway Intents) — required to read message content via discord read. Without it, the Discord API returns empty content for messages the bot didn't author and isn't mentioned in.
  3. Invite the bot (OAuth2 → URL Generator, scope bot) with these permissions: View Channel, Read Message History, Send Messages, Send Messages in Threads, Create Public Threads, Add Reactions.
  4. Enable Developer Mode in Discord (Settings → Advanced) to copy channel/server IDs (right-click → Copy ID).

Credentials

The quickest path is discord login, which prompts for the bot token (hidden input) and writes ~/.config/discord-cli/credentials.json at chmod 600:

discord login            # paste the token at the hidden prompt
discord login --force    # overwrite an existing credentials file

Or do it by hand — set DISCORD_BOT_TOKEN, or create ~/.config/discord-cli/credentials.json:

{ "botToken": "your-bot-token" }

Override the config path with DISCORD_CLI_CONFIG. Token precedence: env var first, then file. Run discord init first to scaffold the config files and print the full setup steps.

Allowlist

~/.config/discord-cli/allowlist.json (override with DISCORD_ALLOWLIST):

{
  "channels": ["123456789012345678"],
  "servers": ["987654321098765432"]
}
  • channels: array of channel-ID strings. All content access (post, read, react, reply, thread create) requires an allowlisted channel. A thread is gated by its parent channel.
  • servers: array of guild-ID strings. Used by open mode (see below) to permit writes to any visible channel in an allowlisted server.
  • No allowlist file → nothing is accessible (fail-closed). Missing file returns { channels: [], servers: [] }.
  • --channel accepts a channel ID only — aliases have been removed. Use discord channels to look up name→ID mappings.
  • Backward compatible: the loader still accepts the v0.1.0 alias-object form ({ alias, channelId, serverId }) — it extracts channelId and ignores alias. A bare top-level array is treated as channels with servers: [].

Config

~/.config/discord-cli/config.json (override with DISCORD_CLI_SETTINGS):

{ "mode": "restricted", "auditLog": { "enabled": true, "logBody": false } }

All fields are optional. Defaults: mode: "restricted", auditLog.enabled: true, auditLog.logBody: false.

Mode (restricted vs open)

restricted (default, fail-closed): content access is limited to channels explicitly listed in allowlist.channels. Any other channel ID is blocked with exit 3.

open: content access extends to any channel visible to the bot, as long as the channel belongs to a server in allowlist.servers. Channels already in allowlist.channels are always permitted without an extra API lookup. Channels not in allowlist.channels incur one GET /channels/{id} call to verify the server membership. If servers is empty, open mode grants nothing beyond already-allowlisted channels.

Mode precedence (highest to lowest):

  1. --unrestricted flag (per-command)
  2. DISCORD_MODE=open environment variable
  3. mode in config.json
  4. Default: restricted

Audit log

Every successful post, react, and thread create appends a JSONL line to ~/.config/discord-cli/audit.jsonl (override with DISCORD_AUDIT_LOG):

{ "ts": "2026-…Z", "action": "post|react|thread", "channelId": "…", "messageId": "…",
  "mode": "restricted|open", "allowlisted": true }
  • The message body is excluded unless auditLog.logBody: true in config.json or --log-body is passed.
  • Auditing is controlled by auditLog.enabled (default true); pass --no-audit to skip a single action.
  • A failed audit write warns to stderr but never fails the operation.
  • Dry-runs are not logged.
  • View recent entries with discord audit [--limit N].

Commands

All commands print JSON by default; add --format table for a human summary. Global flags: --format json|table (default json), --profile <name> (reserved; single identity in v1).

discord post

discord post --channel <id> --message "..."

Post a message to an allowlisted channel. Options:

  • --channel <id> — target channel ID
  • --message <text> — message content (or pipe on stdin)
  • --reply-to <messageId> — reply to this message (pings the author)
  • --thread <threadId> — post into an existing thread (gated by its parent channel); takes precedence over --channel
  • --unrestricted — open mode: allow any visible channel in an allowlisted server
  • --dry-run — preview without sending or logging (exit 0 even if it would be blocked)
  • --no-audit — skip writing this action to the audit log
  • --log-body — include the message body in the audit entry
  • --allow-everyone — permit @everyone/@here pings (suppressed by default)
  • --allow-roles — permit role pings (suppressed by default)

Mention safety (default-on): @everyone, @here, and role pings are stripped by default. Only user @mentions resolve. Pass --allow-everyone or --allow-roles to opt back in. Replying with --reply-to always pings the replied-to author.

The message body can be piped on stdin when --message is omitted.

Examples:

discord post --channel 123456789012345678 --message "Deploy complete."
echo "Nightly report ready." | discord post --channel 123456789012345678
discord post --channel 123456789012345678 --message "test" --dry-run

discord read

discord read --channel <id> [--limit N] [--before <messageId>] [--after <messageId>]
discord read --thread <threadId> [--limit N] [--before <messageId>] [--after <messageId>]

Fetch recent messages from an allowlisted channel or thread (blocked in restricted mode if channel is not allowlisted). Options:

  • --channel <id> — channel ID (must be allowlisted in restricted mode)
  • --thread <threadId> — read from a thread; gated by its parent channel (symmetric with post --thread)
  • --limit <n> — max messages to return (1–100, default 25)
  • --before <messageId> — only messages before this ID
  • --after <messageId> — only messages after this ID
  • --unrestricted — open mode: any visible channel in an allowlisted server

Either --channel or --thread is required.

discord react

discord react --channel <id> --message <messageId> --emoji 👍
discord react --thread <threadId> --message <messageId> --emoji 👍

Add a reaction to a message (allowlist-gated). Options:

  • --channel <id> — channel ID (must be allowlisted in restricted mode)
  • --thread <threadId> — react to a message in a thread; gated by its parent channel (symmetric with post --thread)
  • --message <messageId> — target message ID
  • --emoji <emoji> — unicode emoji, or custom emoji as name:id
  • --unrestricted — open mode: any visible channel in an allowlisted server
  • --dry-run — preview without reacting or logging
  • --no-audit — skip writing this action to the audit log

Either --channel or --thread is required.

discord thread create

discord thread create --channel <id> --from <messageId> --name "..."

Start a thread from an existing message (allowlist-gated by parent channel). Options:

  • --channel <id> — parent channel ID
  • --from <messageId> — message to start the thread from
  • --name <name> — thread name
  • --auto-archive <minutes> — auto-archive duration: 60 | 1440 | 4320 | 10080
  • --unrestricted — open mode: any visible channel in an allowlisted server
  • --dry-run — preview without creating or logging
  • --no-audit — skip writing this action to the audit log

discord channels

discord channels [--server <guildId>] [--type <type>]

List a server's channels (name→ID, type, category). Marks allowlisted channels with *. Metadata only — never fetches message content. Ungated; visibility follows the bot's Discord permissions.

  • --server <guildId> — guild/server ID. Defaults to the single entry in allowlist.servers; required if servers contains 0 or 2+ entries.
  • --type <type> — filter by channel type: text | voice | category | announcement | stage | forum

Example:

discord channels --server 987654321098765432
discord channels --server 987654321098765432 --type text

discord allow list

discord allow list

Show allowlisted channel IDs and server IDs. Edit ~/.config/discord-cli/allowlist.json by hand to add or remove entries.

discord audit

discord audit [--limit N]

Show recent audited actions, newest first.

  • --limit <n> — max entries to show (default 20)

discord doctor

discord doctor

Verify the bot token; report active mode, bot identity (username, ID, credential source), allowlist channel count, and server count.

discord init

discord init

Scaffold ~/.config/discord-cli/ with starter allowlist.json (empty — fail-closed) and config.json, report whether credentials are present, and print the remaining setup steps. Non-clobbering: existing files are reported as exists and left untouched. Never writes secrets — use discord login for the token.

discord login

discord login [--force]

Set up the bot token: prompts for it with hidden input and writes credentials.json at chmod 600. The token flows prompt → file only — it is never echoed, returned, logged, or accepted as a flag. Refuses to overwrite an existing credentials file unless --force is passed.

Exit codes

| Code | Meaning | |---|---| | 0 | Success (including dry-run, even when it reports blocked: true) | | 1 | Discord API error, network failure, or unexpected exception | | 2 | User-fixable config: missing token, malformed config file, bad flags | | 3 | Blocked by allowlist or mode (non-allowlisted channel in restricted mode, or channel not in an allowlisted server in open mode) |

MCP server

discord-cli ships a stdio Model Context Protocol server — the portable counterpart to the CLI, so MCP-aware clients (Claude Code, Claude Desktop) can drive Discord as structured tools without shell invocations.

Install

npm install -g . installs both the discord CLI and the discord-mcp MCP server binary.

Register with Claude Code

claude mcp add discord -- discord-mcp

The server reads the same ~/.config/discord-cli/ credentials, config, and allowlist files as the CLI. No extra setup needed.

Tools

| Tool | Description | |---|---| | discord_post | Post a message to an allowlisted channel (or thread). @everyone/@here/role pings are stripped unless allow_everyone/allow_roles. | | discord_read | Read recent messages from an allowlisted channel or thread. | | discord_react | Add a reaction to a message in an allowlisted channel or thread. | | discord_create_thread | Create a thread from a message in an allowlisted channel. | | discord_channels | List a server's channels (names → ids, type; marks allowlisted). Metadata only. | | discord_audit | Show recent audited actions (newest first). | | discord_doctor | Verify the bot token; report mode, identity, allowlist + server counts. | | discord_allowlist | Show the allowlisted channel ids and server ids. |

Safety

Every tool delegates directly to the same run*(opts, deps) command functions used by the CLI. The allowlist gate, restricted/open mode, mention-safety, dry-run, and audit log all apply unchanged. A blocked channel returns an MCP error result (the tool call succeeds at the protocol level, but isError: true is set in the response) — the server never crashes on a blocked request.

Related tools

discord-cli is one of a small family of fail-closed CLIs built for AI coding agents — each a focused wrapper around a single service, in the spirit of gh:

  • gmail-cli — send + IMAP read over Gmail, with a fail-closed recipient allowlist and an optional MCP server.
  • dot-ai — the agent-agnostic .ai/ project-intelligence convention these tools are documented with.