Server
The core Express + WebSocket server. Spawns real pseudo-terminals and bridges them to authenticated clients over WebSocket.
server/src/index.tsInstall
terminal
npm install @walkie-talkie/serverNote: This package depends on
node-pty, which requires a native compiler. On macOS, install Xcode Command Line Tools. On Linux, ensure make and g++ are available.Quick Start
my-server.ts
import { createServer } from '@walkie-talkie/server';
const server = createServer(3456);
await server.start();
console.log('Listening on port 3456');
const { value, expiresAt } = server.generateToken();
console.log(`Token: ${value} (expires in 5 minutes)`);
// React to terminal count changes
server.onStateChange(() => {
console.log(`Active terminals: ${server.terminalCount}`);
});API
createServer(port?, cwd?)
Creates and returns a server instance.
portnumberPort to listen on. Default:
3456cwdstring?Working directory for spawned terminals. Default: user home.
The returned object has these methods and properties:
| Member | Type | Description |
|---|---|---|
start() | Promise<void> | Start listening on the port |
stop() | Promise<void> | Gracefully shut down — kills all terminals, closes connections |
generateToken() | {value, expiresAt} | Generate a single-use token (5 min TTL) |
getActiveToken() | Token | null | Get the current active (unused, unexpired) token |
onStateChange(cb) | (cb: () => void) => void | Subscribe to terminal/session count changes |
terminalCount | number | Number of active terminals |
sessionCount | number | Number of known sessions |
port | number | The port the server is bound to |
REST API
The server exposes a few REST endpoints alongside WebSocket:
| Endpoint | Auth | Description |
|---|---|---|
GET / | None | Server info (name, status, port) |
GET /api/health | None | Health check (status, version, uptime) |
GET /api/terminals | Bearer | List all active terminals |
DELETE /api/terminals/:id | Bearer | Kill a terminal by ID |
Authenticated endpoints require Authorization: Bearer <sessionId>.
terminal
# List terminals
curl -H "Authorization: Bearer <sessionId>" http://localhost:3456/api/terminals
# Kill a terminal
curl -X DELETE -H "Authorization: Bearer <sessionId>" \
http://localhost:3456/api/terminals/<terminalId>QR Utilities
Helper functions for generating connection QR codes:
qr-example.ts
import {
generateQR,
generateConnectionQR,
buildConnectionUrl,
} from '@walkie-talkie/server';
// ASCII QR code for the terminal
const ascii = await generateQR('https://example.com?token=abc');
console.log(ascii);
// Data URL for embedding in HTML (280x280px)
const dataUrl = await generateConnectionQR(
'https://example.com',
'abc-def-123-456'
);
// Just build the URL
const url = buildConnectionUrl('https://example.com', 'abc-def-123-456');
// → "https://example.com?token=abc-def-123-456"Token System
The server uses a two-phase authentication model:
- Token — a random hex string formatted as
XXXX-XXXX-XXXX-XXXX. Tokens are single-use with a 5-minute TTL. They exist only in memory. - Session — when a valid token is consumed, the server issues a UUID session ID. Sessions are persisted to
~/.walkie-talkie/sessions.jsonand survive server restarts (with a 24-hour expiry).
Embedding in Your App
Since the server is just an Express app with a WebSocket server attached, you can embed it alongside your existing HTTP server:
embed.ts
import { createServer } from '@walkie-talkie/server';
import express from 'express';
// Your existing app
const app = express();
app.get('/', (req, res) => res.send('My App'));
// Start walkie-talkie on a separate port
const wt = createServer(4000, '/home/deploy/app');
await wt.start();
const token = wt.generateToken();
console.log('Terminal token:', token.value);