
洪 民憙 (Hong Minhee)
@hongminhee@hollo.social
Big update for our type-safe combinatorial #CLI parser for #TypeScript:
- Labeled merge groups: organize options logically
- Rich docs: brief, description & footer support
- @optique/temporal: new package for date/time parsing
showDefault
: automatic default value display
The help text has never looked this good!

洪 民憙 (Hong Minhee)
@hongminhee@hackers.pub
We're excited to announce Optique 0.4.0, which brings significant improvements to help text organization, enhanced documentation capabilities, and introduces comprehensive Temporal API support.
Optique is a type-safe combinatorial CLI parser for TypeScript that makes building command-line interfaces intuitive and maintainable. This release focuses on making your CLI applications more user-friendly and maintainable.
Better help text organization
One of the most visible improvements in Optique 0.4.0 is the enhanced help text organization. You can now label and group your options more effectively, making complex CLIs much more approachable for users.
Labeled merge groups
The merge()
combinator now accepts an optional label parameter, solving
a common pain point where developers had to choose between clean code structure
and organized help output:
// Before: unlabeled merged options appeared scattered
const config = merge(connectionOptions, performanceOptions);
// Now: group related options under a clear section
const config = merge(
"Server Configuration", // New label parameter
connectionOptions,
performanceOptions
);
This simple addition makes a huge difference in help text readability, especially for CLIs with many options spread across multiple reusable modules.
The resulting help output clearly organizes options under
the Server Configuration
section:
Demo app showcasing labeled merge groups
Usage: demo-merge.ts --host STRING --port INTEGER --timeout INTEGER --retries
INTEGER
Server Configuration:
--host STRING Server hostname or IP address
--port INTEGER Port number for the connection
--timeout INTEGER Connection timeout in seconds
--retries INTEGER Number of retry attempts
The new group()
combinator
For cases where merge()
doesn't apply, the new group()
combinator lets you wrap any parser with a documentation label:
// Group mutually exclusive options under a clear section
const outputFormat = group(
"Output Format",
or(
map(flag("--json"), () => "json"),
map(flag("--yaml"), () => "yaml"),
map(flag("--xml"), () => "xml"),
)
);
This is particularly useful for organizing mutually exclusive flags, multiple inputs, or any parser that doesn't natively support labeling. The resulting help text becomes much more scannable and user-friendly.
Here's how the grouped output format options appear in the help text:
Demo app showcasing group combinator
Usage: demo-group.ts --json
demo-group.ts --yaml
demo-group.ts --xml
Output Format:
--json Output in JSON format
--yaml Output in YAML format
--xml Output in XML format
Rich documentation support
Optique 0.4.0 introduces comprehensive documentation fields that can be added
directly through the run()
function, eliminating the need to modify parser
definitions for documentation purposes.
Brief descriptions, detailed explanations, and footers
Both @optique/core/facade and @optique/run now support brief
,
description
, and footer
options through the run()
function:
import { run } from "@optique/run";
import { message } from "@optique/core/message";
const result = run(parser, {
brief: message`A powerful data processing tool`,
description: message`This tool provides comprehensive data processing capabilities with support for multiple formats and transformations. It can handle JSON, YAML, and CSV files with automatic format detection.`,
footer: message`Examples:
myapp process data.json --format yaml
myapp validate config.toml --strict
For more information, visit https://example.com/docs`,
help: "option"
});
These documentation fields appear in both help output and error messages (when configured), providing consistent context throughout your CLI's user experience.
The complete help output demonstrates the rich documentation features with brief description, detailed explanation, option descriptions, default values, and footer information:
A powerful data processing tool
Usage: demo-rich-docs.ts [--port INTEGER] [--format STRING] --verbose STRING
This tool provides comprehensive data processing capabilities with support for
multiple formats and transformations. It can handle JSON, YAML, and CSV files
with automatic format detection.
--port INTEGER Server port number [3000]
--format STRING Output format [json]
--verbose STRING Verbosity level
Examples:
myapp process data.json --format yaml
myapp validate config.toml --strict
For more information, visit https://example.com/docs
These documentation fields appear in both help output and error messages (when configured), providing consistent context throughout your CLI's user experience.
Display default values
A frequently requested feature is now available: showing default values
directly in help text. Enable this with the new showDefault
option when
using withDefault()
:
const parser = object({
port: withDefault(
option("--port", integer(), { description: message`Server port number` }),
3000,
),
format: withDefault(
option("--format", string(), { description: message`Output format` }),
"json",
),
});
run(parser, { showDefault: true });
// Or with custom formatting:
run(parser, {
showDefault: {
prefix: " (default: ",
suffix: ")"
} // Shows: --port (default: 3000)
});
Default values are automatically dimmed when colors are enabled, making them visually distinct while remaining readable.
The help output shows default values clearly marked next to each option:
Usage: demo-defaults.ts [--port INTEGER] [--format STRING]
--port INTEGER Server port number [3000]
--format STRING Output format [json]
Temporal API support
Optique 0.4.0 introduces a new package, @optique/temporal, providing comprehensive support for the modern Temporal API. This brings type-safe parsing for dates, times, durations, and time zones:
import { instant, duration, zonedDateTime } from "@optique/temporal";
import { option } from "@optique/core/parser";
const parser = object({
// Parse ISO 8601 timestamps
timestamp: option("--at", instant()),
// Parse durations like "PT30M" or "P1DT2H"
timeout: option("--timeout", duration()),
// Parse zoned datetime with timezone info
meeting: option("--meeting", zonedDateTime()),
});
The temporal parsers return native Temporal objects with full functionality:
const result = parse(timestampArg, ["2023-12-25T10:30:00Z"]);
if (result.success) {
const instant = result.value;
console.log(`UTC: ${instant.toString()}`);
console.log(`Seoul: ${instant.toZonedDateTimeISO("Asia/Seoul")}`);
}
Install the new package with:
npm add @optique/temporal
Improved type inference
The merge()
combinator now supports up to 10 parsers (previously 5), and
the tuple()
parser has improved type inference using TypeScript's const
type parameter. These enhancements enable more complex CLI structures while
maintaining perfect type safety.
Breaking changes
While we've maintained backward compatibility for most APIs, there are a few changes to be aware of:
- The
Parser.getDocFragments()
method now usesDocState<TState>
instead of direct state values (only affects custom parser implementations) - The
merge()
combinator now enforces stricter type constraints at compile time, rejecting non-object-producing parsers
Learn more
For a complete list of changes, bug fixes, and improvements, see the full changelog.
Check out the updated documentation:
- Structured messages guide for the new documentation features
- Construct combinators reference for
merge()
andgroup()
usage - Value parsers guide for temporal parsing
- CLI patterns cookbook for practical examples
Installation
Upgrade to Optique 0.4.0:
npm update @optique/core @optique/run
# or
deno add jsr:@optique/core@^0.4.0 jsr:@optique/run@^0.4.0
Add temporal support (optional):
npm add @optique/temporal
# or
deno add jsr:@optique/temporal
We hope these improvements make building CLI applications with Optique even more enjoyable. As always, we welcome your feedback and contributions on GitHub.