Introduction
Quick Start
Create, run, and extend your first tuil application.
Prerequisites
- Bun 1.3.14 or newer
- A terminal with color and Unicode support
- React experience; Ink experience is useful but not required
Create the application
The initializer owns package selection, configuration, application structure, and the first runnable screen:
npx @mwillbanks/tuil create my-terminal-app
cd my-terminal-app
npm run devThe generated entry point defines one application boundary and passes it to the Ink renderer:
import { createApp } from "@mwillbanks/tuil";
import { Box, Heading, Text, render } from "@mwillbanks/tuil-ink";
function App() {
return (
<Box flexDirection="column" padding="md">
<Heading>My first tuil</Heading>
<Text label="Status">Runtime ready.</Text>
</Box>
);
}
const app = createApp({
id: "my-terminal-app",
component: App,
});
const instance = render(<App />, { app });
await instance.waitUntilExit();Add a component
Registry components are copied into your project so you own their source:
npx @mwillbanks/tuil add button field text-inputThe CLI resolves transitive registry dependencies, detects every destination conflict before writing, and leaves unrelated project files untouched.
Add runtime behavior
Define events next to the application boundary:
import { createApp, defineEvents, event } from "@mwillbanks/tuil";
const app = createApp({
component: App,
events: defineEvents({
"task:completed": event<{ id: string }>(),
}),
});
app.events.on("task:completed", ({ payload }) => {
console.log(`Completed ${payload.id}`);
});Continue with What is tuil?, then use the architecture guide to choose the right package boundaries.