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
Problem
@effect/clicurrently 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.
--colorvs--color=alwaysin GNU tools,--watchvs--watch=modein various dev tools.Desired behavior
A flag like
--watchthat:Option.none--watch) → defaults to a specified value (e.g.'first-failure')--watch=until-done) → uses the provided valuePossible API
Or alternatively:
Prior art
--color[=WHEN]--watch--watchvs--watch=modenargs='?'withconstfor the bare-flag default