> ## 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-0b861dc6/7KPav8EV2jXc1gHe/images/heros/package-format-light.svg?fit=max&auto=format&n=7KPav8EV2jXc1gHe&q=85&s=c2cd899f8662942485a91df26d64fb9a" 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-0b861dc6/7KPav8EV2jXc1gHe/images/heros/package-format-dark.svg?fit=max&auto=format&n=7KPav8EV2jXc1gHe&q=85&s=06ef67cd941123490ccc274d4a1108c2" 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 builds typed resources, calls Helm charts or Kustomize overlays, and aggregates the result. 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: ambient context, typed Kubernetes schemas, a chart dependency
import akua.ctx
import k8s.api.core.v1 as corev1
import charts.traefik

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

input: Input = ctx.input()

# (3) body: typed resources, chart calls, aggregation
resources = [
    *traefik.template(traefik.TemplateOpts {
        values = traefik.Values {deployment.replicas = input.replicas}
        release = input.appName
    })
    corev1.ConfigMap {
        metadata.name = input.appName
        data.replicas = str(input.replicas)
    }
]
```

`akua pkg render` writes every entry of `resources` as a YAML file under `--out`. Resources are typed against the Kubernetes version and CRDs the Package depends on, so a misspelled field fails the render; see [Typed resources](/akua/typed-resources). 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 builds resources from typed schemas and from Helm charts or Kustomize overlays, and combines them:

```python theme={null}
import crds.cert_manager.cert_manager_io.v1 as certmanager

_app = traefik.template(traefik.TemplateOpts {
    values = traefik.Values {deployment.replicas = input.replicas}
})

_certificate = certmanager.Certificate {
    metadata.name = input.appName
    spec = {
        secretName = "${input.appName}-tls"
        dnsNames = [input.hostname]
        issuerRef = {name = "letsencrypt", kind = "ClusterIssuer"}
    }
}

resources = [*_app, _certificate]
```

For every engine call (Helm, Kustomize, nested Packages), see the [akua package format spec](https://github.com/akua-dev/akua/blob/main/docs/package-format.md#calling-engines).

## Exporting vs rendering

| Verb | Purpose | Needs inputs? | Output |
| - | - | - | - |
| `akua pkg export` | Convert the Package's `Input` schema to a standard interchange format | No | JSON Schema 2020-12 or OpenAPI 3.1 |
| `akua pkg 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>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.