# Package with Dependencies

This guide shows how to create a package that depends on other aux4 packages. When your package is installed, its dependencies are automatically installed as well.

## Package Structure

```text
my-package/
├── .aux4         # Package metadata with dependencies
├── LICENSE
└── README.md
```

## Step 1: Create the Package

### Create the .aux4 file

Add the `dependencies` field to specify which aux4 packages your package requires:

```json
{
  "scope": "myorg",
  "name": "data-processor",
  "version": "1.0.0",
  "description": "Process and validate data files",
  "license": "MIT",
  "dependencies": [
    "aux4/config",
    "aux4/validator"
  ],
  "profiles": [
    {
      "name": "main",
      "commands": [
        {
          "name": "process",
          "execute": [
            "profile:process"
          ],
          "help": {
            "text": "Data processing commands"
          }
        }
      ]
    },
    {
      "name": "process",
      "commands": [
        {
          "name": "file",
          "execute": [
            "aux4 config get --file ${configFile} mapping",
            "aux4 validate json ${file}"
          ],
          "help": {
            "text": "Process a data file using config and validation",
            "variables": [
              {
                "name": "configFile",
                "text": "Configuration file",
                "default": "config.yaml"
              },
              {
                "name": "file",
                "text": "Data file to process",
                "arg": true
              }
            ]
          }
        }
      ]
    }
  ]
}
```

## Dependency Format

Dependencies are specified as an array of strings in the format:

- `scope/name` — installs the latest version, and accepts **any** version already installed
- `scope/name@version` — an exact version
- `scope/name@range` — an npm-style semver range, resolved to the highest published version that satisfies it

```json
{
  "dependencies": [
    "aux4/config",
    "aux4/validator@0.1.0",
    "myorg/utils@^2.0.0",
    "myorg/parser@~1.4.0"
  ]
}
```

### Version Ranges

The same range grammar works here and on the install command line (`aux4 aux4 pkger install 'aux4/config@^0.2.0'`).

| Form | Example | Means |
|------|---------|-------|
| Caret | `^1.2.3` | `>=1.2.3 <2.0.0` — the left-most non-zero segment is held, so `^0.2.3` is `>=0.2.3 <0.3.0` and `^0.0.3` is `>=0.0.3 <0.0.4` |
| Tilde | `~1.2.3` | `>=1.2.3 <1.3.0`; `~1.2` is `>=1.2.0 <1.3.0`; `~1` is `>=1.0.0 <2.0.0` |
| Comparators | `>=1.2.0` `>1.2.0` `<=2.0.0` `<2.0.0` `=1.2.3` `!=1.2.3` | A partial version is allowed after a comparator: `>=1.2` is `>=1.2.0`, `>1.2` is `>=1.3.0`, `<=1.2` is `<1.3.0` |
| x-range | `1.x` `1.2.x` | `1.x` is `>=1.0.0 <2.0.0`; `1.2.x` is `>=1.2.0 <1.3.0` |
| Any | `*` | Any published version |
| Hyphen | `1.2.3 - 2.0.0` | `>=1.2.3 <=2.0.0` |
| AND | `>=0.1.0 <0.2.0` | A space between terms means both must hold |
| OR | `^0.1.0 \|\| ^0.2.0` | `\|\|` separates alternatives |

Prereleases are excluded unless the range itself mentions one.

**A bare version is never a range — including a partial one.** `1.2.3` is exact, the prerelease `1.0.0-local` is exact, `latest` is latest, and a bare partial such as `2.0` is **exact** too, unlike npm where it means `2.0.x`. That is deliberate: every version already written in an existing `.aux4` keeps meaning exactly what it meant before ranges existed. Write `2.0.x` (or `~2.0`) when you want the range.

## Step 2: Create Supporting Files

### LICENSE

```bash
cat > LICENSE << 'EOF'
MIT License
...
EOF
```

**Tip:** You can also use [aux4/license](https://hub.aux4.io/r/public/packages/aux4/license) to generate your LICENSE file:

```bash
aux4 license use \
  --name mit \
  --owner "MyOrg" \
  --year 2024 \
  --project "data-processor"
```

### README.md

````bash
cat > README.md << 'EOF'
# Data Processor

Process and validate data files.

## Dependencies

This package requires:
- aux4/config
- aux4/validator

These are installed automatically when you install this package.

## Usage

```bash
aux4 process file data.json --configFile settings.yaml
```
EOF
````

## Step 3: Build the Package

```bash
aux4 aux4 pkger build ./out .
```

## Step 4: Install from File

```bash
aux4 aux4 pkger install --fromFile ./out/myorg_data-processor_1.0.0.zip
```

When installing, aux4 automatically:
1. Resolves all dependencies
2. Downloads and installs each dependency
3. Installs your package

## Step 5: Publish

```bash
aux4 aux4 login
aux4 aux4 pkger publish ./out/myorg_data-processor_1.0.0.zip
```

## Step 6: Install from aux4 Hub

```bash
aux4 aux4 pkger install myorg/data-processor
```

This automatically installs:
- `aux4/config`
- `aux4/validator`
- `myorg/data-processor`

## Transitive Dependencies

If your dependencies have their own dependencies, those are also resolved and installed automatically. aux4 handles the entire dependency tree.

For example, if `aux4/config` depends on `aux4/aux4`, the installation order would be:

1. `aux4/aux4`
2. `aux4/config`
3. `aux4/validator`
4. `myorg/data-processor`

## Version Resolution

Only **one** version of a package is installed at a time, so when several packages depend on the same package their declarations have to agree. What each form contributes:

| Declaration | Constraint |
|-------------|-----------|
| `aux4/config` | **Unconstrained** — accepts any installed version and never blocks an upgrade |
| `aux4/config@latest` | Unconstrained, same as above |
| `aux4/config@0.2.10` | **Exact pin** — a constraint of exactly `0.2.10`, so it **caps the whole tree**: while your package is installed, nothing can move `aux4/config` off `0.2.10` |
| `aux4/config@^0.2.0` | Range — any version it matches is acceptable |

When a newly installed package requires a version the installed dependency does not satisfy, the dependency is upgraded **only with unanimous consent** — to the highest published version satisfying the new requirer *and* every package that already depends on it. The upgrade is reported, never silent:

```text
Upgrading aux4/config 0.1.1 -> 0.2.10 (required by tester/upgrade-b@^0.2.0)
```

If no published version satisfies everyone, the install fails and names the package holding it back — usually an exact pin in another package:

```text
tester/upgrade-b requires aux4/config@^0.2.0, but aux4/config 0.1.1 is installed.
Cannot upgrade: tester/upgrade-a requires aux4/config@0.1.1.
Published versions: 0.2.10, 0.2.0, 0.1.1, 0.1.0
```

A dependency is **never downgraded automatically**. If the only agreeable version is older than the installed one, the install fails instead of breaking the dependent that works today.

Prefer a range (`^`, `~`) over an exact pin in your `dependencies`: an exact pin caps every other package in the user's installation, and it is the most common reason an install of an unrelated package is refused. `--force` bypasses range enforcement entirely, leaving the dependency at the version already installed.

For the full grammar and the resolution rules, see [Package Manager → Version Ranges](/package-manager#version-ranges).

## List Dependencies

To see all installed packages and their dependencies:

```bash
aux4 aux4 pkger list
```

---

## See Also

- [Simple Package](/packaging/simple)
- [Package with System Dependencies](/packaging/system-dependencies)
- [Multi-Platform Package](/packaging/multi-platform)
