docs / server

Server

The core Express + WebSocket server. Spawns real pseudo-terminals and bridges them to authenticated clients over WebSocket.

server/src/index.ts

Install

terminal
npm install @walkie-talkie/server
Note: 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: 3456
cwdstring?Working directory for spawned terminals. Default: user home.

The returned object has these methods and properties:

MemberTypeDescription
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 | nullGet the current active (unused, unexpired) token
onStateChange(cb)(cb: () => void) => voidSubscribe to terminal/session count changes
terminalCountnumberNumber of active terminals
sessionCountnumberNumber of known sessions
portnumberThe port the server is bound to

REST API

The server exposes a few REST endpoints alongside WebSocket:

EndpointAuthDescription
GET /NoneServer info (name, status, port)
GET /api/healthNoneHealth check (status, version, uptime)
GET /api/terminalsBearerList all active terminals
DELETE /api/terminals/:idBearerKill 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:

  1. 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.
  2. Session — when a valid token is consumed, the server issues a UUID session ID. Sessions are persisted to ~/.walkie-talkie/sessions.json and 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);