Back to skills
SKILL.md
Langfuse Local Dev Loop
ASecurity'Set up Langfuse local development workflow with hot reload and debugging.
- 2,719 stars
- 0 votes
- 0 copies
- 1 view
- Added September 21, 2026
Works with
Security analysis
92/100- Installs packages at runtime which could introduce malicious dependencies
npx -y skills add jeremylongshore/claude-code-plugins-plus --skill langfuse-local-dev-loop --agent claude-codeAre you the author of Langfuse Local Dev Loop?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/jeremylongshore-langfuse-local-dev-loop-b89de62e)---
name: langfuse-local-dev-loop
description: 'Set up Langfuse local development workflow with hot reload and debugging.
Use when developing LLM applications locally, debugging traces,
or setting up a fast iteration loop with Langfuse.
Trigger with phrases like "langfuse local dev", "langfuse development",
"debug langfuse traces", "langfuse hot reload", "langfuse dev workflow".
'
allowed-tools: Read, Write, Edit, Bash(npm:*), Bash(docker:*), Bash(pnpm:*)
version: 1.17.0
license: MIT
author: Jeremy Longshore <jeremy@intentsolutions.io>
tags:
- saas
- langfuse
- llm
- debugging
- workflow
compatibility: Designed for Claude Code
---
# Langfuse Local Dev Loop
## Overview
Fast local development workflow with Langfuse tracing, immediate trace visibility, debug logging, and optional self-hosted local instance via Docker.
## Prerequisites
- Completed `langfuse-install-auth` setup
- Node.js 18+ with `tsx` for hot reload (`npm install -D tsx`)
- Docker (optional, for self-hosted local instance)
## Instructions
### Step 1: Development Environment File
```bash
# .env.local (git-ignored)
LANGFUSE_PUBLIC_KEY=pk-lf-dev-...
LANGFUSE_SECRET_KEY=sk-lf-dev-...
LANGFUSE_BASE_URL=https://cloud.langfuse.com
# Dev-specific settings
NODE_ENV=development
OPENAI_API_KEY=sk-...
```
### Step 2: Dev-Optimized Langfuse Setup (v4+)
```typescript
// src/lib/langfuse-dev.ts
import { LangfuseSpanProcessor } from "@langfuse/otel";
import { NodeSDK } from "@opentelemetry/sdk-node";
import { LangfuseClient } from "@langfuse/client";
const isDev = process.env.NODE_ENV !== "production";
// Configure span processor with dev-friendly settings
const processor = new LangfuseSpanProcessor({
// In dev: flush immediately for instant visibility
...(isDev && { exportIntervalMillis: 1000, maxExportBatchSize: 1 }),
});
const sdk = new NodeSDK({ spanProcessors: [processor] });
sdk.start();
export const langfuse = new LangfuseClient();
// Print trace URLs in development
export function logTrace(traceId: string) {
if (isDev) {
const host = process.env.LANGFUSE_BASE_URL || "https://cloud.langfuse.com";
console.log(`\n Trace: ${host}/trace/${traceId}\n`);
}
}
// Clean shutdown
process.on("SIGINT", async () => {
await sdk.shutdown();
process.exit(0);
});
```
### Step 3: Dev-Optimized Setup (v3 Legacy)
```typescript
// src/lib/langfuse-dev.ts
import { Langfuse } from "langfuse";
const isDev = process.env.NODE_ENV !== "production";
export const langfuse = new Langfuse({
flushAt: isDev ? 1 : 15, // Immediate flush in dev
flushInterval: isDev ? 1000 : 10000,
...(isDev && { debug: true }), // Verbose SDK logging
});
export function logTraceUrl(trace: ReturnType<typeof langfuse.trace>) {
if (isDev) {
console.log(`\n Trace: ${trace.getTraceUrl()}\n`);
}
}
process.on("beforeExit", async () => {
await langfuse.shutdownAsync();
});
```
### Step 4: Hot Reload Scripts
```json
{
"scripts": {
"dev": "tsx watch --env-file=.env.local src/index.ts",
"dev:debug": "DEBUG=langfuse* tsx watch --env-file=.env.local src/index.ts",
"dev:trace": "LANGFUSE_DEBUG=true tsx watch --env-file=.env.local src/index.ts"
}
}
```
### Step 5: Development Tracing Utilities
```typescript
// src/lib/dev-utils.ts
import { observe, updateActiveObservation, startActiveObservation } from "@langfuse/tracing";
// Quick traced function wrapper with console output
export function devTrace<T extends (...args: any[]) => Promise<any>>(
name: string,
fn: T
): T {
return observe({ name }, async (...args: Parameters<T>) => {
updateActiveObservation({ input: args, metadata: { env: "dev" } });
const start = Date.now();
const result = await fn(...args);
const duration = Date.now() - start;
updateActiveObservation({ output: result });
console.log(` [${name}] ${duration}ms`);
return result;
}) as T;
}
// Quick debug trace -- fire-and-forget diagnostic trace
export async function debugTrace(name: string, data: Record<string, any>) {
await startActiveObservation(`debug/${name}`, async () => {
updateActiveObservation({
input: data,
metadata: { debug: true, timestamp: new Date().toISOString() },
});
});
}
```
### Step 6: Example Dev Workflow
```typescript
// src/index.ts
import "dotenv/config";
import { initTracing, langfuse } from "./lib/langfuse-dev";
import { devTrace } from "./lib/dev-utils";
import OpenAI from "openai";
import { observeOpenAI } from "@langfuse/openai";
initTracing();
const openai = observeOpenAI(new OpenAI());
const askQuestion = devTrace("ask-question", async (question: string) => {
const response = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: question }],
});
return response.choices[0].message.content;
});
// Run on file save (tsx watch restarts automatically)
const answer = await askQuestion("What is Langfuse?");
console.log("Answer:", answer);
```
## Local Self-Hosted Langfuse (Optional)
For offline development or data privacy:
```yaml
# docker-compose.langfuse.yml
services:
langfuse:
image: langfuse/langfuse:latest
ports:
- "3000:3000"
environment:
- DATABASE_URL=${DATABASE_URL}
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
- NEXTAUTH_URL=http://localhost:3000
- SALT=${SALT}
- ENCRYPTION_KEY=${ENCRYPTION_KEY}
depends_on:
- db
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: langfuse
volumes:
- langfuse-db:/var/lib/postgresql/data
volumes:
langfuse-db:
```
Before starting the stack, place unique local-only values for `DATABASE_URL`,
`POSTGRES_PASSWORD`, `NEXTAUTH_SECRET`, `SALT`, and `ENCRYPTION_KEY` in a git-ignored
`.env` file. Do not commit a database URI or reuse example or production values.
```bash
set -euo pipefail
# Start local Langfuse
docker compose -f docker-compose.langfuse.yml up -d
# Wait for startup, then visit http://localhost:3000
# Create account, project, and API keys in the local UI
# Update .env.local
echo 'LANGFUSE_BASE_URL=http://localhost:3000' >> .env.local
```
## Error Handling
| Issue | Cause | Solution |
|-------|-------|----------|
| Traces delayed in dev | Batching still active | Set `flushAt: 1` or `exportIntervalMillis: 1000` |
| No debug output | Debug not enabled | Set `LANGFUSE_DEBUG=true` or `DEBUG=langfuse*` |
| Hot reload not working | Wrong watch command | Use `tsx watch` (not `ts-node`) |
| Local instance 502 | DB not ready | Wait 10s for PostgreSQL startup |
| Traces going to cloud | Wrong `LANGFUSE_BASE_URL` | Point to `http://localhost:3000` |
## Output
Produce a local development receipt naming the SDK/runtime version, local or cloud host,
sample trace identifier, and debug setting used. Keep `.env.local` secret values and
local database credentials out of logs and commits.
## Examples
Start the watch process, change a prompt or traced function, and verify the reload emits
one local trace. For self-hosting, bring up Compose, create a disposable project and key
in the local UI, then prove that the application points to `localhost` rather than cloud.
## Resources
- [TypeScript SDK Setup](https://langfuse.com/docs/observability/sdk/typescript/setup)
- [Self-Hosting Docker Compose](https://langfuse.com/self-hosting/deployment/docker-compose)
- [Advanced SDK Configuration](https://langfuse.com/docs/observability/sdk/typescript/advanced-usage)
## Next Steps
For SDK patterns and best practices, see `langfuse-sdk-patterns`.
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.