voxalsh
v0.1.4
Published
Voxal CLI for creating and deploying interactive terminal apps over SSH
Maintainers
Readme
voxal
The developer CLI for building and deploying interactive terminal apps that anyone
can reach with ssh <app>@<host>. You write a small JavaScript app against
@voxalsh/sdk; voxal deploy bundles it,
validates that it boots, and ships it. No shell is ever exposed — each SSH session is
wired to your sandboxed app.
Install
npm install -g voxalshThis installs the voxal command (and a voxalsh alias). You can also run it
without installing: npx voxalsh login. Requires Node.js >= 20.
The CLI validates your bundle in a real
isolated-vmsandbox before upload — the same boundary the server runs apps in.isolated-vmis a native module and therefore an optional dependency: if it can't be installed or built on your machine, the CLI still installs and works; it just falls back to a lighter, non-executing bundle check and the server does the full validation on deploy.
Quick start
voxal init myapp # connect/create a project, then scaffold ./myapp
cd myapp && npm i
voxal dev # preview locally, reload on save (Ctrl-C to stop)
voxal deploy # bundle, validate, and ship it
ssh myapp@<host> -p 2222 # reach your running appvoxal init runs an interactive menu to connect an existing project or create a new
one, writes the result into voxal.json, and scaffolds the app. If you aren't logged
in yet, it offers to log you in inline (the browser device flow) and then continues. From
then on voxal deploy is non-interactive — it reads the linked project from voxal.json.
If you ever run voxal deploy in a directory without a linked voxal.json, it runs the
same connect/create menu before deploying.
Commands
| Command | Description |
| --- | --- |
| voxal init [name] | Connect/create a project (interactive menu; offers inline login if needed), then scaffold the app in ./<name> with the linked project written into voxal.json. |
| voxal dev [dir] | Run the app locally against your own terminal — no server, no deploy. Dev-builds (unminified, sourcemapped), wires the host globals to your TTY, and reloads on save. Press q (or Ctrl-C) to stop. Needs a TTY. |
| voxal build [dir] [--out <file>] | Produce the exact production bundle deploy would upload, validate it boots, and write it to dist/<name>.js (or --out). Offline — no login. |
| voxal login [--no-browser] | Log in via the browser. --no-browser prints the URL instead of opening it (handy on headless boxes). |
| voxal logout | Log out and revoke this machine's token server-side. |
| voxal whoami | Show the signed-in account, plan, and projects. |
| voxal deploy [dir] [--name <n>] | Resolve a project (from voxal.json/--name, else the connect/create menu), bundle + validate the app, and deploy. Offers inline login if needed. |
| voxal projects [rm <name>] | List your projects, or delete one. |
Global flags
| Flag | Meaning |
| --- | --- |
| --dashboard <url> | Control-plane / login URL (default https://voxal.sh; the /api/cli/* calls go to https://app.voxal.sh). For local dev: --dashboard http://localhost:5173. |
| --host <url> | Deploy-server URL (default https://api.voxal.sh). For local dev: --host http://localhost:8787. |
| --token <t> | Use a raw token instead of the saved login (skips the account/project flow). |
These are saved into ~/.voxal/config.json by voxal login, so you only pass them once;
override per-invocation with the flags (or the VOXAL_DASHBOARD / VOXAL_API / VOXAL_HOST
env vars). URLs must be http(s); anything else is rejected before a request is made.
Configuration & security
- Your token is stored in
~/.voxal/config.json. The CLI enforces0700on the directory and0600on the file (re-applied on every write), so a leaked token isn't world-readable. voxal logoutrevokes the token server-side, so a stolen config can't be reused.- Every network call is bounded by a timeout, so a stalled server can't hang the CLI.
- A failed request names the host and the reason (
ENOTFOUND/ECONNREFUSED/timeout) with a fix hint, instead of a barefetch failed— e.g. pointing you at--dashboard http://localhost:5173when DNS fails, orcd dashboard && npm run devwhen nothing is listening locally (the common "saved local-dev config, server not running" case). voxal deploysends asha256of the bundle; the server and the bundle store both re-verify it, so the bundle can't be tampered with in flight or at rest.- Bundles are capped at 5 MiB (warning past 4 MiB), matching the server.
License
MIT
