Blog
shadcn-ui/ui codebase analysis: How does shadcn-ui CLI work? — Part 1.0

shadcn-ui/ui codebase analysis: How does shadcn-ui CLI work? — Part 1.0

I wanted to find out how shadcn-ui CLI works. In this article, I discuss the code used to build the shadcn-ui/ui CLI. In part 1, we will look at a code snippet picked from packages/cli/src/index.ts.

// source: https://github.com/shadcn-ui/ui/blob/main/packages/cli/src/index.ts
#!/usr/bin/env node
import { add } from "@/src/commands/add"
import { diff } from "@/src/commands/diff"
import { init } from "@/src/commands/init"
import { Command } from "commander"

import { getPackageInfo } from "./utils/get-package-info"

process.on("SIGINT", () => process.exit(0))
process.on("SIGTERM", () => process.exit(0))

async function main() {
  const packageInfo = await getPackageInfo()

  const program = new Command()
    .name("shadcn-ui")
    .description("add components and dependencies to your project")
    .version(
      packageInfo.version || "1.0.0",
      "-v, --version",
      "display the version number"
    )

  program.addCommand(init).addCommand(add).addCommand(diff)

  program.parse()
}

main()

There’s about 29 lines of code in index.ts

Imports used

#!/usr/bin/env node
import { add } from "@/src/commands/add"
import { diff } from "@/src/commands/diff"
import { init } from "@/src/commands/init"
import { Command } from "commander"

import { getPackageInfo } from "./utils/get-package-info"

Shadcn CLI docs discuss three commands; add , diff , init

These commands are imported from a folder named commands in src folder.

Commander is an npm package used here to enable CLI interactions.

getPackageInfo

getPackageInfo is a small utility function found in utils/get-package-info.ts

import path from "path"
import fs from "fs-extra"
import { type PackageJson } from "type-fest"

export function getPackageInfo() {
  const packageJsonPath = path.join("package.json")

  return fs.readJSONSync(packageJsonPath) as PackageJson
}

Notice how there’s an enforced PackageJson type from type-fest. It is from the Legend, Sindre Sorhus. I see this guy’s name so often when I dig into open source.

fs.readJSONSync reads a JSON file and then parses it into an object. In this case, it is an object of type PackageJson.

process.on("SIGINT", () => process.exit(0))
process.on("SIGTERM", () => process.exit(0))

SIGINT: This is a signal that is typically sent to a process when a user types Ctrl+C in the terminal. It is often used to request that a process terminate gracefully. When a process receives a SIGINT signal, it can catch it and perform any necessary cleanup operations before terminating.

SIGTERM: This is a signal that is typically sent to a process by the operating system to request that the process terminate. It is often used as a graceful way to ask a process to terminate, allowing it to perform any necessary cleanup operations before exiting. Processes can catch this signal and perform cleanup operations before terminating. (Source)

Conclusion:

I have seen Commander.js being used in Next.js create-next-app package, I see it in use here again in shadcn-ui/ui. I will continue picking small code snippets from this CLI package and discuss the code. I liked the way package.json is read using a utility function getPackageInfo. This getPackageInfo uses fs.readJSONSync. There is Type assertion applied using PackageJson provided by type-fest on the Object returned by fs.readJSONSync.

Want to learn how to build shadcn-ui/ui from scratch? Check out build-from-scratch

About me:

Hey, my name is Ramu Narasinga. I study large open-source projects and create content about their codebase architecture and best practices, sharing it through articles, videos.

I am open to work on interesting projects. Send me an email at ramu.narasinga@gmail.com

My Github — https://github.com/ramu-narasinga

My website — https://ramunarasinga.com

My Youtube channel — https://www.youtube.com/@thinkthroo

Learning platform — https://thinkthroo.com

Codebase Architecture — https://app.thinkthroo.com/architecture

Best practices — https://app.thinkthroo.com/best-practices

Production-grade projects — https://app.thinkthroo.com/production-grade-projects

References:

  1. https://github.com/shadcn-ui/ui/blob/main/packages/cli/src/index.ts

  2. https://github.com/shadcn-ui/ui/blob/main/packages/cli/src/utils/get-package-info.ts#L5

  3. https://dev.to/superiqbal7/graceful-shutdown-in-nodejs-handling-stranger-danger-29jo

We use cookies
We use cookies to ensure you get the best experience on our website. For more information on how we use cookies, please see our cookie policy.

By clicking "Accept", you agree to our use of cookies.

Learn more