SDK
The @voxalsh/sdk package, its two exports, and how the core and React UI layers fit together
@voxalsh/sdk is the library you build voxal apps against. It is ESM only and its core has zero runtime dependencies. The CLI bundles it into your app at build time, so you never install it at runtime, and voxal init adds it to your package.json for you.
Two exports
The core package has exactly two named exports.
import { createApp, fetch } from '@voxalsh/sdk';| Export | What it is |
|---|---|
createApp() | Creates a chainable app, registers connection and input handlers, and wires it to the host with .listen(). |
fetch(url, opts?) | A host-bridged HTTP client. Your sandbox has no network, so fetch runs the request in the trusted host and returns the result. It is not the standard fetch. |
A complete app is createApp(), a few handlers, and .listen():
import { createApp } from '@voxalsh/sdk';
createApp()
.onConnect((conn) => conn.write('hello from voxal\r\n'))
.onKey((conn, data) => {
if (data === 'q' || data === '\x03') return conn.close();
conn.write('you pressed ' + JSON.stringify(data) + '\r\n');
})
.listen();Two packages
The SDK ships in two layers. Both run entirely in the sandbox and share the same host contract, so you can use either without changing how your app is deployed or run.
| Package | Import | Use it for |
|---|---|---|
| Core | @voxalsh/sdk | Direct control of the terminal. You write ANSI strings and handle raw keystrokes yourself. |
| UI layer | @voxalsh/sdk/ui | Building terminal UIs with React and flexbox layout, one to one with Ink. |
The UI layer is pure in-sandbox code built on top of the same core primitives, so it adds no new host surface. See the UI overview for details.
When to use core vs UI
Use the core when you want full control over which bytes reach the terminal, you are writing small or highly custom output, or you do not want a React runtime in your bundle.
conn.write('\x1b[2J\x1b[H'); // clear screen, cursor home
conn.write('\x1b[1;32mready\x1b[0m\r\n'); // bold green, then a newlineUse the UI layer when you want components, declarative layout, and state-driven re-rendering instead of hand-managing the cursor and screen. It diff-renders for you and is the better default for anything with more than a few lines of interactive output.
If that is your path, start with the UI overview.