Skip to content

Support CLI options with optional values in @effect/cli #6182

@schickling-assistant

Description

@schickling-assistant

Problem

@effect/cli currently has a hard split between boolean flags and value-accepting options:

  • Options.boolean — never consumes a value (--watch)
  • Options.text / Options.choice — always require a value (--watch=mode)

There's no way to define an option that works as both a standalone flag and a value-accepting option. This is a common CLI pattern — e.g. --color vs --color=always in GNU tools, --watch vs --watch=mode in various dev tools.

Desired behavior

A flag like --watch that:

  • When absent → Option.none
  • When bare (--watch) → defaults to a specified value (e.g. 'first-failure')
  • When explicit (--watch=until-done) → uses the provided value

Possible API

const watch = Options.choice('watch', ['first-failure', 'until-done']).pipe(
  Options.withOptionalValue('first-failure'), // bare --watch → 'first-failure'
  Options.optional, // absent → Option.none
)

Or alternatively:

const watch = Options.boolean('watch').pipe(
  Options.withOptionalValue(Options.choice(['first-failure', 'until-done']), 'first-failure'),
)

Prior art

  • GNU coreutils: --color[=WHEN]
  • TypeScript compiler: --watch
  • Vitest / Jest: --watch vs --watch=mode
  • Python argparse: nargs='?' with const for the bare-flag default

Filed on behalf of @schickling

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions