Use an npm script as “bin”


I have a command line application written in TypeScript with some npm scripts defined in package.json.

"scripts": { "start": "ts-node src/index.ts", "start-args": "ts-node src/index.ts -- some args" },

I would like to link and alias the TypeScript file so that I can call the program easily, so I am looking for something like a "bin" key in the package.json file.

"scripts": { "start": "ts-node ./src/index.ts", "start-args": "ts-node src/index.ts -- some args" }, "bin": { "foobar": "./src/index.ts", "bazqux": "./src/index.ts some args" }

ts-node is installed locally.

However, since TypeScript is not natively supported by node, just putting a shebang on ./src/index.ts won't work.

I would also like to be able to create an aliased command with default arguments, like bazqux above. When I link or install the package as global, I can run "foobar" globally as if I run "npm run start" inside the repository; or run "bazqux" globally as it's "npm run start-args".

How to achieve this?


It will work, if ts-node is in path variable use

#!/usr/bin/env ts-node console.log("Hello World");

Checkout repo: https://github.com/deepakshrma/ts-cli

Try out:

$ npm i -g https://git@github.com:deepakshrma/ts-cli.git $ ts-test

Update: The issue described below has been fixed in ts-node@8.9.0 thanks to my report. --script-mode now resolves symlinks before looking for the tsconfig.json file. The correct shebang to use is #!/usr/bin/env ts-node-script, which is now also documented. Make sure you have the newest version installed globally with npm -g install ts-node. (I'm not sure whether you also/still need TypeScript installed globally for this. If yes: npm -g install typescript.)

Outdated: For those who also still stumble across this problem, I documented my current approach in detail in this issue. In short, many modules (including those of Node.js itself) require that you use the --esModuleInterop option for the TypeScript compiler. (You can specify this in your tsconfig.json file.) In order to be able to use your command from anywhere and not just from within your package directory, you have to use the undocumented --script-mode option for ts-node or the undocumented ts-node-script command, which does the same.

In other words, your shebang should either be #!/usr/bin/env -S ts-node --script-mode or #!/usr/bin/env ts-node-script. (The former uses -S to pass arguments to the specified interpreter. If this doesn't work on your platform, you can try to hack around this limitation.)

If you want to use the bin functionality of npm (e.g. by running npm link from the package directory), the above doesn't work because --script-mode does not (yet?) follow symbolic links. To work around this, you can use #!/usr/bin/env -S ts-node --project /usr/local/lib/node_modules/<your-project>/tsconfig.json on the first line of your script. This is not ideal, though, as it breaks platform independence. The only other option I see at the moment is to use a bash script instead and call your script from there.



  • How to return a Rx Single transaction using Room Db?
  • Trying to display users information in a recyclerview - Firebase
  • rails 3, paperclip (& formtastic) - deleting image attachments
  • Field \\“me\\” of type \\“User\\” must have a selection of subfields
  • Numbering/Labeling images (eg 1,2,3 or A,B,C) with ImageMagick montage
  • how do I array from a GET request function in viewdidload function in swift
  • Starting a javascript prompt after a button is clicked
  • Bounding csv data to topojson path - cloropleth
  • How to see if all values within group are unique/identify those that aren't
  • how can i open a webpage in a webview from a fragment with buttons?
  • Box shadow not working in microsoft edge
  • Setup SignalR and Service Bus inside a Azure Service Fabric service
  • Google Data Studio MySql data source connection does not exist Error
  • How to achieve density/heat map effect in iOS (iPhone/iPad)?
  • Need to pass object and operation in a function that executes it
  • Retrieving custom entities in CRM 4 C#
  • How to use grep to output unique lines of code from a file?
  • C++ Time measurement of functions
  • QueryOver - add restriction on primitive collection
  • In Moment.js, how do you get the date of the next occurrence of a specific month (ex: 'next Jan
  • Adding custom message on Thank You page by shipping method
  • Identifying dates in strings using NLTK
  • Google Compute instance receiving email
  • async GET request with body from browser
  • Tensorflow crash using tf.train.Saver() with GPU
  • How do I change the names of buttons on a message box?
  • internal javascript not works in angular2
  • Delete a ListItem by clicking the ImageView within the ListItem
  • First dynamically-added TinyMCE editor displays, others do not
  • What does “T extends Junk” mean in a generic class in Java?
  • How to use Typescript with libraries like Ampersand.js that parse configs to build prototypes
  • Stop an element moving with padding on hover
  • Add font awesome icon to custom add to cart button in Woocommerce 3
  • how to read to huge file into buffer
  • I am consuming a WCF service that requires headers from a .NET 2 website. How can I programmatically
  • Cloud Code: Creating a Parse.File from URL
  • How to handle div that is created dynamically in a table
  • Google App Engine backend servlet not responding