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

opctl

v0.1.6

Published

Conservative local CLI bridge for OpenProject API v3

Readme

opctl

opctl is a small local Node.js + TypeScript CLI bridge for OpenProject API v3. It uses the current user's personal API token and is read-only by default.

Install

Published package:

Install globally:

npm install -g opctl
opctl --help

Or run without a global install:

npx opctl --help

Configuration

Export variables in your shell, load a local file with --env <path>, or save non-write defaults in a profile. By default, opctl also reads .env from the current working directory when present; pass --no-env to disable that. Required:

  • OPENPROJECT_URL: OpenProject instance URL, optionally including an instance path prefix.
  • OPENPROJECT_TOKEN: personal OpenProject API token.

Optional:

  • OPENPROJECT_AUTH_MODE: bearer (default) or basic. Basic auth uses username apikey and the token as password.
  • OPENPROJECT_DEFAULT_PROJECT: project identifier/id used by wp search when --project is omitted.
  • OPENPROJECT_ALLOW_WRITE: must be exactly 1 to allow write-capable commands.

Profile commands:

opctl profile set navlin-qa --url https://openproject.example.com --auth-mode bearer --default-project qa --token ...
opctl profile use navlin-qa
opctl --profile navlin-qa me --json
opctl profile show navlin-qa
opctl profile list

Profiles are stored under ${XDG_CONFIG_HOME:-~/.config}/opctl/profiles.json. The file is written with restrictive permissions where supported, tokens may be stored there, and profile display commands redact tokens. OPENPROJECT_ALLOW_WRITE is never loaded from .env files or profiles; writes still require the real process environment variable.

Usage

Show the authenticated OpenProject user:

opctl me
opctl me --json

Inspect API root links:

opctl api-root
opctl api-root --json

List projects:

opctl projects --page-size 20
opctl projects --json

Read work packages:

opctl wp get 123
opctl wp get 123 --json
opctl wp get 123 --raw-json
opctl wp get 123 124 --table
opctl wp get --ids 123,124 --fields id,subject,status,assignee --table
opctl wp get --ids 123,124 --jsonl

Field selection supports id,subject,status,type,assignee,project,href,updatedAt,description,shortDescription,attachmentsCount,lockVersion; aliases: title=subject, url=href.

Search work packages:

opctl wp search --project my-project --subject "pump"
opctl wp search --project my-project --assignee-me --status open
opctl wp search --open --subject "pump" --compact
opctl wp search --subject "pump" --fields id,subject,status --json

If --project is omitted, opctl wp search uses OPENPROJECT_DEFAULT_PROJECT when set. Without either, it searches the instance-wide work package endpoint.

List work packages assigned to the authenticated user:

opctl wp mine
opctl wp mine --open --table
opctl wp mine --project my-project --page-size 50 --fields id,subject,status,updatedAt

Triage a known list:

opctl wp check 123 124
opctl wp check --ids 123,124 --fields id,title,status,assignee,shortDescription,attachmentsCount --table

Pull the OpenAPI spec (defaults to the public community instance):

opctl spec pull
opctl spec pull --output openapi/my-spec.json
opctl spec pull --url https://openproject.example.com

Write-capable command:

OPENPROJECT_ALLOW_WRITE=1 opctl wp comment 123 --dry-run "Investigating"
OPENPROJECT_ALLOW_WRITE=1 opctl wp comment 123 "Investigating"

wp comment fetches the work package first and posts only when a documented HAL comment action link is present. It fails safely instead of guessing a mutation URL.

OpenAPI

The repository commits openapi/openproject.json and generated types in src/generated/openproject.ts. The committed spec is an auditable public OpenProject baseline.

npm run openapi:pull and opctl spec pull default to the official public spec at https://community.openproject.org. They do not read OPENPROJECT_URL or OPENPROJECT_TOKEN, so running tests or pulling the spec never sends credentials to a private instance.

# Refresh from the public community spec (safe, no credentials needed)
npm run openapi:update

# Pull from a specific private instance (explicit opt-in)
OPENPROJECT_SPEC_URL=https://openproject.example.com \
OPENPROJECT_SPEC_TOKEN=... \
  npm run openapi:pull

# Or via the CLI
opctl spec pull --url https://openproject.example.com

Private-instance pulls use dedicated OPENPROJECT_SPEC_URL / OPENPROJECT_SPEC_TOKEN / OPENPROJECT_SPEC_AUTH_MODE variables. Normal OPENPROJECT_URL and OPENPROJECT_TOKEN are never used for spec pulling.

Build and verification

npm run typecheck
npm run test
npm run build
node dist/cli.js --help
node dist/cli.js wp --help

Safety model

  • No token or Authorization header is printed by normal errors, JSON output, spec pulling, or tests.
  • Spec pulling defaults to the public community spec and ignores OPENPROJECT_URL / OPENPROJECT_TOKEN; private-instance pulls require explicit --url or OPENPROJECT_SPEC_URL.
  • Local .env files are loaded for read configuration by default; --no-env disables that, and .env cannot enable writes.
  • OpenProject writes are blocked unless the real process environment contains OPENPROJECT_ALLOW_WRITE=1 exactly.
  • Every write-capable command supports --dry-run and avoids mutation in dry-run mode.
  • No destructive commands are implemented: no delete, close, archive, move, or bulk edit.