From flyio-pack
Provides typed FlyClient patterns for the Fly.io Machines REST API: machine lifecycle management, auth, error handling with retry, and multi-region orchestration.
How this skill is triggered — by the user, by Claude, or both
Slash command
/flyio-pack:flyio-sdk-patternsThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Production-ready patterns for the Fly.io Machines REST API at `https://api.machines.dev`. Fly.io exposes both GraphQL (organization queries) and REST (machine lifecycle) APIs. The Machines REST API is the primary integration surface for creating, starting, stopping, and destroying VMs across 30+ global regions. A structured client ensures consistent auth, typed machine states, and reliable wait...
Production-ready patterns for the Fly.io Machines REST API at https://api.machines.dev. Fly.io exposes both GraphQL (organization queries) and REST (machine lifecycle) APIs. The Machines REST API is the primary integration surface for creating, starting, stopping, and destroying VMs across 30+ global regions. A structured client ensures consistent auth, typed machine states, and reliable wait-for-state polling.
const FLY_API = 'https://api.machines.dev';
let _client: FlyClient | null = null;
export function getClient(appName: string): FlyClient {
if (!_client) {
const token = process.env.FLY_API_TOKEN;
if (!token) throw new Error('FLY_API_TOKEN must be set');
_client = new FlyClient(appName, token);
}
return _client;
}
class FlyClient {
private h: Record<string, string>;
constructor(private app: string, token: string) {
this.h = { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' };
}
async listMachines(): Promise<FlyMachine[]> {
const r = await fetch(`${FLY_API}/v1/apps/${this.app}/machines`, { headers: this.h });
if (!r.ok) throw new FlyError(r.status, await r.text()); return r.json();
}
async createMachine(config: MachineConfig, region: string): Promise<FlyMachine> {
const r = await fetch(`${FLY_API}/v1/apps/${this.app}/machines`, {
method: 'POST', headers: this.h, body: JSON.stringify({ region, config }) });
if (!r.ok) throw new FlyError(r.status, await r.text()); return r.json();
}
async waitForState(id: string, state: string, timeout = 30): Promise<void> {
const r = await fetch(`${FLY_API}/v1/apps/${this.app}/machines/${id}/wait?state=${state}&timeout=${timeout}`,
{ headers: this.h });
if (!r.ok) throw new FlyError(r.status, `Wait for ${state} timed out`);
}
}
export class FlyError extends Error {
constructor(public status: number, message: string) { super(message); this.name = 'FlyError'; }
}
export async function safeCall<T>(operation: string, fn: () => Promise<T>): Promise<T> {
try { return await fn(); }
catch (err: any) {
if (err instanceof FlyError && err.status === 429) { await new Promise(r => setTimeout(r, 2000)); return fn(); }
if (err instanceof FlyError && err.status === 401) throw new FlyError(401, 'Invalid FLY_API_TOKEN');
throw new FlyError(err.status ?? 0, `${operation} failed: ${err.message}`);
}
}
class DeployBuilder {
private regions: string[] = []; private config: Partial<MachineConfig> = {};
toRegions(...r: string[]) { this.regions = r; return this; }
withImage(img: string) { this.config.image = img; return this; }
withGuest(cpus: number, mem: number) { this.config.guest = { cpu_kind: 'shared', cpus, memory_mb: mem }; return this; }
async execute(client: FlyClient): Promise<FlyMachine[]> {
return Promise.all(this.regions.map(async r => {
const m = await client.createMachine(this.config as MachineConfig, r);
await client.waitForState(m.id, 'started'); return m;
}));
}
}
// Usage: await new DeployBuilder().toRegions('iad','lhr','nrt').withImage('app:latest').withGuest(1,256).execute(client);
type MachineState = 'created' | 'starting' | 'started' | 'stopping' | 'stopped' | 'destroying' | 'destroyed';
interface FlyMachine {
id: string; name: string; state: MachineState; region: string;
config: MachineConfig; created_at: string; updated_at: string;
}
interface MachineConfig {
image: string; guest: { cpu_kind: string; cpus: number; memory_mb: number };
services: Array<{ ports: Array<{ port: number; handlers: string[] }>; internal_port: number }>;
env: Record<string, string>;
}
interface FlyVolume { id: string; name: string; region: string; size_gb: number; attached_machine_id: string | null; }
export function mockMachine(overrides: Partial<FlyMachine> = {}): FlyMachine {
return { id: 'mach-001', name: 'test-machine', state: 'started', region: 'iad',
config: { image: 'app:latest', guest: { cpu_kind: 'shared', cpus: 1, memory_mb: 256 }, services: [], env: {} },
created_at: '2025-01-01T00:00:00Z', updated_at: '2025-01-01T00:00:00Z', ...overrides };
}
| Pattern | When to Use | Example |
|---|---|---|
safeCall wrapper | All Machines API calls | Catches network + API errors uniformly |
| Retry on 429 | Bulk machine creation | 2s delay before retry |
waitForState timeout | After create/start/stop | Prevents hanging deploys |
| Region fallback | Multi-region deploy failure | Skip failed region, continue others |
Apply patterns in flyio-core-workflow-a.
2plugins reuse this skill
First indexed Jul 18, 2026
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin flyio-packRate-limits Fly.io Machines API calls using token bucket and retry with exponential backoff. Provides TypeScript implementation for concurrency and batching.
Deploy, configure, and manage applications on the Fly.io platform using flyctl CLI, fly.toml configuration, Fly Machines, Fly Volumes, private networking, secrets, health checks, autoscaling, and GitHub Actions CI/CD. Use when deploying any application to Fly.io, writing or modifying fly.toml configuration, managing Fly Machines or Volumes, configuring networking (public services, private 6PN, Flycast, custom domains, TLS), setting secrets, configuring health checks, setting up autostop/autostart or metrics-based autoscaling, deploying with GitHub Actions, managing Fly Postgres databases, or preparing an app for production on Fly.io.
Deploys and manages Fly.io apps using Docker containers, Fly Machines, fly.toml configs, databases, volumes, secrets. Supports fly launch/deploy, debugging, multi-region setups for Python/Node/Rails/Django apps.