← Recipes

阅读中文版本

Package a Node CLI with a bin Entry

Publish a Node CLI with a bin mapping and executable shebang so it installs as a global command with the right name.

~25 minclinodejspackaging

Task

Configure package.json bin and a shebang so the CLI installs as a command.

When to use this

Installing the package globally does not produce a runnable command because the bin entry is missing.

Prerequisites

  • A Node.js CLI project
  • npm or pnpm
  • A test install environment

Steps

1. Add a shebang and a bin mapping.

#!/usr/bin/env node
// src/cli.js
console.log('tool runs');

Expected output: The file is directly executable on Unix when marked executable.

2. Declare the bin name in package.json.

{
  "name": "tool-cli",
  "bin": { "tool": "./src/cli.js" },
  "files": ["src"]
}

Expected output: npm link or install creates a tool command that runs the script.

Troubleshooting

Problem

Permission denied on Unix

Solution

Commit the executable bit or document a chmod in the packaging step.

Problem

Windows runs it differently

Solution

Rely on npm shims generated from bin instead of assuming a shell shebang.

Limitations

  • Global installs need a writable prefix or a manager like pnpm.
  • Shebang portability varies on Windows.
  • Does not handle updates or versions.

What this recipe does

Configure package.json bin and a shebang so the CLI installs as a command.

Installing the package globally does not produce a runnable command because the bin entry is missing.

Prerequisites

  • A Node.js CLI project
  • npm or pnpm
  • A test install environment

Procedure

  1. Add a shebang and a bin mapping.
#!/usr/bin/env node
// src/cli.js
console.log('tool runs');

Expected result: The file is directly executable on Unix when marked executable.

  1. Declare the bin name in package.json.
{
  "name": "tool-cli",
  "bin": { "tool": "./src/cli.js" },
  "files": ["src"]
}

Expected result: npm link or install creates a tool command that runs the script.

How to confirm it worked

Run the commands above and confirm every expected result in order. If a step does not produce the stated output, use the troubleshooting notes before continuing. A passing run shows installing the package exposes a command whose name matches bin and runs the entry point.

Troubleshooting

Permission denied on Unix — Commit the executable bit or document a chmod in the packaging step.

Windows runs it differently — Rely on npm shims generated from bin instead of assuming a shell shebang.

Limitations

  • Global installs need a writable prefix or a manager like pnpm.
  • Shebang portability varies on Windows.
  • Does not handle updates or versions.