Skip to main content
Every pack ships a khal-app.json at its root. The schema lives in @khal-os/types — this page is a field-by-field reference. The @khal-os/dev-cli tool validates your manifest at build time; invalid manifests fail CI before they ship.

Top-level fields

id
string
required
Unique pack identifier. Must match the package directory name. Lowercase, dash-separated.
name
string
Human-readable pack name shown in the desktop launcher.
version
string
Semantic version. Normally kept in sync with package/package.json.
description
string
Short description for the marketplace listing.
author
string
Author name or organization.
icon
string
Path to the pack icon, relative to the pack root.
permissions
string[]
Permission strings the pack requires. Examples: "nats:publish", "nats:subscribe", "user:read". Permissions are checked by the platform before the frontend loads and before services are started.
frontend
object
Frontend package declaration.
backend
object
Backend configuration. Omit entirely for frontend-only packs.
env
array
Environment variables customers configure per install. See Customer install for the customer-side flow.
views
array
Optional. If your pack exposes multiple windows or view modes, declare them here with per-view permission and role requirements. Most packs have a single implicit view from frontend.package.
services
array
Alternative to backend for multi-service packs. Each entry declares a named service with optional command, entry, runtime (node or python), health, restart, and ports. See Backend overview.
sandbox
object
Advanced. Provision a per-user container when the pack is installed. Used for high-isolation packs (e.g., ephemeral workspaces). See the app-kit/packages/types source for full field shape.

Complete example

khal-app.json
{
  "$schema": "https://raw.githubusercontent.com/khal-os/app-kit/dev/packages/types/src/khal-app-schema.json",
  "id": "my-pack",
  "name": "My Pack",
  "version": "1.0.0",
  "icon": "./package/src/assets/icon.svg",
  "description": "What my pack does in one line",
  "author": "My Company",
  "permissions": ["nats:publish", "nats:subscribe", "user:read"],
  "frontend": {
    "package": "@khal-os/pack-my-pack"
  },
  "backend": {
    "image": "ghcr.io/khal-os/pack-my-pack-service",
    "helmChart": "oci://ghcr.io/khal-os/charts/pack-my-pack",
    "env": {
      "KHAL_NATS_URL": "nats://nats.khal-system.svc:4222"
    },
    "ports": [8080]
  },
  "env": [
    {
      "key": "MY_API_KEY",
      "description": "API key for the external service",
      "required": true,
      "type": "secret"
    }
  ]
}
For fields this page does not enumerate (e.g., views, sandbox, desktop), consult app-kit/packages/types/src/manifest.ts directly. The Zod schema there is the canonical source.

What’s next

Example packs

Reference packs grouped by pattern — read the manifest that ships in each.

Anatomy of a pack

How the manifest fits into the rest of the pack structure.