cleye 2.4.0 → 2.5.0
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 +3 -2
- package/skills/cleye/SKILL.md +263 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cleye",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "The intuitive CLI development tool",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"email": "hiroki.osame@gmail.com"
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
|
-
"dist"
|
|
22
|
+
"dist",
|
|
23
|
+
"skills"
|
|
23
24
|
],
|
|
24
25
|
"type": "module",
|
|
25
26
|
"main": "./dist/index.cjs",
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cleye
|
|
3
|
+
description: cleye CLI development tool — argv parsing with typed parameters, flags, commands, and auto-generated help. Use when building Node.js CLI scripts with cleye or when the user imports `cli` or `command` from `cleye`.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# cleye
|
|
7
|
+
|
|
8
|
+
## Quick Patterns
|
|
9
|
+
|
|
10
|
+
| Task | Pattern |
|
|
11
|
+
|------|---------|
|
|
12
|
+
| Basic CLI | `cli({ name, parameters, flags })` |
|
|
13
|
+
| Named command | `command({ name, parameters, flags }, callback)` |
|
|
14
|
+
| Register commands | `cli({ commands: [cmd1, cmd2] })` |
|
|
15
|
+
| Async callback | `await cli({ ... }, async (argv) => { ... })` |
|
|
16
|
+
| Raw argv | `cli({ ... }, callback, process.argv.slice(2))` |
|
|
17
|
+
|
|
18
|
+
## Parameters
|
|
19
|
+
|
|
20
|
+
Positional arguments mapped to named properties on `argv._`.
|
|
21
|
+
|
|
22
|
+
| Format | Description |
|
|
23
|
+
|--------|-------------|
|
|
24
|
+
| `<name>` | Required |
|
|
25
|
+
| `[name]` | Optional |
|
|
26
|
+
| `<name...>` | Required spread (1+) |
|
|
27
|
+
| `[name...]` | Optional spread (0+) |
|
|
28
|
+
| `--` | End-of-flags separator |
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
const argv = cli({
|
|
32
|
+
parameters: ['<required>', '[optional]', '[rest...]']
|
|
33
|
+
})
|
|
34
|
+
argv._.required // string
|
|
35
|
+
argv._.optional // string | undefined
|
|
36
|
+
argv._.rest // string[]
|
|
37
|
+
argv._['--'] // string[] — everything after --
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Multi-word names use camelCase on `argv._`: `'<first name>'` → `argv._.firstName`.
|
|
41
|
+
|
|
42
|
+
## Flags
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
const argv = cli({
|
|
46
|
+
flags: {
|
|
47
|
+
verbose: Boolean, // shorthand
|
|
48
|
+
output: {
|
|
49
|
+
type: String,
|
|
50
|
+
alias: 'o',
|
|
51
|
+
default: 'dist',
|
|
52
|
+
description: 'Output directory',
|
|
53
|
+
placeholder: '<path>'
|
|
54
|
+
},
|
|
55
|
+
count: {
|
|
56
|
+
type: [Number], // array: -n 1 -n 2
|
|
57
|
+
alias: 'n'
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
argv.flags.verbose // boolean | undefined
|
|
63
|
+
argv.flags.output // string
|
|
64
|
+
argv.flags.count // number[]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Flag name is camelCase; parsed from kebab-case CLI input (`--output-dir` → `outputDir`).
|
|
68
|
+
|
|
69
|
+
**Delimiters** — `=`, `:`, and `.` all work as value separators:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
--flag=value --flag:value --flag.value
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Use `:` when the value itself contains `=` (e.g. `--define:KEY=VALUE`).
|
|
76
|
+
|
|
77
|
+
**Counting flags** — use `[Boolean]` and check `.length`:
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
cli({
|
|
81
|
+
flags: {
|
|
82
|
+
verbose: {
|
|
83
|
+
type: [Boolean],
|
|
84
|
+
alias: 'v'
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
// -vvv → argv.flags.verbose.length === 3
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Optional value** — custom type returns `true` when no value is given:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
const OptionalString = (value: string) => value || true
|
|
95
|
+
cli({ flags: { tag: OptionalString } })
|
|
96
|
+
// --tag → true
|
|
97
|
+
// --tag beta → 'beta'
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Boolean Flag Negation
|
|
101
|
+
|
|
102
|
+
By default, set a boolean flag to `false` using the `=` operator:
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
--verbose=false # → false
|
|
106
|
+
--verbose false # → true (false treated as separate argument)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
To also support the `--no-<flag>` convention, enable `booleanFlagNegation` (additive — `=false` still works):
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
cli({
|
|
113
|
+
flags: { verbose: Boolean },
|
|
114
|
+
booleanFlagNegation: true
|
|
115
|
+
})
|
|
116
|
+
// --no-verbose → false
|
|
117
|
+
// --verbose=false → false (still works)
|
|
118
|
+
// Last-wins: --verbose --no-verbose → false
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Commands inherit `booleanFlagNegation` from the parent `cli()` but can override it.
|
|
122
|
+
|
|
123
|
+
## Strict Flags
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
cli({
|
|
127
|
+
flags: { foo: Boolean },
|
|
128
|
+
strictFlags: true
|
|
129
|
+
})
|
|
130
|
+
// --baz → Error: Unknown flag: --baz. (Did you mean --foo?)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Commands inherit `strictFlags` but can override it.
|
|
134
|
+
|
|
135
|
+
## Commands
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
// install-command.ts
|
|
139
|
+
export const installCommand = command({
|
|
140
|
+
name: 'install',
|
|
141
|
+
alias: ['i', 'add'],
|
|
142
|
+
parameters: ['<package name>'],
|
|
143
|
+
flags: { saveDev: Boolean }
|
|
144
|
+
}, (argv) => {
|
|
145
|
+
argv._.packageName // string
|
|
146
|
+
argv.flags.saveDev // boolean | undefined
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
// main.ts
|
|
150
|
+
cli({
|
|
151
|
+
name: 'npm',
|
|
152
|
+
version: '1.0.0',
|
|
153
|
+
commands: [installCommand]
|
|
154
|
+
})
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
When a command is matched, `argv.command` narrows the type for type-safe branching.
|
|
158
|
+
|
|
159
|
+
## Help & Version
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
cli({
|
|
163
|
+
name: 'my-script',
|
|
164
|
+
version: '1.2.3', // enables --version; also shown in --help
|
|
165
|
+
help: {
|
|
166
|
+
description: 'Does things',
|
|
167
|
+
usage: 'my-script [flags] <file>',
|
|
168
|
+
examples: ['my-script foo.txt', 'my-script --output=dist foo.txt'],
|
|
169
|
+
version: '1.2.3' // show version in --help without handling --version
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
// help: false — disables --help handling; call argv.showHelp() manually
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Custom Flag Types
|
|
176
|
+
|
|
177
|
+
Any function `(value: string) => T` works as a flag type — the return type is inferred.
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
// Validation + narrowing
|
|
181
|
+
const Port = (value: string) => {
|
|
182
|
+
const n = Number(value)
|
|
183
|
+
if (!Number.isInteger(n) || n < 1 || n > 65_535) { throw new Error(`Invalid port: ${value}`) }
|
|
184
|
+
return n
|
|
185
|
+
}
|
|
186
|
+
// argv.flags.port → number
|
|
187
|
+
|
|
188
|
+
// Enum
|
|
189
|
+
const sizes = ['small', 'medium', 'large'] as const
|
|
190
|
+
const Size = (v: string) => {
|
|
191
|
+
if (!(sizes as readonly string[]).includes(v)) { throw new Error(`Expected: ${sizes.join(', ')}`) }
|
|
192
|
+
return v as typeof sizes[number]
|
|
193
|
+
}
|
|
194
|
+
// argv.flags.size → 'small' | 'medium' | 'large'
|
|
195
|
+
|
|
196
|
+
// Comma-separated list
|
|
197
|
+
const List = (v: string) => v.split(',')
|
|
198
|
+
// --tags a,b,c → argv.flags.tags === ['a', 'b', 'c']
|
|
199
|
+
|
|
200
|
+
// Inline JSON
|
|
201
|
+
cli({ flags: { data: JSON.parse } })
|
|
202
|
+
// --data '{"key":1}' → argv.flags.data === { key: 1 }
|
|
203
|
+
|
|
204
|
+
// Dot-nested object (combine with . delimiter)
|
|
205
|
+
const Env = (v: string): Record<string, string | true> => {
|
|
206
|
+
const [k, value] = v.split('=')
|
|
207
|
+
return { [k]: value ?? true }
|
|
208
|
+
}
|
|
209
|
+
cli({ flags: { env: [Env] } })
|
|
210
|
+
// --env.TOKEN=abc --env.CI → merge to { TOKEN: 'abc', CI: true }
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Help Customization
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
cli({
|
|
217
|
+
help: {
|
|
218
|
+
render(nodes, renderers) {
|
|
219
|
+
nodes.push('\nDocs: https://example.com')
|
|
220
|
+
renderers.flagOperator = () => '=' // --flag=<value>
|
|
221
|
+
return renderers.render(nodes)
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
})
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Default renderers: `/src/render-help/renderers.ts`.
|
|
228
|
+
|
|
229
|
+
## ignoreArgv
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
cli({
|
|
233
|
+
ignoreArgv(type, flagOrArgv, value) {
|
|
234
|
+
if (type === 'unknown-flag') { return true } // silently skip unknown flags
|
|
235
|
+
}
|
|
236
|
+
})
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
`type`: `'known-flag' | 'unknown-flag' | 'argument'`
|
|
240
|
+
|
|
241
|
+
## Return Type
|
|
242
|
+
|
|
243
|
+
```ts
|
|
244
|
+
type ParsedArgv = {
|
|
245
|
+
_: string[] & Parameters
|
|
246
|
+
flags: { [name: string]: InferredType }
|
|
247
|
+
unknownFlags: { [name: string]: (string | boolean)[] }
|
|
248
|
+
showVersion: () => void
|
|
249
|
+
showHelp: (options?: HelpOptions) => void
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## TypeScript Exports
|
|
254
|
+
|
|
255
|
+
```ts
|
|
256
|
+
import type { Flags, Renderers, TypeFlag } from 'cleye'
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
| Type | Use |
|
|
260
|
+
|------|-----|
|
|
261
|
+
| `Flags` | Type for the `flags` option object |
|
|
262
|
+
| `Renderers` | Help renderer class type for `help.render` customization |
|
|
263
|
+
| `TypeFlag` | Re-export from `type-flag` for portable type declarations |
|