From e03d0a221c7927a8a845e3b9618f4b7504f93e9d Mon Sep 17 00:00:00 2001 From: Danilo Campos Date: Thu, 30 Apr 2026 15:17:24 -0400 Subject: [PATCH 1/3] feat: add bundle definitions for synthetic git plugin distribution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds bundles.yaml defining 11 framework-oriented skill bundles (nextjs, react, python, node, react-native, svelte, vue, ruby, go, llm, android). Each bundle groups skills across categories (integration, feature flags, error tracking, logs) for a specific framework. The build script loads bundle definitions and includes them in the manifest. The MCP server reads these to serve each bundle as a single synthetic git repo — one install gives the user the right set of skills for their stack. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/build.js | 42 +++++++- transformation-config/bundles.yaml | 148 +++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 transformation-config/bundles.yaml diff --git a/scripts/build.js b/scripts/build.js index a618c1a..742842b 100755 --- a/scripts/build.js +++ b/scripts/build.js @@ -71,10 +71,23 @@ async function createBundledArchive(outputPath, manifest, skillZips) { } +/** + * Load bundle definitions from bundles.yaml + */ +function loadBundles(configDir) { + const bundlesPath = path.join(configDir, 'bundles.yaml'); + if (!fs.existsSync(bundlesPath)) { + return {}; + } + const content = fs.readFileSync(bundlesPath, 'utf8'); + const config = yaml.load(content); + return config.bundles || {}; +} + /** * Generate manifest with skill URIs, download URLs, and MCP resource representations */ -function generateManifest(skills, uriSchema, version, guideContents = {}) { +function generateManifest(skills, uriSchema, version, guideContents = {}, bundles = {}) { const scheme = uriSchema.scheme; const skillPattern = uriSchema.patterns.skill; const docPattern = uriSchema.patterns.doc; @@ -126,6 +139,20 @@ function generateManifest(skills, uriSchema, version, guideContents = {}) { }, }; }), + bundles: Object.entries(bundles).reduce((acc, [id, bundle]) => { + const validSkills = bundle.skills.filter(sid => + skills.some(s => s.id === sid) + ); + if (validSkills.length > 0) { + acc[id] = { + name: bundle.name, + description: bundle.description, + keywords: bundle.keywords || [], + skills: validSkills, + }; + } + return acc; + }, {}), }; } @@ -222,8 +249,11 @@ async function main() { })); const allResources = [...skills, ...docResources]; + // Load bundle definitions + const bundles = loadBundles(configDir); + // Generate manifest - const manifest = generateManifest(allResources, uriSchema, BUILD_VERSION, docContents); + const manifest = generateManifest(allResources, uriSchema, BUILD_VERSION, docContents, bundles); const manifestPath = path.join(skillsDir, 'manifest.json'); fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2)); @@ -287,6 +317,14 @@ async function main() { console.log(` - ${doc.id} (${docContents[doc.id].length} chars)`); } } + const bundleCount = Object.keys(manifest.bundles || {}).length; + if (bundleCount > 0) { + console.log(`\nBundles: ${bundleCount}`); + for (const [id, bundle] of Object.entries(manifest.bundles)) { + console.log(` - ${id}: ${bundle.skills.length} skills`); + } + } + console.log(`\nMarketplace: ${marketplaceResult.marketplaceDir}`); console.log(` ${marketplaceResult.pluginCount} plugins, ${marketplaceResult.skillCount} skills`); diff --git a/transformation-config/bundles.yaml b/transformation-config/bundles.yaml new file mode 100644 index 0000000..5c9587f --- /dev/null +++ b/transformation-config/bundles.yaml @@ -0,0 +1,148 @@ +# Bundle definitions for synthetic git plugin distribution. +# +# Each bundle groups skills by framework/platform so users install one +# thing and get the right set. Skills are referenced by their generated +# ID (e.g. "integration-nextjs-app-router", "error-tracking-nextjs"). +# +# The MCP server reads these from the manifest and serves each bundle +# as a synthetic git repo at /git/bundles/:name. + +bundles: + nextjs: + name: PostHog for Next.js + description: Analytics, feature flags, error tracking, and logging for Next.js applications + keywords: [nextjs, react, ssr, javascript] + skills: + - integration-nextjs-app-router + - integration-nextjs-pages-router + - feature-flags-nextjs + - feature-flags-react + - error-tracking-nextjs + - error-tracking-react + - logs-nextjs + - omnibus-instrument-product-analytics + - omnibus-instrument-feature-flags + - omnibus-instrument-error-tracking + + react: + name: PostHog for React + description: Analytics, feature flags, and error tracking for React applications + keywords: [react, javascript, spa] + skills: + - feature-flags-react + - error-tracking-react + - omnibus-instrument-product-analytics + - omnibus-instrument-feature-flags + - omnibus-instrument-error-tracking + + python: + name: PostHog for Python + description: Analytics, feature flags, error tracking, and logging for Python applications + keywords: [python, django, flask, fastapi] + skills: + - integration-django + - integration-flask + - integration-fastapi + - integration-python + - feature-flags-python + - error-tracking-python + - logs-python + - omnibus-instrument-product-analytics + - omnibus-instrument-feature-flags + - omnibus-instrument-error-tracking + + node: + name: PostHog for Node.js + description: Analytics, feature flags, error tracking, and logging for Node.js applications + keywords: [nodejs, javascript, typescript] + skills: + - integration-javascript_node + - feature-flags-nodejs + - error-tracking-node + - logs-nodejs + - omnibus-instrument-product-analytics + - omnibus-instrument-feature-flags + - omnibus-instrument-error-tracking + + react-native: + name: PostHog for React Native + description: Analytics, feature flags, and error tracking for React Native applications + keywords: [react-native, mobile, ios, android] + skills: + - integration-react-native + - integration-expo + - feature-flags-react-native + - error-tracking-react-native + - omnibus-instrument-product-analytics + - omnibus-instrument-feature-flags + - omnibus-instrument-error-tracking + + svelte: + name: PostHog for Svelte + description: Analytics, feature flags, and error tracking for SvelteKit applications + keywords: [svelte, sveltekit, javascript] + skills: + - integration-sveltekit + - error-tracking-svelte + - omnibus-instrument-product-analytics + - omnibus-instrument-feature-flags + - omnibus-instrument-error-tracking + + vue: + name: PostHog for Vue / Nuxt + description: Analytics, feature flags, and error tracking for Vue.js and Nuxt applications + keywords: [vue, nuxt, javascript] + skills: + - integration-vue-3 + - integration-nuxt-3-6 + - integration-nuxt-4 + - error-tracking-nuxt + - omnibus-instrument-product-analytics + - omnibus-instrument-feature-flags + - omnibus-instrument-error-tracking + + ruby: + name: PostHog for Ruby + description: Analytics, feature flags, error tracking, and logging for Ruby and Rails applications + keywords: [ruby, rails, ruby-on-rails] + skills: + - integration-ruby + - integration-ruby-on-rails + - feature-flags-ruby + - error-tracking-ruby + - error-tracking-ruby-on-rails + - omnibus-instrument-product-analytics + - omnibus-instrument-feature-flags + - omnibus-instrument-error-tracking + + go: + name: PostHog for Go + description: Analytics, feature flags, error tracking, and logging for Go applications + keywords: [go, golang] + skills: + - feature-flags-go + - error-tracking-go + - logs-go + - omnibus-instrument-product-analytics + - omnibus-instrument-feature-flags + - omnibus-instrument-error-tracking + + llm: + name: PostHog LLM Analytics + description: Monitor LLM usage, costs, traces, and evaluations with PostHog + keywords: [llm, ai, observability, tracing] + skills: + - llm-analytics-setup + - omnibus-instrument-llm-analytics + + android: + name: PostHog for Android + description: Analytics, feature flags, and error tracking for Android applications + keywords: [android, kotlin, java, mobile] + skills: + - integration-android + - feature-flags-android + - error-tracking-android + - omnibus-instrument-product-analytics + - omnibus-instrument-feature-flags + - omnibus-instrument-error-tracking From a704604ee6d07c2ee4ddd612f887943520328903 Mon Sep 17 00:00:00 2001 From: Danilo Campos Date: Thu, 30 Apr 2026 15:44:39 -0400 Subject: [PATCH 2/3] feat: add recommend-posthog-skills to bundle manifest The recommend_skill section in bundles.yaml defines a SKILL.md that ships with the core plugin. It detects the user's tech stack and recommends the right bundle. The build script generates the bundle list from the bundle definitions and includes the rendered skill content in the manifest for the MCP server to pass through. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/build.js | 41 +++++++++++++++++----- transformation-config/bundles.yaml | 56 ++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 8 deletions(-) diff --git a/scripts/build.js b/scripts/build.js index 742842b..e7a2c6b 100755 --- a/scripts/build.js +++ b/scripts/build.js @@ -72,22 +72,46 @@ async function createBundledArchive(outputPath, manifest, skillZips) { /** - * Load bundle definitions from bundles.yaml + * Load bundle definitions and recommend skill from bundles.yaml */ -function loadBundles(configDir) { +function loadBundlesConfig(configDir) { const bundlesPath = path.join(configDir, 'bundles.yaml'); if (!fs.existsSync(bundlesPath)) { - return {}; + return { bundles: {}, recommendSkill: null }; } const content = fs.readFileSync(bundlesPath, 'utf8'); const config = yaml.load(content); - return config.bundles || {}; + const bundles = config.bundles || {}; + + let recommendSkill = null; + if (config.recommend_skill) { + const rs = config.recommend_skill; + const bundleList = Object.entries(bundles) + .map(([id, b]) => `- **posthog-${id}**: ${b.description} (keywords: ${b.keywords.join(', ')})`) + .join('\n'); + + const frontmatter = [ + '---', + `name: ${rs.name}`, + `description: >`, + ...rs.description.trim().split('\n').map(l => ` ${l}`), + ...(rs.allowed_tools ? [`allowed-tools:\n${rs.allowed_tools.map(t => ` - ${t}`).join('\n')}`] : []), + '---', + ].join('\n'); + + recommendSkill = { + name: rs.name, + content: frontmatter + '\n\n' + rs.content.replace('{bundle_list}', bundleList), + }; + } + + return { bundles, recommendSkill }; } /** * Generate manifest with skill URIs, download URLs, and MCP resource representations */ -function generateManifest(skills, uriSchema, version, guideContents = {}, bundles = {}) { +function generateManifest(skills, uriSchema, version, guideContents = {}, bundles = {}, recommendSkill = null) { const scheme = uriSchema.scheme; const skillPattern = uriSchema.patterns.skill; const docPattern = uriSchema.patterns.doc; @@ -153,6 +177,7 @@ function generateManifest(skills, uriSchema, version, guideContents = {}, bundle } return acc; }, {}), + ...(recommendSkill ? { recommendSkill } : {}), }; } @@ -249,11 +274,11 @@ async function main() { })); const allResources = [...skills, ...docResources]; - // Load bundle definitions - const bundles = loadBundles(configDir); + // Load bundle definitions and recommend skill + const { bundles, recommendSkill } = loadBundlesConfig(configDir); // Generate manifest - const manifest = generateManifest(allResources, uriSchema, BUILD_VERSION, docContents, bundles); + const manifest = generateManifest(allResources, uriSchema, BUILD_VERSION, docContents, bundles, recommendSkill); const manifestPath = path.join(skillsDir, 'manifest.json'); fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2)); diff --git a/transformation-config/bundles.yaml b/transformation-config/bundles.yaml index 5c9587f..9f96f34 100644 --- a/transformation-config/bundles.yaml +++ b/transformation-config/bundles.yaml @@ -6,6 +6,62 @@ # # The MCP server reads these from the manifest and serves each bundle # as a synthetic git repo at /git/bundles/:name. +# +# The recommend_skill section defines a SKILL.md that ships with the +# core plugin. It detects the user's stack and recommends the right +# bundle. The build script generates {bundle_list} from the bundle +# definitions below. + +recommend_skill: + name: recommend-posthog-skills + description: > + Detect the user's technology stack and recommend the right PostHog skill + bundle. Run this when the user installs the PostHog plugin, asks about + PostHog setup, or when you detect a project that could benefit from + PostHog integration. + allowed_tools: + - Bash + - Read + content: | + # Recommend PostHog Skills + + You are helping the user install the right PostHog skills for their project. + + ## Step 1: Detect the technology stack + + Check the project for framework indicators: + + ```bash + # Check for key files + ls package.json requirements.txt Gemfile go.mod Cargo.toml build.gradle pubspec.yaml 2>/dev/null + + # If package.json exists, check dependencies + cat package.json 2>/dev/null | grep -E '"(next|react|react-native|expo|vue|nuxt|svelte|@sveltejs|astro|angular)"' | head -10 + + # If requirements.txt or setup.py exists + cat requirements.txt setup.py pyproject.toml 2>/dev/null | grep -iE '(django|flask|fastapi)' | head -5 + + # If Gemfile exists + cat Gemfile 2>/dev/null | grep -iE '(rails|sinatra)' | head -5 + ``` + + ## Step 2: Match to a bundle + + Based on what you find, recommend ONE bundle from this list: + + {bundle_list} + + ## Step 3: Recommend installation + + Tell the user which bundle matches their stack and give them the install command: + + ``` + /plugin install posthog-{bundle-name}@posthog + ``` + + If the project uses multiple frameworks (e.g., a Next.js frontend + Python backend), recommend multiple bundles. + + If no framework is detected, ask the user what they're building. bundles: nextjs: From d457a86fee155cef9d3c25215a2d0745e489f17a Mon Sep 17 00:00:00 2001 From: Danilo Campos Date: Thu, 30 Apr 2026 20:15:50 -0400 Subject: [PATCH 3/3] feat: broaden recommend skill triggers to match user intent The recommend skill now triggers on generic analytics/tracking language (analytics, event tracking, feature flags, error monitoring, logging, observability) rather than only "PostHog setup." Adds when_to_use field for additional trigger context. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/build.js | 16 ++++++++++++---- transformation-config/bundles.yaml | 20 +++++++++++++++----- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/scripts/build.js b/scripts/build.js index e7a2c6b..fb349cc 100755 --- a/scripts/build.js +++ b/scripts/build.js @@ -90,14 +90,22 @@ function loadBundlesConfig(configDir) { .map(([id, b]) => `- **posthog-${id}**: ${b.description} (keywords: ${b.keywords.join(', ')})`) .join('\n'); - const frontmatter = [ + const frontmatterLines = [ '---', `name: ${rs.name}`, `description: >`, ...rs.description.trim().split('\n').map(l => ` ${l}`), - ...(rs.allowed_tools ? [`allowed-tools:\n${rs.allowed_tools.map(t => ` - ${t}`).join('\n')}`] : []), - '---', - ].join('\n'); + ]; + if (rs.when_to_use) { + frontmatterLines.push(`when_to_use: >`); + frontmatterLines.push(...rs.when_to_use.trim().split('\n').map(l => ` ${l}`)); + } + if (rs.allowed_tools) { + frontmatterLines.push(`allowed-tools:`); + frontmatterLines.push(...rs.allowed_tools.map(t => ` - ${t}`)); + } + frontmatterLines.push('---'); + const frontmatter = frontmatterLines.join('\n'); recommendSkill = { name: rs.name, diff --git a/transformation-config/bundles.yaml b/transformation-config/bundles.yaml index 9f96f34..bd8cc41 100644 --- a/transformation-config/bundles.yaml +++ b/transformation-config/bundles.yaml @@ -15,17 +15,27 @@ recommend_skill: name: recommend-posthog-skills description: > - Detect the user's technology stack and recommend the right PostHog skill - bundle. Run this when the user installs the PostHog plugin, asks about - PostHog setup, or when you detect a project that could benefit from - PostHog integration. + Recommend the right PostHog skill bundle for the user's project. + Use when the user wants to add analytics, event tracking, product analytics, + feature flags, A/B testing, experiments, error tracking, exception monitoring, + crash reporting, logging, observability, LLM tracing, or customer behavior + tracking to their application. Also use when the user mentions understanding + user behavior, measuring engagement, tracking conversions, monitoring errors, + or instrumenting their app. + when_to_use: > + The user asks about adding analytics, tracking, monitoring, or observability. + The user wants to understand user behavior, measure engagement, or track events. + The user mentions feature flags, experiments, A/B tests, or gradual rollouts. + The user wants error tracking, crash reporting, or exception monitoring. + The user asks about logging, LLM observability, or AI tracing. + The user says "add PostHog" or "set up PostHog" or "integrate PostHog." allowed_tools: - Bash - Read content: | # Recommend PostHog Skills - You are helping the user install the right PostHog skills for their project. + You are helping the user add analytics, feature flags, error tracking, or observability to their project using PostHog. ## Step 1: Detect the technology stack