khal-app.json manifest pasted inline so you can see the shape before you clone.
Reference map
| Pack | Shape | Why you’d read it |
|---|---|---|
pack-hello | Bundle (4 frontends + 1 service) | Multi-app bundle pattern — several frontends under one manifest, sharing a backend. |
pack-settings | Frontend-only | useKhalAuth, React state, no service. Canonical frontend-only shape. |
pack-notes | Frontend-only (public) | Clean data-model example. Public repo — the best code you can read without access permissions. |
pack-terminal | Full-stack (PTY) | useNats + Bun service + Dockerfile + helm/ chart. Canonical full-stack reference. |
pack-files | Full-stack (filesystem) | Sandboxed filesystem access + NATS bridge. Shows full permission surface. |
pack-genie | Full-stack + AI | Embedding agent features; uses the automagik genie toolchain inside a pack. |
pack-nats-viewer | Dev tool | Introspecting NATS messages during development. Keep it installed in your dev instance — it earns its keep. |
Real manifests, side by side
Every manifest below is verbatim from the pack repo as of this sprint. Compare howpermissions, backend, env, and ports scale with the pack’s ambition.
pack-settings — frontend-only, minimal
Nobackend block. No ports. Reads user config via useKhalAuth() and writes UI preferences via NATS.
pack-settings/khal-app.json
pack-terminal — full-stack, single service
The canonical full-stack pattern. Frontend subscribes to PTY output; backend owns the PTY and publishes stdout over NATS.pack-terminal/khal-app.json
pack-files — full-stack, filesystem permissions
Same shape as pack-terminal but a different permission surface (files:read, files:write) and a customer-scoped OCI registry (gru.ocir.io — this pack is deployed into a specific customer’s OCI tenancy).
pack-files/khal-app.json
pack-hello — bundle (4 frontends + 1 shared service)
When you’re shipping a suite of related apps, declare them under a singleapps[] array. One manifest, one publish, four windowed apps in the shell, sharing one backend.
pack-hello/khal-app.json
GEMINI_API_KEY — customers fill that in at install time.
What the manifests teach you
Reading four real manifests side by side reveals the shape language:| Want | Look at | Copy this pattern |
|---|---|---|
| Minimal pack, no backend | pack-settings | permissions + frontend.package — that’s it |
| Full-stack with one service | pack-terminal | frontend.package + backend.{image, helmChart, env, ports} |
| Permission-heavy pack | pack-files | permissions grows with what you touch (filesystem, PTY, network) |
| Customer-scoped registry | pack-files | backend.image can target any OCI registry, not just ghcr.io/khal-os/* |
| Multi-frontend suite | pack-hello | Swap frontend for apps[], keep a single shared backend |
How to use these
Find the shape closest to what you need
Frontend-only with auth?
pack-settings. Full-stack with a long-lived process? pack-terminal. Multi-app suite? pack-hello.Read its `khal-app.json`
The manifest tells you what permissions, ports, env, and services the pack uses. Copy the shape, not the identifiers.
Read its `service/` (if full-stack)
The Bun entry. See how it subscribes, how it publishes, and how it handles the NATS connection.
Reference packs evolve. The repo READMEs are the canonical state; this page is a map. If a reference pack’s README contradicts this page, trust the README.
What’s next
khal-app.json schema
Every field these manifests use, exhaustively.
Patterns: full-stack
The pattern writeup of pack-terminal’s shape.