Variables
It is possible to use variables in the command. There are multiple ways to define the values for those variables. But first, let's see how we define the variables.
We recommend using camel case to define the names of the variables. Variable names don't allow dashes.
If we change the previous command, we use hello to use a variable ${name} (line 9). Documenting what the variables mean is essential (lines 13-18). That will make it easier for the user to understand how to use the CLI tool.
1{
2 "profiles": [
3 {
4 "name": "main",
5 "commands": [
6 {
7 "name": "hello",
8 "execute": [
9 "echo 'Hello ${name}'"
10 ],
11 "help": {
12 "text": "say hello",
13 "variables": [
14 {
15 "name": "name",
16 "text": "the name to say hello"
17 }
18 ]
19 }
20 }
21 ]
22 }
23 ]
24}When you run the aux4 command, it will list the commands from the main profile and their variables.
1> aux41hello
2say hello
3 --nameNote that it doesn't show the variable's description. To do that, you must use aux4 --help.
1> aux4 --help1hello
2say hello
3
4 --name
5 the name to say helloParameter
The most common way to define the value for the variable is by passing it as a parameter in the CLI tool. To pass the parameter, send the variable name with a -- prefix as an argument to the aux4 command line.
1> aux4 hello --name David1Hello DavidAnother way to use it is with the = sign.
1> aux4 hello --name=David1Hello DavidIt's important to know that you must use quotes to send multiple words as the parameter's value.
1> aux4 hello --name "David SG"
2> aux4 hello --name 'David SG'
3> aux4 hello "--name=David SG"If you use the parameter without specifying the value, the value will be true.
1> aux4 hello --name1Hello trueBut if you use the = sign and don't specify the value, the value will be an empty string.
1> aux4 hello --name=1HelloPrompt
If you don't provide any parameters in the aux4 command, it will prompt the user to enter the missing variables.
1> aux4 hello1✔ name the name to say hello: |After the user inputs the name, it proceeds with the execution:
1name the name to say hello: David SG
2Hello David SGThe user can cancel using Ctrl+c.
1
2User abortedImportant: It will prompt the user to input the variable only if that variable is defined in the variables section of help.
Default
It's possible to define a default value for your variable. When you have the default value defined, the user will not be prompted to input the value if the parameter for that variable is not specified.
You can specify the variable's default value in the help section of the variable (line 18).
1{
2 "profiles": [
3 {
4 "name": "main",
5 "commands": [
6 {
7 "name": "create-dir",
8 "execute": [
9 "mkdir ${dir}",
10 "echo 'the directory ${dir} was created successfully'"
11 ],
12 "help": {
13 "text": "create a new directory",
14 "variables": [
15 {
16 "name": "dir",
17 "text": "the directory to be created",
18 "default": "new"
19 }
20 ]
21 }
22 }
23 ]
24 }
25 ]
26}The default value will be included in your command documentation.
1> aux4 create-dir --help1create-dir
2create a new directory
3
4 --dir
5 the directory to be created
6
7 Default: newThe default value will be overridden if you pass the parameter for the dir variable.
1> aux4 create-dir --dir downloads1the directory downloads was created successfullyOtherwise, it will use the default value immediately without prompting the user to input it.
1> aux4 create-dir1the directory new was created successfullyAn empty string is also a valid default value if you want to make that variable optional and not display the prompt for user input.
1...
2 {
3 ...
4 "default": ""
5 }
6...Type
By default every variable value is a string. Declaring a type coerces the value — from a flag, a default, or anywhere else — into that type. The typed value is used when the variable is placed into JSON (for example by object), while it still stringifies naturally when interpolated into a shell command.
| type | value becomes | example |
|---|---|---|
| string (default) | text, unchanged | "7" |
| number | a JSON number (the exact numeric text is kept, so 12.50 stays 12.50) | 7, 12.50 |
| boolean | true / false | true |
| json | a parsed JSON value — object, array, number, … | ["a","b"] |
An unparseable value (e.g. a number type given abc) falls back to the original string, so a mismatched declaration never loses data.
1...
2 {
3 "name": "keep",
4 "execute": [
5 "log:object(name,retain,active,tags)"
6 ],
7 "help": {
8 "text": "build a typed record",
9 "variables": [
10 { "name": "name", "text": "the name", "default": "shop" },
11 { "name": "retain", "type": "number", "text": "days to keep", "default": "7" },
12 { "name": "active", "type": "boolean", "text": "is active", "default": "true" },
13 { "name": "tags", "type": "json", "text": "labels", "default": "[\"a\",\"b\"]" }
14 ]
15 }
16 }
17...1> aux4 keep1{"active":true,"name":"shop","retain":7,"tags":["a","b"]}retain is a number, active a boolean and tags an array — no jq or manual conversion needed. Overriding with a flag keeps the type: --retain 30 --active false produces "retain":30,"active":false.
Environment Variable
You can also use environment variables to set the value of your variables. To do that, you just need to specify the name of the environment variable in the documentation of your variable (line 17).
1{
2 "profiles": [
3 {
4 "name": "main",
5 "commands": [
6 {
7 "name": "run",
8 "execute": [
9 "echo 'execute in ${env} environment'"
10 ],
11 "help": {
12 "text": "execute in the specified environment",
13 "variables": [
14 {
15 "name": "env",
16 "text": "the environment",
17 "env": "ENV"
18 }
19 ]
20 }
21 }
22 ]
23 }
24 ]
25}The name of the environment variable will show in the command documentation when you use --help.
1> aux4 run --help1run
2execute in the specified environment
3
4 --env
5 the environment
6
7 Environment variable: ENVThe environment variable value will be used only if you do not specify the parameter for your variable.
1> export ENV=DEV1> aux4 run --env PROD1execute in PROD environment1> aux4 run1execute in DEV environmentHidden Value
Sometimes, you will have to send some sensitive data to your CLI. It's not recommended to send them as parameters because they will be saved in the history of your terminal. Prompting is the best approach, but hiding the value is essential if someone is watching the user type that data.
Let's return to our Hello example. To hide the variable's value, we must set hide = true in the variable's documentation (line 17).
1{
2 "profiles": [
3 {
4 "name": "main",
5 "commands": [
6 {
7 "name": "hello",
8 "execute": [
9 "echo 'Hello ${name}'"
10 ],
11 "help": {
12 "text": "say hello",
13 "variables": [
14 {
15 "name": "name",
16 "text": "the name to say hello",
17 "hide": true
18 }
19 ]
20 }
21 }
22 ]
23 }
24 ]
25}Now, when you don't specify a parameter for that variable, it will prompt the user in the same way as before, but now, when the user types the value, it will be hidden.
1> aux4 hello1✔ name the name to say hello: *****Be aware that logging or printing the value will still display it in the output.
1name the name to say hello: *****
2Hello DavidPrivate Variable
Some variables exist for the command's own plumbing rather than for the person running it. Setting private = true keeps the variable out of the help, the man page and the shell autocomplete, while leaving it working exactly like any other variable (line 17).
1{
2 "profiles": [
3 {
4 "name": "main",
5 "commands": [
6 {
7 "name": "hello",
8 "execute": [
9 "echo 'Hello ${name} (${greeting})'"
10 ],
11 "help": {
12 "text": "say hello",
13 "variables": [
14 {
15 "name": "name",
16 "text": "the name to say hello"
17 },
18 {
19 "name": "greeting",
20 "text": "internal greeting template",
21 "default": "friendly",
22 "private": true
23 }
24 ]
25 }
26 }
27 ]
28 }
29 ]
30}The help only mentions name.
1> aux4 hello --help1hello
2say hello.
3
4 --name
5 the name to say hello.The variable is hidden, not disabled. It still applies its default, and it still accepts a value if you pass one.
1> aux4 hello --name Sally1Hello Sally (friendly)1> aux4 hello --name Sally --greeting formal1Hello Sally (formal)If every variable of a command is private, no parameters section is printed at all.
private is not the same as hide. hide conceals the value a user types while still listing the variable in the help. private conceals the variable itself. Use hide for secrets, and private for plumbing the user does not need to know about.
Commands support private in the same way, keeping a command out of the help while leaving it callable.
Argument
You can use only one of the variables as an argument of your command. It can be used to improve the usability of the command. Set the arg=true in the help section of the variable (line 17).
1{
2 "profiles": [
3 {
4 "name": "main",
5 "commands": [
6 {
7 "name": "get-data",
8 "execute": [
9 "echo 'get data from the website ${url}'"
10 ],
11 "help": {
12 "text": "get data from the website",
13 "variables": [
14 {
15 "name": "url",
16 "text": "the url of the API to get the data from",
17 "arg": true
18 }
19 ]
20 }
21 }
22 ]
23 }
24 ]
25}You can still send the url as a parameter.
1> aux4 get-data --url https://my.api.comOr you can also send it as an argument.
1> aux4 get-data https://my.api.comOptions
You can predefine a list of options for the user to choose from. It only works when the parameter is not defined.
If you have a default value defined, the list of options will be ignored.
1{
2 "profiles": [
3 {
4 "name": "main",
5 "commands": [
6 {
7 "name": "copy-files",
8 "execute": [
9 "echo 'copy files to ${target}'"
10 ],
11 "help": {
12 "text": "copy files to the target directory",
13 "variables": [
14 {
15 "name": "target",
16 "text": "the directory to copy the files to",
17 "options": [
18 "folder1",
19 "folder2",
20 "folder3"
21 ]
22 }
23 ]
24 }
25 }
26 ]
27 }
28 ]
29}When you run the command, it will prompt the user to select an option.
1> aux4 copy-files1Use the arrow keys to navigate: ↓ ↑ → ←
2? target the directory to copy the files to:
3 ▸ folder1
4 folder2
5 folder3The user can use the arrow keys to navigate and enter to choose the option they want.
1✔ folder2
2copy files to folder2The options are just suggestions to help the user choose the value of that variable. However, it will not validate the user's parameter, which means the user can pass a value not listed in the options.
1> aux4 copy-files --target folder41copy files to folder4Multi-Select Options
When a variable has both multiple: true and options, aux4 shows an interactive checkbox list instead of a single-select dropdown. The user can toggle multiple options using the space bar and confirm with enter.
1{
2 "profiles": [
3 {
4 "name": "main",
5 "commands": [
6 {
7 "name": "deploy",
8 "execute": [
9 "log:Deploying to: ${target*}"
10 ],
11 "help": {
12 "text": "deploy to target environments",
13 "variables": [
14 {
15 "name": "target",
16 "text": "target environments",
17 "multiple": true,
18 "options": [
19 "dev",
20 "staging",
21 "production"
22 ]
23 }
24 ]
25 }
26 }
27 ]
28 }
29 ]
30}When you run the command without the parameter, it shows a checkbox list:
1> aux4 deploy1? target target environments:
2 [x] dev
3 [ ] staging
4 [x] productionUse arrow keys to navigate, space to toggle, and enter to confirm. The selected values are stored as a multiple-value variable.
1Deploying to: ["dev","production"]You can still pass values directly as parameters:
1> aux4 deploy --target dev --target stagingMultiple Variables
You can allow a variable to accept multiple values by setting multiple: true in the variable definition.
1{
2 "profiles": [
3 {
4 "name": "main",
5 "commands": [
6 {
7 "name": "print-tags",
8 "execute": [
9 "log:Tags: ${tag*}"
10 ],
11 "help": {
12 "text": "print all tags",
13 "variables": [
14 {
15 "name": "tag",
16 "text": "tag to add",
17 "multiple": true
18 }
19 ]
20 }
21 }
22 ]
23 }
24 ]
25}Passing multiple values
You can pass multiple values by repeating the parameter:
1> aux4 print-tags --tag first --tag second --tag third1Tags: ["first","second","third"]Accessing specific values
Use ${variable*[index]} to access a specific value by index (0-based):
1...
2 {
3 "execute": [
4 "log:Second tag: ${tag*[1]}"
5 ],
6 ...
7 }
8...Accessing all values
Use ${variable*} to get all values as a JSON array:
1...
2 {
3 "execute": [
4 "log:All tags: ${tag*}"
5 ],
6 ...
7 }
8...Accessing last value
Use ${variable} (without *) to get only the last value:
1...
2 {
3 "execute": [
4 "log:Last tag: ${tag}"
5 ],
6 ...
7 }
8...Multiple with Argument
You can combine multiple: true with arg: true to accept multiple positional arguments:
1...
2 {
3 "help": {
4 "variables": [
5 {
6 "name": "file",
7 "text": "files to process",
8 "arg": true,
9 "multiple": true
10 }
11 ]
12 }
13 }
14...1> aux4 process file1.txt file2.txt file3.txtDollar Escape
Use $$ to output a literal $ character. This is useful when your execute command needs a real dollar sign that shouldn't be treated as a variable reference.
1...
2 {
3 "name": "show-price",
4 "execute": [
5 "echo 'Price: $$$amount'"
6 ],
7 "help": {
8 "variables": [
9 {
10 "name": "amount",
11 "text": "the price amount"
12 }
13 ]
14 }
15 }
16...1> aux4 show-price --amount 101Price: $10All Parameters
Use $* to get all named parameters as a JSON object. This is useful for forwarding all parameters to another command.
1...
2 {
3 "name": "forward",
4 "execute": [
5 "log:$*"
6 ],
7 "help": {
8 "variables": [
9 {
10 "name": "name",
11 "text": "the name"
12 },
13 {
14 "name": "age",
15 "text": "the age"
16 }
17 ]
18 }
19 }
20...1> aux4 forward --name Joe --age 201{"age":"20","name":"Joe"}Variable Lookup Order
When aux4 resolves a variable, it checks multiple sources in this order. The first source that provides a value wins:
- Parameter — CLI arguments (--name value)
- Argument — Positional argument (when arg: true)
- Environment Variable — OS environment variable (when env is set)
- Config File — Value from config.yaml (when configFile/config is set)
- Encrypted Parameter — Decrypted value (when encrypt: true)
- Default — Default value from the variable definition
- Prompt — Interactive user input (only if no default is set)
Predefined Variables
Response Variable
After executing each instruction, the output will go to the ${response} variable, so you can use it in the next instruction.
1...
2 {
3 "name": "now",
4 "execute": [
5 "echo 'file1.txt'",
6 "cat ${response}"
7 ],
8 ...
9 }Package Directory Variable
You can use the ${packageDir} variable to get the directory where the .aux4 file is located. If this is part of an aux4 package, it will be the directory where the package is installed.
1...
2 {
3 "name": "read-package-file",
4 "execute": [
5 "cat ${packageDir}/my-package-file.txt"
6 ],
7 ...
8 }Home Directory Variable
You can use the ${aux4HomeDir} variable to get the directory where aux4 is installed.
1...
2 {
3 "name": "read-config-file",
4 "execute": [
5 "cat ${aux4HomeDir}/config/my-config-file.txt"
6 ],
7 ...
8 }Config Directory Variable
You can use the ${configDir} variable to get the config directory for the current package. For packages, this resolves to ~/.aux4.config/config/scope/name/.
1...
2 {
3 "name": "read-settings",
4 "execute": [
5 "cat ${configDir}/settings.json"
6 ],
7 ...
8 }Dynamic Variable Access
You can use a variable to dynamically access properties of objects or elements of arrays using the bracket notation [$variable].
Extract Value from Object
Use ${object[$key]} to access a property of an object using a dynamic key:
1{
2 "profiles": [
3 {
4 "name": "main",
5 "commands": [
6 {
7 "name": "print",
8 "execute": [
9 "json:cat data.json",
10 "set:field=name",
11 "log:${response.person[$field]}"
12 ]
13 }
14 ]
15 }
16 ]
17}With the following data.json:
1{
2 "person": {
3 "name": "John"
4 }
5}1> aux4 print1JohnExtract Value from Array
Use ${array[$index]} to access an element of an array using a dynamic index:
1...
2 {
3 "execute": [
4 "set:index=1",
5 "log:${items[$index]}"
6 ],
7 ...
8 }
9...