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

@pactto/cli

v1.7.0

Published

Pactto CLI - external programmatic surface for LLMs and scripts

Readme

Pactto CLI

External CLI to read meeting context from Pactto rooms — transcription, PDFs, images, canvas shapes, participants — without opening the web app.

Made to be used by LLMs in the terminal (Claude Code, ChatGPT in a shell) or by humans piping JSON through jq.


Prerequisites

  • Node.js 20 or newer Check with node --version. If older, install from nodejs.org or via your package manager.
  • An API key from the Pactto web app Go to Settings → API Keys → Create. Copy the token shown — it appears only once. Tokens start with pact_dev_ (dev environment) or pact_prod_ (production).

Install

The CLI is on the npm public registry. Install globally:

npm install -g @pactto/cli

Verify:

pactto --version    # should print 0.4.0 (or newer)
pactto --help       # shows all commands

If pactto: command not found: your npm global bin is not in $PATH. Run npm bin -g to see where npm installs global binaries, and add that to $PATH in your ~/.zshrc or ~/.bashrc. With nvm this is automatic.

No-install try-out: npx -y @pactto/cli <command> runs a one-shot without installing globally — handy for exploring.

Pre-release tarballs (internal / fallback)

If you received a pactto-cli-X.Y.Z.tgz file directly (for an unreleased canary, or when the public registry is unavailable), cd into the directory holding it and install with a relative path:

cd ~/Downloads                                 # or wherever the .tgz is
npm install -g ./pactto-cli-0.4.0.tgz

Or use the absolute path (starts with /, no leading ./):

npm install -g /Users/yourname/Downloads/pactto-cli-0.4.0.tgz

Common pitfall: npm install -g ./Users/yourname/Downloads/... (with ./ before an absolute path) is treated as relative, and npm looks inside your current working directory — producing ENOENT: no such file or directory. Use one of the two patterns above.

First-time setup

pactto auth login
# Paste the token from the web app when prompted

The CLI auto-detects which environment (dev/prod) to talk to based on the token prefix and saves the config in ~/.pactto/config.json (chmod 600 — only you can read).

Set a default room so you don't need --room on every command:

pactto rooms              # list rooms you have access to
pactto use room_<roomPk>  # pick one
pactto context            # confirm

Common commands

# Read meeting context
pactto transcription                       # last session
pactto transcription --scope full          # entire history
pactto participants                        # who is in the room + online status
pactto canvas list                         # all shapes in the room
pactto canvas list --type pacttoNote       # filter
pactto canvas show <shapeId> [<id>...]     # full details
pactto pdf <shapeId>                       # text content of a PDF shape
pactto pdf <shapeId> --pages 1-5           # only some pages
pactto pdf-visual <shapeId>                # describe figures / scanned PDFs
pactto image <shapeId>                     # describe an image shape
pactto doc <docId>                         # read a Pactto Doc by UUID
pactto room-instructions get               # the room's durable instructions

# Get help on any command
pactto <cmd> --help

All output is JSON in stdout. Use jq to filter. Errors are JSON in stderr with non-zero exit code.

Add --pretty for human-readable indented output.

Tip: using with Claude Code (or any external LLM)

Generate a primer doc and feed it to your LLM so it knows the surface:

pactto instructions > ~/myproject/.claude/PACTTO.md
# (or just `pactto instructions | pbcopy` and paste into your prompt)

Then Claude Code (running in ~/myproject) automatically knows it can do pactto rooms, pactto transcription, etc.

Update to a new version

npm install -g @pactto/cli@latest
pactto --version    # confirm

Your config in ~/.pactto/config.json is preserved across upgrades.

To see all published versions:

npm view @pactto/cli versions

Logout / uninstall

pactto auth logout         # clears local config (token + default room)
npm uninstall -g @pactto/cli  # removes the binary

Troubleshooting

| Symptom | Likely cause | Fix | |---|---|---| | getaddrinfo ENOTFOUND ... | CLI is pointing at a wrong endpoint | PACTTO_API_ENDPOINT=<url> pactto rooms to override, or get a fresh token | | {"error":"invalid_api_key"} | Token expired/revoked, or wrong env (dev vs prod) | Generate a new token in the web app | | {"error":"not_logged_in"} | Config missing or pactto auth logout was run | pactto auth login again | | {"error":"forbidden_room"} | Your API key was scoped to specific rooms; you tried another | Create a key with broader allowedRooms in the web app | | {"error":"room_required"} | No --room and no default set | pactto use <roomPk> or pass --room <roomPk> per command | | pactto: command not found | npm global bin not in $PATH | See Install section | | npm error ENOENT: no such file or directory ... .tgz on install | Used ./ before an absolute path during install (./Users/...) — npm treats it as relative | cd into the directory holding the .tgz and use ./pactto-cli-X.Y.Z.tgz, or use the full absolute path (starts with /) without leading ./ |

Status of commands in 0.4.0

All Phase 1 read commands, Phase 2 write commands, Phase 3 Pactto-specific shape commands, and Phase 4 board commands have been smoke-tested end-to-end against the dev backend (CLI version 0.4.0+). Tracking matters because the Pactto backend has a few subtle invariants (data model, claim formats, tldraw v4 schemas) that unit tests stub away.

| Command | Status | Notes | |---|---|---| | pactto auth login | confirmed | Validates token by calling /whoami | | pactto auth whoami | confirmed | Returns userPk + scope + allowedRooms | | pactto auth logout | works locally | Just clears ~/.pactto/config.json — no backend call | | pactto rooms | confirmed | Delegates to /v1/roomActions/rooms via Lambda invoke | | pactto use <roomPk> | works locally | Writes to config — no backend call | | pactto context | works locally | Reads config | | pactto instructions | works locally | Prints bundled primer Markdown | | pactto transcription | confirmed | Resolves transcription_chat_room_id via Lambda invoke, then reads S3. Use --scope full for all sessions; default last_session returns only the active session window | | pactto participants | confirmed | Reuses the same handler that the Bedrock agent uses | | pactto canvas list | confirmed | Same handler as agent | | pactto canvas show <id> | confirmed | Same handler as agent | | pactto pdf <shapeId> | confirmed | Reads PDF from S3 + extracts text | | pactto pdf-visual <shapeId> | confirmed | Calls Gemini for visual description | | pactto image <shapeId> | confirmed | Calls Gemini | | pactto doc <docId> | confirmed | Calls docs.pactto.com | | pactto room-instructions get | confirmed | Reads from S3 | | pactto canvas create-note <text> | confirmed | Phase 2. Sticky note (yellow default; --color) | | pactto canvas create-text <text> | confirmed | Phase 2. Plain text shape | | pactto canvas create-arrow --from --to | confirmed | Phase 2. Arrow + 2 bindings linking two existing shapes | | pactto canvas update-shape <id> | confirmed | Phase 2. Patch x/y/w/h/rotation/color/parent | | pactto canvas update-text <id> <text> | confirmed | Phase 2. Replace text on note/text shape (other types rejected) | | pactto canvas delete <id>... | confirmed | Phase 2. Cascades bindings | | pactto canvas align <id>... --mode | confirmed | Phase 2. top/middle/bottom/left/center/right | | pactto canvas distribute <id>... --axis | confirmed | Phase 2. horizontal/vertical | | pactto canvas link --url | confirmed | Phase 3. URL as pacttoLink shape + Link/Asset/RoomAsset records | | pactto canvas image --file | confirmed | Phase 3. Local image upload → pacttoImage. Dims via image-size | | pactto canvas video --file | confirmed | Phase 3. Local video upload → pacttoVideo. Dims via ffprobe (or --w --h override) | | pactto canvas pdf --file | confirmed | Phase 3. Local PDF upload → pacttoPdf. totalPages + first-page dims via pdf-lib | | pactto canvas comment --content | confirmed | Phase 3. pacttoComment pin with optional anchor + cascade (commentPerson/commentFlag/attachment). Author resolved via Person+RoomPerson DDB | | pactto canvas annotation --comment-shape-id --strokes | confirmed | Phase 3. Freehand drawing tied to a pacttoComment (optional annotationBinding to an asset) | | pactto canvas board | confirmed | Phase 4. Empty board (tldraw frame shape). Flags: --at --w --h --name --color | | pactto canvas group-into-board | confirmed | Phase 4. Wrap ≥2 existing shapes in a new board. Backend validates atomically (details.missing[] / details.locked[]) | | pactto room-instructions set | deliberately omitted | Durable memory changes only via web app | | pactto ask / pactto session * | deliberately omitted | The CLI does not invoke the Pactto agent — your external LLM is the brain | | pactto media generate / edit | deliberately omitted | AI image generation only via web app; Phase 3 canvas image is for uploading existing files, not generation | | pactto canvas board --items ... / create-frame | deliberately omitted | Single-shot "board with items" was cut in 2026-05-26 scope review. Workflow: create children individually via create-note etc., then group-into-board |

"Implemented, not smoke-tested" means: the code path is in place, unit tests pass, code is deployed to dev, but nobody has run the command against real data yet. They should work — if you try one and something breaks, please report so the maintainer can investigate (include the full error JSON from stderr).

Limitations (0.4.0)

  • Canvas writes require an API key with scope=write. A read-only key receives 403 on any write. Web UI creates write-scoped keys explicitly.
  • No room-instructions set. Durable memory updates happen only via the web app (Cognito-authenticated).
  • No AI image/media generation. Phase 3 added file uploads (canvas image/video/pdf take local file paths), NOT generation from text prompts. AI-generated media is web-app-only (Pactto's media_op tool).
  • No single-shot "board with items". pactto canvas board creates an empty board. To populate, create the children individually (canvas create-note, etc.) and call pactto canvas group-into-board with their IDs.
  • No editing of Pactto-specific shape props. You can move/resize/recolor/delete any shape, but you cannot edit the content of a pacttoComment, the url of a pacttoLink, etc. via CLI. Use the web app for content edits.

Environment overrides

| Env var | Effect | |---|---| | PACTTO_API_KEY | Overrides the token from config (useful to run as another user temporarily) | | PACTTO_ROOM | Overrides the default room | | PACTTO_API_ENDPOINT | Overrides the auto-detected backend URL (testing, staging, or fallback) |


For maintainers — releasing a new version

This section is for whoever ships new versions of @pactto/cli to the public npm registry.

Standard release flow (publish via GitHub Actions)

  1. Bump the version in cli/package.json (semver — major for breaking, minor for new commands, patch for bug fix). Mirror the bump in cli/package-lock.json.
  2. Update the bundled primer (src/assets/PACTTO_CLI_PRIMER.md) if behavior changed.
  3. Run tests locally:
    cd cli
    npm install        # if deps changed
    npm test           # all tests must pass
    cd ..
  4. Open a PR with the version bump and merge it to main.
  5. From main, create and push the tag matching the new version:
    git checkout main && git pull
    git tag cli-vX.Y.Z
    git push origin cli-vX.Y.Z
  6. The .github/workflows/cli-publish-v2.yml workflow runs on tag push: it validates that the tag matches cli/package.json version, runs tests, and publishes via npm publish --access public. Total runtime ~15 seconds. (Filename is -v2.yml after the original workflow ID got stuck on GitHub's side during the 0.3.1 publish; recreating under a new path restored a fresh workflow registration. See roadmap Gate 3 post-delivery notes.)
  7. Verify:
    npm view @pactto/cli version    # should match the tag

The published tarball includes only what's listed in files of cli/package.json (bin/, src/, README.md, LICENSE). Tests, lockfiles, and config are excluded by default.

Token rotation (every 90 days)

The npm publish token consumed by GitHub Actions (secrets.PACTTO_CLI_PUBLISH_CI) has a 90-day expiry by design. Rotate before it lapses to avoid release downtime.

  1. The npm org owner (pacttoinc — currently Demian) creates a new Granular Access Token at https://www.npmjs.com/settings/~/tokens with:
    • Permission: Read and write, scope All packages (narrower scopes have failed at publish time — see docs/features/pactto-cli/roadmap-npm-publish.md Gate 6)
    • Bypass 2FA for publishes enabled (CI cannot prompt for OTP)
    • Expiry: 90 days
  2. Copy the token immediately — npm shows it only once.
  3. Update the secret in GitHub:
    gh secret set PACTTO_CLI_PUBLISH_CI --repo PrepForImpact/pfi-pactto
    # paste the token when prompted
  4. (Recommended) Revoke the previous token in npm once the new one is confirmed working.
  5. Validate with a patch release or a canary publish (see roadmap Gate 6 for canary playbook).

If the token expires before rotation, the workflow will fail with npm error code E401 / EOTP. Same fix: rotate.

Manual npm pack fallback

For pre-public-release distribution (canary tarballs shared via Slack) or when GitHub Actions is unavailable:

cd cli
npm test            # all tests must pass
npm pack            # produces pactto-cli-<version>.tgz in cwd

Inspect before shipping:

npm pack --dry-run                # prints file list, no .tgz produced
tar tf pactto-cli-0.3.0.tgz       # list contents

This path does not register the version on the public npm registry — once GA is back, do a proper release with a new patch number to publish for real.