diff --git a/README.md b/README.md
index d39bfdc..15b8f58 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,53 @@
A dependency-free TypeScript terminal UI runtime. Screens are plain data; JSX is one way to write them.
```bash
-npm install @textui/kit @textui/widgets
+npm install @textui/kit
+```
+
+```tsx
+import { Box, Text, render, useInput, useState } from '@textui/kit';
+
+function Counter() {
+ const [count, setCount] = useState(0);
+ useInput((e) => {
+ if (e.name !== '+') return false;
+ setCount((c) => c + 1);
+ return true;
+ });
+
+ return (
+
+ Count: {count}
+ + to increment, ctrl+c to quit
+
+ );
+}
+
+const { waitUntilExit } = render();
+await waitUntilExit();
+```
+
+> Status: pre-1.0. The surface is still moving.
+
+## Installing
+
+One package is enough to have something on screen. The rest are additive, and
+nothing pulls in a third-party dependency.
+
+```bash
+npm install @textui/kit # pnpm add @textui/kit
+```
+
+`@textui/kit` is the runtime, a terminal to put it on, and `render`. `Box`,
+`Text`, the hooks and `render` all come from here, and the example above needs
+nothing else.
+
+**For the component catalog** - `Panel`, `Table`, `Row`, `Column`, charts,
+overlays, forms - add `@textui/widgets`. Its components are resolved by name at
+mount time, so they have to be registered before they can render:
+
+```bash
+npm install @textui/kit @textui/widgets # pnpm add @textui/kit @textui/widgets
```
```tsx
@@ -14,7 +60,32 @@ const { waitUntilExit } = render(, { onBoot: registerBuiltins });
await waitUntilExit();
```
-> Status: pre-1.0. The surface is still moving.
+Forget `onBoot` and the components are missing registrations rather than
+missing imports - the screen renders, and says so where they should have been.
+
+**For a project set up for you**, and for components copied into your source
+rather than imported, use the CLI. It needs no install:
+
+```bash
+npx @textui/cli init # pnpm dlx @textui/cli init
+npx @textui/cli doctor # what this terminal can actually do
+```
+
+`doctor` is the one to run first when something renders wrong - it reports the
+unicode level, colour depth and keyboard protocol actually detected.
+
+**Working against the pieces directly** - `@textui/core` and `@textui/terminal`
+- is the same thing with a longer name. `@textui/kit` re-exports both and adds
+`render`; there is nothing in them it hides. Take them separately when you want
+the runtime without a terminal attached, which is what the test harness and the
+static renderer do:
+
+```bash
+npm install @textui/core @textui/terminal # pnpm add @textui/core @textui/terminal
+```
+
+Node >= 22, and TypeScript wants `"jsx": "react-jsx"` with
+`"jsxImportSource": "@textui/kit"` - see [getting started](docs/getting-started.md).
## The one idea
diff --git a/docs/getting-started.md b/docs/getting-started.md
index 6213649..701614a 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -10,12 +10,99 @@ type Service = { name: string; status: string; cpu: string };
# Getting started
```bash
-pnpm add @textui/core @textui/terminal
+npm install @textui/kit # pnpm add @textui/kit
```
-Node ≥ 22. There are no other dependencies.
+Node ≥ 22. There are no other dependencies, and this one package is enough to
+put something on screen.
-## The smallest thing that runs
+## Hello, in full
+
+`@textui/kit` is the runtime, a terminal to put it on, and `render`. Everything
+this example uses comes from it.
+
+```tsx
+import { Box, Text, render, useInput, useState } from '@textui/kit';
+
+function Counter() {
+ const [count, setCount] = useState(0);
+ useInput((e) => {
+ if (e.name !== '+') return false;
+ setCount((c) => c + 1);
+ return true;
+ });
+
+ return (
+
+ Count: {count}
+ + to increment, ctrl+c to quit
+
+ );
+}
+
+const { waitUntilExit } = render();
+await waitUntilExit();
+```
+
+`render` mounts and keeps running - it returns a handle rather than a promise,
+so the application is up before the next line. `waitUntilExit()` resolves when
+it stops, however it stopped.
+
+For JSX, point the compiler at the runtime:
+
+```jsonc
+// tsconfig.json
+{
+ "compilerOptions": {
+ "jsx": "react-jsx",
+ "jsxImportSource": "@textui/kit"
+ }
+}
+```
+
+## Adding the catalog
+
+`Box` and `Text` are host primitives and always available. `Panel`, `Table`,
+`Row`, `Column`, the charts, forms and overlays live in `@textui/widgets`, and
+are resolved **by name at mount time** - so they have to be registered before
+they can render:
+
+```bash
+npm install @textui/widgets # pnpm add @textui/widgets
+```
+
+```tsx
+import { Text, render } from '@textui/kit';
+import { Panel, registerBuiltins } from '@textui/widgets';
+
+function Dashboard() {
+ return (
+
+ nothing to report
+
+ );
+}
+
+const { waitUntilExit } = render(, { onBoot: registerBuiltins });
+await waitUntilExit();
+```
+
+Forget `onBoot` and nothing throws at compile time: a missing registration is a
+runtime miss, rendered visibly where the component should have been.
+
+## The pieces underneath
+
+`@textui/kit` re-exports `@textui/core` and [`@textui/terminal`](terminal)
+and adds `render`; it hides nothing. Take them
+separately when you want the runtime without a terminal attached - which is
+what the test harness and the static renderer do - or when you want to own the
+wiring:
+
+```bash
+npm install @textui/core @textui/terminal # pnpm add @textui/core @textui/terminal
+```
+
+Wired by hand, that same hello is:
```tsx
import { createApp, WRITER_KEY } from '@textui/core';
@@ -38,19 +125,11 @@ await app.start();
## JSX
-Point the compiler at the runtime:
-
-```jsonc
-// tsconfig.json
-{
- "compilerOptions": {
- "jsx": "react-jsx",
- "jsxImportSource": "@textui/core"
- }
-}
-```
+Working against the pieces directly, `jsxImportSource` is `@textui/core`
+rather than `@textui/kit` - the runtime is where the factory lives, and the kit
+re-exports it.
-Then `` produces `{ component: 'Row', gap: 1 }`. Lowercase names are host primitives - `box`, `text`, `canvas`, `spacer` - and capitalised names are components you import, which is what gives them prop types.
+`` produces `{ component: 'Row', gap: 1 }`. Lowercase names are host primitives - `box`, `text`, `canvas`, `spacer` - and capitalised names are components you import, which is what gives them prop types.
```tsx
import { useStoreValue } from '@textui/core';
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2fd2152..5a0db73 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -304,6 +304,9 @@ importers:
'@textui/documents':
specifier: workspace:*
version: link:../../../packages/documents
+ '@textui/kit':
+ specifier: workspace:*
+ version: link:../../../packages/facade
'@textui/terminal':
specifier: workspace:*
version: link:../../../packages/terminal
diff --git a/scripts/docs/snippets/package.json b/scripts/docs/snippets/package.json
index 283211a..5b01888 100644
--- a/scripts/docs/snippets/package.json
+++ b/scripts/docs/snippets/package.json
@@ -11,6 +11,7 @@
"dependencies": {
"@textui/cli": "workspace:*",
"@textui/core": "workspace:*",
+ "@textui/kit": "workspace:*",
"@textui/documents": "workspace:*",
"@textui/terminal": "workspace:*",
"@textui/textide": "workspace:*",