0
# Annotations API
1
2
Declarative command definition using annotations for options, parameters, commands, and argument groups. The annotation approach provides the most concise way to define CLI interfaces with minimal boilerplate code.
3
4
## Capabilities
5
6
### @Command Annotation
7
8
Marks a class or method as a command with metadata like name, description, version, and subcommands.
9
10
```java { .api }
11
@Target({ElementType.TYPE, ElementType.METHOD})
12
@Retention(RetentionPolicy.RUNTIME)
13
public @interface Command {
14
String name() default "";
15
String[] aliases() default {};
16
String description() default "";
17
String[] header() default {};
18
String[] footer() default {};
19
boolean abbreviateSynopsis() default false;
20
String customSynopsis() default "";
21
boolean hidden() default false;
22
String version() default "";
23
boolean mixinStandardHelpOptions() default false;
24
Class<?>[] subcommands() default {};
25
String separator() default " ";
26
String synopsisSubcommandLabel() default "COMMAND";
27
Class<? extends IVersionProvider> versionProvider() default IVersionProvider.class;
28
boolean sortOptions() default true;
29
boolean showDefaultValues() default false;
30
Class<? extends IDefaultValueProvider> defaultValueProvider() default IDefaultValueProvider.class;
31
Class<? extends IHelpFactory> helpFactory() default IHelpFactory.class;
32
String parameterListHeading() default "";
33
String optionListHeading() default "";
34
String commandListHeading() default "";
35
String headerHeading() default "";
36
String synopsisHeading() default "";
37
String descriptionHeading() default "";
38
String footerHeading() default "";
39
ScopeType scope() default ScopeType.INHERIT;
40
}
41
```
42
43
**Usage Example:**
44
45
```java
46
@Command(name = "git",
47
description = "The Git version control system",
48
version = "Git 2.30.0",
49
mixinStandardHelpOptions = true,
50
subcommands = {GitAdd.class, GitCommit.class, GitPush.class})
51
public class Git implements Runnable {
52
@Override
53
public void run() {
54
System.out.println("Git - version control system");
55
}
56
}
57
```
58
59
### @Option Annotation
60
61
Marks a field or method parameter as a command line option with names, description, and various configuration attributes.
62
63
```java { .api }
64
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
65
@Retention(RetentionPolicy.RUNTIME)
66
public @interface Option {
67
String[] names();
68
boolean required() default false;
69
boolean help() default false;
70
boolean usageHelp() default false;
71
boolean versionHelp() default false;
72
boolean interactive() default false;
73
boolean echo() default true;
74
String prompt() default "";
75
String description() default "";
76
String descriptionKey() default "";
77
String paramLabel() default "";
78
boolean hideParamSyntax() default false;
79
boolean hidden() default false;
80
Class<?>[] type() default {};
81
String defaultValue() default NULL_VALUE;
82
String fallbackValue() default NULL_VALUE;
83
String mapFallbackValue() default NULL_VALUE;
84
Help.Visibility showDefaultValue() default Help.Visibility.ON_DEMAND;
85
Class<? extends ITypeConverter<?>>[] converter() default {};
86
Class<? extends Iterable<String>> completionCandidates() default Iterable.class;
87
String split() default "";
88
String splitSynopsisLabel() default "";
89
boolean negatable() default false;
90
Class<? extends IParameterConsumer> parameterConsumer() default IParameterConsumer.class;
91
Class<? extends IParameterPreprocessor> preprocessor() default IParameterPreprocessor.class;
92
ScopeType scope() default ScopeType.INHERIT;
93
int order() default -1;
94
String arity() default "";
95
Class<? extends IDefaultValueProvider> defaultValueProvider() default IDefaultValueProvider.class;
96
97
public static final String NULL_VALUE = "__no_default_value__";
98
}
99
```
100
101
**Usage Examples:**
102
103
```java
104
@Option(names = {"-v", "--verbose"}, description = "Enable verbose output")
105
boolean verbose;
106
107
@Option(names = {"-f", "--file"},
108
description = "Input file",
109
required = true,
110
paramLabel = "FILE")
111
File inputFile;
112
113
@Option(names = {"-n", "--count"},
114
description = "Number of iterations (default: ${DEFAULT-VALUE})",
115
defaultValue = "1",
116
showDefaultValue = true)
117
int count;
118
119
@Option(names = {"-c", "--config"},
120
arity = "0..1",
121
fallbackValue = "default.conf",
122
description = "Configuration file (default: ${FALLBACK-VALUE})")
123
String configFile;
124
```
125
126
### @Parameters Annotation
127
128
Marks a field or method parameter as positional parameters with index, description, and arity specification.
129
130
```java { .api }
131
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
132
@Retention(RetentionPolicy.RUNTIME)
133
public @interface Parameters {
134
String index() default "";
135
String arity() default "";
136
String paramLabel() default "";
137
boolean hideParamSyntax() default false;
138
boolean hidden() default false;
139
Class<?>[] type() default {};
140
Class<? extends ITypeConverter<?>>[] converter() default {};
141
String description() default "";
142
String descriptionKey() default "";
143
String defaultValue() default NULL_VALUE;
144
String mapFallbackValue() default NULL_VALUE;
145
Help.Visibility showDefaultValue() default Help.Visibility.ON_DEMAND;
146
Class<? extends Iterable<String>> completionCandidates() default Iterable.class;
147
boolean interactive() default false;
148
boolean echo() default true;
149
String prompt() default "";
150
String split() default "";
151
String splitSynopsisLabel() default "";
152
Class<? extends IParameterConsumer> parameterConsumer() default IParameterConsumer.class;
153
Class<? extends IParameterPreprocessor> preprocessor() default IParameterPreprocessor.class;
154
ScopeType scope() default ScopeType.INHERIT;
155
int order() default -1;
156
Class<? extends IDefaultValueProvider> defaultValueProvider() default IDefaultValueProvider.class;
157
158
public static final String NULL_VALUE = "__no_default_value__";
159
}
160
```
161
162
**Usage Examples:**
163
164
```java
165
@Parameters(index = "0", description = "Input file to process")
166
String inputFile;
167
168
@Parameters(index = "1..*",
169
description = "Output files",
170
arity = "1..*")
171
List<String> outputFiles;
172
173
@Parameters(description = "Files to process",
174
arity = "0..*")
175
String[] files;
176
177
@Parameters(index = "0",
178
description = "Command to execute",
179
completionCandidates = "start,stop,restart,status")
180
String command;
181
```
182
183
### @ParentCommand Annotation
184
185
Injects a reference to the parent command object into a field or parameter of a subcommand.
186
187
```java { .api }
188
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
189
@Retention(RetentionPolicy.RUNTIME)
190
public @interface ParentCommand { }
191
```
192
193
**Usage Example:**
194
195
```java
196
@Command(name = "add")
197
public class GitAdd implements Runnable {
198
@ParentCommand
199
Git parent;
200
201
@Override
202
public void run() {
203
// Access parent command configuration
204
if (parent.verbose) {
205
System.out.println("Verbose mode inherited from parent");
206
}
207
}
208
}
209
```
210
211
### @Unmatched Annotation
212
213
Collects unmatched command line arguments into a field or parameter.
214
215
```java { .api }
216
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
217
@Retention(RetentionPolicy.RUNTIME)
218
public @interface Unmatched { }
219
```
220
221
**Usage Example:**
222
223
```java
224
@Command(name = "wrapper")
225
public class CommandWrapper implements Runnable {
226
@Unmatched
227
List<String> unmatchedArgs;
228
229
@Override
230
public void run() {
231
// Pass unmatched arguments to another process
232
ProcessBuilder pb = new ProcessBuilder();
233
pb.command().addAll(unmatchedArgs);
234
// ... execute process
235
}
236
}
237
```
238
239
### @Mixin Annotation
240
241
Includes options and parameters from another class, enabling composition and reuse of common option sets.
242
243
```java { .api }
244
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
245
@Retention(RetentionPolicy.RUNTIME)
246
public @interface Mixin {
247
String name() default "";
248
}
249
```
250
251
**Usage Example:**
252
253
```java
254
public class VerbosityMixin {
255
@Option(names = {"-v", "--verbose"}, description = "Enable verbose output")
256
boolean verbose;
257
258
@Option(names = {"-q", "--quiet"}, description = "Suppress output")
259
boolean quiet;
260
}
261
262
@Command(name = "mycommand")
263
public class MyCommand implements Runnable {
264
@Mixin
265
VerbosityMixin verbosity;
266
267
@Override
268
public void run() {
269
if (verbosity.verbose) {
270
System.out.println("Verbose mode enabled");
271
}
272
}
273
}
274
```
275
276
### @Spec Annotation
277
278
Injects the CommandSpec model object into a field or parameter, providing access to the programmatic API.
279
280
```java { .api }
281
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
282
@Retention(RetentionPolicy.RUNTIME)
283
public @interface Spec { }
284
```
285
286
**Usage Example:**
287
288
```java
289
@Command(name = "dynamic")
290
public class DynamicCommand implements Runnable {
291
@Spec
292
CommandSpec spec;
293
294
@Override
295
public void run() {
296
// Access command metadata programmatically
297
System.out.printf("Command name: %s%n", spec.name());
298
System.out.printf("Number of options: %d%n", spec.options().size());
299
}
300
}
301
```
302
303
### @ArgGroup Annotation
304
305
Groups related arguments with validation rules for mutually exclusive or dependent options.
306
307
```java { .api }
308
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
309
@Retention(RetentionPolicy.RUNTIME)
310
public @interface ArgGroup {
311
boolean exclusive() default true;
312
String multiplicity() default "";
313
int order() default -1;
314
String heading() default "";
315
boolean validate() default true;
316
}
317
```
318
319
**Usage Examples:**
320
321
```java
322
// Mutually exclusive options
323
static class ExclusiveGroup {
324
@Option(names = "-a") boolean a;
325
@Option(names = "-b") boolean b;
326
@Option(names = "-c") boolean c;
327
}
328
329
@Command(name = "app")
330
public class App {
331
@ArgGroup(exclusive = true, multiplicity = "1")
332
ExclusiveGroup group;
333
}
334
335
// Dependent options (all or none)
336
static class DependentGroup {
337
@Option(names = "--user", required = true) String user;
338
@Option(names = "--password", required = true) String password;
339
}
340
341
@Command(name = "login")
342
public class LoginCommand {
343
@ArgGroup(exclusive = false, multiplicity = "0..1")
344
DependentGroup credentials;
345
}
346
```
347
348
## Supporting Types
349
350
```java { .api }
351
public enum ScopeType {
352
/** Inherit parent command's configuration */
353
INHERIT,
354
/** Use local configuration only */
355
LOCAL
356
}
357
```