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

@delorenj/pjangler

v1.5.18

Published

Project subsystem bootstrapper CLI

Readme

pjangler

Project definitions now live in repository .project.json files with one case-insensitive project_id. Use pj info, pj list, and pj doctor; the singleton PostgreSQL registry indexes those manifests. See project registry for installation, migration, and compatibility details.

Project subsystem bootstrapper CLI + MCP server.

Install

Requires Node 24 or newer. Project skills use @delorenj/skillex 0.1.2; see the integration contract.

npm install
npm run build

CLI usage

npm run build
node dist/index.js --help
# or if installed globally
pjangler --help

Repository ignore contract

CommonProject preserves an existing .gitignore and adds only portable project rules for secrets and local .agents projections. It never copies the operator's core.excludesFile. .agents/ is the sole canonical agent-config tree; .claude/, .codex/, and the other supported client roots are generated local projections covered by machine-wide ignore policy. bmad.cli-roots removes only exact obsolete lines previously generated by pjangler and never changes Git's index. Use the gitignore-maintenance skill to audit effective rule provenance and reconcile already-tracked ignored paths.

Project notebook

pjangler notebook manages one companion Open Notebook for a registered repository. The binding and stable Overview note IDs live in .project.json and the project registry; endpoint, authentication mode, defaults, and finite capture limits live in the registry's global notebook configuration.

pjangler notebook status . --json
pjangler notebook create . --live --json
pjangler notebook list notes . --json
pjangler notebook search notes "release evidence" . --json
pjangler notebook audit . --json
pjangler notebook migrate . --live --apply --json

True SessionStart and SessionEnd hooks are projected separately from the project-scoped hook masters. Their per-repository policy stays fail-open and disabled until explicitly enabled in .project.json.

Parity audit

BMAD recipes support an optional owner-provided g33 companion for registered 33GOD projects, with explicit opt-in/out, no-write previews, and structured optional outcomes. See g33 companion for the callable configuration and the actual pj recipe run bmad --dry-run --json commands.

pjangler audit runs the deterministic 33god parity rules against a repository and exits nonzero when any of them fails. pjangler migrate applies the idempotent fix the owning rule declares.

pjangler audit                                          # every rule, human report
pjangler audit --json                                   # machine-parseable
pjangler audit --rules mise.config-root,sot.project-json
pjangler migrate sot.project-json --dry-run
pjangler migrate --all

--rules reports only the rules you name. An unknown id is an error, never an empty pass — a caller probing for one rule learns that the rule is gone instead of reading a clean report over nothing.

pjangler audit --json and the pjangler_list_parity_rules MCP tool report the live catalog. The rules are owned by the recipes in src/recipes/, not by a central table, so that catalog is the only authority on which ones exist.

Obsidian plugins

pjangler init <name> --obsidian-plugin does everything a normal init does (registry, .project.json, board, BMAD, skills, hooks, mise, the init commit). The difference is the CommonProject render: it is the variant built on the canonical obsidian-sample-plugin. That means manifest.json, versions.json, npm + esbuild + TypeScript in src/, eslint-plugin-obsidianmd, and build/release workflows on the self-hosted runners.

pjangler init tag-wrangler --obsidian-plugin --description "Wrangle tags across a vault"
cd tag-wrangler && npm install && npm run dev
mise run plugin:link ~/Vaults/Main   # symlink into <vault>/.obsidian/plugins/<id>
  • The type is recorded as template.commonproject.project_type and in .copier-answers.yml. It is fixed at creation, and re-running init keeps it.
  • On an existing repo, the flag only records the type, and only when the repo already has an Obsidian manifest.json.
  • mise run version:bump keeps package.json, manifest.json and versions.json in step. It never tags. Release with npm version patch|minor|major, which commits and then tags a bare X.Y.Z (Obsidian matches that), and push the tag.
  • MCP takes the same choice as projectType: "obsidian-plugin" on pjangler_project_init and pjangler_bootstrap_33god_project.

Agents

pjangler does not hire, provision, or inspect agents. That is Flume's surface — flume hire, flume roster, flume record, flume review — and the org chart is Flume's record.

pjangler describe still reports a repository's employees, and pjangler init carries existing .project.json agents entries forward. Neither writes a new one: that block is a one-way projection of the org chart, not a place a project declares intent.

Orienting in a repo

describe reads a repo and reports what it actually is — detected type, installed subsystems, config files present, and what to do next. It is the first call for an agent (or a human) landing somewhere unfamiliar, and it works in any repo, 33GOD or not.

pjangler describe                # current directory
pjangler describe ../some-repo
pjangler describe --json         # machine-parseable, for agent context
pjangler describe --interactive  # tick off fixable findings, press A to apply

Subsystem presence and subsystem correctness are reported separately: presence comes from marker files on disk, parity from the recipe's own audit rules. A subsystem that was never installed reads absent, not broken.

Last activity, not lifecycle status

Projects report when work last happened, not a lifecycle word. The old status field said planned for 22 of 27 registered projects — including ones with commits the same day — so it never varied and never informed.

Activity is computed from git at read time, so it cannot go stale and no cron has to walk the registry. It spans more than the checked-out branch:

| source | covers | | --- | --- | | refs | every local branch, remote-tracking branch, and tag | | worktrees | every linked worktree's HEAD, including detached ones whose commits are on no ref | | uncommitted | working-tree edits that are not committed yet |

The newest of those wins, and the winning source is always reported. Remote state reflects your last fetch — nothing here touches the network.

pj list orders by that signal, newest work first.

Shell prompt

pjangler-prompt prints one compact line when the working directory is inside a pjangler project, and nothing at all when it is not:

pjangler (PJAN) · 3m

It is a separate binary from the main CLI on purpose — the CLI loads the whole parity rule set and takes ~52ms to boot, while this runs in ~30ms, well inside starship's 500ms budget.

Add it to ~/.config/starship.toml as a second, project-scoped prompt line:

format = "…$all${custom.pjangler}$line_break$character"

[custom.pjangler]
description = "pjangler project context"
when = true
shell = ["sh"]
symbol = "◆"
style = "bold purple"
# The newline lives INSIDE the conditional group, so nothing is emitted —
# not even a blank line — outside a pjangler project.
format = "(\n[$symbol $output]($style))"
command = 'exec pjangler-prompt 2>/dev/null'

$line_break must be named explicitly: it is otherwise absorbed by $all and the extra line lands in the wrong place.

MCP server usage

Run over stdio:

npm run mcp
# or
pjangler-mcp

Exposed tools:

  • pjangler_list_capabilities
  • pjangler_list_parity_rules
  • pjangler_audit_project
  • pjangler_migrate_project
  • pjangler_bootstrap_33god_project
  • pjangler_project_init
  • pjangler_project_list
  • pjangler_project_show
  • pjangler_info
  • pjangler_describe_project
  • pjangler_describe_recipe
  • pjangler_run_recipe