{"slug": "show-hn-ai-flight-recorder-record-replay-and-track-ai-session-costs", "title": "Show HN: AI Flight Recorder – record, replay, and track AI session costs", "summary": "AI Flight Recorder, an open-source developer tool for recording, replaying, and inspecting AI application sessions, has been released on GitHub. The tool captures prompts, streamed tokens, tool calls, latency, and cost, and provides a DevTools-style timeline with features such as streaming replay at speeds from 0.25× to 8×, cost analysis, and OpenTelemetry export. It includes one-line SDK wrappers for OpenAI, Anthropic, and Google Gemini, and supports Node.js 18+ with pnpm 10+.", "body_md": "DevTools for AI Applications\n\nAI Flight Recorder is an open-source developer tool for recording, replaying, and inspecting every interaction in an AI application — prompts, streamed tokens, tool calls, latency, and cost — all in one place.\n\nInstead of piecing together console logs after the fact, you drop in a one-line SDK wrapper and get a full DevTools-style timeline you can pause, rewind, and hand off to a teammate as a `.flight`\n\nfile.\n\n**Session recording:** capture every prompt, token, tool call, and completion as a structured event stream**Streaming replay:** watch a session play back in real time with speed controls (0.25×–8×)**Timeline & Waterfall:** visualize the full request lifecycle including parallel tool calls and streaming latency**Cost Analysis:** break down token usage and estimated spend per session**Search & Filter:** filter events by type or keyword across the full timeline**Provider Adapters:** one-line wrappers for OpenAI, Anthropic, and Google Gemini (streaming and non-streaming)share a session as a portable file another developer can replay locally`.flight`\n\nExport/Import:**Plugin System:** hook into the recorder lifecycle with custom observers**Transport System:** plug in any storage backend (in-memory, filesystem, your own API)**OpenTelemetry Export:** convert any session to an OTLP trace payload for ingestion into Jaeger, Grafana Tempo, Honeycomb, or any OTel-compatible backend (`toOtlp`\n\nfrom`@ai-flight-recorder/sdk`\n\n)\n\n```\nai-flight-recorder/\n├── apps/\n│   ├── devtools/          Next.js DevTools application\n│   ├── docs/              Starlight documentation site\n│   └── vscode/            VS Code extension — custom editor for .flight files\n├── packages/\n│   ├── core/              Domain model — events, session, recorder, replay engine\n│   ├── sdk/               Developer-facing API — FlightRecorder, adapters, plugins, transports\n│   ├── ui/                Shared React components (future)\n│   └── types/             Shared TypeScript types (future)\n├── scripts/\n│   └── smoke.ts           SDK integration smoke test\n└── examples/\n    ├── nextjs-chat/       Full-stack chat app — OpenAI streaming + .flight export\n    ├── node-anthropic/    Node.js example — Anthropic + FileTransport\n    └── node-gemini/       Node.js example — Google Gemini + FileTransport\n```\n\n- Node.js 18+\n- pnpm 10+\n\n```\npnpm install\npnpm dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000). The app loads with two demo sessions so you can explore the UI immediately — no API keys required.\n\n```\npnpm smoke\n```\n\nExercises recording, plugins, transport, serialization, and replay end-to-end. All 40 assertions should pass.\n\n``` js\nimport { FlightRecorder } from \"@ai-flight-recorder/sdk\";\n\nconst fr = new FlightRecorder();\nconst session = fr.startSession({ label: \"my-chat\" });\n\nfr.record({\n  type: \"prompt\",\n  model: \"gpt-4o\",\n  prompt: \"What is the capital of France?\",\n});\nfr.record({\n  type: \"completion\",\n  response: \"Paris.\",\n  finishReason: \"stop\",\n  totalTokens: 18,\n});\n\nconst ended = fr.endSession();\n```\n\nDrop-in wrappers that intercept the provider client and record every call automatically.\n\n**OpenAI**\n\n``` python\nimport OpenAI from \"openai\";\nimport { FlightRecorder, wrapOpenAI } from \"@ai-flight-recorder/sdk\";\n\nconst fr = new FlightRecorder();\nconst openai = wrapOpenAI(new OpenAI(), fr.recorder);\n\nfr.startSession({ label: \"chat\" });\n\nconst response = await openai.chat.completions.create({\n  model: \"gpt-4o\",\n  messages: [{ role: \"user\", content: \"Hello\" }],\n});\n\nfr.endSession();\n```\n\n**Anthropic**\n\n``` python\nimport Anthropic from \"@anthropic-ai/sdk\";\nimport { FlightRecorder, wrapAnthropic } from \"@ai-flight-recorder/sdk\";\n\nconst fr = new FlightRecorder();\nconst client = wrapAnthropic(new Anthropic(), fr.recorder);\n\nfr.startSession({ label: \"claude-chat\" });\n\nconst message = await client.messages.create({\n  model: \"claude-sonnet-4-5\",\n  max_tokens: 1024,\n  messages: [{ role: \"user\", content: \"Hello\" }],\n});\n\nfr.endSession();\n```\n\n**Google Gemini**\n\n``` js\nimport { GoogleGenerativeAI } from \"@google/generative-ai\";\nimport { FlightRecorder, wrapGeminiModel } from \"@ai-flight-recorder/sdk\";\n\nconst fr = new FlightRecorder();\nconst genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY!);\nconst model = wrapGeminiModel(\n  genAI.getGenerativeModel({ model: \"gemini-1.5-pro\" }),\n  fr.recorder,\n);\n\nfr.startSession({ label: \"gemini-chat\" });\nconst result = await model.generateContent(\"Hello\");\nfr.endSession();\n```\n\nAll three adapters support streaming. Wrap your existing client and all calls are recorded automatically.\n\n``` js\nimport { FlightRecorder, ConsoleLogPlugin } from \"@ai-flight-recorder/sdk\";\n\nconst fr = new FlightRecorder({\n  plugins: [\n    new ConsoleLogPlugin({ logEvents: true, logSummary: true }),\n\n    // Inline plugin\n    {\n      name: \"my-plugin\",\n      onSessionStart: (session) => console.log(\"Started:\", session.id),\n      onEvent: (event) => myMetrics.record(event),\n      onSessionEnd: (session) => alerting.flush(session),\n    },\n  ],\n});\n```\n\n`use()`\n\nis chainable and checks for duplicate names at registration time:\n\n```\nfr.use(pluginA).use(pluginB);\njs\nimport { FlightRecorder, InMemoryTransport } from \"@ai-flight-recorder/sdk\";\n\nconst transport = new InMemoryTransport();\n\nconst fr = new FlightRecorder({ transport });\n\nfr.startSession();\n// ... record events ...\nfr.endSession(); // automatically saves to transport\n\nconst sessions = transport.getAll();\n```\n\n**Node.js filesystem transport:**\n\n``` js\nimport { FlightRecorder } from \"@ai-flight-recorder/sdk\";\nimport { FileTransport } from \"@ai-flight-recorder/sdk/node\";\n\nconst transport = new FileTransport(\"./recordings\");\nconst fr = new FlightRecorder({ transport });\n\nfr.startSession({ label: \"my-session\" });\n// ... record events ...\nfr.endSession();\n// saves to ./recordings/<sessionId>.flight\n\nconst sessions = transport.loadAll();\npython\nimport type { Transport } from \"@ai-flight-recorder/sdk\";\n\nclass MyApiTransport implements Transport {\n  async save(session) {\n    await fetch(\"/api/sessions\", {\n      method: \"POST\",\n      body: JSON.stringify(session),\n    });\n  }\n}\n\nconst fr = new FlightRecorder({ transport: new MyApiTransport() });\n```\n\nSessions can be exported as portable `.flight`\n\nfiles (JSON with a version envelope):\n\n```\n{\n  \"version\": \"1\",\n  \"exportedAt\": 1721484000000,\n  \"session\": {\n    \"id\": \"...\",\n    \"label\": \"bug-report-123\",\n    \"status\": \"ended\",\n    \"startedAt\": 1721484000000,\n    \"endedAt\": 1721484060000,\n    \"events\": [ ... ]\n  }\n}\n```\n\n**Export from the DevTools UI:** click the Export button in the toolbar while a session is active.\n\n**Import into the DevTools UI:** click Import and select a `.flight`\n\nfile. The session is added to the session list and becomes the active session immediately.\n\n**Programmatic export/import:**\n\n``` js\nimport { serializeSession, deserializeSession } from \"@ai-flight-recorder/sdk\";\nimport { writeFileSync, readFileSync } from \"node:fs\";\n\n// Export\nwriteFileSync(\"bug-123.flight\", serializeSession(endedSession));\n\n// Import\nconst session = deserializeSession(readFileSync(\"bug-123.flight\", \"utf-8\"));\n```\n\nThe DevTools app (`apps/devtools`\n\n) is a Next.js application providing a visual interface for recorded sessions.\n\n**Tabs:**\n\n**Timeline:** chronological event list with type badges, descriptions, and timing offsets**Waterfall:** visual latency breakdown showing streaming spans and tool call durations**Cost Analysis:** token usage breakdown and estimated spend per request\n\n**Replay:**\n\n- Click \"Replay Session\" to enter replay mode\n- Speed controls: 0.25×, 0.5×, 1×, 2×, 4×, 8×\n- Seek bar for jumping to any point in the session\n- Token stream assembles in real time as tokens replay\n\n**Search:**\n\n- Filter by event type using the chip row (Prompt, Token, Tool, Result, Completion, Error)\n- Text search across event content\n\n`examples/nextjs-chat`\n\nis a minimal Next.js app showing a full end-to-end integration — streaming chat with GPT-4o-mini, automatic session recording, and `.flight`\n\nexport.\n\n```\ncd examples/nextjs-chat\ncp .env.example .env.local\n```\n\nEdit `.env.local`\n\nand add your OpenAI API key:\n\n```\nOPENAI_API_KEY=sk-...\npnpm dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000). Chat with the assistant, then click **Export .flight** in the header to download your session.\n\nOpen the DevTools app (`pnpm dev`\n\nfrom the repo root), click **Import** in the toolbar, and select the `.flight`\n\nfile. Your session loads instantly — timeline, waterfall, cost breakdown, and full streaming replay.\n\nThe example wires up three things from the SDK:\n\n`FlightRecorder`\n\n: starts a session per request`wrapOpenAI`\n\n: intercepts the OpenAI client and records every prompt, token, and completion automatically`serializeSession`\n\n: serializes the ended session to JSON for download\n\nTo use Anthropic or Gemini instead, swap `wrapOpenAI`\n\nfor `wrapAnthropic`\n\nor `wrapGeminiModel`\n\nin `src/app/api/chat/route.ts`\n\n.\n\n```\n# Build all packages\npnpm build\n\n# Run DevTools in development mode\npnpm dev\n\n# Typecheck all packages\npnpm typecheck\n\n# Lint all packages\npnpm lint\n\n# SDK smoke test (no build required)\npnpm smoke\n```\n\n- Add the type literal to\n`packages/core/src/events/EventType.ts`\n\n- Create the interface in\n`packages/core/src/events/YourEvent.ts`\n\nextending`BaseEvent`\n\n- Add it to the\n`AIEvent`\n\nunion in`packages/core/src/events/AIEvent.ts`\n\n- Export it from\n`packages/core/src/events/index.ts`\n\n- Add a case to\n`eventMeta.ts`\n\nin the DevTools app for display metadata\n\nImplement the `Plugin`\n\ninterface from `@ai-flight-recorder/core`\n\n:\n\n``` python\nimport type { Plugin, AIEvent, Session } from \"@ai-flight-recorder/sdk\";\n\nexport class MyPlugin implements Plugin {\n  readonly name = \"my-plugin\";\n\n  onSessionStart(session: Session) { ... }\n  onEvent(event: AIEvent) { ... }\n  onSessionEnd(session: Session) { ... }\n}\n```\n\nThis project is licensed under the MIT License - see the [LICENSE](/AllThingsSmitty/ai-flight-recorder/blob/main/LICENSE) file for details.", "url": "https://wpnews.pro/news/show-hn-ai-flight-recorder-record-replay-and-track-ai-session-costs", "canonical_source": "https://github.com/AllThingsSmitty/ai-flight-recorder", "published_at": "2026-08-13 12:30:28+00:00", "updated_at": "2026-08-13 12:43:04.700631+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools", "ai-infrastructure"], "entities": ["AI Flight Recorder", "OpenAI", "Anthropic", "Google Gemini", "Jaeger", "Grafana Tempo", "Honeycomb"], "alternates": {"html": "https://wpnews.pro/news/show-hn-ai-flight-recorder-record-replay-and-track-ai-session-costs", "markdown": "https://wpnews.pro/news/show-hn-ai-flight-recorder-record-replay-and-track-ai-session-costs.md", "text": "https://wpnews.pro/news/show-hn-ai-flight-recorder-record-replay-and-track-ai-session-costs.txt", "jsonld": "https://wpnews.pro/news/show-hn-ai-flight-recorder-record-replay-and-track-ai-session-costs.jsonld"}}