@optique/core 1.2.0-dev.2259 → 1.2.0-dev.2262

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.2.0-dev.2259",
3
+ "version": "1.2.0-dev.2262",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",
@@ -36,8 +36,17 @@
36
36
  "files": [
37
37
  "dist/",
38
38
  "package.json",
39
- "README.md"
39
+ "README.md",
40
+ "skills/optique/SKILL.md"
40
41
  ],
42
+ "agents": {
43
+ "skills": [
44
+ {
45
+ "name": "optique",
46
+ "path": "./skills/optique"
47
+ }
48
+ ]
49
+ },
41
50
  "type": "module",
42
51
  "module": "./dist/index.js",
43
52
  "main": "./dist/index.cjs",
@@ -216,14 +225,14 @@
216
225
  "fast-check": "^4.7.0",
217
226
  "tsdown": "^0.13.0",
218
227
  "typescript": "^5.8.3",
219
- "@optique/env": "1.2.0-dev.2259+0b30260e"
228
+ "@optique/env": "1.2.0-dev.2262+c3fb3a95"
220
229
  },
221
230
  "scripts": {
222
231
  "build": "tsdown",
223
232
  "prepublish": "tsdown",
224
233
  "test": "node --test",
225
234
  "test:bun": "bun test",
226
- "test:deno": "deno test",
227
- "test-all": "tsdown && node --test && bun test && deno test"
235
+ "test:deno": "deno test --allow-read --allow-env",
236
+ "test-all": "tsdown && node --test && bun test && deno test --allow-read --allow-env"
228
237
  }
229
238
  }
@@ -0,0 +1,229 @@
1
+ ---
2
+ name: optique
3
+ description: >
4
+ Use this skill when writing any code that builds a command-line interface
5
+ with Optique in TypeScript or JavaScript. Covers the combinatorial parser
6
+ model, choosing @optique/core vs @optique/run, value parsers, structured
7
+ messages, optional()/withDefault()/multiple(), subcommands with command()
8
+ and or(), shell completion, async parsing, the integration packages, and
9
+ common mistakes to avoid. Trigger whenever the user is parsing command-line
10
+ arguments, building a CLI, or adding options or subcommands to a tool.
11
+ license: MIT
12
+ ---
13
+
14
+ Optique is a type-safe combinatorial CLI parser. Use it by describing the CLI
15
+ grammar with parsers and combinators, not by manually walking `argv`.
16
+
17
+ If web access is available, start from <https://optique.dev/llms.txt> for the
18
+ maintained documentation index. Keep the rules below in mind even when offline;
19
+ they cover the parts agents most often get wrong.
20
+
21
+
22
+ Core rules
23
+ ----------
24
+
25
+ - Use `run()` from `@optique/run` for real CLI applications. It reads
26
+ `process.argv`/`Deno.args`, handles help, version output, errors, exit
27
+ codes, colors, terminal width, and shell completion. Use `parse()` from
28
+ `@optique/core/parser` or `runParser()` from `@optique/core/facade` when
29
+ embedding Optique in tests, libraries, tools, or custom runtimes.
30
+ - Compose parsers with `object()`, `tuple()`, `seq()`, `or()`, `merge()`, and
31
+ modifiers. Do not write imperative `if`/`else` argument scanners around
32
+ Optique parsers.
33
+ - Let TypeScript infer the parsed value type from the parser. Do not
34
+ hand-maintain a separate interface for the result unless another API
35
+ boundary requires it.
36
+ - Most parsers are required until you wrap them. `optional(p)` yields
37
+ `undefined`; `withDefault(p, value)` yields a fallback value. For Boolean
38
+ flags, use `withDefault(flag("--name"), false)` when absence should mean
39
+ `false`.
40
+ - Use `message` from `@optique/core/message` for descriptions, help text, and
41
+ custom errors. Prefer semantic message helpers such as `optionName()` and
42
+ `metavar()` over string concatenation when naming CLI elements.
43
+ - Use value parsers such as `integer()`, `choice()`, `url()`, and `uuid()`
44
+ instead of validating raw strings after parsing. Use `path()` from
45
+ `@optique/run/valueparser` for file-system paths. Write a custom
46
+ `{ mode, metavar, parse, format }` value parser only when the catalog does
47
+ not cover the domain.
48
+ - Async value parsers make the containing parser async. If you use packages
49
+ such as `@optique/git`, remember to `await run(...)`, `await parse(...)`, or
50
+ `await runParser(...)` as appropriate.
51
+ - Build subcommands with `command()` combined by `or()`. Put a literal field
52
+ such as `command: constant("serve")` in each branch when you want a
53
+ discriminated union.
54
+ - Enable completion through `run(parser, { completion: "both" })` for CLI
55
+ apps. Do not hand-write completion scripts from parser metadata.
56
+
57
+
58
+ Canonical app shape
59
+ -------------------
60
+
61
+ ~~~~ typescript
62
+ import { object } from "@optique/core/constructs";
63
+ import { message } from "@optique/core/message";
64
+ import { withDefault } from "@optique/core/modifiers";
65
+ import { argument, flag, option } from "@optique/core/primitives";
66
+ import { integer, string } from "@optique/core/valueparser";
67
+ import { run } from "@optique/run";
68
+
69
+ const parser = object({
70
+ input: argument(string({ metavar: "FILE" }), {
71
+ description: message`Input file to process.`,
72
+ }),
73
+ port: withDefault(
74
+ option("--port", integer({ min: 1, max: 65535 }), {
75
+ description: message`Port to listen on.`,
76
+ }),
77
+ 3000,
78
+ ),
79
+ verbose: withDefault(
80
+ flag("-v", "--verbose", { description: message`Enable verbose logging.` }),
81
+ false,
82
+ ),
83
+ });
84
+
85
+ const config = run(parser, {
86
+ brief: message`Process a file.`,
87
+ completion: "both",
88
+ showDefault: true,
89
+ });
90
+
91
+ console.log(`Processing ${config.input} on port ${config.port}.`);
92
+ ~~~~
93
+
94
+
95
+ Subcommands
96
+ -----------
97
+
98
+ Use `command()` for each branch and `or()` to require exactly one matching
99
+ subcommand. Use `optional(or(...))` only when no subcommand is valid.
100
+
101
+ ~~~~ typescript
102
+ import { object, or } from "@optique/core/constructs";
103
+ import { withDefault } from "@optique/core/modifiers";
104
+ import { parse } from "@optique/core/parser";
105
+ import { command, constant, flag, option } from "@optique/core/primitives";
106
+ import { integer } from "@optique/core/valueparser";
107
+
108
+ const parser = or(
109
+ command("build", object({
110
+ command: constant("build"),
111
+ watch: withDefault(flag("--watch"), false),
112
+ })),
113
+ command("serve", object({
114
+ command: constant("serve"),
115
+ port: withDefault(option("--port", integer({ min: 1 })), 3000),
116
+ })),
117
+ );
118
+
119
+ const result = parse(parser, ["serve", "--port", "8080"]);
120
+
121
+ if (result.success) {
122
+ switch (result.value.command) {
123
+ case "build":
124
+ result.value.watch;
125
+ break;
126
+ case "serve":
127
+ result.value.port;
128
+ break;
129
+ }
130
+ }
131
+ ~~~~
132
+
133
+
134
+ Custom value parsers
135
+ --------------------
136
+
137
+ Prefer the built-in catalog first. When a custom domain is needed, keep the
138
+ validation in a value parser so help, errors, defaults, prompts, and completion
139
+ all see the same typed value.
140
+
141
+ ~~~~ typescript
142
+ import { message } from "@optique/core/message";
143
+ import type { ValueParser, ValueParserResult } from "@optique/core/valueparser";
144
+
145
+ const levels = ["debug", "info", "warn", "error"] as const;
146
+ type Level = typeof levels[number];
147
+
148
+ function isLevel(input: string): input is Level {
149
+ return (levels as readonly string[]).includes(input);
150
+ }
151
+
152
+ function logLevel(): ValueParser<"sync", Level> {
153
+ return {
154
+ mode: "sync",
155
+ metavar: "LEVEL",
156
+ placeholder: "info",
157
+ parse(input: string): ValueParserResult<Level> {
158
+ if (isLevel(input)) return { success: true, value: input };
159
+ return { success: false, error: message`Invalid log level: ${input}.` };
160
+ },
161
+ format(value: Level): string {
162
+ return value;
163
+ },
164
+ };
165
+ }
166
+
167
+ const parser = logLevel();
168
+ ~~~~
169
+
170
+
171
+ Common mistakes checklist
172
+ -------------------------
173
+
174
+ - Do not parse `process.argv` manually before calling Optique. Pass the parser
175
+ to `run()` for applications, or pass explicit argument arrays to `parse()`
176
+ in tests and embedded use.
177
+ - Do not treat `or(a, b)` as “zero or more alternatives.” It requires one
178
+ matching branch unless the whole `or()` is wrapped in `optional()` or
179
+ `withDefault()`.
180
+ - Do not use `object()` for mutually exclusive subcommands. Use
181
+ `or(command(...), command(...))`.
182
+ - Do not forget that `flag("--x")` is required. Wrap it in `optional()` or
183
+ `withDefault(..., false)` for ordinary optional flags.
184
+ - Do not expect `multiple(p)` to fail when absent; it returns `[]`. Wrap with
185
+ `nonEmpty()` when at least one value is required.
186
+ - Do not confuse free-order parsing with `seq()`. Most constructs let child
187
+ parsers compete by priority; use `seq()` only when the grammar is truly
188
+ ordered.
189
+ - Do not concatenate plain strings for errors or descriptions. Use structured
190
+ `message` values.
191
+ - Do not forget to register source contexts when using `bindEnv()`,
192
+ `bindConfig()`, or `bindDerivedDefault()`.
193
+
194
+ For the detailed maintained guide, use <https://optique.dev/pitfalls.md>.
195
+
196
+
197
+ Reference links
198
+ ---------------
199
+
200
+ - Documentation index for agents: <https://optique.dev/llms.txt>
201
+ - Runners and entry points: <https://optique.dev/concepts/runners.md>
202
+ - Primitive parsers: <https://optique.dev/concepts/primitives.md>
203
+ - Construct combinators: <https://optique.dev/concepts/constructs.md>
204
+ - Modifiers: <https://optique.dev/concepts/modifiers.md>
205
+ - Value parser catalog: <https://optique.dev/concepts/valueparsers.md>
206
+ - Structured messages: <https://optique.dev/concepts/messages.md>
207
+ - Shell completion: <https://optique.dev/concepts/completion.md>
208
+ - Command discovery: <https://optique.dev/concepts/discover.md>
209
+ - Man pages: <https://optique.dev/concepts/man.md>
210
+
211
+
212
+ Integration packages
213
+ --------------------
214
+
215
+ | Package | Use for | Docs |
216
+ | --------------------------- | ----------------------------------------- | -------------------------------------------------- |
217
+ | `@optique/env` | Environment variable fallbacks | <https://optique.dev/integrations/env.md> |
218
+ | `@optique/config` | Configuration file fallbacks | <https://optique.dev/integrations/config.md> |
219
+ | `@optique/derived-defaults` | Defaults computed from first-pass results | <https://optique.dev/concepts/derived-defaults.md> |
220
+ | `@optique/prompt` | Generic prompt adapter foundation | <https://optique.dev/integrations/prompt.md> |
221
+ | `@optique/clack` | Clack interactive fallback prompts | <https://optique.dev/integrations/clack.md> |
222
+ | `@optique/inquirer` | Inquirer.js interactive fallback prompts | <https://optique.dev/integrations/inquirer.md> |
223
+ | `@optique/zod` | Zod-backed value parsing | <https://optique.dev/integrations/zod.md> |
224
+ | `@optique/valibot` | Valibot-backed value parsing | <https://optique.dev/integrations/valibot.md> |
225
+ | `@optique/temporal` | Temporal date and time parsers | <https://optique.dev/integrations/temporal.md> |
226
+ | `@optique/git` | Async Git reference validation | <https://optique.dev/integrations/git.md> |
227
+ | `@optique/logtape` | LogTape verbosity and log-level options | <https://optique.dev/integrations/logtape.md> |
228
+ | `@optique/man` | Man page generation | <https://optique.dev/concepts/man.md> |
229
+ | `@optique/discover` | File-based command discovery | <https://optique.dev/concepts/discover.md> |