npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@posthog/openclaw

v0.2.1

Published

PostHog LLM Analytics plugin for OpenClaw

Readme

@posthog/openclaw

npm version CI License: MIT

PostHog LLM Analytics plugin for OpenClaw. Captures LLM generations, tool executions, and conversation traces, sending them to PostHog as structured $ai_* events for the LLM Analytics dashboard.

https://github.com/user-attachments/assets/bf7ce150-becb-4df9-b78d-5660d0a3e489

Install

openclaw plugins install @posthog/openclaw

Configuration

Add to your openclaw.json (or openclaw.yaml):

{
    "plugins": {
        "entries": {
            "posthog": {
                "enabled": true,
                "config": {
                    "apiKey": "phc_your_project_key",
                    "host": "https://us.i.posthog.com",
                    "privacyMode": false,
                    "traceGrouping": "message",
                    "sessionWindowMinutes": 60,
                },
            },
        },
    },
    "diagnostics": {
        "enabled": true,
    },
}

Options

| Option | Type | Default | Description | | ---------------------- | -------------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------- | | apiKey | string | (required) | Your PostHog project API key | | host | string | https://us.i.posthog.com | PostHog instance URL | | privacyMode | boolean | false | When enabled, LLM input/output content is not sent to PostHog | | traceGrouping | "message" | "session" | "message" | Trace grouping mode. "message": one trace per runId. "session": group all generations in a session into one trace | | sessionWindowMinutes | number | 60 | Minutes of inactivity before starting a new session window. Applies to both trace grouping modes | | enabled | boolean | true | Enable or disable the plugin |

Note: diagnostics.enabled must be true in your OpenClaw config for trace-level events ($ai_trace) to be captured.

What gets captured

$ai_generation

Captured on every LLM call (correlated llm_input + llm_output hooks).

| Property | Description | | ----------------------------- | ---------------------------------------------------------------- | | $ai_model | Model name (e.g. gpt-4o, claude-3) | | $ai_provider | Provider name (e.g. openai, anthropic) | | $ai_latency | Request duration in seconds | | $ai_input_tokens | Input token count | | $ai_output_tokens | Output token count | | $ai_total_cost_usd | Total cost in USD | | $ai_input_cost_usd | Input cost in USD | | $ai_output_cost_usd | Output cost in USD | | $ai_stop_reason | Why generation stopped (stop, length, tool_calls, error) | | $ai_is_error | Whether the generation errored | | $ai_error | Error message (if any) | | $ai_input | Input messages in OpenAI format (redacted in privacy mode) | | $ai_output_choices | Output choices (redacted in privacy mode) | | $ai_trace_id | Trace ID for hierarchical grouping | | $ai_span_id | Span ID for this generation | | $ai_session_id | Session identifier | | $ai_channel | Message channel (e.g. telegram, slack) | | $ai_agent_id | Agent identifier | | cache_read_input_tokens | Cache read token count | | cache_creation_input_tokens | Cache creation token count |

$ai_span

Captured for each tool call (after_tool_call hook).

| Property | Description | | ------------------ | ------------------------------------------------ | | $ai_span_name | Tool name | | $ai_latency | Tool execution duration in seconds | | $ai_is_error | Whether the tool call errored | | $ai_error | Error message (if any) | | $ai_input_state | Tool input parameters (redacted in privacy mode) | | $ai_output_state | Tool output result (redacted in privacy mode) | | $ai_trace_id | Trace ID | | $ai_span_id | Span ID for this tool call | | $ai_parent_id | Parent generation span ID |

$ai_trace

Captured when a message cycle completes (message.processed diagnostic event).

| Property | Description | | ------------------------- | ------------------------------------------------------------- | | $ai_trace_id | Trace ID | | $ai_session_id | Session identifier | | $ai_latency | Total message cycle duration in seconds | | $ai_total_input_tokens | Accumulated input tokens across all generations in the trace | | $ai_total_output_tokens | Accumulated output tokens across all generations in the trace | | $ai_is_error | Whether the message cycle errored | | $ai_error | Error message (if any) | | $ai_channel | Message channel |

Privacy

With privacyMode: true, no message content, prompts, or tool parameters are sent to PostHog. Token counts, latency, model info, and error status are always captured.

Development

pnpm install
pnpm test
pnpm typecheck
pnpm lint

Local testing with OpenClaw

To test the plugin locally against a running OpenClaw gateway, use plugins.load.paths to point OpenClaw at your local checkout:

// ~/.openclaw/openclaw.json
{
    "plugins": {
        "load": {
            "paths": ["/path/to/posthog-openclaw"],
        },
        "entries": {
            "posthog": {
                "enabled": true,
                "config": {
                    "apiKey": "phc_your_project_key",
                    "host": "https://us.i.posthog.com",
                    "privacyMode": false,
                },
            },
        },
    },
    "diagnostics": { "enabled": true },
}

Then start the gateway:

cd /path/to/openclaw
pnpm install && pnpm build
node openclaw.mjs gateway --force --allow-unconfigured

Open WebChat at http://127.0.0.1:18789/openclaw/canvas/ and send a message. Events will appear in your PostHog project under LLM Analytics.

Note: The config entry key must be "posthog" (matching the id field in openclaw.plugin.json), not the npm package name.

License

MIT