Guide

Build a greeting command

Read a name and an optional greeting from the command line.

On this page

Before you start

  • Bun and a directory for a small TypeScript project.

Build a greeting command that reads a name and prints a message. Add a --greeting option so the person running it can choose what it says.

In an empty project directory, initialize a package:

Install the parser and Zod in your project. Use Zod 3 for this release:

Use Zod 3 with this parser release

@hulla/args@0.0.4 declares its schemas using Zod 3 types. Zod 4 schemas can fail TypeScript overload checks even when the runtime call works. Keep zod@3 in this demo; the API package’s Zod examples use a separate installation.

Save this as src/cli.ts. Bun’s argv includes the executable and script path, so argv.slice(2) leaves only the words supplied by the user. This parser opts into case-sensitive matching, so option names must match their declared casing.

src/cli.ts
import { option, parser, positional } from '@hulla/args'
import { argv } from 'node:process'

const cli = parser({
  name: 'greet',
  arguments: [positional({ name: 'name' }), option({ name: 'greeting' })],
  settings: { caseSensitive: true },
})

const result = cli.parse(argv.slice(2))
const name = result.arguments.name.value ?? 'World'
const greeting = result.arguments.greeting.value ?? 'Hello'
console.log(`${greeting}, ${name}!`)

Run it with Bun, which executes TypeScript files directly:

Terminal
$ bun src/cli.ts Alice --greeting Hi
Hi, Alice!

With no arguments, the explicit fallbacks apply:

Terminal
$ bun src/cli.ts
Hello, World!

Try bun src/cli.ts Alice --greeting=Hi. It should still print Hi, Alice!. The parser accepts both a space and = between an option and its value.

Preserve user text

The default parser is case-insensitive, and equals-form values such as --greeting=Hi are lowercased in that mode. This example sets caseSensitive: true to preserve the user’s casing. See Parser options before changing it.

To change the default message, edit the ?? 'Hello' fallback and run the command without --greeting.

Continue with Build a notes CLI for commands, persistence, validation, and exit codes. The argument guide explains the value, raw, index, and detected fields.