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

agsmith

v0.2.1

Published

Smith CLI — your extensible agent toolkit

Downloads

346

Readme

Agent Smith

Smith CLI — your extensible agent toolkit.

Installation

npm install
npm run build
npm link

Requires Node.js >= 18.

Configuration

All config and credentials live in ~/.agsmith/ (override the directory by setting AGSMITH_CONFIG_DIR).

~/.agsmith/
  config.json                               # Slack + OpenClaw + Outlook settings
  credentials/
    gmail-client.json                       # Gmail OAuth client secret
    gmail-user-readonly-token.json          # Gmail read-only token
    gmail-user-modify-token.json            # Gmail modify token
    outlook-token-cache.json                # Outlook (Microsoft Graph) MSAL token cache

Commands

agsmith config

agsmith config show       Show current config with secrets masked
agsmith config path       Print the path to the config file

agsmith slack

Setup

agsmith slack set api-key <value>         Set the Slack bot/user OAuth token (xoxb-... or xoxp-...)
agsmith slack set main-user-id <value>    Set the primary Slack user ID (e.g. U0123456789)

Commands

agsmith slack channel list                List all channels in the workspace
  --include-archived                    Include archived channels
  --private-only                        Show only private channels
  --public-only                         Show only public channels
  --wrap                                Wrap cell content in table output
  --truncate                            Truncate cell content to column widths

agsmith slack channel create <name>       Create a channel in the workspace
  --private                             Create as a private channel

agsmith slack send <channel> <text...>    Send a message to a channel

<channel> accepts a channel name with or without a leading #, or a channel ID. Names are resolved to an ID via conversations.list before posting, so the bot token needs channels:read (and groups:read for private channels) in addition to chat:write.


agsmith gmail

Setup

agsmith gmail import-credentials <path>   Copy OAuth client secret to ~/.agsmith/credentials/gmail-client.json

agsmith gmail auth                        Run the OAuth flow (read-only, default)
  --readonly                            Request read-only access (default)
  --modify                              Request modify access (required for label operations)

Tokens are saved automatically to ~/.agsmith/credentials/.

Commands

agsmith gmail list                        List Gmail messages
  --filter <filter>                     Gmail search query (e.g. "is:unread")
  --limit <n>                           Max messages to fetch (default: 20)
  --offset <n>                          Number of messages to skip (default: 0)
  --json                                Output JSON
  --wrap                                Wrap cell content in table output
  --truncate                            Truncate cell content to column widths

agsmith gmail message <message-id>        Show a single message by ID
  --json                                Output JSON
  --pdf [output-path]                   Render the message to a PDF file

agsmith gmail labels                      List all Gmail labels
  --json                                Output JSON
  --wrap                                Wrap cell content in table output
  --truncate                            Truncate cell content to column widths

agsmith gmail update-labels [message-ids...]   Add or remove labels on messages
  --filter <filter>                     Gmail search query to select messages
  --add <label-id>                      Label ID to add (repeatable)
  --remove <label-id>                   Label ID to remove (repeatable)
  --add-name <label-name>               Label name to add (repeatable)
  --remove-name <label-name>            Label name to remove (repeatable)
  --json                                Output JSON

agsmith gmail attachment list <message-id>             List attachments on a message
  --json                                             Output JSON

agsmith gmail attachment download <message-id> <attachment-id>   Download an attachment
  --output-dir <dir>                    Directory to write the file into (default: .)
  --filename <name>                     Override the output filename
  --json                                Output JSON

agsmith outlook

Read-only access to Outlook / Microsoft 365 mail via Microsoft Graph.

Setup

You'll need an Azure Entra app registration (free — see the Microsoft docs for "App registrations"). Register a public client / native app with the redirect URI http://localhost, enable "Allow public client flows", and grant the delegated permissions Mail.Read, User.Read, and offline_access. Then save your client ID:

agsmith outlook set client-id <azure-app-client-id>     Required
agsmith outlook set tenant-id <tenant-id>               Optional (default: "common"); set to a tenant
                                                        GUID if your app is single-tenant
agsmith outlook set token-cache-path <path>             Optional; override the MSAL token cache location

agsmith outlook auth                                    Run the OAuth flow in the browser

The MSAL token cache is saved automatically to ~/.agsmith/credentials/outlook-token-cache.json.

Commands

agsmith outlook list                       List Outlook messages via Microsoft Graph
  --filter <odata>                       Raw OData $filter expression
  --search <query>                       Free-text $search (subject/body/from/etc.)
  --from <address>                       Shortcut for $filter on from/emailAddress/address
  --to <address>                         Shortcut for $filter on toRecipients
  --subject <text>                       Shortcut for $filter contains(subject, ...)
  --in <folder>                          Well-known folder (inbox, sentitems, drafts,
                                         deleteditems, junkemail, archive)
  --unread                               $filter isRead eq false
  --starred                              $filter flag/flagStatus eq 'flagged'
  --has-attachment                       $filter hasAttachments eq true
  --before <date>                        $filter receivedDateTime lt <date> (YYYY-MM-DD)
  --after <date>                         $filter receivedDateTime ge <date> (YYYY-MM-DD)
  --on <date>                            $filter receivedDateTime within a single day
  --limit <n>                            Max messages to fetch (default: 20)
  --offset <n>                           Number of messages to skip (default: 0)
  --json                                 Output JSON
  --wrap                                 Wrap cell content in table output
  --truncate                             Truncate cell content to column widths

agsmith outlook message <message-id>      Show a single message by Graph ID
  --json                                 Output JSON
  --pdf [output-path]                    Render the message to a PDF file (inline cid: images
                                         and image attachments are embedded)

agsmith openclaw

Setup

agsmith openclaw set config-dir <path>      Set the path to the OpenClaw config directory
agsmith openclaw set default-model <model>  Set the default model for new agents

Commands

agsmith openclaw agent create <agent-name>

Creates an OpenClaw agent, a matching Slack channel, and binds them together. If the channel or agent already exists, the existing resources are reused.


agsmith iterm

Requires macOS with iTerm2 installed.

agsmith iterm list                         List all iTerm2 windows, tabs, and sessions
  --json                                 Output JSON

agsmith iterm new <session> [cwd] [command] [args...]
                                         Create a new tab, optionally cd and run a command

agsmith iterm read <session>             Read the visible screen contents of a named session

agsmith iterm rename <session> <new-name>
                                         Rename a named session

agsmith iterm run <session> <command> [args...]
                                         Run a command in a named session (sends Ctrl+C first)

agsmith iterm send <session> <text...>   Type raw text into a session (no Ctrl+C, no auto-Enter)
  -e, --enter                            Press Enter after the text

agsmith iterm send-ctrl <session> <keys...>
                                         Send control codes / named keys, in order
                                         Single letters become Ctrl+<letter> (`c` = Ctrl+C);
                                         named keys: enter, return, esc, tab, space,
                                         backspace, bs, newline
  --delay <ms>                           Delay between keys (default 400)

agsmith iterm split <direction> <target> [session]
                                         Split a named session horizontally or vertically
                                         <direction> is `horizontal` or `vertical`

Sessions created by iterm new and iterm split are tagged with the user.agsmithTerminal iTerm2 variable, and every <session> lookup above matches that tag before falling back to the session name — names get rewritten by whatever runs in the tab. See agsmith cc below.


agsmith cc

Claude Code session helpers.

agsmith cc rc <path>                       Open a new iTerm2 tab, cd to <path>, and launch
                                           `claude --remote-control "<session>"`
  -t, --terminal <name>                  iTerm2 terminal to reuse (no new tab). If no such
                                         terminal exists, a new tab with this name is created
  -s, --session <name>                   Remote-control session name (default: <dirname>-MMDD)
  -p, --prompt <text>                    Initial prompt to send to Claude on startup

With no flags, a new tab is opened, named after the target directory, and the remote-control session is <dirname>-MMDD.

-t never restarts a Claude that is already running. What it does depends on the terminal:

| Terminal state | What happens | |---|---| | Does not exist | New tab is created, then claude --remote-control is launched in it | | Exists, running Claude | --prompt is typed into that Claude session; --session is ignored | | Exists, running Claude, no --prompt | Nothing — reports that Claude is already running | | Exists, plain shell | cds and launches claude --remote-control in it |

"Running Claude" is detected by looking for a claude process on the session's tty. The iTerm2 session.jobName variable is not usable for this: it reports the deepest child process, so a Claude session that has spawned an LSP or caffeinate reports that child instead.

Terminals touched by cc rc, iterm new, and iterm split are tagged with the iTerm2 user variable user.agsmithTerminal, which -t and all iterm lookups match on first. Session names are rewritten by whatever runs in the tab — Claude Code retitles them to ✳ Claude Code and then to a summary of the conversation — so the tag is what makes a terminal reliably addressable. Untagged sessions, including any created by hand, still match on name.