Langfuse Claude Code Plugin
A Claude Code plugin that traces conversations to Langfuse with full fidelity — multiple LLM generations per turn, thinking blocks, token usage, and properly nested tool observations.
What it traces
Session (session_id)
└── Trace: "Claude Code - Turn N"
├── Generation: "LLM Call 1/3" (model, usage, thinking in output)
│ ├── Span: "Tool: Glob" (input, output, duration_ms)
│ └── Span: "Tool: Read" (input, output, duration_ms)
├── Generation: "LLM Call 2/3" (model, usage)
│ └── Span: "Tool: Edit" (input, output, duration_ms)
└── Generation: "LLM Call 3/3" (model, usage, final response)
- Multiple generations per turn — each LLM API call gets its own generation observation
- Thinking blocks preserved — stored in the generation
output.thinking field
- Token usage tracked —
input_tokens, output_tokens, cache metrics in metadata
- Tools nested under their parent generation — shows which LLM call triggered which tool
- Streaming chunks merged — content blocks from all transcript lines with the same
message.id are concatenated
- Subagent tracing — Agent tool calls and their subagent transcripts are traced
- Context compaction events — tracked via PreCompact/PostCompact hooks
- Interrupted turn recovery — turns interrupted by user escape are properly closed
Installation
From the marketplace
/plugin marketplace add pdhoolia/langfuse-claude-code-plugin
/plugin install langfuse-tracing@langfuse-claude-code-plugin
/reload-plugins
For local development
Clone the repo and build:
git clone https://github.com/pdhoolia/langfuse-claude-code-plugin.git
cd langfuse-claude-code-plugin
pnpm install
pnpm build
Then run Claude Code with the plugin directory:
claude --plugin-dir /path/to/langfuse-claude-code-plugin
Configure environment variables
The plugin reads these env vars (full reference table below). Most users
set credentials and Langfuse host once globally in ~/.claude/settings.json,
then control which projects get traced via the two-knob model
below. Shell exports also work if you prefer the per-shell-session pattern.
Tracing is off by default. The plugin exits silently unless either:
TRACE_TO_LANGFUSE=true is set (typically in a project's .claude/settings.json), or
CC_LANGFUSE_TRACE_DEFAULT=all is set globally.
See Enabling tracing selectively below for the recommended setup.
| Variable | Default | Description |
|---|
TRACE_TO_LANGFUSE | (none) | Per-invocation override. true → trace; false → don't trace. Wins over the global default. See Enabling tracing selectively. |
CC_LANGFUSE_TRACE_DEFAULT | (none — opt-in) | Global default policy. all → trace by default unless a project opts out. Anything else / unset → opt-in (don't trace unless a project opts in). |
CC_LANGFUSE_PUBLIC_KEY | falls back to LANGFUSE_PUBLIC_KEY | Langfuse public key |
CC_LANGFUSE_SECRET_KEY | falls back to LANGFUSE_SECRET_KEY | Langfuse secret key |
CC_LANGFUSE_BASE_URL | https://cloud.langfuse.com | Langfuse API host (for self-hosted) |
CC_LANGFUSE_DEBUG | false | Enable debug logging |
CC_LANGFUSE_MAX_CHARS | 50000 | Max characters before truncation |
Enabling tracing selectively
The expectation is that you install the plugin once globally and then
declare per-project whether each project should be traced. Two env
vars make that work; you only ever set them inside Claude Code's
settings.json files.
The two-knob model