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

@plany/cli

v1.0.0

Published

Plany CLI: browser-based login, project picker, document and work item commands, memory MCP server

Readme

@plany/cli

The Plany command line. It signs you in through the browser, binds a directory to a Project, and reads and changes Work Items, note documents, Drive files and project memory. It also runs the memory MCP server for coding agents.

Bins

  • plany: the CLI. The command reference below is generated from the command table in src/command-table.ts, the same table plany help prints.
  • plany-mcp: the memory MCP server on stdio, for Cursor, Claude Code and OpenCode. Editor configs point at it directly.

Install

npm i -g @plany/cli
# or: pnpm add -g @plany/cli

The package is a self-contained bundle with no runtime dependencies.

First-time setup

plany login     # opens the web app; you click Authorize and the CLI stores the token
plany init      # pick a Project for this directory
plany status    # show the stored credentials and the binding

plany login checks the new token with the deployment before it stores it in ~/.plany/credentials.json.

Choosing a Project

Every command that works inside a Project takes --project SELECTOR. A selector is a Project ID, an exact name, or a unique part of a name. The deployment resolves it across all your workspaces, so a command works from any directory. Without --project, a command uses the Project that plany init bound to the current directory. With neither, it fails and says how to pick one.

Work Item keys (BIE-42), document IDs and file IDs are found in any of your workspaces. A binding only supplies the default Project. With --project, the item must be in that Project.

Output and exit codes

--json prints the deployment's answer as JSON, unchanged. Use it whenever a program reads the output.

Exit codes: 0 on success, 1 when the command failed (including an edit conflict), 2 when the command line was wrong. Errors print as error: <message>.

Setup

plany login  # Sign in through the browser. Stores the token in ~/.plany/credentials.json.
plany logout  # Forget the stored token.
plany whoami [--json]  # Show the signed-in user and their workspaces.
plany init [--project SELECTOR] [--json]  # Bind this directory to a Project and pull its memory.
plany status  # Show the stored credentials, this directory's binding, and the last memory sync.
plany skill  # Install the Plany agent skill into .claude/skills/.
plany update  # Update the CLI to the latest version.
plany version  # Print the CLI version.
plany help [COMMAND]  # Show help for every command, or for one command or group.
  • init: Without --project, init lists your Projects and asks you to pick one.

Workspace

plany projects [--json]  # List the Projects you can access, across workspaces.
plany members [--project SELECTOR] [--json]  # List the Project team's members and the workspace's pending invites.
plany teams [--project SELECTOR] [--json]  # List the teams you can see in the Project's workspace.
plany labels [--project SELECTOR] [--json]  # List the labels in the Project's workspace.
  • members: These are the people items assign accepts, by email or display name.
  • labels: These are the names items label and items create --label accept.

members and labels list the values items assign and items label accept. Look them up first instead of guessing.

Work Items

plany items list [--status STATUS] [--project SELECTOR] [--json]  # List the Project's Work Items.
plany items mine [--limit N] [--project SELECTOR] [--json]  # List open Work Items assigned to you and open items in your personal space.
plany items show KEY [--project SELECTOR] [--json]  # Show a Work Item and its description as Markdown.
plany items search QUERY [--limit N] [--project SELECTOR] [--json]  # Search Work Item titles in the Project.
plany items create TITLE [--type TYPE] [--status STATUS] [--priority P0..P4] [--description TEXT | --description-file PATH|-] [--assignee USER]... [--label LABEL]... [--due DATE[ TIME]] [--parent KEY] [--project SELECTOR] [--json]  # Create a Work Item in the Project.
plany items update KEY [--title TITLE] [--type TYPE] [--project SELECTOR] [--json]  # Change a Work Item's title, type, or both.
plany items edit KEY [--file PATH|-] [--base-version N | --overwrite] [--allow-lossy] [--dry-run] [--project SELECTOR] [--json]  # Edit a Work Item description as Markdown.
plany items set KEY STATUS [--project SELECTOR] [--json]  # Set a Work Item's status.
plany items assign KEY (--to USER... | --me | --clear) [--project SELECTOR] [--json]  # Replace a Work Item's assignees.
plany items priority KEY P0..P4 [--project SELECTOR] [--json]  # Set a Work Item's priority.
plany items due KEY (DATE [TIME] | --clear) [--project SELECTOR] [--json]  # Set or clear a Work Item's due date, optionally with a time.
plany items label KEY [--add LABEL]... [--remove LABEL]... [--project SELECTOR] [--json]  # Add or remove Work Item labels.
plany items parent KEY (PARENT_KEY | --clear) [--project SELECTOR] [--json]  # Put a Work Item under a parent in the same Project, or detach it.
plany items move KEY --to PROJECT [--project SELECTOR] [--json]  # Move a Work Item to another Project.
plany items comments KEY [--limit N] [--project SELECTOR] [--json]  # List a Work Item's comments.
plany items comment KEY (BODY | --file PATH|-) [--project SELECTOR] [--json]  # Comment on a Work Item.
  • items mine: items mine covers every workspace; --project limits it to that Project's workspace.
  • items create: The description is Markdown.
  • items edit: Pass --file PATH (or --file - for stdin) with --base-version N or --overwrite.
  • items edit: Without --file the command opens $VISUAL or $EDITOR on the current text and merges against the version it opened.
  • items edit: --base-version N is the version from items show KEY --json. The deployment merges your text with every change made since that version, block by block.
  • items edit: A block changed both by you and by someone else since your base is a conflict: nothing is written and the command exits 1. Re-read, reapply your change, and retry against the new version.
  • items edit: --overwrite replaces the current text without merging.
  • items edit: An edit that replaces a block holding formatting Markdown cannot express is refused unless --allow-lossy is passed. Blocks you leave alone keep their formatting.
  • items edit: --dry-run reports the merge without writing it.
  • items edit: Markdown input is limited to 500000 characters.
  • items assign: --to and --me combine. USER is an email or display name from plany members.
  • items due: DATE is YYYY-MM-DD and TIME is HH:MM, read in this machine's time zone like the web picker. A date alone means the whole day.
  • items move: --to takes a Project selector, like --project.

CLI edits write the same activity events as web edits, so they show in the activity feed, and new assignees get the usual inbox notification.

Documents

plany docs list [--limit N] [--cursor CURSOR] [--project SELECTOR] [--json]  # List one page of the Project's documents.
plany docs show DOCUMENT [--project SELECTOR] [--json]  # Print a note document as Markdown.
plany docs create TITLE [--file PATH|-] [--personal] [--project SELECTOR] [--json]  # Create a note document, optionally from Markdown.
plany docs edit DOCUMENT [--file PATH|-] [--base-version N | --overwrite] [--allow-lossy] [--dry-run] [--project SELECTOR] [--json]  # Edit a note document as Markdown.
  • docs list: Pass nextCursor from --json output to --cursor to read the next page.
  • docs show: DOCUMENT is a document ID, or an exact title in the Project. An ID works from any directory.
  • docs create: --personal makes the document visible only to you.
  • docs edit: Pass --file PATH (or --file - for stdin) with --base-version N or --overwrite.
  • docs edit: Without --file the command opens $VISUAL or $EDITOR on the current text and merges against the version it opened.
  • docs edit: --base-version N is the version from docs show DOCUMENT --json. The deployment merges your text with every change made since that version, block by block.
  • docs edit: A block changed both by you and by someone else since your base is a conflict: nothing is written and the command exits 1. Re-read, reapply your change, and retry against the new version.
  • docs edit: --overwrite replaces the current text without merging.
  • docs edit: An edit that replaces a block holding formatting Markdown cannot express is refused unless --allow-lossy is passed. Blocks you leave alone keep their formatting.
  • docs edit: --dry-run reports the merge without writing it.
  • docs edit: Markdown input is limited to 500000 characters.

Files

plany files list [--folder PATH] [--limit N] [--cursor CURSOR] [--project SELECTOR] [--json]  # List one page of the Project's Drive files.
plany files search QUERY [--limit N] [--project SELECTOR] [--json]  # Search Drive file names in the Project.
plany files show FILE [--project SELECTOR] [--json]  # Show a file's metadata and download URL.
plany files download FILE [--output PATH] [--project SELECTOR] [--json]  # Save a file's current version. Never overwrites a local file.
plany files upload PATH [--folder FOLDER] [--replace FILE] [--project SELECTOR] [--json]  # Upload a local file to the Project's Drive.
plany files mkdir PATH [--project SELECTOR] [--json]  # Create a Drive folder and any missing parents.
plany files move FILE --to FOLDER [--project SELECTOR] [--json]  # Move a Drive file to another folder.
plany files link FILE KEY [--project SELECTOR] [--json]  # Attach a Drive file to a Work Item.
plany files unlink FILE KEY [--project SELECTOR] [--json]  # Detach a Drive file from a Work Item.
  • files list: Without --folder it lists every file in the Project; with it, the files directly in that folder. Folder paths look like / or /Specs/2026.
  • files list: Pass nextCursor from --json output to --cursor to read the next page.
  • files show: FILE is a file ID from files list, or the file's path in the Project (/Specs/plan.pdf). An ID works from any directory.
  • files download: The file lands in the current directory under its own name unless --output is given.
  • files upload: --folder creates any missing folders.
  • files upload: --replace FILE stores the upload as a new version of that file, in its folder.

Drive files are separate from note documents and from Work Item attachments.

Memory

plany memory pull [--project SELECTOR] [--json]  # Write the Project's memory to the mirror file your editor loads.
plany memory mcp  # Run the memory MCP server on stdio. Same as `plany-mcp`.

Editor config (Claude Code, Cursor and OpenCode use this shape):

{
  "mcpServers": {
    "plany-memory": { "command": "plany-mcp" }
  }
}

The server runs in a bound directory and works on that Project. Its tools:

create_memory { title, body }  # Create a private memory in the bound Project. The user promotes it to shared in the Plany web app.
update_memory { key, title?, body? }  # Change the title or body of a memory you wrote. `key` is its publicKey, such as MEM-Kabc1-001.
search_memories { query, limit? }  # Search memory bodies. Use it when the auto-loaded mirror file does not hold what you need.

The mirror file is the agent's main read surface. Claude Code, Cursor rules and OpenCode load it on their own. The tools are for writing back and for searching past the mirror.

Agent skill

The package ships an agent skill (skills/plany/SKILL.md) that teaches coding agents these commands. plany init installs it into .claude/skills/ when the repo has .claude/ or CLAUDE.md. plany skill installs or refreshes it.

The skills/ directory follows the skills.sh layout, so other agents (Cursor, Codex, OpenCode) can install it from the package:

npx skills add ./node_modules/@plany/cli   # or the global install path

Updating

Commands read a cached latest version from ~/.plany/version.json and never wait on the registry. A detached background process refreshes a stale cache. The notice shows in TTY sessions only; --json and MCP runs stay silent. Set PLANY_NO_UPDATE_CHECK=1 to turn it off.

A deployment that has moved to a newer protocol answers upgrade_required, and the CLI tells you to run plany update.

Protocol

Each command is one POST {deployment}/cli/v2/<command id> with a bearer token and the command's input as JSON. The contract lives in packages/backend/src/cli-contract and is bundled into the CLI. The CLI checks every answer against the command's output validator, so a CLI and a deployment that disagree fail on the first call.

Environment

| Variable | Default | Purpose | | ----------------------- | ------------------------------- | --------------------------------------------------- | | PLANY_WEB_URL | https://plany.bielcrystal.app | Web app that plany login opens. Override for dev. | | PLANY_NO_UPDATE_CHECK | unset | Any value turns off the update notice. |

Local files

~/.plany/credentials.json    {"apiUrl": "...", "token": "plany_pat_..."}
<cwd>/.plany/config.json     Project binding (projectId, workspaceId, mirrorTarget).
<cwd>/.plany/memory.md       Memory mirror (or wherever mirrorTarget points).

The credentials file has mode 0600. Revoke a device's token in the Plany web app under Settings → API Tokens.