{"id":337,"date":"2024-06-18T09:50:58","date_gmt":"2024-06-18T09:50:58","guid":{"rendered":"https:\/\/andrearethy.com\/blog\/?p=337"},"modified":"2024-06-20T10:00:11","modified_gmt":"2024-06-20T10:00:11","slug":"how-to-add-a-command-line-interface-cli-to-your-typescript-project-using-commander","status":"publish","type":"post","link":"https:\/\/andrearethy.com\/blog\/how-to-add-a-command-line-interface-cli-to-your-typescript-project-using-commander\/","title":{"rendered":"How to Add a Command-Line Interface (CLI) to Your TypeScript Project Using Commander"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Command-line interfaces (CLI) are powerful tools that can significantly enhance the usability and automation capabilities of your application. By adding a CLI to your TypeScript project, you can provide users with a simple and efficient way to interact with your application through the terminal. In this article, I will guide you through the process of adding a CLI to an existing TypeScript project using the popular&nbsp;<code>commander<\/code>&nbsp;library. This article assumes that you have already <a href=\"https:\/\/andrearethy.com\/blog\/how-to-set-up-your-first-typescript-project-with-tdd-and-ci-macos\/\" target=\"_blank\" rel=\"noopener\" title=\"\">set up a TypeScript project with testing using Jest<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you run into EACCES permission errors I recommend <a href=\"https:\/\/docs.npmjs.com\/resolving-eacces-permissions-errors-when-installing-packages-globally\" target=\"_blank\" rel=\"noopener nofollow\" title=\"\">reading this article about how to solve it<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Table of Contents<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><a href=\"#intro\" title=\"\">Introduction to Commander<\/a><\/li>\n\n\n\n<li><a href=\"#install\" title=\"\">Installing Commander<\/a><\/li>\n\n\n\n<li><a href=\"#creating-the-cli-entry-point\">Creating the CLI Entry Point<\/a><\/li>\n\n\n\n<li><a href=\"#defining-commands-and-options\">Defining Commands and Options<\/a><\/li>\n\n\n\n<li><a href=\"#building-and-distributing-your-cli\">Building and Distributing Your CLI<\/a><\/li>\n\n\n\n<li><a href=\"#conclusion\">Conclusion<\/a><\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"intro\">Introduction to Commander<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/www.npmjs.com\/package\/commander\" target=\"_blank\" rel=\"noopener nofollow\" title=\"\">Commander.js<\/a> is a lightweight, expressive, and versatile library for building command-line interfaces in Node.js. It provides a comprehensive set of features, including:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Command and option parsing<\/li>\n\n\n\n<li>Automated help generation<\/li>\n\n\n\n<li>Nested subcommands<\/li>\n\n\n\n<li>Customizable error handling<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">By leveraging Commander, you can quickly develop a robust and user-friendly CLI for your TypeScript project.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"install\">Installing Commander<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To get started, you need to install Commander. Open your terminal and navigate to your project directory, then run the following command:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"# Use 'sudo' keyword if necessary\nnpm install commander\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #7F848E; font-style: italic\"># Use &#39;sudo&#39; keyword if necessary<\/span><\/span>\n<span class=\"line\"><span style=\"color: #61AFEF\">npm<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">install<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">commander<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"creating-the-cli-entry-point\">Creating the CLI Entry Point<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In your&nbsp;<code>src<\/code>&nbsp;folder, create a new file called&nbsp;<code>cli.ts<\/code>. This file will serve as the entry point for your CLI. Here is a basic example:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"#!\/usr\/bin\/env node\n\nimport { program } from 'commander';\n\nprogram\n  .description('My TypeScript CLI');\n\nprogram.parse(process.argv);\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #7F848E; font-style: italic\">#!\/usr\/bin\/env node<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #C678DD\">import<\/span><span style=\"color: #ABB2BF\"> { <\/span><span style=\"color: #E06C75\">program<\/span><span style=\"color: #ABB2BF\"> } <\/span><span style=\"color: #C678DD\">from<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">&#39;commander&#39;<\/span><span style=\"color: #ABB2BF\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #E06C75\">program<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  .<\/span><span style=\"color: #61AFEF\">description<\/span><span style=\"color: #ABB2BF\">(<\/span><span style=\"color: #98C379\">&#39;My TypeScript CLI&#39;<\/span><span style=\"color: #ABB2BF\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #E5C07B\">program<\/span><span style=\"color: #ABB2BF\">.<\/span><span style=\"color: #61AFEF\">parse<\/span><span style=\"color: #ABB2BF\">(<\/span><span style=\"color: #E5C07B\">process<\/span><span style=\"color: #ABB2BF\">.<\/span><span style=\"color: #E06C75\">argv<\/span><span style=\"color: #ABB2BF\">);<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">This script sets up the basic structure of your CLI, including a description. The&nbsp;<code>#!\/usr\/bin\/env node<\/code>&nbsp;shebang line at the top allows the script to be executed as a standalone executable.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"defining-commands-and-options\">Defining Commands and Options<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Next, you will define the commands and options for your CLI. Since this CLI was created for an existing TypeScript project let&#8217;s import your functions. In the below example I&#8217;m importing addNewItem and throttle. <a href=\"https:\/\/github.com\/AndreaRethy\/throttle.git\" target=\"_blank\" rel=\"noopener nofollow\" title=\"\">Complete example is shared in my GitHub<\/a>:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"import { program } from 'commander';\nimport { addNewItem, throttle } from '.\/script';\n\nprogram\n  .command('add &lt;item&gt;')\n  .description('Add item')\n  .action((item: string) =&gt; {\n    \/\/ Initialize array\n    let array: string[] = [];\n\n    \/\/Define throttle function\n    const throttledAddNewItem = throttle(() =&gt; {addNewItem(array, item); console.log(array);}, 1000);\n\n    \/\/ Simulate rapid calls\n    throttledAddNewItem();\n    throttledAddNewItem();\n    throttledAddNewItem();\n    \n  });\n  \n\nprogram.parse(process.argv);\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #C678DD\">import<\/span><span style=\"color: #ABB2BF\"> { <\/span><span style=\"color: #E06C75\">program<\/span><span style=\"color: #ABB2BF\"> } <\/span><span style=\"color: #C678DD\">from<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">&#39;commander&#39;<\/span><span style=\"color: #ABB2BF\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C678DD\">import<\/span><span style=\"color: #ABB2BF\"> { <\/span><span style=\"color: #E06C75\">addNewItem<\/span><span style=\"color: #ABB2BF\">, <\/span><span style=\"color: #E06C75\">throttle<\/span><span style=\"color: #ABB2BF\"> } <\/span><span style=\"color: #C678DD\">from<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">&#39;.\/script&#39;<\/span><span style=\"color: #ABB2BF\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #E06C75\">program<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  .<\/span><span style=\"color: #61AFEF\">command<\/span><span style=\"color: #ABB2BF\">(<\/span><span style=\"color: #98C379\">&#39;add &lt;item&gt;&#39;<\/span><span style=\"color: #ABB2BF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  .<\/span><span style=\"color: #61AFEF\">description<\/span><span style=\"color: #ABB2BF\">(<\/span><span style=\"color: #98C379\">&#39;Add item&#39;<\/span><span style=\"color: #ABB2BF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  .<\/span><span style=\"color: #61AFEF\">action<\/span><span style=\"color: #ABB2BF\">((<\/span><span style=\"color: #E06C75; font-style: italic\">item<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #E5C07B\">string<\/span><span style=\"color: #ABB2BF\">) <\/span><span style=\"color: #C678DD\">=&gt;<\/span><span style=\"color: #ABB2BF\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #7F848E; font-style: italic\">\/\/ Initialize array<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #C678DD\">let<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #E06C75\">array<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #E5C07B\">string<\/span><span style=\"color: #ABB2BF\">[] <\/span><span style=\"color: #56B6C2\">=<\/span><span style=\"color: #ABB2BF\"> [];<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #7F848E; font-style: italic\">\/\/Define throttle function<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #C678DD\">const<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #E5C07B\">throttledAddNewItem<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #56B6C2\">=<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #61AFEF\">throttle<\/span><span style=\"color: #ABB2BF\">(() <\/span><span style=\"color: #C678DD\">=&gt;<\/span><span style=\"color: #ABB2BF\"> {<\/span><span style=\"color: #61AFEF\">addNewItem<\/span><span style=\"color: #ABB2BF\">(<\/span><span style=\"color: #E06C75\">array<\/span><span style=\"color: #ABB2BF\">, <\/span><span style=\"color: #E06C75\">item<\/span><span style=\"color: #ABB2BF\">); <\/span><span style=\"color: #E5C07B\">console<\/span><span style=\"color: #ABB2BF\">.<\/span><span style=\"color: #61AFEF\">log<\/span><span style=\"color: #ABB2BF\">(<\/span><span style=\"color: #E06C75\">array<\/span><span style=\"color: #ABB2BF\">);}, <\/span><span style=\"color: #D19A66\">1000<\/span><span style=\"color: #ABB2BF\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #7F848E; font-style: italic\">\/\/ Simulate rapid calls<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #61AFEF\">throttledAddNewItem<\/span><span style=\"color: #ABB2BF\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #61AFEF\">throttledAddNewItem<\/span><span style=\"color: #ABB2BF\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #61AFEF\">throttledAddNewItem<\/span><span style=\"color: #ABB2BF\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  });<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  <\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #E5C07B\">program<\/span><span style=\"color: #ABB2BF\">.<\/span><span style=\"color: #61AFEF\">parse<\/span><span style=\"color: #ABB2BF\">(<\/span><span style=\"color: #E5C07B\">process<\/span><span style=\"color: #ABB2BF\">.<\/span><span style=\"color: #E06C75\">argv<\/span><span style=\"color: #ABB2BF\">);<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"building-and-distributing-your-cli\">Building and Distributing Your CLI<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To make your CLI executable, you need to compile your TypeScript code to JavaScript. If necessary update your&nbsp;<code>tsconfig.json<\/code>&nbsp;to include the src directory where your cli.ts lives:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"{\n  &quot;compilerOptions&quot;: {\n    &quot;outDir&quot;: &quot;.\/dist&quot;,\n    &quot;rootDir&quot;: &quot;.\/src&quot;,\n    &quot;module&quot;: &quot;commonjs&quot;,\n    &quot;target&quot;: &quot;es6&quot;,\n    &quot;strict&quot;: true\n  },\n  &quot;include&quot;: [\n    &quot;src\/**\/*&quot;,\n  ],\n  &quot;exclude&quot;: [\n    &quot;node_modules&quot;,\n    &quot;dist&quot;\n  ]\n}\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #ABB2BF\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  <\/span><span style=\"color: #E06C75\">&quot;compilerOptions&quot;<\/span><span style=\"color: #ABB2BF\">: {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">&quot;outDir&quot;<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">&quot;.\/dist&quot;<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">&quot;rootDir&quot;<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">&quot;.\/src&quot;<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">&quot;module&quot;<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">&quot;commonjs&quot;<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">&quot;target&quot;<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">&quot;es6&quot;<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #E06C75\">&quot;strict&quot;<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #D19A66\">true<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  },<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  <\/span><span style=\"color: #E06C75\">&quot;include&quot;<\/span><span style=\"color: #ABB2BF\">: [<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #98C379\">&quot;src\/**\/*&quot;<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  ],<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  <\/span><span style=\"color: #E06C75\">&quot;exclude&quot;<\/span><span style=\"color: #ABB2BF\">: [<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #98C379\">&quot;node_modules&quot;<\/span><span style=\"color: #ABB2BF\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">    <\/span><span style=\"color: #98C379\">&quot;dist&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  ]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Then, add a build script to your&nbsp;<code>package.json<\/code>:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"&quot;scripts&quot;: {\n  &quot;cli&quot;: &quot;node dist\/cli.js&quot;\n}\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #98C379\">&quot;scripts&quot;<\/span><span style=\"color: #ABB2BF\">: {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">  <\/span><span style=\"color: #E06C75\">&quot;cli&quot;<\/span><span style=\"color: #ABB2BF\">: <\/span><span style=\"color: #98C379\">&quot;node dist\/cli.js&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ABB2BF\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Compile your code with TypeScript compiler:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"tsc src\/cli.ts --outDir dist\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #61AFEF\">tsc<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">src\/cli.ts<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #D19A66\">--outDir<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">dist<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Then, link your package globally:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282c34\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"npm link\" style=\"color:#abb2bf;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki one-dark-pro\" style=\"background-color: #282c34\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #61AFEF\">npm<\/span><span style=\"color: #ABB2BF\"> <\/span><span style=\"color: #98C379\">link<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">You can now run your CLI commands from anywhere using the&nbsp;npm run <code>cli<\/code>&nbsp;command.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"conclusion\">Conclusion<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Adding a CLI to your existing TypeScript project using Commander is a straightforward process that can significantly enhance the usability of your application. By following the steps outlined in this article, you can create a robust and user-friendly CLI that allows users to interact with your application through the terminal. Remember to write tests to ensure the reliability of your CLI commands and consider distributing your CLI as a global npm package for broader accessibility. Happy coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>By adding a CLI to your TypeScript project, you can provide users with a simple and efficient way to interact with your application through the terminal.<\/p>\n","protected":false},"author":1,"featured_media":352,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_siteseo_robots_primary_cat":"none","footnotes":""},"categories":[40],"tags":[57,58,29,28,43,46,22],"class_list":["post-337","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-guide","tag-cli","tag-command-line-interface","tag-freelance-webdevelopment","tag-guide","tag-node-js","tag-typescript","tag-webdevelopment"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/posts\/337","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/comments?post=337"}],"version-history":[{"count":15,"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/posts\/337\/revisions"}],"predecessor-version":[{"id":364,"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/posts\/337\/revisions\/364"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/media\/352"}],"wp:attachment":[{"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/media?parent=337"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/categories?post=337"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/andrearethy.com\/blog\/wp-json\/wp\/v2\/tags?post=337"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}