Flags

Command line arguments parser with built-in validations.

Installation

deno add jsr:@cliffy/flags

Usage

The parseFlags method takes as its first argument the arguments to be parsed, usually Deno.args, or a parse context. As the second argument you can pass an options object. A list of all available options can be found here.

Basic usage

If parseFlags is called without defining specific flags with the options object, all arguments are parsed and added to the flags object returned by the parseFlags method. All non-options arguments are added to the unknown array and all flags specified after the double dash (--) are added to the literal array.

import { parseFlags } from "@cliffy/flags";

console.log(parseFlags());

// or: console.log(parseFlags(Deno.args));
$ deno run https://cliffy.io/examples/v1.2.1/flags/flags.ts -a foo -b bar
{
  flags: { a: "foo", b: "bar" },
  literal: [],
  unknown: [],
  stopEarly: false,
  stopOnUnknown: false
}

$ deno run https://cliffy.io/examples/v1.2.1/flags/flags.ts \
    -x 3 \
    -y.z -n5 \
    -abc \
    --beep=boop \
    foo bar baz \
    --deno.land \
    --deno.com -- --cliffy
{
  flags: {
    x: "3",
    y: { z: true },
    n: "5",
    a: true,
    b: true,
    c: true,
    beep: "boop",
    deno: { land: true, com: true }
  },
  literal: [ "--cliffy" ],
  unknown: [ "foo", "bar", "baz" ],
  stopEarly: false,
  stopOnUnknown: false
}

Define flags

You can specify flags with the options object. For all unknown or invalid flags an ValidationError is thrown. Read more about error handling here. A list of all available flag options can be found here.

import { parseFlags } from "@cliffy/flags";

const { flags } = parseFlags(Deno.args, {
  flags: [{
    name: "help",
    aliases: ["h"],
    standalone: true,
  }, {
    name: "verbose",
    aliases: ["v"],
    collect: true,
    value: (val: boolean, previous = 0) => val ? previous + 1 : 0,
  }, {
    name: "file",
    aliases: ["f"],
    type: "string",
  }],
});

console.log(flags);
$ deno run https://cliffy.io/examples/v1.2.1/flags/options.ts -vvv -f ./example.ts
{ verbose: 3, file: "./example.ts" }

Positional arguments

The args option allows you to define typed positional arguments alongside flags. Positional arguments are collected into the args array in the returned context and removed from the unknown array.

import { parseFlags } from "@cliffy/flags";

const { flags, args } = parseFlags(["--count", "3", "file.txt"], {
  flags: [{ name: "count", type: "number" }],
  args: [{ name: "file", type: "string" }],
});

console.log(flags); // { count: 3 }
console.log(args); // [ "file.txt" ]

Positional arguments can be required, optional, or variadic — the same ArgumentOptions interface is used for both options and positional arguments. Positional arguments that have a leading dash (-foo) are allowed when the argument is explicitly defined via the args option.

import { parseFlags } from "@cliffy/flags";

const { flags, args } = parseFlags(["--foo", "bar", "a", "b", "c"], {
  flags: [{ name: "foo", type: "string" }],
  args: [{ name: "files", type: "string", variadic: true }],
});

console.log(args); // [ "a", "b", "c" ]

Parse context

The parseFlags method accepts also a parse context as first argument. The context can either be a manually created object or the result of a previously called parseFlags method.

This can be used to parse command line flags in multiple steps, for example, when parsing options that precede a subcommand.

import { parseFlags } from "@cliffy/flags";

const globalFlags = [{
  name: "foo-global",
  alias: ["g"],
  collect: true,
}];

const flags = [{
  name: "foo",
  alias: ["f"],
  collect: true,
}];

const args = ["--foo-global", "cmd1", "--foo-global", "--foo", "arg1", "--foo"];

// Parse main command args (all flags until the first unknown argument).
const ctx = parseFlags(args, {
  flags: globalFlags,
  stopEarly: true, // Stop on first non option argument.
  stopOnUnknown: true, // Stop on first option argument.
  dotted: false, // Don't convert dotted option keys to nested objects.
});

// Shift sub-command from arguments.
const subCommand = ctx.unknown.shift();

// Parse all sub command args.
parseFlags(ctx, {
  flags: [
    ...globalFlags,
    ...flags,
  ],
});

console.log("sub-command:", subCommand); // -> cmd1
console.log("options:", ctx.flags); // -> { fooGlobal: [ true, true ], foo: [ true, true ] }
console.log("arguments:", ctx.unknown); // -> [ "arg1" ]

Parsed flags

The parse context returned by parseFlags contains a parsedFlags property: a read-only array of the raw flag tokens in the order they were encountered, preserving the exact form used on the command line. Positional arguments are not included — only flag names and their values appear here.

  • Space form — flag and value as separate tokens: command --port 80['--port', '80']
  • Equals form — flag and value as one token: command --port=80['--port=80']
import { parseFlags } from "@cliffy/flags";

const { parsedFlags } = parseFlags([
  "--port=80",
  "--host",
  "localhost",
  "file.txt",
], {
  flags: [
    { name: "port", type: "number" },
    { name: "host", type: "string" },
  ],
  args: [{ name: "file", type: "string" }],
});

console.log(parsedFlags); // [ "--port=80", "--host", "localhost" ]