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

producs

v3.0.1

Published

Professional Documentation Shell DSL — a modular, pipeable terminal scripting language

Readme

ProDucs v3.0

Professional Documentation Shell DSL — a modular, pipeable terminal scripting language for advanced CLI documentation and automation.

Install

npm install          # install deps
npm link             # optional: install `producs` globally

Run

node cli.js script.pd          # run a .pd file
node cli.js --demo             # built-in feature demo
node cli.js --ast script.pd    # dump AST as JSON
node cli.js --help             # full usage

Or if installed globally:

producs script.pd

Syntax

// line comment

#$CommandName['arg1','arg2']       inline command
#$Cmd1 | #$Cmd2 | #$Cmd3          pipe chain (output of each → input of next)
${varname}                         variable interpolation

#$BlockName['arg']                 open a block
  ...children...
#$End_BlockName                    close the block

Branching

ProDucs replaces if/else with an explicit check → branch model:

  1. A Check_* command runs and sets failed=0 (pass) or failed=1 (fail)
  2. #$Branch runs its children only when failed=0
  3. #$BranchElse runs its children only when failed=1
#$Set['score','92']
#$Check_gte['score','90']
#$Branch
  #$Color['green','A grade!']
#$End_Branch
#$BranchElse
  #$Color['yellow','Below A grade']
#$End_BranchElse

All Check Commands

String checks (operate on VALUE)

| Command | Description | |---|---| | Check_eq['expected'] | Pass if VALUE === expected | | Check_neq['expected'] | Pass if VALUE !== expected | | Check_contains['needle'] | Pass if VALUE contains needle | | Check_not_contains['needle'] | Pass if VALUE does NOT contain needle | | Check_starts['prefix'] | Pass if VALUE starts with prefix | | Check_ends['suffix'] | Pass if VALUE ends with suffix | | Check_matches['regex','flags'] | Pass if VALUE matches regex | | Check_empty | Pass if VALUE is empty string | | Check_nonempty | Pass if VALUE is not empty |

Numeric checks

Two forms: Check_gt['varname','number'] or Check_gt['number'] (uses VALUE as number).

| Command | Description | |---|---| | Check_gt['var','n'] | Pass if var > n | | Check_gte['var','n'] | Pass if var >= n | | Check_lt['var','n'] | Pass if var < n | | Check_lte['var','n'] | Pass if var <= n | | Check_num_eq['var','n'] | Pass if var == n (numeric) | | Check_num_neq['var','n'] | Pass if var != n (numeric) | | Check_between['var','lo','hi'] | Pass if lo <= var <= hi |

Variable comparison

| Command | Description | |---|---| | Check_var_eq['a','b'] | Pass if var a === var b | | Check_var_neq['a','b'] | Pass if var a !== var b |

Result checks

| Command | Description | |---|---| | Check_failed | Pass if previous result was failed | | Check_passed | Pass if previous result was passed | | Check_failed_error['msg'] | Throw error if previous result was failed | | Check_passed_error['msg'] | Throw error if previous result passed |


Command Reference

I/O

| Command | Description | |---|---| | > ['prompt'] | Prompt user for input | | Print['text'] | Print to stdout | | Warn['text'] | Print yellow warning to stderr | | Error_print['text'] | Print red error to stderr | | Pause['msg'] | Block until ENTER | | Confirm['msg','default'] | y/n prompt | | Select['label','opt1',...] | Numbered menu |

Variables

| Command | Description | |---|---| | Set['name','value'] | Set a variable | | Unset['name'] | Delete a variable | | Export['name','value'] | Set variable and push to process.env | | Env_get['KEY'] | Read process.env.KEY → VALUE | | Env_set['KEY'] | Write VALUE → process.env.KEY |

Shell

| Command | Description | |---|---| | Shell_run | Run VALUE/text child as shell command (inherit stdio) | | Shell_capture | Run command, capture stdout → VALUE |

String ops

Trim Upper Lower Len Replace['pat','rep','flags'] Slice['start','end'] Split['sep'] Join['sep'] Default['fallback'] Concat['suffix',...]

Math

Int Float Abs Round Floor Ceil Math['expr'] Inc['var','step'] Dec['var','step']

Data

Hash['algo'] Timestamp['iso'|'unix'|'ms'] Json_get['a.b.c'] Json_set['a.b','val']

File I/O

Read_file['path'] Write_file['path'] Append_file['path']

Control

Goto['label'] Label['name'] Exit['code'] Assert['JS expr','msg'] Require_env['VAR'] Require_cmd['cmd']

Timing

Wait['ms'] — blocking sleep in milliseconds

Blocks

| Block | Description | |---|---| | #$> ['prompt'] | Prompt block | | #$Branch | Run if last check passed (failed=0) | | #$BranchElse | Run if last check failed (failed=1) | | #$Repeat['N'] | Loop N times (_i = index) | | #$ForEach['var','a','b',...] | Iterate over items | | #$Try + #$Catch | Error handling (_error set in Catch) | | #$Section['title'] | Formatted section heading | | #$Step['desc'] | Auto-numbered step | | #$Group['label'] | Logical grouping with bracket lines | | #$Table + #$Row[...] | ASCII table |

Visual

HR['char'] Header['title'] Color['name','text'] Progress['pct','width','label'] Spinner['msg'] Status['label']

Runtime

Debug['on'|'off'] Strict['on'|'off'] Color_off Log['label'] Dump_log Help Version


Example Script

// install.pd — sample deployment doc script

#$Header['Deploy Checklist']
#$Require_cmd['git']
#$Require_cmd['node']

#$Section['Pre-flight']
  #$Shell_capture['git branch --show-current'] | #$Set['branch']
  #$Print['Branch: ${branch}']
  #$Set['branch','${branch}'] | #$Check_eq['main']
  #$BranchElse
    #$Warn['Not on main branch!']
  #$End_BranchElse
#$End_Section

#$Section['Build']
  #$Step['Install dependencies']
    #$Shell_run
    npm ci
    #$End_Shell_run
  #$End_Step
#$End_Section

#$Status['Deploy complete']

Programmatic API

const { ProDucs } = require("producs");

const prod = new ProDucs({ debug: false, strict: false, noColor: false });

// Register custom command
prod.register("Shout", (node, input) => {
  const msg = input.VALUE.toUpperCase() + "!!!";
  process.stdout.write(msg + "\n");
  return { VALUE: msg, failed: 0 };
}, { doc: "Uppercase and add exclamation marks" });

// Pre-set variables
prod.set("env", "production");

// Run a script
prod.run(`
  #$Set['greeting','hello']
  #$Set['greeting','${greeting}'] | #$Shout
`);

// Read back vars
console.log(prod.vars()); // { greeting: "HELLO!!!", env: "production" }