{"id":10572,"library":"bin-links","title":"bin-links: Package Binary Linker","description":"bin-links is a fundamental JavaScript library within the npm ecosystem, responsible for linking package binaries and man pages. It handles the creation of symbolic links or shims for executable scripts defined in a package's `bin` field, directing them to appropriate locations like `node_modules/.bin` for local installs or global binary directories for global packages. It also manages linking man pages from the `man` field. The current stable version is v6.0.0, released in late 2025. This package generally follows the Node.js release cadence for its engine support, aligning with npm's own requirements. Its key differentiator is being a core, low-level utility maintained by the npm team, providing robust and cross-platform binary linking functionality crucial for package execution and discoverability in Node.js environments.","status":"active","version":"6.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/npm/bin-links","tags":["javascript","npm","link","bins"],"install":[{"cmd":"npm install bin-links","lang":"bash","label":"npm"},{"cmd":"yarn add bin-links","lang":"bash","label":"yarn"},{"cmd":"pnpm add bin-links","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Used for reading command shims, essential for cross-platform binary linking.","package":"read-cmd-shim","optional":false},{"reason":"Ensures atomicity when writing files, preventing data corruption during link operations.","package":"write-file-atomic","optional":false},{"reason":"Normalizes and validates package `bin` field entries for consistent linking.","package":"npm-normalize-package-bin","optional":false},{"reason":"Creates Windows command shims for package binaries, ensuring executability.","package":"cmd-shim","optional":false},{"reason":"Provides consistent logging capabilities for process events within the npm ecosystem.","package":"proc-log","optional":false}],"imports":[{"note":"While primarily a CommonJS module, it's designed to be imported as a default export in ES Modules. Using 'require' in an ESM context will throw a 'require is not defined' error.","wrong":"const binLinks = require('bin-links');","symbol":"binLinks","correct":"import binLinks from 'bin-links';"},{"note":"'getPaths' is a method directly attached to the default 'binLinks' function/object, not a separate named export. Attempting a named import will result in 'getPaths is not exported from bin-links'.","wrong":"import { getPaths } from 'bin-links';","symbol":"binLinks.getPaths","correct":"import binLinks from 'bin-links';\nconst paths = await binLinks.getPaths({ /* ... */ });"},{"note":"'checkBins' is a method directly attached to the default 'binLinks' function/object, not a separate named export. Attempting a named import will result in 'checkBins is not exported from bin-links'.","wrong":"import { checkBins } from 'bin-links';","symbol":"binLinks.checkBins","correct":"import binLinks from 'bin-links';\nawait binLinks.checkBins({ /* ... */ });"}],"quickstart":{"code":"const binLinks = require('bin-links');\nconst path = require('path');\nconst fs = require('fs/promises');\n\n// Simulate a package.json read for demonstration\nasync function readPackageJson(packagePath) {\n  try {\n    const pkgContent = await fs.readFile(packagePath, 'utf8');\n    return JSON.parse(pkgContent);\n  } catch (err) {\n    // Create a dummy package.json content if file not found\n    return {\n      name: 'some-package',\n      version: '1.0.0',\n      bin: {\n        'my-cli': 'cli.js'\n      },\n      man: [\n        'man/my-cli.1'\n      ]\n    };\n  }\n}\n\nasync function runBinLinkingExample() {\n  // Define paths relative to the current script execution\n  const tempDir = path.join(__dirname, 'temp-link-test');\n  const packageDir = path.join(tempDir, 'node_modules', 'some-package');\n  const binDir = path.join(tempDir, 'node_modules', '.bin');\n  const manDir = path.join(tempDir, 'share', 'man');\n\n  // Ensure necessary directories exist\n  await fs.mkdir(packageDir, { recursive: true });\n  await fs.mkdir(binDir, { recursive: true });\n  await fs.mkdir(path.join(packageDir, 'man'), { recursive: true });\n  await fs.mkdir(manDir, { recursive: true });\n\n  // Create dummy executable and man page files\n  await fs.writeFile(path.join(packageDir, 'cli.js'), '#!/usr/bin/env node\\nconsole.log(\"Hello from my-cli!\");', { mode: 0o755 });\n  await fs.writeFile(path.join(packageDir, 'man', 'my-cli.1'), '.TH \"MY-CLI\" \"1\" \"2025-01-01\" \"1.0.0\" \"My CLI Manual\"\\n.SH NAME\\nmy-cli - A sample command-line interface', { recursive: true });\n\n  const pkg = await readPackageJson(path.join(packageDir, 'package.json'));\n\n  console.log('Attempting to link binaries and man pages for ' + pkg.name + '...');\n  try {\n    await binLinks({\n      path: packageDir,\n      pkg: pkg,\n      global: false, // Set to true for global install simulation\n      top: true,     // This is the top-level package being linked\n      force: true    // Overwrite existing links if any\n    });\n    console.log('Binaries and man pages linked successfully!');\n\n    // Demonstrate checking for conflicts (should pass with force: true)\n    await binLinks.checkBins({\n      path: packageDir,\n      pkg: pkg,\n      global: false,\n      top: true,\n      force: true\n    });\n    console.log('No conflicting bins found (or forced overwrite).');\n\n    // List potential link paths (does not touch filesystem)\n    const potentialPaths = binLinks.getPaths({\n      path: packageDir,\n      pkg: pkg,\n      global: false,\n      top: true\n    });\n    console.log('Potential link paths:', potentialPaths);\n\n  } catch (error) {\n    console.error('Error during binary linking example:', error.message);\n  } finally {\n    // Clean up temporary directory after example\n    await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});\n    console.log('Cleanup complete.');\n  }\n}\n\nrunBinLinkingExample();","lang":"javascript","description":"This quickstart demonstrates how to use `bin-links` to create symbolic links for a package's binaries and man pages, simulating a local package installation. It shows the core `binLinks` function, along with `getPaths` and `checkBins` utility methods. The example includes directory setup and cleanup."},"warnings":[{"fix":"Upgrade your Node.js runtime to a compatible version (e.g., Node.js 20.17.0+ or 22.9.0+). Use nvm or your system's package manager to manage Node.js versions.","message":"Node.js engine requirements have been progressively tightened. Version 6.0.0 requires Node.js `^20.17.0 || >=22.9.0`. Ensure your Node.js environment meets these specifications to avoid compatibility issues.","severity":"breaking","affected_versions":">=6.0.0"},{"fix":"Upgrade your Node.js runtime to version 18.17.0+ or 20.5.0+.","message":"With the release of v5.0.0, the Node.js engine requirement was updated to `^18.17.0 || >=20.5.0`. Running on older Node.js versions will lead to failures.","severity":"breaking","affected_versions":">=5.0.0 <6.0.0"},{"fix":"Review your installation scripts and environment. If file ownership changes are critical for your setup (e.g., for specific user permissions), implement explicit `chown` or similar commands after `binLinks` execution, or ensure appropriate permissions are set beforehand.","message":"Version 4.0.0 introduced a significant change where `bin-links` no longer automatically attempts to change file ownership. Operations that previously relied on this automatic ownership alteration may now require manual handling of file permissions.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Always invoke the binary by its name (e.g., `my-cli` not `my-cli.js`) to allow the shell to correctly pick up the generated shim. Ensure your `PATH` includes the `node_modules/.bin` directory.","message":"On Windows, `bin-links` creates `.cmd` and `.ps1` shims in addition to the binary itself. Directly invoking the raw `.js` binary file or relying on Unix-style symbolic link behavior might not work as expected in standard Windows command prompts.","severity":"gotcha","affected_versions":"*"},{"fix":"If you encounter issues with global binary overwrites, consider explicitly uninstalling the old package version first, or investigate if the conflicting binary truly belongs to a different package. Avoid relying on `force: true` to override existing binaries from unrelated packages in global contexts.","message":"For global package installations, `bin-links` (via npm's internal logic) will only overwrite existing binaries if they were previously installed by the *same* package. This is a security measure to prevent arbitrary file overwrites. Using `force: true` might not bypass this specific safety check for global installs in all npm versions.","severity":"gotcha","affected_versions":">=4.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure the user running the Node.js process has write permissions to the destination directory (e.g., `node_modules/.bin` or global `bin` directory). On Unix-like systems, you might need to use `sudo` for global installations, though this is generally discouraged for local `npm install`.","cause":"The Node.js process lacks the necessary file system permissions to create symbolic links or shims in the target directory.","error":"Error: EACCES: permission denied, link '...' -> '...'"},{"fix":"Refactor your import statement to use `import binLinks from 'bin-links';` to align with ESM syntax. Ensure your project is configured for ESM (e.g., `\"type\": \"module\"` in `package.json`).","cause":"Attempting to use `require('bin-links')` in an ES Module context where CommonJS `require` is not natively available or polyfilled.","error":"TypeError: require is not a function"},{"fix":"Upgrade your Node.js runtime to a version that satisfies the `engines.node` requirement specified in `bin-links`'s `package.json` (e.g., `^20.17.0 || >=22.9.0` for v6.0.0). Use a Node Version Manager (NVM) to switch to a compatible version.","cause":"The `bin-links` package specifies a strict Node.js engine range in its `package.json`, and your current Node.js version falls outside this range.","error":"Error: The 'engines' field is not compatible with the current Node.js version."}],"ecosystem":"npm"}