A bin field pointing to ./dist/cli.js when no dist/ directory exists is a package that installs successfully and then fails on first invocation with env: node: No such file or directory or Cannot find module. Pointing bin at a .ts file is worse — npx mytool dies with a syntax error on the first import statement. Users uninstall immediately and leave a one-star review. This is the single most common CLI publish-to-npm failure mode.
Critical because a broken entry point makes the CLI uninstallable or non-executable on every user's first try.
Set bin in package.json to the compiled JS file, wire a prepublishOnly build script, and include the output directory in files. Verify dist/cli.js exists after npm run build:
{
"bin": { "mytool": "./dist/cli.js" },
"files": ["dist"],
"scripts": {
"build": "tsc",
"prepublishOnly": "npm run build"
}
}
ID: cli-quality.config-distribution.bin-field
Severity: critical
What to look for: Count all package.json files. For each, check the distribution entry point configuration for the detected language:
bin field in package.json — must point to a file that exists. If "bin": "./dist/cli.js", verify dist/cli.js exists or is produced by the build step. If using TypeScript, the bin field must point to the compiled JS, not the .ts source.[project.scripts] in pyproject.toml, or console_scripts in setup.cfg/setup.py. Must point to a valid module:function path.package main with func main() in the expected location (cmd/toolname/main.go or root main.go).[[bin]] in Cargo.toml or default src/main.rs. name field must be set if not using default.Pass criteria: The entry point configuration exists, points to a valid file/function, and the file is either present in source or produced by the build step listed in package.json scripts — at least 1 bin field entry must be defined in the root package.json. Report: "X package.json files found, Y have bin field configured."
Fail criteria: No entry point configuration, or the configured path points to a nonexistent file, or bin points to a .ts file (will fail on execution), or the entry point module/function doesn't exist.
Skip (N/A) when: All checks skip when no CLI entry point is detected.
Detail on fail: "package.json bin field points to './dist/cli.js' but no dist/ directory exists and no build script is configured" or "bin field points to 'src/cli.ts' — TypeScript files cannot be executed directly as CLI entry points"
Remediation: The bin field is what makes your CLI installable and executable:
// package.json — correct bin field
{
"name": "my-cli-tool",
"bin": {
"mytool": "./dist/cli.js"
},
"scripts": {
"build": "tsc",
"prepublishOnly": "npm run build"
},
"files": ["dist"]
}
# pyproject.toml — correct script entry point
[project.scripts]
mytool = "my_tool.cli:main"
# Cargo.toml — binary target
[[bin]]
name = "mytool"
path = "src/main.rs"