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

@nytka/cli

v0.4.5

Published

The nytka CLI: lint a project against the format, report what is installed and what it is allowed to do, and keep @nytka packages current.

Downloads

256

Readme

@nytka/cli

Lint a nytka project, see what is installed and what it is allowed to do, and keep the @nytka/* packages current.

npm i -g @nytka/cli

nytka add gtm
nytka check
nytka info
nytka upgrade

Nothing needs installing at all if you would rather not — npx @nytka/cli <command> works the same way. Add it as a dev dependency (npm i -D @nytka/cli) to run it in CI.

One caveat on the global install, if you use nvm. Global packages belong to a single node version. Install under v22, switch to v20, and nytka is not there — which reads as a broken install and is not one. nvm reinstall-packages v22 brings them across, or use npx and stop thinking about it.


add

Install a connector and document what it needs.

nytka add gtm                 # short name
nytka add plugin-ads          # or the prefixed form — both resolve
nytka add @acme/connector     # or any package at all
nytka add gsc --yes           # skip the prompt
nytka add gsc --dev           # as a devDependency
  resolving @nytka/plugin-ads ... 0.1.0

  ./package.json     + "@nytka/plugin-ads": "^0.1.0"
  .env.example        (new file)
                     + # free, from your manager account's API Center
                     + # Shape: aBcDeFgHiJkLmNoPqRsT
                     + GOOGLE_ADS_DEVELOPER_TOKEN=
                     ...
  Continue? (Y/n)

It writes .env.example, never .env. The variable name is documentation and belongs in the committed file. The value is yours, and this command has no business near it. So add makes a capability available and you turn it on by filling the value in.

The consequence worth having: add cannot destroy a credential. There is no code path from it to your .env. A test plants a secret there and asserts it is neither read nor modified.

There is no list of plugins in this CLI. A package opts in by carrying nytka-plugin in its package.json keywords and describing what it needs in a nytka block — so npm's own search is the catalogue, and a third-party connector works identically to a first-party one. A test greps the source and fails if a plugin name is ever hardcoded.

Other things it does, each with a test:

  • Running it twice is a no-op, keyed on the variable name rather than the text written last time — so a reworded note or a manual edit doesn't produce a second copy.
  • Byte-clean. Your .env.example is appended to, never parsed and rewritten, so every comment, blank line and hand edit survives exactly.
  • In a project with no project.yaml it installs and documents anyway, and scaffolds nothing. A connector is useful on its own; adopting the format is a separate, deliberate act.
  • A package declaring no nytka block still installs, and says it declared nothing — a consumer must not reject a package over a field it doesn't recognise.
  • A failed npm install leaves everything as it was. The install runs first; the .env.example write only happens after it succeeds.

Without a TTY it refuses rather than hanging on a prompt nobody can answer — pass --yes.

check

Lints the project against the nytka format: required files, frontmatter, expiry dates, decision-graph consistency, dangling links, dataset registry sanity.

npx @nytka/cli check                  # the current project
npx @nytka/cli check ./some/project
npx @nytka/cli check --json           # for CI, or for an agent
npx @nytka/cli check --today=2026-07-29

Exit codes: 0 clean or warnings only, 1 at least one error, 2 the directory does not exist.

Warnings never fail the command. A lint that exits non-zero for advice cannot go in CI, and one that is not in CI does not run.

This is the same lint as tools/nytka-lint.mjs in the framework repo — same source, same output, byte for byte, and there is a test that proves it. See decision 0009 for why it exists in two places and which one you are allowed to edit.

info

What is installed, and what it can actually do.

  Node                      v22.17.1
  Platform                  darwin (arm64)
  Project                   my-site

  Plugins
    @nytka/plugin-gsc           0.3.2             ready
    @nytka/plugin-gtm           0.1.1             partial
      GOOGLE_SERVICE_ACCOUNT_KEY_WRITE  unset, optional — enables the mutating commands
    @nytka/plugin-sanity        0.3.0 → 0.3.1     ready

  1 package(s) behind the published version.
  npm update will NOT move these — see:  npx @nytka/cli upgrade

  Warnings
    GSC_SERVICE_ACCOUNT_KEY is set but GOOGLE_SERVICE_ACCOUNT_KEY takes precedence

A credential value is never read, printed or returned — only whether it is set. There is a test that asserts a token planted in .env appears nowhere in the output, the JSON, or anything the function returns. Credential paths count as values too.

Three states:

| | | |---|---| | ready | every declared variable is present | | partial | an optional variable is unset, so some commands are unavailable. Not a fault | | blocked | a required variable is missing. This is the only state that exits 1 |

partial is deliberate. A nytka plugin does what its filled-in variables let it do — there are no feature flags and no config keys, so an unset optional variable is a capability that is off, not a broken install.

Add --latest to also ask npm what the current versions are. Without it, info makes no network request at all.

upgrade

npx @nytka/cli upgrade            # show what would change
npx @nytka/cli upgrade --write    # apply it
npm install

Why this is not npm update. A caret range means something different below 1.0.0. ^1.2.0 allows anything under 2.0.0, but ^0.1.0 allows only >=0.1.0 <0.2.0 — while the major is 0, npm treats the second number as the breaking one.

So a project pinned at ^0.1.0 never sees 0.3.0. npm update reports success, npm outdated reports nothing wrong — because by the range's own terms nothing is wrong — and the project sits two minor versions behind indefinitely. Every @nytka package is 0.x, so every project has this.

upgrade asks the registry what is actually published, compares it against what your range permits, and rewrites the range. It marks the entries npm update could never have reached.

It writes nothing without --write, and when it does write it changes only the version strings — your indentation, blank lines and key order survive byte for byte.


Importing it

import { lintProject, projectInfo, planUpgrade } from '@nytka/cli'

const { counts, findings } = lintProject('./my-project', { today: '2026-07-29' })

Every export is pure: reads the filesystem, writes nothing, prints nothing, never exits. upgradeProject is the one exception and only writes when passed { write: true }.

Declaring a plugin

Any package can be a nytka plugin. There is no central list and nothing to register — npm's own search is the catalogue.

{
  "keywords": ["nytka-plugin"],
  "nytka": {
    "env": [
      { "name": "ACME_API_KEY" },
      { "name": "ACME_WRITE_KEY", "required": false, "enables": "the mutating commands" },
      { "name": "ACME_REGION", "aliases": ["ACME_ZONE"] }
    ],
    "retired": [
      { "name": "ACME_TOKEN", "replacedBy": "ACME_API_KEY" }
    ]
  }
}

Three relationships, which are not interchangeable:

  • aliases — an older name this plugin still reads. Satisfies the requirement, and warns, because a fallback nobody remembers is how a vocabulary drifts.
  • alternatives — an equally valid other name. Satisfies it and warns about nothing.
  • retired — a name the plugin no longer reads. Satisfies nothing, and is reported loudly: a project with a retired variable in .env looks configured to its owner and is not.

A package with no nytka block is reported as installed and declaring nothing. That is not an error — a consumer must not reject something over a field it does not recognise.

What this does not do

No telemetry. Nothing is sent anywhere. The only network requests are upgrade and info --latest, both to the npm registry, both stated in the command. There is a test that fails if any other command opens a socket.

Licence

MIT