Claude Code for OpenReplay: Open-Source Session Replay — Claude Skills 360 Blog
Blog / AI / Claude Code for OpenReplay: Open-Source Session Replay
AI

Claude Code for OpenReplay: Open-Source Session Replay

Published: July 26, 2027
Read time: 5 min read
By: Claude Skills 360

OpenReplay is the open-source, self-hostable session replay tool — import Tracker from "@openreplay/tracker", const tracker = new Tracker({ projectKey, ingestPoint: "https://your-host/ingest" }) initializes. tracker.start() begins recording — call after consent if required. tracker.setUserID(userId) associates the session with a user. tracker.setMetadata("plan", "pro") adds searchable attributes. tracker.event("checkout_started", { cartValue: 49 }) fires a custom event visible in the session timeline. Plugins: tracker.use(trackerNetwork({ failuresOnly: false })) records XHR/fetch requests. tracker.use(trackerRedux({ store })) shows Redux state diffs. tracker.use(trackerPerf()) captures Core Web Vitals. tracker.use(trackerAssist()) enables co-browsing for live support. Privacy: obscureTextEmails: true, obscureInputDates: true, defaultInputMode: 1 (obscure all inputs by default), blockClass: "or-hidden" CSS class hides elements. tracker.stop() ends recording. Issue recording: call tracker.issue("Bug title", { severity: "critical" }) to flag problems. Self-hosting: deploy with Docker Compose or Kubernetes — OpenReplay Community Edition is fully open-source. Claude Code generates OpenReplay tracker setup, plugin configuration, and privacy-first session recording.

CLAUDE.md for OpenReplay

## OpenReplay Stack
- Version: @openreplay/tracker >= 14.x
- Init: const tracker = new Tracker({ projectKey: process.env.NEXT_PUBLIC_OPENREPLAY_KEY!, ingestPoint: process.env.NEXT_PUBLIC_OPENREPLAY_INGEST! })
- Start: tracker.start() — call once after mount (or after user consent)
- Identity: tracker.setUserID(userId); tracker.setMetadata("plan", value)
- Custom event: tracker.event("event_name", { prop: value }) — visible in session timeline
- Privacy: add className="or-hidden" to mask DOM elements; set defaultInputMode: 1 to obscure all inputs
- Plugins: trackerNetwork (xhr recording), trackerPerf (web vitals), trackerRedux (state)
- Stop: tracker.stop() — call on sign-out

OpenReplay Tracker Client

// lib/openreplay/tracker.ts — OpenReplay singleton with typed events
import Tracker from "@openreplay/tracker"
import trackerNetwork from "@openreplay/tracker-network"
import trackerPerf from "@openreplay/tracker-perf"

let tracker: Tracker | null = null

export function getTracker(): Tracker {
  if (tracker) return tracker

  tracker = new Tracker({
    projectKey:    process.env.NEXT_PUBLIC_OPENREPLAY_KEY!,
    ingestPoint:   process.env.NEXT_PUBLIC_OPENREPLAY_INGEST!,

    // Privacy controls
    obscureTextEmails:  true,   // redact email addresses in text nodes
    obscureInputDates:  true,   // redact date inputs
    defaultInputMode:   0,      // 0=plain, 1=obscured, 2=ignored
    respectDoNotTrack:  true,   // honor DNT header

    // Performance
    captureIFrames:    false,
    connAttemptCount:  3,
    connAttemptGap:    5000,
  })

  // Network request recording (redact auth tokens)
  tracker.use(
    trackerNetwork({
      failuresOnly:  false,
      sessionTokenHeader: false,
      ignoreHeaders: ["authorization", "cookie", "set-cookie"],
      sanitizer: (data) => {
        // Redact response bodies for auth endpoints
        if (data.url?.includes("/api/auth")) {
          data.response = "[REDACTED]"
        }
        return data
      },
    }),
  )

  // Core Web Vitals
  tracker.use(trackerPerf())

  return tracker
}

// ── Identity ───────────────────────────────────────────────────────────────

export function identifySession(
  userId: string,
  metadata: Record<string, string> = {},
): void {
  const t = getTracker()
  t.setUserID(userId)
  Object.entries(metadata).forEach(([key, value]) => {
    t.setMetadata(key, value)
  })
}

// ── Custom events (typed) ──────────────────────────────────────────────────

type SessionEvents = {
  "checkout_started":   { cartValue: number; itemCount: number }
  "checkout_completed": { orderId: string; revenue: number }
  "search_performed":   { query: string; results: number }
  "feature_used":       { feature: string }
  "error_displayed":    { code: string; message: string }
  "upgrade_clicked":    { from: string; to: string; location: string }
}

type SessionEventName = keyof SessionEvents

export function trackEvent<E extends SessionEventName>(
  event: E,
  properties: SessionEvents[E],
): void {
  const t = getTracker()
  t.event(event, properties as Record<string, unknown>)
}

/** Flag an issue from code — appears in OpenReplay issue tracker */
export function flagIssue(title: string, context: Record<string, unknown> = {}): void {
  const t = getTracker()
  t.issue(title, context)
}

export function stopRecording(): void {
  tracker?.stop()
}

Next.js App Router Integration

// components/OpenReplayProvider.tsx — session replay with privacy controls
"use client"
import { useEffect, useRef } from "react"
import { usePathname } from "next/navigation"
import { getTracker, identifySession, trackEvent } from "@/lib/openreplay/tracker"

type Props = {
  userId?:    string
  userPlan?:  string
  children:   React.ReactNode
}

export default function OpenReplayProvider({ userId, userPlan, children }: Props) {
  const pathname = usePathname()
  const started = useRef(false)

  // Start tracker once
  useEffect(() => {
    if (started.current) return
    const tracker = getTracker()
    tracker.start().then(() => {
      started.current = true
      if (userId) {
        identifySession(userId, { plan: userPlan ?? "free" })
      }
    })
  }, [userId, userPlan])

  // Track route changes as custom events
  useEffect(() => {
    if (!started.current) return
    trackEvent("feature_used", { feature: `page:${pathname}` })
  }, [pathname])

  return <>{children}</>
}

Redux Plugin Setup

// lib/openreplay/redux-plugin.ts — capture Redux state in session
import trackerRedux from "@openreplay/tracker-redux"
import { getTracker } from "./tracker"
import type { Store } from "redux"

/** Attach Redux store to OpenReplay — state diff visible in sessions */
export function attachReduxStore(store: Store): Store {
  const tracker = getTracker()

  tracker.use(
    trackerRedux({
      actionFilter: (action: { type: string }) =>
        !action.type.startsWith("@@INIT"),       // skip noisy init actions
      actionTransformer: (action: unknown) => action, // optionally redact action payloads
      stateTransformer: (state: Record<string, unknown>) => {
        // Redact sensitive state fields
        const { auth, ...safe } = state
        return { ...safe, auth: { isLoggedIn: !!(auth as any)?.user } }
      },
    }),
  )

  return store
}

React Error Boundary with OpenReplay

// components/OpenReplayErrorBoundary.tsx — capture render errors in session
"use client"
import { Component, type ReactNode } from "react"
import { flagIssue } from "@/lib/openreplay/tracker"

type Props = { children: ReactNode; fallback?: ReactNode }
type State = { hasError: boolean; errorMessage?: string }

export class OpenReplayErrorBoundary extends Component<Props, State> {
  state: State = { hasError: false }

  static getDerivedStateFromError(error: Error): State {
    return { hasError: true, errorMessage: error.message }
  }

  componentDidCatch(error: Error, info: { componentStack: string }) {
    // Flag the issue — it appears in the session timeline and issue tracker
    flagIssue(`React Error: ${error.message}`, {
      errorName:      error.name,
      componentStack: info.componentStack.slice(0, 500),
    })
  }

  render() {
    if (this.state.hasError) {
      return this.props.fallback ?? (
        <div className="p-8 text-center border border-red-200 rounded-xl bg-red-50">
          <p className="text-red-600 font-medium">An unexpected error occurred.</p>
          <button
            className="mt-4 px-4 py-2 bg-white border border-red-300 text-red-600 rounded-lg text-sm hover:bg-red-50"
            onClick={() => {
              this.setState({ hasError: false })
              window.location.reload()
            }}
          >
            Reload page
          </button>
        </div>
      )
    }
    return this.props.children
  }
}

For the Highlight.io alternative when wanting an open-source full-stack observability tool that combines session replay with backend error monitoring and distributed tracing via OpenTelemetry — Highlight.io connects frontend session replay to backend spans in a single trace while OpenReplay focuses on deeper frontend session replay with co-browsing and a dedicated self-hosted infrastructure you can run on your own servers, see the Highlight.io guide. For the LogRocket alternative when needing the proprietary LogRocket product with ML-powered session search, rage-click heatmaps, performance dashboards, and enterprise GDPR/HIPAA compliance — LogRocket is the leading commercial session replay service while OpenReplay is its open-source self-hostable counterpart with a comparable feature set and no per-session pricing, see the LogRocket guide. The Claude Skills 360 bundle includes OpenReplay skill sets covering session recording, plugins, and privacy controls. Start with the free tier to try open-source session replay generation.

Keep Reading

AI

Claude Code for email.contentmanager: Python Email Content Accessors

Read and write EmailMessage body content with Python's email.contentmanager module and Claude Code — email contentmanager ContentManager for the class that maps content types to get and set handler functions allowing EmailMessage to support get_content and set_content with type-specific behaviour, email contentmanager raw_data_manager for the ContentManager instance that handles raw bytes and str payloads without any conversion, email contentmanager content_manager for the standard ContentManager instance used by email.policy.default that intelligently handles text plain text html multipart and binary content types, email contentmanager get_content_text for the handler that returns the decoded text payload of a text-star message part as a str, email contentmanager get_content_binary for the handler that returns the raw decoded bytes payload of a non-text message part, email contentmanager get_data_manager for the get-handler lookup used by EmailMessage get_content to find the right reader function for the content type, email contentmanager set_content text for the handler that creates and sets a text part correctly choosing charset and transfer encoding, email contentmanager set_content bytes for the handler that creates and sets a binary part with base64 encoding and optional filename Content-Disposition, email contentmanager EmailMessage get_content for the method that reads the message body using the registered content manager handlers, email contentmanager EmailMessage set_content for the method that sets the message body and MIME headers in one call, email contentmanager EmailMessage make_alternative make_mixed make_related for the methods that convert a simple message into a multipart container, email contentmanager EmailMessage add_attachment for the method that attaches a file or bytes to a multipart message, and email contentmanager integration with email.message and email.policy and email.mime and io for building high-level email readers attachment extractors text body accessors HTML readers and policy-aware MIME construction pipelines.

5 min read Feb 12, 2029
AI

Claude Code for email.charset: Python Email Charset Encoding

Control header and body encoding for international email with Python's email.charset module and Claude Code — email charset Charset for the class that wraps a character set name with the encoding rules for header encoding and body encoding describing how to encode text for that charset in email messages, email charset Charset header_encoding for the attribute specifying whether headers using this charset should use QP quoted-printable encoding BASE64 encoding or no encoding, email charset Charset body_encoding for the attribute specifying the Content-Transfer-Encoding to use for message bodies in this charset such as QP or BASE64, email charset Charset output_codec for the attribute giving the Python codec name used to encode the string to bytes for the wire format, email charset Charset input_codec for the attribute giving the Python codec name used to decode incoming bytes to str, email charset Charset get_output_charset for returning the output charset name, email charset Charset header_encode for encoding a header string using the charset's header_encoding method, email charset Charset body_encode for encoding body content using the charset's body_encoding, email charset Charset convert for converting a string from the input_codec to the output_codec, email charset add_charset for registering a new charset with custom encoding rules in the global charset registry, email charset add_alias for adding an alias name that maps to an existing registered charset, email charset add_codec for registering a codec name mapping for use by the charset machinery, and email charset integration with email.message and email.mime and email.policy and email.encoders for building international email senders non-ASCII header encoders Content-Transfer-Encoding selectors charset-aware message constructors and MIME encoding pipelines.

5 min read Feb 11, 2029
AI

Claude Code for email.utils: Python Email Address and Header Utilities

Parse and format RFC 2822 email addresses and dates with Python's email.utils module and Claude Code — email utils parseaddr for splitting a display-name plus angle-bracket address string into a realname and email address tuple, email utils formataddr for combining a realname and address string into a properly quoted RFC 2822 address with angle brackets, email utils getaddresses for parsing a list of raw address header strings each potentially containing multiple comma-separated addresses into a list of realname address tuples, email utils parsedate for parsing an RFC 2822 date string into a nine-tuple compatible with time.mktime, email utils parsedate_tz for parsing an RFC 2822 date string into a ten-tuple that includes the UTC offset timezone in seconds, email utils parsedate_to_datetime for parsing an RFC 2822 date string into an aware datetime object with timezone, email utils formatdate for formatting a POSIX timestamp or the current time as an RFC 2822 date string with optional usegmt and localtime flags, email utils format_datetime for formatting a datetime object as an RFC 2822 date string, email utils make_msgid for generating a globally unique Message-ID string with optional idstring and domain components, email utils decode_rfc2231 for decoding an RFC 2231 encoded parameter value into a tuple of charset language and value, email utils encode_rfc2231 for encoding a string as an RFC 2231 encoded parameter value, email utils collapse_rfc2231_value for collapsing a decoded RFC 2231 tuple to a Unicode string, and email utils integration with email.message and email.headerregistry and datetime and time for building address parsers date formatters message-id generators header extractors and RFC-compliant email construction utilities.

5 min read Feb 10, 2029

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free