Skip to main content

Documentation Index

Fetch the complete documentation index at: https://akua-1dce587a.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

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

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:
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.
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:
KeyEffect
orderNumeric position within the form (lower = earlier)
groupSection header the field appears under (e.g. "Identity", "Capacity")
widgetField renderer hint: "slider", "password", "textarea", "select"
placeholderPlaceholder text shown in empty inputs
min / maxNumeric 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/<slug> install wizard
Form rendered with x-ui hints respected
See Install links for the wizard side of this flow.

Composition body

The body composes resources by calling engine functions:
# 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.

Exporting vs rendering

VerbPurposeNeeds inputs?Output
akua exportConvert the Package’s Input schema to a standard interchange formatNoJSON Schema 2020-12 or OpenAPI 3.1
akua renderExecute the Package’s full pipeline against customer inputsYesRendered 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.

Install links

How @ui drives the install wizard.

Concepts

How Packages, Products, and Installations relate.

Customize an installation via git

Edit inputs.yaml and package.k directly.

Akua package format spec

Full spec: engines, lockfile, signing.