Skip to content

ycmds/npmgrep

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

6 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ” npmgrep

LSK.js NPM version NPM downloads Have TypeScript types Package size License Write us in Telegram

npmgrep logo

πŸ” Find available npm package names in CLI or JS/TS API πŸ”

🧬 Pattern DSL β€” expand shell-safe %a/%w classes, ranges, literals and optionals into every name combination
⚑ Parallel checks β€” query the npm registry with configurable concurrency (default 100)
πŸ—‚οΈ Sorted output β€” taken, free and error names written to separate files
🧩 Predefined sets β€” vowel, consonant, alpha, alnum, digit, hex built in
πŸ”Œ Library + CLI β€” run the npmgrep binary or import the generator/checker functions
🎯 Dry-run generate β€” print candidate names without touching the network
πŸ“¦ Typed ESM build β€” ships ESM + .d.ts to lib/ via tsdown
πŸ§ͺ Tested generator β€” the DSL parser is covered by bun:test


Installation

Install the CLI globally:

npm install -g npmgrep
# or
bun add -g npmgrep
# or
pnpm add -g npmgrep
# or
yarn global add npmgrep

Then run npmgrep ... anywhere. The published binary is built to ESM and runs on Node.js or Bun.

From source

The project uses Bun for development:

bun install
bun run start "<pattern>"     # run the CLI from source (src/cli.ts)
bun run build                 # build to lib/ (ESM + .d.ts)

Usage

The CLI exposes two commands. check is the default, so a bare pattern runs a check.

npmgrep <command> [options]

Commands:
  npmgrep check <pattern>      Generate names and check availability on the npm registry  [default]
  npmgrep generate <pattern>   Generate names and print them (no network requests)

check β€” generate and check availability

npmgrep %a%a%a                       # check all 3-letter names (no quotes needed)
npmgrep check example%w              # explicit command form
npmgrep react-%a%a --name react2     # custom output-file name
npmgrep %w%w --out results --quiet   # write to results/, no per-name logs
npmgrep %a%a%a -c 50                 # lower the request concurrency

The %-syntax is shell-safe: it has no [ ] { } ? *, so zsh/bash won't try to glob-expand it and you never need quotes. (npm[alnum] fails in zsh with no matches found β€” the shell eats the brackets before npmgrep ever runs.)

Option Alias Default Description
--name -n derived from pattern Base name for the output files
--concurrency -c 100 Number of parallel requests to the npm registry
--out -o . Directory where result files are written
--quiet -q false Suppress per-name logging
--retries -r 3 Retries for transient network errors (e.g. ENOTFOUND, ECONNRESET, 429, 5xx)
--retry-delay 500 Base delay in ms between retries (grows exponentially)

At the end it prints a summary, e.g.:

β„Ή Done "example-w": 36 checked β€” 30 free, 6 taken, 0 errors β†’ ./

generate β€” print names only (no network)

npmgrep generate %v%c            # print all combinations
npmgrep generate %a%a --limit 20 # print only the first 20
Option Alias Description
--limit -l Limit the number of printed names

Run npmgrep --help (or npmgrep <command> --help) for the full reference.

Output file names

<name> comes from --name, otherwise it is derived from the pattern (every non-alphanumeric char becomes -). For example, the pattern example%w yields <name> = example-w, i.e.:

exists-example-w.txt
free-example-w.txt
errors-example-w.txt

Files are appended to (appendFile), not overwritten β€” re-running adds lines to the end.

Name generator DSL

Shell-safe syntax (recommended)

Classes start with %, literals are just plain text. No [ ] { } ? *, so it works in zsh/bash without quotes.

Construct Meaning Example
plain text literal react- β†’ react-
%a one letter a-z %a β†’ a, b, … z
%d one digit 0-9 %d β†’ 0, … 9
%w letter or digit (alnum / word) npm%w β†’ npma, … npm9
%v vowel aeiouy %v β†’ a, e, i, …
%c consonant %c β†’ b, c, d, …
%h hex char 0-9a-f %h β†’ 0, … f
%:set: one char from a custom set / range %:a-c: β†’ a, b, c
%A %D … UPPERCASE code = optional (0 or 1) %a%D β†’ a, a0, … a9
%% a literal % a%%b β†’ a%b

Example patterns (paste as-is, no quoting):

%a%a%a            # all 3-letter combinations
%w%w              # 2 chars: letters and digits
react-%a%a        # react-aa, react-ab, …
%a-kit            # a-kit, b-kit, …
@scope/%a-ui      # @scope/a-ui, @scope/b-ui, …
%v%c%v            # vowel-consonant-vowel
%ash              # ash, bsh, …, zsh   (%a + literal "sh")
%:a-z:sh          # same, via an explicit range

⚠️ The number of combinations grows multiplicatively. For example, %a%a%a is 26Β³ β‰ˆ 17,576 names, and each one is a separate HTTP request to npm.

Legacy bracket syntax

Still supported, but the brackets are special in zsh/bash, so you must quote these:

Construct Meaning Example
{text} literal text {react-} β†’ react-
[abc] one character from the set [abc] β†’ a, b, c
[a-z] character range [a-c] β†’ a, b, c
[0-9] digit range [0-2] β†’ 0, 1, 2
? makes the previous token optional [ab][cd]? β†’ a, ac, ad…

Predefined sets work in both syntaxes: [vowel], [consonant], [alpha] (26 letters), [digit], [alnum] (36), [hex].


How it works

pattern (positional arg)
      β”‚
      β–Ό
tools/generator.ts ──► list of names ──► utils/checker.ts ──► npm registry
                                              β”‚
            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
            β–Ό                                 β–Ό                                    β–Ό
   exists-<name>.txt                  free-<name>.txt                     errors-<name>.txt
   (taken + version)                  (available, 404)                    (other errors)

Each name becomes a request to https://registry.npmjs.org/<name>:

  • 200 β†’ package exists; the name is written to exists-<name>.txt along with dist-tags.latest;
  • 404 β†’ name is available; written to free-<name>.txt;
  • any other status / network error β†’ written to errors-<name>.txt.

Checking runs with a concurrency of 100 requests by default (an internal worker-pool), tunable with --concurrency.

Programmatic API

The generator and checker can be used as a library:

import {
  generatePackageNames,
  generateWithName,
  generateNLetters,
  generateWithSuffix,
  generateWithPrefix,
  checkPackages,
  type CheckOptions,
  type CheckResult,
} from "npmgrep";

generatePackageNames("[ab][cd]");   // ["ac", "ad", "bc", "bd"]
generateWithName("[ab]", "my-set"); // { name: "my-set", packages: ["a", "b"] }
generateNLetters(2);                 // all 2-letter combinations
generateWithSuffix("sh", 1);         // ash, bsh, …, zsh
generateWithPrefix("react-", 2);     // react-aa, …, react-zz

// generate + check against the registry; returns a CheckResult summary
await checkPackages("{react-}[alpha]", { outDir: "results", quiet: true });
Function Description
generatePackageNames(pattern) expands a pattern into an array of unique names
generateWithName(pattern, name?) same, plus a name for naming the output files
generateNLetters(n) all combinations of n letters
generateWithSuffix(suffix, letters) letters letters + suffix
generateWithPrefix(prefix, letters) prefix + letters letters
checkPackages(pattern, options?) generate, query the registry, write the result files

checkPackages accepts CheckOptions (name, concurrency, outDir, quiet, retries, retryDelay) and resolves to a CheckResult (name, outDir, total, free, exists, errors). Transient network errors (DNS failures like ENOTFOUND, dropped connections, timeouts, plus HTTP 429/5xx) are retried with exponential backoff; 404 (name is free) is never retried.

Invalid patterns throw: an unclosed [ / { / %:, a dangling %, an unknown %-code, or a ? with no preceding token.

Tests

Generator tests are written with bun:test:

bun run test:unit   # bun test (fast)
bun run test        # full check: lint + types + unit + size

Project structure

src/
β”œβ”€β”€ index.ts            # library entry β€” re-exports generator + checker
β”œβ”€β”€ cli.ts              # CLI entry (yargs) β€” built to lib/cli.js, the `npmgrep` bin
β”œβ”€β”€ tools/
β”‚   └── generator.ts    # pure DSL parser + name-combination generator (no I/O)
└── utils/
    β”œβ”€β”€ checker.ts      # checkPackages(): npm registry queries + result files
    └── concurrent.ts   # mapWithConcurrency(): worker-pool with a concurrency cap
tests/
└── generator.test.ts   # generator tests (bun:test)

The build emits to lib/ (gitignored); bin, main and exports point at the built lib/*.js. Run output (exists-*/free-*/errors-*.txt) and scratch dirs (results/, packages/) are gitignored.

Stack

  • TypeScript (strict) + tsdown β€” ESM build to lib/ with .d.ts
  • Bun + bun:test β€” runtime and test runner
  • Biome β€” lint + format
  • yargs β€” CLI argument parsing
  • axios β€” HTTP requests to the npm registry
  • @lsk4/log β€” logging
  • @lskjs/algos β€” uniq helper

License

Licensed under the MIT license β€” see LICENSE.

About

Find available npm package names in CLI

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors