Episode 8: Understanding Bin Scripts and Their Use in Yarn Workspaces

What Are Bin Scripts?
Bin scripts are executable files defined within a package that can be invoked:
From other packages in the workspace.
Globally when installed as a dependency.
They’re commonly used for:
CLIs (Command Line Interfaces), such as Babel, ESLint, or Create React App.
Custom scripts for automating tasks within projects.
How Bin Scripts Work
Definition
Bin scripts are specified in thepackage.json
of a package under thebin
property.Example for
moduleB
:{ "name": "moduleB", "version": "1.0.0", "bin": { "my-script": "./index.js" } }
The key (
my-script
) becomes the command name.The value (
./index.js
) points to the script file that will run.
Installation
Run
yarn install
(with--force
if necessary) to link the bin script.The script will appear in the root
node_modules/.bin/
folder as a symlink to the defined file.
Usage
The bin script can be run from:
The root package.json:
{ "scripts": { "start": "my-script" } }
Other packages in the workspace:
{ "scripts": { "start": "my-script" } }
Steps to Create and Use a Bin Script
1. Define a Bin Script
In the package.json
of the package (e.g., moduleB
):
{
"name": "moduleB",
"version": "1.0.0",
"bin": {
"moduleB-script": "./index.js"
}
}
2. Add a Shebang to the Script File
At the start of index.js
, include the shebang for Node.js:
#!/usr/bin/env node
console.log("Hello from moduleB!");
This tells the terminal to use Node.js to execute the script.
3. Install Dependencies and Link the Script
Run:
yarn install --force
This updates the node_modules/.bin/
directory in the root with a symlink for moduleB-script
.
4. Run the Script
From the Root package.json
Add a start
script:
{
"scripts": {
"start": "moduleB-script"
}
}
Run:
yarn start
From Another Package (e.g., moduleA
)
In moduleA/package.json
:
{
"scripts": {
"start": "moduleB-script"
}
}
Run from the workspace root:
yarn workspace moduleA start
Customizing Bin Script Names and Adding Multiple Scripts
Custom Command Names
Instead of using the package name as the default command, specify a custom name:{ "bin": { "custom-command": "./index.js" } }
Multiple Commands
Provide an object with multiple keys and corresponding script paths:{ "bin": { "command-one": "./script-one.js", "command-two": "./script-two.js" } }
Run yarn install --force
again to update the bin directory.
Using Bin Scripts Across the Workspace
Symlinks to the Root
Bin scripts are symlinked to the root node_modules/.bin
directory, making them accessible:
Globally across the monorepo.
Without needing to install the package multiple times.
Accessing from Other Packages
Packages in the workspace can directly call the bin script in their own scripts, such as yarn workspace moduleA start
.
Troubleshooting
Bin Script Errors
Missing Shebang
Ensure#!/usr/bin/env node
is at the top of the file to specify Node.js for execution.No Action on
yarn install
Use the--force
flag to ensure Yarn recognizes changes to thebin
property.Conflicting Names
Choose unique command names to avoid conflicts.
Summary
Bin scripts enable CLI functionality within and across workspace packages.
They are easy to set up using the
bin
property inpackage.json
.Use the shebang to run JavaScript as a script.
Symlinks in
node_modules/.bin
make scripts accessible globally within the monorepo.You can define custom command names and add multiple bin scripts per package.
Subscribe to my newsletter
Read articles from Muhammad Sufiyan directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Muhammad Sufiyan
Muhammad Sufiyan
As a former 3D Animator with more than 12 years of experience, I have always been fascinated by the intersection of technology and creativity. That's why I recently shifted my career towards MERN stack development and software engineering, where I have been serving since 2021. With my background in 3D animation, I bring a unique perspective to software development, combining creativity and technical expertise to build innovative and visually engaging applications. I have a passion for learning and staying up-to-date with the latest technologies and best practices, and I enjoy collaborating with cross-functional teams to solve complex problems and create seamless user experiences. In my current role as a MERN stack developer, I have been responsible for developing and implementing web applications using MongoDB, Express, React, and Node.js. I have also gained experience in Agile development methodologies, version control with Git, and cloud-based deployment using platforms like Heroku and AWS. I am committed to delivering high-quality work that meets the needs of both clients and end-users, and I am always seeking new challenges and opportunities to grow both personally and professionally.