Introduction
voxal is a platform for interactive terminal apps that anyone can run with a single SSH command, no install required
voxal is a platform for interactive terminal apps that anyone can run over SSH. You
write a small JavaScript app, deploy it with one command, and from then on anyone can use
it with ssh your-app@voxal.sh. No frontend to host, no binary to ship, nothing for your
users to install. If they have an SSH client, and every machine does, they can run your app.
Think of it as Vercel, except the interface is delivered over SSH instead of the browser. You ship the logic; voxal runs it, renders it live to each user's terminal, and keeps your backend code (API calls, secrets, business logic) on the server where users never see it.
import { createApp } from '@voxalsh/sdk';
createApp()
.onConnect((conn) => {
conn.write('hello from voxal\r\n');
conn.write('press q to quit\r\n');
})
.onKey((conn, data) => {
if (data === 'q') conn.close();
})
.listen();npm create voxal-app my-app
cd my-app && npm run deploy
# then anyone can run: ssh my-app@voxal.shStart here
Quickstart
Go from nothing to a deployed app you can SSH into, in about five minutes.
How voxal works
The connection lifecycle and the model your app runs in.
Guides
Build real things: React UIs, keyboard input, data fetching, and a chat app.
SDK reference
createApp, the connection, fetch, and the full React UI layer.
CLI reference
The commands for scaffolding, previewing, and shipping an app.
Limits and quotas
Bundle size, compute, timers, and fetch limits, in one place.
What you write
Every voxal app imports one package, @voxalsh/sdk, which gives you two ways to
build. Use whichever fits the app.
- Core.
createAppplus a connection object. You handle events and write strings (with ANSI escapes) straight to the terminal. Ideal for small tools, streams, and anything you want byte-level control over. - UI (React).
@voxalsh/sdk/uiis a real terminal UI framework: flexbox layout,<Box>and<Text>, and hooks likeuseInput. It mirrors Ink one to one, so React knowledge transfers directly.
import { serve, Box, Text, useInput, useApp } from '@voxalsh/sdk/ui';
import { useState } from 'react';
function Counter() {
const [n, setN] = useState(0);
const { exit } = useApp();
useInput((input, key) => {
if (input === 'q') exit();
if (key.upArrow) setN((c) => c + 1);
if (key.downArrow) setN((c) => c - 1);
});
return (
<Box borderStyle="round" padding={1} flexDirection="column">
<Text>count: <Text bold color="green">{n}</Text></Text>
<Text dimColor>up and down to change, q to quit</Text>
</Box>
);
}
serve(() => <Counter />);How it runs
When someone connects, voxal hands the SSH session to your app and nothing else. There is
no shell, no login prompt, and no filesystem on the other end. The username in
ssh your-app@voxal.sh is your app's name.
Your app runs in an isolated sandbox, one per app, that serves every connected user at once. Each user gets their own connection; your shared logic lives in one place. Idle apps scale to zero and boot again in milliseconds on the next connection, so you only run when someone is actually using your app. Read How voxal works for the full picture.
New here?
The fastest path to a running app is npm create voxal-app. The
Quickstart walks through it end to end.