Kehto is an unopinionated toolkit and protocol kernel for building NIP-5D Nostr applet ("napplet") runtimes. It supplies routing, lifecycle, capability, service, and browser-shell primitives without deciding a runtime's origin, signer, or deployment policy. Paja is Kehto's reference developer runtime.
Alpha status: kehto/web is under heavy development and is far from complete, It presently offers components but still requires the implementer to manage envelope security, process isolation, performance optimization and more. It is presently being dogfooded where lessons and implementations will be reflected back into the packages. Additionally, NIP-5D is still under development, and NAP contracts are not final. Package APIs, capability names,
requiresdeclarations, andsupports()behavior may change as the spec evolves.
It provides packages for building a napplet host client by handling capability
enforcement, message routing, host service registration, gateway artifacts, and
development tooling. The applet-side packages (@napplet/core, @napplet/shim,
@napplet/sdk, and @napplet/vite-plugin) live in the
@napplet repo; Kehto supplies the
runtime toolkit, while Paja demonstrates one complete implementation.
- Public web portal: https://kehto.github.io/web/
- Paja Runtime: https://kehto.github.io/web/paja/
- Docs: https://kehto.github.io/web/docs/
- Alpha status: docs/alpha-status.md
- Local docs entry: docs/index.md
- Package reference index: docs/packages/index.md
- Generated API reference index: docs/reference/api.md
If you are building a host app, start with the minimal host shell tutorial, then use the package table below to jump into the implementation surface you need.
To run the same pointer-entry Paja Runtime published on GitHub Pages, use:
pnpm install
pnpm pajaThen open http://127.0.0.1:4175/web/paja/ and enter a napplet naddr or
nevent. This builds only Paja and its workspace dependencies, not the
documentation site.
| Package | Use it for | Package root | Markdown docs | VitePress docs |
|---|---|---|---|---|
@kehto/acl |
Pure capability state, grants, blocks, quotas, and policy checks. | packages/acl | docs/packages/acl.md | ACL docs |
@kehto/firewall |
Pure, zero-dependency behavioral anti-abuse engine — rate/burst/content rules with allow/deny/ask policy and focus-aware tightening. | packages/firewall | docs/packages/firewall.md | Firewall docs |
@kehto/runtime |
Browser-agnostic NIP-5D dispatch, ACL gates, service registry, sessions, manifests, replay checks, and event buffering. | packages/runtime | docs/packages/runtime.md | Runtime docs |
@kehto/shell |
Browser iframe/session adapter over a Kehto runtime, gateway loading, postMessage transport, hosted supports(), and shell policy. |
packages/shell | docs/packages/shell.md | Shell docs |
@kehto/services |
Reference handlers for identity, relay, keys, media, notify, config, resource, cache, theme, and audio surfaces. | packages/services | docs/packages/services.md | Services docs |
@kehto/mocks |
Deterministic mock services for every NAP domain (merged and draft), so a shell has data while implementing a NAP without a real relay, device, downloader, or provider. | packages/mocks | docs/packages/mocks.md | Mocks docs |
@kehto/nip |
Tree-shakable bundle of unique Nostr NIP utilities, including NIP-5A/5D napplet artifact verification and optional Cache Storage reuse, plus NIP-51/65/66/89 helpers. | packages/nip | docs/packages/nip.md | NIP docs |
@kehto/wm |
Structural window-management contracts for shell-owned layout strategies. | packages/wm | docs/packages/wm.md | WM docs |
@kehto/paja |
Reference developer runtime with concrete browser, relay, resource, and signer choices. | packages/paja | docs/packages/paja.md | Paja docs |
Package roots link to package-local READMEs and source. Markdown docs are the same pages used by the VitePress site.
| Need | Local markdown | Published docs |
|---|---|---|
| Understand the architecture | docs/concepts/architecture.md | Architecture |
| Understand runtime vs shell boundaries | docs/concepts/runtime-shell-boundaries.md | Runtime and shell boundaries |
| Decide how to cache napplets on the web | docs/concepts/napplet-web-cache-strategy.md | Napplet web cache strategy |
| Implement the shipped artifact cache | docs/how-tos/implement-napplet-artifact-cache.md | Implement a napplet artifact cache |
| Build a minimal host shell | docs/tutorials/minimal-host-shell.md | Minimal host shell |
| Integrate a napplet with Kehto | docs/tutorials/napplet-integration.md | Napplet integration |
| Register runtime services | docs/how-tos/register-service.md | Register a service |
| Grant capabilities | docs/how-tos/grant-capability.md | Grant a capability |
| Verify gateway artifacts | docs/how-tos/verify-gateway-artifact.md | Verify gateway artifacts |
| Read shell policy documents | docs/policies/index.md | Policies |
| Browse generated API docs | docs/reference/api.md | API reference |
The @kehto/playground demo app is deprecated and has been removed; it is no
longer maintained. Use Paja to host napplets. The old
https://kehto.github.io/web/playground/ URL now redirects to Paja; see
KEHTO_PLAYGROUND_RETIRED in the
compatibility register. Its source remains in git
history.
The harness uses port 4173. If another local
service owns the harness port, run KEHTO_HARNESS_PORT=42873 pnpm test:e2e.
The harness, Playwright base URL, and resource redirect fixtures share this port.
| Path | Contents |
|---|---|
| packages/acl | Capability and ACL primitives. |
| packages/firewall | Pure behavioral anti-abuse firewall engine. |
| packages/runtime | Protocol runtime and service routing. |
| packages/shell | Browser shell adapter and gateway/session integration. |
| packages/services | Reference service implementations. |
| packages/nip | Standalone Nostr NIP utilities (per-NIP subpaths). |
| packages/wm | Window-management type contracts. |
| docs | VitePress documentation source. |
| specs | Pinned protocol specifications consumed by this repo. |
| scripts | Build and audit helpers. |
pnpm install
pnpm build
pnpm type-check
pnpm test:unit
pnpm exec playwright install chromium
pnpm test:e2eBrowser tests use Playwright's matching full Chromium installation in modern
headless mode by default, as CI does. Set PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH only when explicitly testing a
different browser executable.
Docs and Pages artifact commands:
pnpm docs:site:dev
pnpm docs:check
pnpm build:pages
pnpm audit:pagesGenerated API docs are produced by:
pnpm docs:apiMIT
Current manifests use a direct artifact x hash, plain-text content, independent
z/i routing declarations, and required R / optional O domains. Kehto also
accepts legacy aggregate events through an isolated compatibility adapter.
Existing aggregateHash host/cache/ACL fields carry the verified artifact hash
for current events; legacy identities keep their original aggregate. Both paths
verify signatures and bytes before runtime injection and srcdoc execution.
For the schema and removal boundary, see event migration.