Remote command execution for Sprites, with an API that mirrors Node.js child_process.
- Node.js 24.0.0 or later
- No external dependencies (uses only Node.js standard library)
npm install @superfly/spritesimport { SpritesClient } from '@superfly/sprites';
const client = new SpritesClient(process.env.SPRITES_TOKEN!);
const sprite = client.sprite('my-sprite');
// Event-based API (most Node.js-like)
const cmd = sprite.spawn('ls', ['-la']);
cmd.stdout.on('data', (chunk) => {
  process.stdout.write(chunk);
});
cmd.on('exit', (code) => {
  console.log(`Exited with code ${code}`);
});
// Promise-based API
const { stdout } = await sprite.exec('echo hello');
console.log(stdout); // 'hello\n'Main client for interacting with the Sprites API.
const client = new SpritesClient(token, options);Options:
- baseURL: API base URL (default: https://api.sprites.dev)
- timeout: HTTP request timeout in ms (default: 30000)
Methods:
- sprite(name: string): Sprite- Get a handle to a sprite
- createSprite(name: string, config?: SpriteConfig): Promise<Sprite>- Create a new sprite
- getSprite(name: string): Promise<Sprite>- Get sprite information
- listSprites(options?: ListOptions): Promise<SpriteList>- List sprites
- listAllSprites(prefix?: string): Promise<Sprite[]>- List all sprites (handles pagination)
- deleteSprite(name: string): Promise<void>- Delete a sprite
- upgradeSprite(name: string): Promise<void>- Upgrade a sprite
- static createToken(flyMacaroon: string, orgSlug: string, inviteCode?: string): Promise<string>- Create an access token
Represents a sprite instance.
const sprite = client.sprite('my-sprite');Command Execution Methods:
// Event-based (mirrors child_process.spawn)
spawn(command: string, args?: string[], options?: SpawnOptions): SpriteCommand
// Promise-based (mirrors child_process.exec)
exec(command: string, options?: ExecOptions): Promise<ExecResult>
// Promise-based with separate args (mirrors child_process.execFile)
execFile(file: string, args?: string[], options?: ExecOptions): Promise<ExecResult>Session Methods:
- createSession(command: string, args?: string[], options?: SpawnOptions): SpriteCommand- Create a detachable session
- attachSession(sessionId: string, options?: SpawnOptions): SpriteCommand- Attach to a session
- listSessions(): Promise<Session[]>- List active sessions
Management Methods:
- delete(): Promise<void>- Delete the sprite
- upgrade(): Promise<void>- Upgrade the sprite
Represents a running command. Extends EventEmitter.
Properties:
- stdin: Writable- Standard input stream
- stdout: Readable- Standard output stream
- stderr: Readable- Standard error stream
Methods:
- wait(): Promise<number>- Wait for exit and return exit code
- kill(signal?: string): void- Kill the command
- resize(cols: number, rows: number): void- Resize TTY (if TTY mode enabled)
- exitCode(): number- Get exit code (-1 if not exited)
Events:
- exit-- (code: number) => void- Emitted when command exits
- error-- (error: Error) => void- Emitted on error
- message-- (msg: any) => void- Emitted for text messages (e.g., port notifications)
interface SpawnOptions {
  cwd?: string;                    // Working directory
  env?: Record<string, string>;    // Environment variables
  tty?: boolean;                   // Enable TTY mode
  rows?: number;                   // TTY rows
  cols?: number;                   // TTY columns
  detachable?: boolean;            // Create detachable session
  sessionId?: string;              // Attach to existing session
  controlMode?: boolean;           // Enable control mode
}Extends SpawnOptions with:
- encoding?: BufferEncoding- Output encoding (default: 'utf8')
- maxBuffer?: number- Maximum buffer size (default: 10MB)
// Streaming output
const cmd = sprite.spawn('ls', ['-la']);
cmd.stdout.pipe(process.stdout);
cmd.stderr.pipe(process.stderr);
await cmd.wait();
// Capture output
const { stdout, stderr } = await sprite.exec('ls -la');
console.log(stdout);const cmd = sprite.spawn('bash', [], {
  tty: true,
  rows: 24,
  cols: 80,
});
process.stdin.pipe(cmd.stdin);
cmd.stdout.pipe(process.stdout);
// Resize terminal
cmd.resize(100, 30);const cmd = sprite.spawn('python', ['app.py']);
cmd.on('message', (msg) => {
  if (msg.type === 'port_opened') {
    console.log(`Port ${msg.port} opened by PID ${msg.pid}`);
    // Start local proxy, etc.
  }
});// Create a detachable session
const session = sprite.createSession('bash');
await session.wait();
// List sessions
const sessions = await sprite.listSessions();
console.log(sessions);
// Attach to a session
const attached = sprite.attachSession(sessions[0].id);import { ExecError } from '@superfly/sprites';
try {
  await sprite.exec('false');
} catch (error) {
  if (error instanceof ExecError) {
    console.log('Exit code:', error.exitCode);
    console.log('Stdout:', error.stdout);
    console.log('Stderr:', error.stderr);
  }
}// Create a sprite
const sprite = await client.createSprite('my-sprite', {
  ramMB: 512,
  cpus: 1,
  region: 'ord',
});
// List sprites
const sprites = await client.listAllSprites();
// Delete a sprite
await sprite.delete();MIT