# 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](https://en.wikipedia.org/wiki/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.

```json
{
  "profiles": [
    {
      "name": "main",
      "commands": [
        {
          "name": "hello",
          "execute": [
            "echo 'Hello ${name}'"
          ],
          "help": {
            "text": "say hello",
            "variables": [
              {
                "name": "name",
                "text": "the name to say hello"
              }
            ]
          }
        }
      ]
    }
  ]
}
```

When you run the `aux4` command, it will list the commands from the _main_ profile and their variables.

```bash
> aux4
```

```text
hello
say hello
  --name
```

Note that it doesn't show the variable's description. To do that, you must use `aux4 --help`.

```bash
> aux4 --help
```

```text
hello
say hello

  --name
    the name to say hello
```

## Parameter

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.

```bash
> aux4 hello --name David
```

```text
Hello David
```

Another way to use it is with the `=` sign.

```bash
> aux4 hello --name=David
```

```text
Hello David
```

It's important to know that you must use quotes to send multiple words as the parameter's value.

```bash
> aux4 hello --name "David SG"
> aux4 hello --name 'David SG'
> aux4 hello "--name=David SG"
```

If you use the parameter without specifying the value, the value will be `true`.

```bash
> aux4 hello --name
```

```text
Hello true
```

But if you use the `=` sign and don't specify the value, the value will be an empty string.

```bash
> aux4 hello --name=
```

```text
Hello
```

## Prompt

If you don't provide any parameters in the aux4 command, it will prompt the user to enter the missing variables.

```bash
> aux4 hello
```

```text
✔ name the name to say hello: |
```

After the user inputs the name, it proceeds with the execution:

```text
name the name to say hello: David SG
Hello David SG
```

The user can cancel using `Ctrl+c`.

```text

User aborted
```

**Important:** 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).

```json
{
  "profiles": [
    {
      "name": "main",
      "commands": [
        {
          "name": "create-dir",
          "execute": [
            "mkdir ${dir}",
            "echo 'the directory ${dir} was created successfully'"
          ],
          "help": {
            "text": "create a new directory",
            "variables": [
              {
                "name": "dir",
                "text": "the directory to be created",
                "default": "new"
              }
            ]
          }
        }
      ]
    }
  ]
}
```

The default value will be included in your command documentation.

```bash
> aux4 create-dir --help
```

```text
create-dir
create a new directory

  --dir
    the directory to be created

    Default: new
```

The default value will be overridden if you pass the parameter for the `dir` variable.

```bash
> aux4 create-dir --dir downloads
```

```text
the directory downloads was created successfully
```

Otherwise, _it will use the default value_ immediately without prompting the user to input it.

```bash
> aux4 create-dir
```

```text
the directory new was created successfully
```

An _empty string_ is also a valid default value if you want to make that variable optional and not display the prompt for user input.

```json
...
  {
    ...
    "default": ""
  }
...
```

## 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`](/functions#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.

```json
...
  {
    "name": "keep",
    "execute": [
      "log:object(name,retain,active,tags)"
    ],
    "help": {
      "text": "build a typed record",
      "variables": [
        { "name": "name", "text": "the name", "default": "shop" },
        { "name": "retain", "type": "number", "text": "days to keep", "default": "7" },
        { "name": "active", "type": "boolean", "text": "is active", "default": "true" },
        { "name": "tags", "type": "json", "text": "labels", "default": "[\"a\",\"b\"]" }
      ]
    }
  }
...
```

```bash
> aux4 keep
```

```text
{"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).

```json
{
  "profiles": [
    {
      "name": "main",
      "commands": [
        {
          "name": "run",
          "execute": [
            "echo 'execute in ${env} environment'"
          ],
          "help": {
            "text": "execute in the specified environment",
            "variables": [
              {
                "name": "env",
                "text": "the environment",
                "env": "ENV"
              }
            ]
          }
        }
      ]
    }
  ]
}
```

The name of the environment variable will show in the command documentation when you use `--help`.

```bash
> aux4 run --help
```

```text
run
execute in the specified environment

  --env
    the environment

    Environment variable: ENV
```

The environment variable value will be used only if you do not specify the parameter for your variable.

```bash
> export ENV=DEV
```

```bash
> aux4 run --env PROD
```

```text
execute in PROD environment
```

```bash
> aux4 run
```

```text
execute in DEV environment
```

## Hidden 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).

```json
{
  "profiles": [
    {
      "name": "main",
      "commands": [
        {
          "name": "hello",
          "execute": [
            "echo 'Hello ${name}'"
          ],
          "help": {
            "text": "say hello",
            "variables": [
              {
                "name": "name",
                "text": "the name to say hello",
                "hide": true
              }
            ]
          }
        }
      ]
    }
  ]
}
```

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.

```bash
> aux4 hello
```

```text
✔ name the name to say hello: *****
```

Be aware that logging or printing the value will still display it in the output.

```text
name the name to say hello: *****
Hello David
```

## Private 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).

```json
{
  "profiles": [
    {
      "name": "main",
      "commands": [
        {
          "name": "hello",
          "execute": [
            "echo 'Hello ${name} (${greeting})'"
          ],
          "help": {
            "text": "say hello",
            "variables": [
              {
                "name": "name",
                "text": "the name to say hello"
              },
              {
                "name": "greeting",
                "text": "internal greeting template",
                "default": "friendly",
                "private": true
              }
            ]
          }
        }
      ]
    }
  ]
}
```

The help only mentions `name`.

```bash
> aux4 hello --help
```

```text
hello
say hello.

  --name
    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.

```bash
> aux4 hello --name Sally
```

```text
Hello Sally (friendly)
```

```bash
> aux4 hello --name Sally --greeting formal
```

```text
Hello Sally (formal)
```

If every variable of a command is private, no parameters section is printed at all.

> `private` is not the same as [`hide`](#hidden-value). `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).

```json
{
  "profiles": [
    {
      "name": "main",
      "commands": [
        {
          "name": "get-data",
          "execute": [
            "echo 'get data from the website ${url}'"
          ],
          "help": {
            "text": "get data from the website",
            "variables": [
              {
                "name": "url",
                "text": "the url of the API to get the data from",
                "arg": true
              }
            ]
          }
        }
      ]
    }
  ]
}
```

You can still send the `url` as a parameter.

```bash
> aux4 get-data --url https://my.api.com
```

Or you can also send it as an argument.

```bash
> aux4 get-data https://my.api.com
```

## Options

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.**

```json
{
  "profiles": [
    {
      "name": "main",
      "commands": [
        {
          "name": "copy-files",
          "execute": [
            "echo 'copy files to ${target}'"
          ],
          "help": {
            "text": "copy files to the target directory",
            "variables": [
              {
                "name": "target",
                "text": "the directory to copy the files to",
                "options": [
                  "folder1",
                  "folder2",
                  "folder3"
                ]
              }
            ]
          }
        }
      ]
    }
  ]
}
```

When you run the command, it will prompt the user to select an option.

```bash
> aux4 copy-files
```

```text
Use the arrow keys to navigate: ↓ ↑ → ←
? target the directory to copy the files to:
  ▸ folder1
    folder2
    folder3
```

The user can use the arrow keys to navigate and enter to choose the option they want.

```text
✔ folder2
copy files to folder2
```

The 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.

```bash
> aux4 copy-files --target folder4
```

```text
copy files to folder4
```

## Multi-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.

```json
{
  "profiles": [
    {
      "name": "main",
      "commands": [
        {
          "name": "deploy",
          "execute": [
            "log:Deploying to: ${target*}"
          ],
          "help": {
            "text": "deploy to target environments",
            "variables": [
              {
                "name": "target",
                "text": "target environments",
                "multiple": true,
                "options": [
                  "dev",
                  "staging",
                  "production"
                ]
              }
            ]
          }
        }
      ]
    }
  ]
}
```

When you run the command without the parameter, it shows a checkbox list:

```bash
> aux4 deploy
```

```text
? target target environments:
  [x] dev
  [ ] staging
  [x] production
```

Use arrow keys to navigate, space to toggle, and enter to confirm. The selected values are stored as a multiple-value variable.

```text
Deploying to: ["dev","production"]
```

You can still pass values directly as parameters:

```bash
> aux4 deploy --target dev --target staging
```

## Multiple Variables

You can allow a variable to accept multiple values by setting `multiple: true` in the variable definition.

```json
{
  "profiles": [
    {
      "name": "main",
      "commands": [
        {
          "name": "print-tags",
          "execute": [
            "log:Tags: ${tag*}"
          ],
          "help": {
            "text": "print all tags",
            "variables": [
              {
                "name": "tag",
                "text": "tag to add",
                "multiple": true
              }
            ]
          }
        }
      ]
    }
  ]
}
```

### Passing multiple values

You can pass multiple values by repeating the parameter:

```bash
> aux4 print-tags --tag first --tag second --tag third
```

```text
Tags: ["first","second","third"]
```

### Accessing specific values

Use `${variable*[index]}` to access a specific value by index (0-based):

```json
...
  {
    "execute": [
      "log:Second tag: ${tag*[1]}"
    ],
    ...
  }
...
```

### Accessing all values

Use `${variable*}` to get all values as a JSON array:

```json
...
  {
    "execute": [
      "log:All tags: ${tag*}"
    ],
    ...
  }
...
```

### Accessing last value

Use `${variable}` (without `*`) to get only the last value:

```json
...
  {
    "execute": [
      "log:Last tag: ${tag}"
    ],
    ...
  }
...
```

### Multiple with Argument

You can combine `multiple: true` with `arg: true` to accept multiple positional arguments:

```json
...
  {
    "help": {
      "variables": [
        {
          "name": "file",
          "text": "files to process",
          "arg": true,
          "multiple": true
        }
      ]
    }
  }
...
```

```bash
> aux4 process file1.txt file2.txt file3.txt
```

## Dollar 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.

```json
...
  {
    "name": "show-price",
    "execute": [
      "echo 'Price: $$$amount'"
    ],
    "help": {
      "variables": [
        {
          "name": "amount",
          "text": "the price amount"
        }
      ]
    }
  }
...
```

```bash
> aux4 show-price --amount 10
```

```text
Price: $10
```

## All Parameters

Use `$*` to get all named parameters as a JSON object. This is useful for forwarding all parameters to another command.

```json
...
  {
    "name": "forward",
    "execute": [
      "log:$*"
    ],
    "help": {
      "variables": [
        {
          "name": "name",
          "text": "the name"
        },
        {
          "name": "age",
          "text": "the age"
        }
      ]
    }
  }
...
```

```bash
> aux4 forward --name Joe --age 20
```

```text
{"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:

1. **Parameter** — CLI arguments (`--name value`)
2. **Argument** — Positional argument (when `arg: true`)
3. **Environment Variable** — OS environment variable (when `env` is set)
4. **[Config File](/config)** — Value from config.yaml (when `configFile`/`config` is set)
5. **Encrypted Parameter** — Decrypted value (when `encrypt: true`)
6. **Default** — Default value from the variable definition
7. **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.

```json
...
  {
    "name": "now",
    "execute": [
      "echo 'file1.txt'",
      "cat ${response}"
    ],
    ...
  }
```

### 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](https://pkger.aux4.io), it will be the directory where the package is installed.

```json
...
  {
    "name": "read-package-file",
    "execute": [
      "cat ${packageDir}/my-package-file.txt"
    ],
    ...
  }
```

### Home Directory Variable

You can use the `${aux4HomeDir}` variable to get the directory where aux4 is installed.

```json
...
  {
    "name": "read-config-file",
    "execute": [
      "cat ${aux4HomeDir}/config/my-config-file.txt"
    ],
    ...
  }
```

### 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/`.

```json
...
  {
    "name": "read-settings",
    "execute": [
      "cat ${configDir}/settings.json"
    ],
    ...
  }
```

## 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:

```json
{
  "profiles": [
    {
      "name": "main",
      "commands": [
        {
          "name": "print",
          "execute": [
            "json:cat data.json",
            "set:field=name",
            "log:${response.person[$field]}"
          ]
        }
      ]
    }
  ]
}
```

With the following `data.json`:

```json
{
  "person": {
    "name": "John"
  }
}
```

```bash
> aux4 print
```

```text
John
```

### Extract Value from Array

Use `${array[$index]}` to access an element of an array using a dynamic index:

```json
...
  {
    "execute": [
      "set:index=1",
      "log:${items[$index]}"
    ],
    ...
  }
...
```

---

## See Also

- [Executors](/executors)
- [Functions](/functions)
- [Config](/config)
- [Commands](/commands)
- [Testing](/testing)
- [Package Manager](/package-manager)
- [Packaging](/packaging)
- [Docker](/docker)
