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

upstream-docs

v0.4.0

Published

Claude Code plugin: enforce PRD/ADR before feature development

Readme

upstream

npm version CI License: MIT

A Claude Code plugin that enforces PRD and ADR documentation before feature development begins.

upstream installs a hook into Claude Code that detects feature work and blocks it until a Product Requirements Document (PRD) exists. If the feature introduces architectural decisions — a new external dependency, a database migration, an API contract change — it also requires an Architecture Decision Record (ADR).

This keeps your team's reasoning in the repository, not scattered across memory.


How it works

After setup (via upstream init or claude plugin install upstream), the first prompt on a feature branch in each Claude Code session gets a context injection:

UPSTREAM: feature detected without PRD. Invoke upstream-guard before continuing.

The hook fires at most once per session (tracked via a PPID-based cache file in /tmp). Subsequent prompts in the same session are silent.

Claude then runs the upstream-guard skill, which:

  1. Classifies the work — feature, bug, fix, chore, or incident
  2. Checks for a PRD — by filename or content match in <docs_path>/
  3. Checks for an ADR — if the PRD describes architectural decisions
  4. Releases to development once docs are in place

PRDs and ADRs can be created in four ways: imported from an existing document, generated through a short interview, auto-drafted from git context, or linked to an external tool (Confluence, Google Docs).

Bypass branches (fix/, hotfix/, chore/, docs/) are skipped automatically.


Quick start

Option A — Claude Code plugin (personal install)

claude plugin install upstream

Skills and hook are loaded automatically. Add upstream.config.yaml to any repo you want guarded (see Configuration).

Option B — npm + upstream init (team setup)

# Install globally
npm install -g upstream-docs

# In your repo (platform engineer runs this once)
cd my-project
upstream init
git add .
git commit -m "feat: add upstream Claude Code plugin"
git push

upstream init runs an interactive wizard that configures upstream.config.yaml, scaffolds .claude/, optionally sets up a CODEOWNERS guardian, and automatically updates .gitignore to exclude .env/.env.local/.env.test.

Your team gets the plugin on their next git pull. No global install required on their machines — Claude Code picks up .claude/ automatically.

Which to choose? Use the plugin install for personal use across your own projects. Use upstream init when your team should all be gated — the config and hook live in the repo and are enforced for everyone.


CLI reference

| Command | Description | | --- | --- | | upstream init | Interactive wizard: scaffold upstream into the current repo | | upstream init --yes | Non-interactive: scaffold with all defaults | | upstream init --from answers.json | Non-interactive: load all answers from a JSON file | | upstream upgrade | Regenerate skills and hook, preserve config and docs | | upstream auth google-docs | Connect Google Docs via OAuth (PKCE) | | upstream auth confluence | Connect Confluence via OAuth (PKCE) | | upstream auth status | Show authentication status for all providers | | upstream logout <provider> | Remove stored token for a provider (or all) | | upstream doctor | Check upstream installation health in the current repo | | upstream doctor --fix | Repair missing or misconfigured files automatically | | upstream status | Show PRD/ADR state for the current git branch | | upstream list | Show PRD/ADR coverage for all local feature branches | | upstream list --format json | Machine-readable coverage output ({ branches, unlinked }) | | upstream validate | Check whether the current branch diff is aligned with its PRD/ADR | | upstream validate --format json | Machine-readable alignment result ({ verdict, engine, findings }) | | upstream validate --base <branch> | Override the base branch used for diff | | upstream validate --report [path] | Write a JSON report artifact to disk (default: upstream-report.json) | | upstream report summary | Print a Markdown summary of the last report artifact to stdout | | upstream report summary --input <path> | Read report from a custom path | | upstream stats | Show PRD/ADR coverage summary across all feature branches | | upstream stats --format json | Machine-readable stats output | | upstream stats --trend | Compare current coverage against the latest snapshot | | upstream stats --adoption | Team adoption analytics — per-author coverage, skip log, and adoption score | | upstream stats --adoption --since <date> | Scope adoption lookback window (default: 90 days, YYYY-MM-DD) | | upstream stats --adoption --no-authors | Show skip log and adoption score without per-author table | | upstream snapshot | Save current coverage stats as a local snapshot | | upstream snapshot --ci | Exit non-zero if coverage regressed since last snapshot | | upstream mcp | Start the upstream MCP server (called automatically by Claude Code) |

upstream init flags

| Flag | Description | | --- | --- | | --from <file> | Load answers from a JSON file (non-interactive, for CI/scripts) | | --docs-storage <value> | local or link | | --provider <id> | google-docs or confluence | | --client-id <id> | OAuth client_id for the provider | | --allowed-domain <domain> | Allowed domain (e.g. acme.com) | | --guardian <handle> | GitHub handle or email written to .github/CODEOWNERS | | --yes | Skip interactive Phase 2 (use org defaults) |


Configuration

upstream.config.yaml is created in your repo root on init. All fields have defaults.

version: 1

# Branch prefixes that bypass all checks
bypass_for:
  - fix/
  - hotfix/
  - chore/
  - docs/

# Fields that must be present in every PRD
prd_required_fields:
  - problem_statement
  - success_metrics
  - out_of_scope

# Conditions that require an ADR
adr_triggers:
  - new_external_dependency
  - database_schema_change
  - api_breaking_change
  - infrastructure_change
  - auth_change

# Directory for PRDs, ADRs, and the skip log
docs_path: docs/upstream/

# 'local': full document content in this repo
# 'link': stub file with URL; actual doc lives externally
docs_storage: local

# Alignment check (used by upstream validate)
align:
  base_branch: main          # branch to diff against
  on_violation: warn         # 'warn' (default) or 'block' (exits 1 when misaligned)
  post_pr_comment: true      # post verdict as a PR comment when GITHUB_TOKEN is set

Link mode — external docs (Confluence, Google Docs)

If your team stores PRDs and ADRs in an external tool, set docs_storage: link. upstream saves a small stub file with the document URL and metadata instead of full content:

# PRD: user-auth

- **Status:** Linked
- **Storage:** external
- **Document:** https://docs.google.com/document/d/...
- **Date:** 2026-06-12

OAuth and PKCE

upstream uses PKCE (Proof Key for Code Exchange, RFC 7636) for all OAuth flows. Only client_id and allowed_domain are stored in upstream.config.yaml — never in version control.

Both Google Docs and Confluence require a client_secret — neither supports public OAuth clients. Secrets are stored as env vars (UPSTREAM_GOOGLE_CLIENT_SECRET, UPSTREAM_CONFLUENCE_CLIENT_SECRET) and loaded at CLI startup. They are never stored in upstream.config.yaml or committed to the repo. upstream init writes the placeholder to .env, .env.local, and .env.example automatically.

Google Docs integration

Setup (platform engineer, done once per org):

  1. Create a project at console.cloud.google.com
  2. Enable the Google Drive API
  3. Create an OAuth 2.0 Client ID → type: Desktop app
    • Desktop app type allows localhost automatically — no redirect URI configuration needed
  4. Copy the Client secret from the credential detail page
  5. Add client_id and allowed_domain to upstream.config.yaml and commit:
integrations:
  google_docs:
    client_id: "xxx.apps.googleusercontent.com"
    allowed_domain: "yourcompany.com"

Add the client_secret to your .env / .env.local — never commit this file:

UPSTREAM_GOOGLE_CLIENT_SECRET=your-secret-here

upstream init creates the placeholder automatically when you choose Google Docs during setup.

Each developer authenticates once:

upstream auth google-docs

Confluence integration

Setup (platform engineer, done once per org):

  1. Create an app at developer.atlassian.com/console/myapps
  2. Enable OAuth 2.0 (3LO)
  3. In Authorization, add callback URL: http://localhost:27182/callback
  4. In Permissions, add scopes: read:confluence-content.all, write:confluence-content
    • offline_access is not listed in Permissions — upstream requests it automatically at auth time
  5. Copy the Client ID and Client secret from the app's Settings tab
  6. Add client_id and allowed_domain to upstream.config.yaml and commit:
integrations:
  confluence:
    client_id: "your-client-id"
    allowed_domain: "yourorg.atlassian.net"

allowed_domain must be your Atlassian site subdomain (e.g. acme.atlassian.net), not your company domain.

Add the client_secret to your .env / .env.local — never commit this file:

UPSTREAM_CONFLUENCE_CLIENT_SECRET=your-secret-here

upstream init creates the placeholder in .env, .env.local, and .env.example automatically.

Each developer authenticates once:

upstream auth confluence

Enforcement policy

Platform engineers can restrict which tools are accepted and require validation before a link can be saved:

link_policy:
  allowed_providers:      # only accept links from these tools
    - google-docs
  require_validation: true  # block unvalidated links (e.g. unauthenticated)

CODEOWNERS guardian

During upstream init, you can designate a GitHub handle or email as the guardian for upstream.config.yaml. upstream writes a .github/CODEOWNERS entry — any PR that modifies the config requires guardian approval.

Note: CODEOWNERS is only enforced when branch protection is enabled on the repository.


Alignment check — upstream validate

upstream validate checks whether the current branch's diff is aligned with its PRD and ADR. It runs automatically in CI via the scaffolded upstream-align.yml workflow, and can also be run locally.

upstream validate             # human-readable output
upstream validate --format json  # machine-readable (for CI scripts)

Engines:

  • LLM — uses claude -p to analyse the diff against the PRD/ADR; provides a natural-language summary and per-dimension findings
  • Heuristic — fallback when Claude CLI is unavailable; detects out-of-scope changes, new dependencies, config drift, and missing test coverage from the diff

Verdict:

  • aligned — diff is consistent with the PRD/ADR
  • warning — minor concerns, but not blocking
  • misaligned — significant scope creep or deviation detected

Set align.on_violation: block in upstream.config.yaml to make upstream validate exit 1 on misaligned, blocking the CI pipeline.

--report [path]

Write a JSON report artifact to disk after the alignment check. Defaults to upstream-report.json in the current directory.

upstream validate --report              # writes upstream-report.json
upstream validate --report ci-report.json  # writes to custom path

The artifact shape:

{
  "branch": "feat/user-auth",
  "verdict": "aligned",
  "engine": "llm",
  "coverage": { "prdPath": "docs/upstream/PRD-user-auth.md", "adrPath": null },
  "findings": [{ "dimension": "problem_statement", "status": "pass", "detail": null }],
  "snapshot": { "timestamp": "2026-06-30T12:00:00Z", "upstream_version": "0.3.1" },
  "trend": { "vsLast": null }
}

trend.vsLast is populated automatically when a previous snapshot exists (see upstream snapshot).

PR comments: when GITHUB_TOKEN and GITHUB_REPOSITORY are set (standard in GitHub Actions), upstream posts the verdict as a PR comment automatically. Set align.post_pr_comment: false to disable.

Link mode: when docs_storage: link, upstream validate fetches the full document from the provider (Google Docs or Confluence) before analysis. If the provider is unavailable or unauthenticated, it falls back to stub content with a warning.


upstream report

upstream report summary [--input <path>]

Reads a report artifact and prints a Markdown summary to stdout. Reads upstream-report.json by default; use --input to specify a different path.

upstream report summary                          # reads upstream-report.json
upstream report summary --input ci-report.json   # reads custom path
upstream report summary >> $GITHUB_STEP_SUMMARY  # pipe to GitHub Actions job summary

GitHub Actions integration

- name: Run alignment check
  run: upstream validate --report upstream-report.json --format json
  env:
    ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }}
    GITHUB_REPOSITORY: ${{ github.repository }}

- name: Upload report
  if: always()
  uses: actions/upload-artifact@v4
  with:
    name: upstream-report
    path: upstream-report.json

- name: Write job summary
  if: always()
  run: upstream report summary --input upstream-report.json >> $GITHUB_STEP_SUMMARY

Coverage stats — upstream stats

upstream stats shows a coverage summary across all local feature branches: how many have PRDs, ADRs, skips, or no docs at all.

upstream stats               # human-readable table
upstream stats --format json # machine-readable
upstream stats --trend       # compare against last snapshot

--adoption — team adoption analytics

--adoption adds a per-author breakdown: which branches each author owns, their PRD/ADR coverage percentages, how many skips they've logged, and an overall adoption score.

upstream stats --adoption
upstream stats --adoption --since 2026-04-01   # scope to a specific date window
upstream stats --adoption --no-authors          # skip log + score only, no per-author table
upstream stats --adoption --format json         # machine-readable for CI/dashboards

Example output:

upstream adoption report
========================
Authors (last 90 days):
  alice    branches:  5   PRD:  5 (100%)   ADR:  3 ( 60%)   skips: 0
  bob      branches:  4   PRD:  2 ( 50%)   ADR:  1 ( 25%)   skips: 2
  carol    branches:  3   PRD:  3 (100%)   ADR:  2 ( 67%)   skips: 0

Skip log (last 90 days):  2 skips
  bob    feat/quick-fix   2026-06-10   "hotfix, no PRD needed"
  bob    feat/typo        2026-06-15   "one-liner, low risk"

Adoption score: 83%  (PRD coverage weighted by branch author)

Flags:

  • --since <date> — scope the report to branches and skips with activity after the given date (YYYY-MM-DD); defaults to 90 days ago
  • --no-authors — suppress per-author table; shows only the skip log and adoption score
  • --format json — emit the raw { authors, skips, adoptionScore, since } object for CI or dashboards

All data is derived from local git history and SKIPS.md — no network calls.

upstream snapshot

Save the current stats as a local snapshot for trend comparison:

upstream snapshot         # save snapshot
upstream snapshot --ci    # exit 1 if coverage regressed vs last snapshot
upstream stats --trend    # compare current stats against the saved snapshot

Skipping

If a PRD or ADR genuinely isn't needed, developers can skip with a justification. The skip is logged to <docs_path>/SKIPS.md and a PR snippet is generated for transparency:

> ⚠️ upstream skip: PRD not created for `feat/quick-fix`.
> Reason: two-line CSS change, no product decisions involved.
> Logged in: <docs_path>/SKIPS.md

What gets committed to your repo

This applies to the upstream init (team) setup. With claude plugin install, skills and the hook live in the Claude Code plugin directory and are not committed to your repo — only upstream.config.yaml and your docs need to be tracked.

.claude/
  hooks/
    upstream-check.sh           # UserPromptSubmit hook
  plugins/upstream/
    skills/
      upstream-guard.md         # orchestration skill
      upstream-prd.md           # PRD creation skill
      upstream-adr.md           # ADR creation skill
      upstream-align.md         # alignment check skill (used by upstream validate)
    templates/
      PRD.md                    # PRD template
      ADR.md                    # ADR template
      PRD-link.md               # stub template for link mode
      ADR-link.md               # stub template for link mode
  settings.json                 # MCP server registration (upstream mcp)
.github/
  workflows/
    upstream-align.yml          # runs upstream validate on every PR
upstream.config.yaml            # org configuration
.env.example                    # env var placeholders (shows required secrets, safe to commit)
.gitignore                      # updated by upstream init to exclude .env/.env.local/.env.test
.github/
  CODEOWNERS                    # guardian entry (if configured)
<docs_path>/                    # your PRDs, ADRs, and skip log
  .gitkeep                      # created by upstream init to track the empty dir

Contributing

See CONTRIBUTING.md.


License

MIT