> ## Documentation Index
> Fetch the complete documentation index at: https://docs.akua.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Package format

> Authoring an akua Package: the Input schema, @ui annotations, and composition

<Frame>
  <img className="block dark:hidden" src="https://mintcdn.com/akua-1dce587a/NTgnQstkErDoAPAb/images/heros/package-format-light.svg?fit=max&auto=format&n=NTgnQstkErDoAPAb&q=85&s=ea9aa4d7fdc6460c455e14577cb2f720" alt="A package file anatomy showing metadata, inputs, render logic, and produced resources." width="1536" height="864" data-path="images/heros/package-format-light.svg" />

  <img className="hidden dark:block" src="https://mintcdn.com/akua-1dce587a/NTgnQstkErDoAPAb/images/heros/package-format-dark.svg?fit=max&auto=format&n=NTgnQstkErDoAPAb&q=85&s=bf8d2493fe0119957c268fc5bd4c9a38" alt="A package file anatomy showing metadata, inputs, render logic, and produced resources." width="1536" height="864" data-path="images/heros/package-format-dark.svg" />
</Frame>

The canonical shape of an akua Package is a KCL program with three regions: imports, an `Input` schema, and a body that calls source engines (Helm, kustomize, RGD) and aggregates resources. This page is an Akua-focused excerpt of the [akua package format spec](https://github.com/akua-dev/akua/blob/main/docs/package-format.md). The full spec covers engine calls, lockfile, and metadata; this page focuses on what an Akua product author touches most: the Input schema and `@ui` annotations.

## Anatomy

Every Package is one KCL program with three typed regions:

```python theme={null}
# package.k

# (1) imports — engines, ambient context, schemas
import akua.ctx
import akua.helm
import charts.webapp as webapp

# (2) schema — the public input contract
schema Input:
    appName:  str
    hostname: str
    replicas: int = 3

input: Input = ctx.input()

# (3) body — engine calls + transforms + aggregation
_app = helm.template(webapp.Chart {
    values = webapp.Values { replicaCount = input.replicas }
})

resources = _app
```

`akua render` writes every entry of `resources` as a YAML file under `--out`. Akua runs that render per-installation and commits the output to the [installation repository](/installs/repositories).

## The `Input` schema

The `Input` schema is the public contract: it declares what customers can configure. This schema is what Akua exports to JSON Schema for the install wizard.

Rules:

* The schema must be named `Input`. The binding line is canonically `input: Input = ctx.input()`.
* Fields use KCL native types: `str`, `int`, `float`, `bool`, `[T]`, `{str: T}`, unions (`"a" | "b" | "c"`), nested schemas.
* Fields without defaults are required; fields with defaults are optional.
* Use KCL docstrings (`"""..."""`) on each field; they become the JSON Schema `description` and surface in autocomplete and the install wizard.
* `check:` blocks express cross-field constraints; they run during render.
* No runtime side effects (no env, no filesystem, no network). KCL's sandbox enforces this.

Example with all shapes:

```python theme={null}
schema Input:
    """Public inputs for this package."""

    appName: str
    """Application name. Lowercase, hyphen-separated."""

    routing: RoutingInput

    replicas: int = 3
    """Number of replicas. Minimum 1 in production."""

    tier: "startup" | "production" = "startup"

    additional_hosts: [HostInput] = []

    labels: {str: str} = {}

    check:
        replicas >= 1, "replicas must be at least 1"
        len(additional_hosts) < 10, "at most 10 additional hosts"

schema RoutingInput:
    hostname: str
    tls:      bool = True

schema HostInput:
    hostname: str
    priority: int = 0
```

## `@ui` annotations

KCL docstrings carry the `description` field, but the install wizard needs more: field ordering, grouping into sections, widget hints, validation bounds. akua provides the `@ui(...)` decorator for this.

`@ui(...)` is an authoring hint that's stripped before the source reaches KCL's resolver and projected onto the JSON Schema property as the OpenAPI-3.1-compliant `x-ui` extension. Akua's install wizard recognizes `x-ui` and renders accordingly; renderers that don't, ignore it.

```python theme={null}
schema Input:
    """Public inputs for this package."""

    @ui(order=10, group="Identity")
    appName: str
    """Application name. Lowercase, hyphen-separated."""

    @ui(order=20, group="Identity", placeholder="app.example.com")
    hostname: str
    """Public hostname. Must be a valid RFC 1123 DNS name."""

    @ui(order=30, group="Capacity", widget="slider", min=1, max=20)
    replicas: int = 3
    """Number of replicas. Minimum 1 in production."""

    @ui(order=40, group="Capacity")
    tier: "startup" | "production" = "startup"
    """Resource tier."""
```

### Recognized keys

The keyword arguments to `@ui(...)` are arbitrary; anything you pass becomes `x-ui` metadata. Akua's wizard currently recognizes:

| Key           | Effect                                                                   |
| ------------- | ------------------------------------------------------------------------ |
| `order`       | Numeric position within the form (lower = earlier)                       |
| `group`       | Section header the field appears under (e.g. `"Identity"`, `"Capacity"`) |
| `widget`      | Field renderer hint: `"slider"`, `"password"`, `"textarea"`, `"select"`  |
| `placeholder` | Placeholder text shown in empty inputs                                   |
| `min` / `max` | Numeric bounds (used by `widget="slider"` and form validation)           |

Unknown keys are ignored, so you can add `@ui(foo=bar)` annotations for your own renderers without breaking Akua.

### How `@ui` reaches the wizard

```
package.k (with @ui annotations)
    │
    ▼  schema export
JSON Schema with x-ui extensions
    │
    ▼  cached per Package version
    │
    ▼  fetched by /i/<hash> install wizard
Form rendered with x-ui hints respected
```

See [Offers](/marketplace/offers) for the wizard side of this flow.

## Composition body

The body composes resources by calling engine functions:

```python theme={null}
# Helm with per-source input mapping
_app = helm.template(webapp.Chart {
    values = webapp.Values {
        replicaCount = input.replicas
        ingress.hostname = input.hostname
    }
})

# Add extra resources declared in KCL
_servicemonitor = {
    apiVersion: "monitoring.coreos.com/v1"
    kind:       "ServiceMonitor"
    metadata.name: input.appName
    spec.selector.matchLabels.app: input.appName
}

resources = [*_app, _servicemonitor]
```

For the full body / engine-callable reference (Helm, kustomize, kro RGD, OCI fetch), see the [akua package format spec](https://github.com/akua-dev/akua/blob/main/docs/package-format.md#4-body--engine-calls--transforms).

## Exporting vs rendering

| Verb          | Purpose                                                               | Needs inputs? | Output                             |
| ------------- | --------------------------------------------------------------------- | ------------- | ---------------------------------- |
| `akua export` | Convert the Package's `Input` schema to a standard interchange format | No            | JSON Schema 2020-12 or OpenAPI 3.1 |
| `akua render` | Execute the Package's full pipeline against customer inputs           | Yes           | Rendered YAML manifests            |

Akua exports the schema once per Package version (cached) to drive the install wizard, and renders once per install and again on every input change.

## Related topics

<CardGroup cols={2}>
  <Card title="Offers" icon="link" href="/marketplace/offers">
    How `@ui` drives the install wizard.
  </Card>

  <Card title="Concepts" icon="diagram-project" href="/concepts">
    How Packages, Products, and Installations relate.
  </Card>

  <Card title="Customize an installation via git" icon="code-branch" href="/installs/install-repo">
    Edit `inputs.yaml` and `package.k` directly.
  </Card>

  <Card title="Akua package format spec" icon="github" href="https://github.com/akua-dev/akua/blob/main/docs/package-format.md">
    Full spec: engines, lockfile, signing.
  </Card>
</CardGroup>
