A pack is a self-contained KhalOS app: a frontend React package plus an optional backend service, a manifest that declares both, and a Helm chart for shipping. In this walkthrough you’ll go from an empty directory to a running “Hello FDE” pack in under ten minutes.Documentation Index
Fetch the complete documentation index at: https://docs.khal.ai/llms.txt
Use this file to discover all available pages before exploring further.
This page is the fast path. For the full pack contract — every manifest field, every CI workflow, every deploy mode — follow the Next steps links at the bottom.
1. Scaffold with khal new
@khal-os/app-kit ships the public khal CLI. Install it from npmjs, verify the version/template bundle, then scaffold locally.
Use
@khal-os/app-kit@next only when a release owner explicitly asks you to validate an unreleased CLI fix. Fresh FDE installs should use @latest.<name> with your pack’s identifier — lowercase, hyphen-separated, and short. It becomes the Helm chart name, the manifest id, and the package name. khal new substitutes the token everywhere it appears in the bundled template.
Run
khal new with no arguments to see the three available types and their one-line descriptions. Add --list to inspect the bundled template versions.Flags you’ll reach for
| Flag | What it does |
|---|---|
--force | Overwrite a non-empty target directory. Default behaviour aborts. |
--from <git-url> | Clone an unofficial template instead of using the bundled one. Prints an “unofficial template — not version-locked” warning to stderr. |
--list | Print bundled template versions and exit. |
The legacy GitHub-template path (using
gh repo create against the deprecated pack-template repo) no longer applies. Existing packs scaffolded that way keep working unchanged — only new scaffolds should use khal new.2. Edit the React component
The frontend lives inpackage/src/index.tsx and must default-export a React component. That’s the only contract — any hook, any styling, any UI library. Start with something that proves the full loop works:
package/src/index.tsx
3. (Optional) edit the service
If your pack needs a backend — a long-running process, a NATS subscriber, a side-effectful endpoint — editservice/src/index.ts. The app template ships a Bun HTTP server with a sample NATS subscription.
If your pack is frontend-only, delete the service/ directory and remove the backend block from khal-app.json. CI will skip the Docker build and Helm release automatically.
Authoring ≠ deployment. You declare what your pack needs in
khal-app.json (permissions, service shape, env vars, requires.postgres, requires.nats.streams, requires.temporal.namespace). The platform provides the runtime — NATS connections, secrets, networking, provisioned resources. You never wire up infrastructure yourself.4. Build and typecheck
bun run build produces CJS + ESM bundles plus TypeScript declarations in package/dist/. bun run typecheck validates both the frontend package and the service (if present).

5. Dry-run install before a target mutation
Before installing into any shared target, run the CLI preflight from the generated repo root:khal-app.json, env declarations, target resolution, and the command that would perform the real install. It performs no mutation. For remote app repos, use an explicit branch:
6. See it in the shell
You’ve got two paths to render your pack in a live shell:- Local shell
- Hosted instance
Install your pack into a local KhalOS instance. The shell hot-reloads the frontend bundle whenever
bun run build emits new output, so you can iterate on the component without re-installing.
For the full CI-driven publish and install story — workflows, tags, rollout — see Publish your pack.
Next steps
Anatomy of a pack
A directory-level tour of every file
khal new just generated and what it’s for at runtime.Hooks reference
The
@khal-os/sdk React hooks — how your component talks to the shell, NATS, and other packs.Full-stack pack pattern
The end-to-end reference pattern for packs with both a frontend and a backend service.