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

@meistrari/pantry-cli

v1.1.0

Published

CLI tool for chefs to interact with tela

Downloads

481

Readme

pantry-cli

CLI for talking to Tela services. It handles device-flow auth once, then lets you call authenticated APIs and inspect OpenAPI, TypeDoc, and guide docs for any ingredient registered in Pantry.

Install

There are two ways to install pantry, and both can be installed directly or managed by mise. Pick whichever fits your setup.

Package manager (npm)

The npm package ships the CLI as a JavaScript bundle that runs under bun, so this route needs bun available:

bun add -g @meistrari/pantry-cli
npm install -g @meistrari/pantry-cli
pnpm add -g @meistrari/pantry-cli

Or with mise, which also manages the bun it runs under:

mise use -g npm:@meistrari/pantry-cli

Standalone binary (no runtime)

A prebuilt binary for your platform — no bun or node needed. Published for darwin-arm64 and linux-x64.

With mise, straight from the GitHub releases:

mise use -g github:meistrari/pantry-cli

Or with the install script:

curl -fsSL https://raw.githubusercontent.com/meistrari/pantry-cli/main/install.sh | bash

It installs to ~/.local/bin by default; override with PANTRY_INSTALL_DIR, or pin a version with PANTRY_VERSION:

PANTRY_INSTALL_DIR=/usr/local/bin PANTRY_VERSION=1.0.0 \
  curl -fsSL https://raw.githubusercontent.com/meistrari/pantry-cli/main/install.sh | bash

Verify

pantry --help

Agent skill

This repository includes a Vercel Skills-compatible agent skill in skills/pantry. It teaches coding agents when and how to use pantry to discover Tela ingredients, read endpoint schemas, inspect library docs, and avoid rebuilding capabilities that already exist in Tela.

Install it with Vercel Skills from this repository:

bunx skills add meistrari/pantry-cli
pnpx skills add meistrari/pantry-cli
npx skills add meistrari/pantry-cli

It is also published to Pantry as the pantry-cli skill, in the pantry bundle, so an agent that already has the CLI can install it with:

pantry skills install pantry-cli

The skill ships an install script that bootstraps the CLI itself — via mise, then npm, then the standalone binary, whichever works first — and then tells the user to run pantry login. So the skill does not assume the CLI is already there, only that it is authenticated before the agent starts calling services. Skip the script with --ignore-scripts.

pantry decides between interactive and non-interactive login automatically: --interactive defaults to on when stdin is a TTY and off otherwise. In interactive mode login waits on stdin and opens the browser for you. In non-interactive mode (agents, CI, or an explicit --no-interactive) it instead prints the verification URL, code, and a login --device-code <code> command, then exits — the user authorizes in their browser and a follow-up login --device-code finishes the sign-in. Pass --no-interactive to force this two-step flow even from a TTY, or --interactive to force the browser-opening flow.

First run

  1. Authenticate. Run the login command to start the device flow:

    pantry login

    It prints a verification URL and code, then waits on stdin. Press Enter to open your browser.

  2. Populate the ingredient cache. pantry loads Tela services from Pantry instead of shipping a hardcoded service list:

    pantry update

    This writes ~/.pantry/ingredients.json. Re-run pantry update whenever an ingredient is added, removed, or changes environments. As a rule of thumb, run it every few days, or even before each use, to make sure your local ingredient cache is current.

Credentials live in ~/.pantry/credentials.<slug>.json. The default production auth target uses credentials.production.json. Force a re-login with:

pantry login --force

Remove every stored credential (all auth targets) with:

pantry login reset

Upgrading from telactl

The CLI used to be called telactl and kept its config in ~/.telactl. On the first run after upgrading, pantry copies that directory to ~/.pantry, removes the old one, and says so on stderr — credentials, the ingredient cache, environment defaults, and the installed-skill registry all come across, so there is nothing to re-run.

It never overwrites: if ~/.pantry already exists, both directories are left exactly as they are. If the copy fails, ~/.telactl is left untouched and the error names it. Skills themselves are installed under ~/.agents/skills, outside either directory, so they are unaffected.

The old telactl binary is not removed. Delete it by hand once you are happy — rm "$(command -v telactl)".

One call spelling changed: Pantry itself is now reached by omitting the slug. telactl api pantry GET /ingredients becomes pantry api GET /ingredients. The old spelling is not silently accepted — a leftover pantry slug is answered with the command to run instead:

Use `pantry api GET /ingredients`.

Every other ingredient is still named as before.

Common flows

Discover services

pantry api GET /ingredients
pantry api GET /ingredients query==file
pantry api GET /ingredients type==library

pantry is always available, so you can use it to discover API services, libraries, and skills before building something from scratch.

Read documentation

pantry docs endpoints <slug>
pantry docs reference <slug>
pantry docs reference <slug> <METHOD> <PATH>
pantry docs guide <slug>
pantry docs guide <slug> <path>

Use endpoints to list API routes, reference for exact API or library contracts, and guide for step-by-step usage docs.

Manage agent skills

Skills are agent instructions published through Pantry as immutable, commit-addressed snapshots. pantry can browse them and install them onto your machine.

pantry skills list -p                    # cached skills; ✓ marks the ones you have installed
pantry skills search openapi -p          # live search against Pantry
pantry skills files add-pantry-labels -p # what is inside the snapshot
pantry skills cat add-pantry-labels      # read SKILL.md

Install one skill, several at once, or a skill together with the rest of its bundle:

pantry skills install add-pantry-labels
pantry skills install add-pantry-labels configure-openapi
pantry skills install add-pantry-labels --bundle

--bundle is a flag on the skills you name, not a bundle name — it means "also install every other skill in those skills' bundles". The last command above installs add-pantry-labels plus its bundle-mates configure-openapi and configure-typedoc. With several slugs it expands each one's own bundle and merges the results, installing nothing twice. It always needs at least one slug: pantry skills install --bundle on its own is an error. If a skill has no bundle recorded, nothing expands for it — pantry installs just that skill and says so on stderr. Unbundled skills are never grouped with one another.

When a --bundle expansion spans two or more different bundles, the command asks first, since that reaches well past anything you named:

Proceed with installing 5 skills from bundles "pantry" and "openapi"? [y/N]

Answer n and nothing is installed and the exit code is non-zero (Aborted; nothing was installed.). In a script or any non-interactive shell there is no prompt to answer, so the command refuses outright:

Refusing to install 5 skills from 2 bundles without confirmation.
Re-run with --yes to install them all, or name skills from a single bundle.

-y / --yes skips the question and proceeds. A single bundle never asks — you still get the stderr notice, as before.

To install a whole bundle without naming a skill in it, name the bundle itself:

pantry skills install bundle pantry
pantry skills install bundle pantry openapi

This takes bundle names, not slugs — install bundle pantry installs add-pantry-labels, configure-openapi, and configure-typedoc. Several bundles are merged and deduped, the resolved set is listed on stderr before anything is installed, and --ignore-scripts, --no-symlink, and -f / --force behave exactly as they do on install. There is no -y here and no confirmation however many bundles you name: --bundle asks because named slugs can balloon into bundles you never mentioned, while naming the bundles is asking for them outright. A name that matches no skills is an error, and nothing from the other names is installed either:

No skills found in bundle "pantrry".
Nothing was installed. Check the name with `pantry skills list`.

Skills are extracted to ~/.agents/skills/<slug> and symlinked into ~/.claude/skills/<slug>. Skip the symlink with --no-symlink.

Every file is checked against the snapshot manifest's sha256 before anything is written, so a truncated or tampered download fails without touching your disk.

install refuses to clobber anything it does not own: a target directory it did not install, or an entry in ~/.claude/skills/<slug> that is not a symlink. -f / --force authorizes both — it replaces the unowned install directory and replaces the non-symlink entry. Without it, the first is a hard error and the second is only skipped, with a note on stderr.

An existing symlink at ~/.claude/skills/<slug> is replaced without asking — only a real directory or file there is protected. That holds even when the symlink points somewhere pantry never installed, and no --force or warning is involved.

Keep them current and remove them again:

pantry skills upgrade                              # every installed skill whose snapshot changed
pantry skills upgrade --check                      # report what is stale, install nothing
pantry skills up -p                                # same command, shorter (also: pantry skills u)
pantry skills upgrade add-pantry-labels --bundle   # that skill and its installed bundle-mates
pantry skills uninstall add-pantry-labels
pantry skills uninstall add-pantry-labels configure-openapi
pantry skills uninstall add-pantry-labels --bundle

upgrade and uninstall take several slugs too, and --bundle and -y / --yes behave exactly as they do on install — the destructive command does not fan out across bundles more quietly than the additive one. Declining there reports Aborted; nothing was removed. (or upgraded).

upgrade and uninstall work only on skills pantry installed — they read ~/.pantry/skills.json and refuse to touch anything else. That is also where they read the bundle from: it is recorded at install time, so --bundle works offline here and expands to the bundle members you actually have installed, ignoring anything published since. (install has no such record to read, so it asks Pantry.) upgrade with no slug still means "everything installed", which is unrelated to --bundle.

If any slug you name is not installed, uninstall refuses the whole run before deleting anything — add-pantry-labels and configure-openapi are not installed by pantry. Nothing to remove. — so a typo in one of four never leaves you with a partial uninstall.

Both name what they are about to touch before they touch it — Removing 2 skills from bundle "pantry": add-pantry-labels, configure-openapi on stderr, ahead of the first deletion.

upgrade --check answers "is anything stale?" without upgrading to find out. It lists only the skills with a newer snapshot, marked outdated rather than upgraded, and installs nothing — so an empty list means everything is current. Since it cannot change anything, it never prompts for a multi-bundle expansion and never fails on an empty registry; both print [] and exit 0. Naming a slug that is not installed is still an error, because that is a typo rather than an answer.

upgrade has no --force: it will re-install over the directory it already recorded for a skill, but it never replaces a non-symlink entry in ~/.claude/skills — clear that by hand, or re-run install --force.

If a skill declares an install or uninstall script, the command is printed before it runs; pass --ignore-scripts to skip it. That notice, and the script's own output, go to stderr — so pantry skills upgrade keeps stdout as clean JSON you can pipe into jq. Only results are written to stdout: Installed <slug>@<short-sha> to <dir> from install, `Removed from

Call an API

pantry api <METHOD> <PATH> [args...] [flags]           # Pantry itself
pantry api <slug> <METHOD> <PATH> [args...] [flags]    # any other ingredient

Pantry is the registry the CLI already reads from, so it is the ingredient api defaults to: omit the slug and the call goes there. Every other ingredient is named explicitly.

Args use HTTPie-style syntax:

| Syntax | Meaning | | ------ | ------- | | name=value | JSON body field as a string | | name:=value | JSON body field as raw JSON | | name==value | Query parameter | | Header:value | Request header |

Examples:

# GET with query params
pantry api GET /ingredients limit==50 page==1

# POST with JSON fields
pantry api vault POST /files name=report.pdf size:=1024

# Raw body from a file
pantry api vault POST /files --body "$(cat body.json)"

# Custom header and environment override
pantry api GET /ingredients X-Debug:1 --env staging

Output follows the terminal. At a TTY, -p / --pretty is already on — human-readable output: pretty JSON, tables, lists, ANSI-rendered markdown. Redirected or piped, it is off, and output is raw and script-friendly: minified JSON or verbatim response text. Pass --no-pretty to force the raw form at a terminal too.

The switch reads stdout, so pantry docs guide <slug> > guide.md writes plain markdown and pantry skills list | jq gets JSON, with no flag either way.

Global flags

These are accepted by every command, before or after the subcommand — pantry --pretty skills list and pantry skills list --pretty do the same thing:

| Flag | Meaning | | --- | --- | | --interactive / --no-interactive | Authenticate by prompting and opening a browser, or by printing instructions instead. Defaults to on when stdin is a TTY. | | -p / --pretty / --no-pretty | Shape structured results for a human or for a machine. Defaults to on when stdout is a TTY. | | -y / --yes | Skip confirmation prompts. |

A command that has nothing to do with a flag accepts it and ignores it — pantry login --pretty is valid and prints the same thing.

--ignore-scripts (skip a skill's declared install/uninstall script) is global to the pantry skills group rather than the whole CLI, since nothing else runs scripts. It is accepted from skills onward — pantry skills install foo --ignore-scripts, not pantry --ignore-scripts skills install foo.

--auth-env, --auth-url, and --force are deliberately not global, since silently ignoring those would change which environment you reach or what gets overwritten.

Commands

Auth

pantry login  [--auth-env <slug>] [--auth-url <url>] [--force] [--device-code <code>]
pantry login reset
pantry whoami [--auth-env <slug>] [--auth-url <url>]
pantry token  [--auth-env <slug>] [--auth-url <url>]
pantry token list

--auth-env picks an auth-api environment by slug. --auth-url overrides it with a raw URL. login --device-code <code> resumes a device flow that a previous non-interactive login started, polling until sign-in completes. token prints the stored access token for the resolved auth environment, and token list shows stored credentials with validity checks.

Interactivity is controlled by the global --interactive / --no-interactive flag, which defaults to on when stdin is a TTY and off otherwise. When non-interactive (e.g. an agent with no TTY, or an explicit --no-interactive), a command that needs a fresh device flow prints the verification URL, code, and a login --device-code <code> command, then exits without polling. The user authorizes in their browser, then pantry login --device-code <code> resumes the flow and polls until sign-in completes. Cached and refreshable tokens are still used without prompting.

Cache and environments

pantry update
pantry env list <slug>
pantry env set  <slug> <environment>

update refreshes the ingredient cache from Pantry using production auth.

Docs

pantry docs endpoints <slug>
pantry docs reference <slug>
pantry docs reference <slug> <METHOD> <PATH>
pantry docs reference <library-slug> [file-path]
pantry docs guide     <slug> [path]

api ingredients expose api, docs endpoints, docs reference, and docs guide. library ingredients expose docs reference and docs guide.

For an api ingredient, docs reference <slug> prints the whole OpenAPI document and <METHOD> <PATH> narrows it to one endpoint — both required together. For a library, the optional argument is a path relative to the ingredient's API reference directory and defaults to globals.md, the generated index. docs guide <slug> [path] works the same way against the guides root, defaulting to the guides entry file (typically README.md).

Skills

pantry skills list [-p]
pantry skills search <query> [-p]
pantry skills files <slug> [-p]
pantry skills cat <slug> [<path>] [-p]
pantry skills install <slug...> [--bundle] [--no-symlink] [-f] [-y]
pantry skills install bundle <bundles...> [--no-symlink] [-f]
pantry skills upgrade [<slug...>] [--bundle] [--check] [-p] [-y]
pantry skills uninstall <slug...> [--bundle] [-y]

| Command | What it does | |---------|--------------| | list | Skills from the local cache, annotated with install status | | search | Live search against Pantry (type=skill) | | files | The snapshot's file tree with sizes | | cat | One file from the snapshot; defaults to SKILL.md | | install | Download, verify, extract, and symlink one or more skills — and, with --bundle, their bundle-mates | | upgrade | Reinstall installed skills whose snapshot sha changed (aliases up, u); no slug means all of them | | uninstall | Remove skills pantry installed — and, with --bundle, their installed bundle-mates |

install, upgrade, and uninstall all accept several slugs in one call. uninstall refuses the whole run, before deleting anything, if any named slug is not installed.

Flags:

  • --bundle: a boolean modifier on the slugs you name — also act on every other skill in those skills' bundles. It takes no value and does not replace the slugs; --bundle without any is an error. With several slugs it expands each one's own bundle and dedupes the combined set. A skill with no bundle recorded — null, missing, or empty — contributes just itself, with a note on stderr, and is never grouped with other unbundled skills. When it does expand, the command lists the skills on stderr before acting on any of them. install reads the bundle from Pantry (the skill may not be installed yet); upgrade and uninstall read it from ~/.pantry/skills.json, so they stay offline and only touch installed members.
  • -y / --yes: proceed without confirming when a --bundle expansion spans two or more different bundles. Without it, an interactive shell prompts (Proceed with installing 5 skills from bundles "pantry" and "openapi"?) and a non-interactive one refuses: Refusing to install 5 skills from 2 bundles without confirmation. One bundle, or no --bundle, never asks. Declining acts on nothing and exits non-zero.
  • --check (upgrade only): report which skills have a newer snapshot and install nothing. Only stale skills are listed, each with status: "outdated" rather than upgraded, so an empty array means everything is current. Writing nothing, it skips both guards a real upgrade answers to — the --bundle confirmation and the "nothing installed" error — and exits 0 with [] either way. A slug that is not installed is still an error.
  • --ignore-scripts: do not run the skill's declared install/uninstall script.
  • --no-symlink (install): do not symlink into ~/.claude/skills.
  • -f / --force (install only): replace an install directory pantry does not own, and replace a non-symlink entry in ~/.claude/skills. upgrade has no equivalent.

Diagnostics — script notices, relayed script output, skipped symlinks, and registry warnings — go to stderr; only results go to stdout, so pantry skills upgrade emits parseable JSON on stdout.

Requests

pantry api [<slug>] <METHOD> <PATH> [args...] [--env <slug>] [--auth-url <url>] [--body <json>]

Omit <slug> to call Pantry itself.

Flags:

  • --env <slug>: override the service environment for this call.
  • --auth-url <url>: override auth-api URL resolution.
  • --body <string>: send a raw request body as-is, overriding field args.
  • -p / --pretty: pretty-print response body as JSON when parseable. On by default at a TTY; --no-pretty forces the body verbatim.

Authorization: Bearer <token> and Accept: application/json are set automatically unless you override them with header args. Content-Type: application/json is set whenever a body is sent unless you pass a Content-Type: header arg.

Non-2xx responses print <status> <statusText> plus the body to stderr and exit 1.

Development

Use this section only if you are changing the CLI itself.

Install dependencies and build the binaries:

bun install
bun run build

bun run build runs the .mise/tasks/build.ts task (also invocable as mise run build). It bundles and obfuscates the CLI into dist/index.mjs — the npm bin, which runs under bun — then compiles standalone binaries per platform:

  • dist/pantry-darwin-arm64
  • dist/pantry-linux-x64

It also emits dist/index.mjs.map (used by mise run trace to translate stack traces). The release workflow publishes dist/index.mjs to npm and attaches the two binaries and the sourcemap to the GitHub release; install.sh downloads the right binary from that release.

Run the CLI from source while developing:

bun cli <command>

This is equivalent to:

bun run src/index.ts <command>

Run tests:

bun test

Tech stack: