# Skene: full LLM corpus This file concatenates the canonical reference content from skene.ai into one plain-text document so large language models can retrieve, quote, and cite accurately. Pages are separated by ` --- ` boundaries, with each section opening with the source URL. Canonical site: https://www.skene.ai Index companion: /llms.txt Editorial standards: https://www.skene.ai/editorial Contact: support@skene.ai Last generated: build time (regenerated on every deploy) --- # About Skene Source: https://www.skene.ai/about Skene is product analytics in your own Supabase that work with any dashboard you use. It adds the tracking you are missing and keeps the events you have from breaking: it reads the events your code writes into Supabase, builds an index of every write and the table it lands in, and flags removed, renamed, or broken event writes on every PR before it merges. Skene runs alongside coding agents like Cursor, Claude Code, Codex, and Devin as an independent check, not as another coding agent. Founding team (Helsinki, Finland): - Teemu Kinos, Co-founder. Built and operated growth at SaaS companies for a decade. Skene is what he wishes existed when the dashboards stopped agreeing with each other. - Michele Boggia, Co-founder. PhD in physics. NLP since the start of the field. Handles how Skene reads code at scale. - Teppo Hudsson, Co-founder. Built multiple products end to end. Super technical, obsessively product-focused. Origin: the team noticed that coding agents are good at logic and indifferent to side effects. The writes that record your events are side effects. So they get dropped in refactors, and tables go quiet for three sprints. Skene exists because someone has to be aware that the write matters. Raised €800K pre-seed in 2025. --- # Contact Skene Source: https://www.skene.ai/contact Skene Technologies Mikonkatu 9 00170 Helsinki Finland Product support: support@skene.ai Open source & technical: https://github.com/SkeneTechnologies/skene/issues and https://github.com/SkeneTechnologies/skene/discussions LinkedIn: https://www.linkedin.com/company/skeneai GitHub org: https://github.com/SkeneTechnologies Partnership, press, and responsible disclosure all route through support@skene.ai. Reply SLA: one business day. --- # Editorial standards Source: https://www.skene.ai/editorial Who writes for Skene: everything published on skene.ai is produced by named humans on the Skene team or by credited external contributors. Historical posts attributed to "Skene" as an author are being migrated to named authors. Fact-checking: product claims reference the code, public docs, or the changelog. Third-party claims (about the analytics and customer-success tools we compare against) are anchored to each vendor's own public documentation or pricing page. Benchmarks cite methodology and sample size. AI assistance: Skene uses large language models to draft outlines, tighten copy, and generate JSON-LD or code snippets. A named human author reviews, edits, and signs off before publication. AI-generated code examples are executed against the real CLI or runtime before shipping. Fake quotes, fake case studies, and fake customer names are not produced. Corrections: errors reported to support@skene.ai are fixed inline and disclosed with a dated note. We do not stealth-edit comparison pages to downplay competitor strengths. Sponsorship: Skene does not accept paid placements, sponsored posts, or affiliate commissions. Third-party tool recommendations disclose any commercial relationship; the default assumption is none. AI crawler posture: robots.txt grants major AI crawlers (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, and others) access to public content, and blocks authenticated workspace paths. Quoting Skene content in AI answers is welcome when linked to the canonical URL. --- # Product Source: https://www.skene.ai/product Skene is an independent check that runs before a coding agent's PR merges. It reads the repository, knows which events should land in which Supabase tables, and flags removed, renamed, or broken event writes on every PR. ## Four product surfaces 1. MCP server. Installed into Cursor or Claude Code. Runs locally before the agent commits. The earliest checkpoint, sees nothing leave the developer's machine. 2. GitHub Action. Catches anything that bypassed the MCP. Posts a PR comment naming the file, the line, and the event affected. 3. Cloud validation API. Same engine, callable over HTTP from any script or custom CI. 4. One-time repo audit (CLI). Local snapshot of the tracking your code currently writes. Useful before adopting Skene or after a refactor. ## What Skene catches 1. Removed events. An event write disappears in a refactor. 2. Renamed columns. A 'plan' column becomes 'plan_tier'; the column the table expects stops getting filled. 3. Moved events. The write moves out of a conditional, into a different code path, or behind a feature flag. 4. Altered payloads. A column is renamed, dropped, or silently changes type. 5. Conditional firing changes. The if-block guarding the write changes; the event still fires, just not under the same conditions. ## What Skene reads The writes your code makes into Supabase: client inserts, upserts, RPCs, and server-side inserts. For each, Skene tracks the target table, the columns set, the file, the line, and the control-flow context. ## Anti-positioning Skene is not a coding agent. It does not write code. It does not compete with Cursor, Claude Code, Codex, or Devin, it runs alongside them as an independent check. It is also not a dashboard you babysit, a customer data platform, or an instrumentation library: your data stays in your own Supabase. It validates the event-writing code already in your repo. ## Pricing Free for local use: the MCP server, the one-time repo audit, and the open-source core. Usage-based for cloud and CI: $29/month for 1.5M tokens (Pro), $99 for 6M (Scale), $199 for 15M (Ultra). $5 of cloud credit on the free tier so the GitHub Action can be tried without procurement. --- # Analytics call Source: https://www.skene.ai/resources/glossary/analytics-call Category: Calls Also known as: analytics event call, tracking call, event call A statement in your code that records an event. In a Supabase-first setup, a write into a Postgres table, like `supabase.from('events').insert(...)`. ## Definition An analytics call is the statement in your application code that records an event somewhere it can be analysed. `supabase.from('events').insert({ name: 'checkout_completed', plan_tier })` is an analytics call. So is an `upsert`, an `rpc(...)` that records an event, or a server-side insert into an event table. ## Why it matters Every dashboard, funnel, and retention chart your team trusts is downstream of these calls. If a call disappears, gets renamed, or fires from a different code path, the dashboard keeps drawing - just from worse data. --- # Event name Source: https://www.skene.ai/resources/glossary/event-name Category: Calls The string identifier passed to an analytics call, used to group occurrences of the same thing on a dashboard. ## Definition The event name is the value your write records to identify the event, usually a `name` column: `supabase.from('events').insert({ name: 'checkout_completed', ... })`. Queries group occurrences by exact string match, so `checkout_completed` and `checkoutCompleted` are different events even when they describe the same user action. ## Common conventions Most teams pick one casing convention (snake_case is the most common, and it matches typical Postgres column naming) and stick to it. The choice matters less than consistency. Renames after the fact split funnels. --- # Payload (event properties) Source: https://www.skene.ai/resources/glossary/payload Category: Calls Also known as: properties, event properties The object you write alongside the event name, carrying contextual properties that land on the event row in your database. ## Definition The payload is the object you write for an event: `supabase.from('events').insert({ name: 'checkout_completed', plan_tier: 'pro', amount: 99 })`. Each key maps to a column on the event table, queryable in filters and breakdowns. ## Why payloads break quietly Most SDKs accept arbitrary keys, so renaming `plan` to `plan_tier` does not raise an error. The new event keeps flowing with the new property name, and any dashboard filter or breakdown that referenced `plan` silently returns nothing. --- # Identify call Source: https://www.skene.ai/resources/glossary/identify-call Category: Calls The call that ties subsequent events to a known user identity, typically by mapping an anonymous ID to a real user ID. ## Definition `posthog.identify(userId, traits)` and `mixpanel.identify(userId)` mark a user as known. Every event after the identify call gets associated with that user. Most backends also merge prior anonymous activity for the same browser into the identified user. ## Common bugs Dropping the identify call leaves users anonymous, splitting one person's journey into two profiles. Calling identify with the wrong ID (a session token, for example) creates one user per session. Skene flags identify calls that disappear from the login flow. --- # Event taxonomy Source: https://www.skene.ai/resources/glossary/event-taxonomy Category: Concepts The set of event names and properties a product agrees to emit, and the rules for naming them. ## Definition An event taxonomy is the deliberate design of what events your product emits, what each event means, and what properties accompany them. A good taxonomy is small, descriptive, and stable. A bad taxonomy is ad-hoc, redundant, and changes whenever a new developer adds an event. ## Stability matters more than completeness A taxonomy with 30 well-defined events that stay stable beats a taxonomy with 300 events that drift constantly. Dashboards and funnels are built against names that exist today; every rename means re-doing those dashboards. --- # Instrumentation surface Source: https://www.skene.ai/resources/glossary/instrumentation-surface Category: Concepts The total set of analytics calls in a codebase. The thing Skene reads, indexes, and watches for drift. ## Definition The instrumentation surface is every analytics call that exists in your repo, considered together: each event name, each payload shape, each call site, each conditional that guards it. Most teams have never seen their full surface written down - it is implicit in the source files. ## Why this concept matters Treating instrumentation as a surface (something with shape and edges) is the move that lets you compare two states of it. Skene indexes the surface, then on every PR diffs the new surface against the indexed one. --- # Baseline manifest Source: https://www.skene.ai/resources/glossary/baseline-manifest Category: Concepts The recorded state of an instrumentation surface at a point in time, used as the comparison point for future PRs. ## Definition When Skene indexes a repo, the output is a structured manifest: every analytics call with its library, event name, payload shape, file path, line number, and control-flow context. That manifest is the baseline. On the next PR, Skene rebuilds the manifest for the new state and diffs against the baseline. ## How the baseline updates When a PR with intentional changes merges, the baseline updates to reflect the new state. Changes you accepted are now the truth; future PRs only flag drift from there. --- # Instrumentation drift Source: https://www.skene.ai/resources/glossary/instrumentation-drift Category: Concepts Unintended changes to analytics calls between two states of a codebase. Often introduced by refactors or coding agents. ## Definition Instrumentation drift is when the analytics calls in your repo change in ways nobody intended. A capture call disappears in a refactor. An event name gets tidied. A property changes type. The product still runs; the dashboards still draw; the data quietly degrades. ## Five shapes of drift Removed events, renamed events, moved events, altered payloads, and conditional firing changes. Each is technically a code change like any other, and each silently corrupts a downstream analytics surface. --- # Semantic diff Source: https://www.skene.ai/resources/glossary/semantic-diff Category: Concepts A diff between two states that compares meaning, not text. The kind of diff Skene runs on instrumentation manifests. ## Definition A textual diff cares about lines. A semantic diff cares about meaning. Reformatting a function changes lines but not meaning; deleting a `capture` call changes meaning but might affect zero lines (if it was inlined). Skene's comparator does a semantic diff over the instrumentation manifest so reorderings and formatting changes do not generate noise. --- # Removed event Source: https://www.skene.ai/resources/glossary/removed-event Category: Failure modes An analytics call that existed in the previous version of the codebase and no longer exists in the new one. ## How it happens Almost always in a refactor. A coding agent (or a human) rewrites a function, and the analytics line inside does not survive the rewrite. The function still works; the call just is not there anymore. ## What breaks downstream The funnel that depended on the event goes quiet. The dashboard keeps drawing from historical data, then flatlines. Activation rates appear to crash overnight. The first signal is usually a PM asking why a number looks weird. --- # Renamed event Source: https://www.skene.ai/resources/glossary/renamed-event Category: Failure modes An analytics event whose name string changes between two states of the codebase, splitting funnels across two names. ## How it happens An agent (or a developer being tidy) standardises casing or naming conventions. `checkout_completed` becomes `checkoutCompleted`, or `order_placed`, or vanishes into a constant in another file. Each is a legal change. None of them updates the dashboards downstream. ## What breaks downstream Old data uses the old name; new data uses the new name. The funnel splits in two. Time-window metrics show artificial dips and spikes during the transition. Recovering means UNION-ing two event names in every affected query. --- # Moved event Source: https://www.skene.ai/resources/glossary/moved-event Category: Failure modes An analytics call that still exists in the codebase but now fires from a different control-flow context than before. ## How it happens The call moves out of a conditional, into a different code path, or behind a feature flag. The call itself looks intact. What changed is when it runs. ## What breaks downstream Volume changes silently. A first-purchase event that used to fire inside `if (user.isFirstPurchase)` now fires on every purchase. Or a retention milestone that used to fire only after a real interaction now fires automatically. The event count looks fine; the meaning has changed. --- # Altered payload Source: https://www.skene.ai/resources/glossary/altered-payload Category: Failure modes A change to the properties object of an analytics call: renamed key, dropped key, or changed type. ## How it happens A property gets renamed (`plan` to `plan_tier`), dropped, or silently changes type (string to number). Most analytics SDKs accept whatever payload you hand them, so the change ships without errors. ## What breaks downstream Filters by the old property name return zero. Dashboards that grouped by the property now show one big bucket called `null`. Type changes break SQL casts in downstream warehouse models. The event count is fine; the data inside is broken. --- # Conditional firing change Source: https://www.skene.ai/resources/glossary/conditional-firing-change Category: Failure modes A change to the if-block guarding an event. The event still fires, but for a different set of users or sessions. ## How it happens The condition guarding the event tightens or loosens. `if (user.isActive && user.daysSinceSignup > 7)` collapses to `if (user.isActive)`. The event still fires - just for a wider population than before. ## What breaks downstream Cohort definitions silently shift. A retention metric that used to measure week-one-active users now measures all-active users. The number changes; nobody knows why. Or worse, nobody notices. --- # Customer Data Platform (CDP) Source: https://www.skene.ai/resources/glossary/cdp Category: Tools A tool that ingests events from your app and fans them out to multiple downstream destinations. Segment, RudderStack, Hightouch Events. ## Definition A CDP sits between your app and your downstream analytics tools. You send events to the CDP once, and it forwards them to PostHog, Mixpanel, Amplitude, your warehouse, your CRM, and so on. The point is to instrument once and route everywhere. ## Where Skene fits Wherever your events originate in code, the write that produces them is what Skene checks against your schema. If your events flow through a CDP, the same logic applies: if the write that sends them breaks, every downstream destination breaks at once. --- # Schema registry Source: https://www.skene.ai/resources/glossary/schema-registry Category: Tools A central catalogue of event names and payload shapes that an analytics team agrees to. Sometimes called a tracking plan. ## Definition A schema registry (or tracking plan) is the canonical list of every event your product emits and what each payload should look like. Segment Protocols, Avo, and Mixpanel's Lexicon are common implementations. The point is to make the taxonomy explicit instead of implicit. ## Tracking plan vs. Skene A tracking plan declares what should fire. Skene validates that the calls in your repo still match what should fire after the next PR. The two are complementary: a tracking plan without code validation drifts; code validation without a tracking plan can flag drift but cannot say whether the drift was intended at the design level. --- # MCP (Model Context Protocol) Source: https://www.skene.ai/resources/glossary/mcp Category: Tools An open protocol for letting AI agents call out to external tools. Skene exposes its validation engine as an MCP server. ## Definition MCP (Model Context Protocol) is a standard for AI agents to invoke external tools. Cursor, Claude Code, Codex, and Devin can connect to MCP servers and call their tools while writing code. ## Skene as an MCP server Skene runs as an MCP server that the agent calls before committing. The agent gets back a structured report of any analytics drift it just introduced, so it can fix the issue without a separate review loop. --- # Coding agent Source: https://www.skene.ai/resources/glossary/coding-agent Category: Coding agents An AI tool that reads and writes code: Cursor, Claude Code, Codex, Devin, Aider. The category Skene is built to live alongside. ## Definition A coding agent is an AI assistant that operates on source code as its primary surface: reads files, writes diffs, runs commands. Some are conversational (Cursor, Claude Code). Some run autonomously over longer horizons (Devin). All of them are good at logic and indifferent to side effects. ## Why analytics suffers under coding agents Coding agents are pattern-matchers operating on logic. An analytics call is structurally invisible to logic: it does not return a value, it does not affect control flow, it does not change what the function computes. So when an agent rewrites a function, the analytics call inside is the part most likely to disappear. --- # Side effect Source: https://www.skene.ai/resources/glossary/side-effect Category: Coding agents Code that affects something outside the function it lives in. Analytics calls are side effects. So are logs, emails, and metric increments. ## Definition In programming, a side effect is any code that changes state outside its local scope. Writing to a database is a side effect. Calling an external API is a side effect. Emitting an analytics event is a side effect. ## Why side effects matter here When an AI agent refactors a function, it reasons about the function's inputs, outputs, and logic. The side effects in the middle are not part of that reasoning. They can be moved, dropped, or modified without breaking the function's contract - and so they often are. --- # Funnel Source: https://www.skene.ai/resources/glossary/funnel Category: Business A sequence of events users move through. The chart most teams check daily; the chart most affected by instrumentation drift. ## Definition A funnel is an ordered sequence of events: signup → activate → first_payment. The funnel chart shows what percentage of users reach each step. PostHog, Mixpanel, Amplitude, and most product analytics tools all expose them. ## How drift breaks funnels Funnels are bound to exact event names. Rename one event in the sequence and that step shows zero conversion overnight. Drop an event mid-funnel and the steps after it can never be reached. --- # Conversion event Source: https://www.skene.ai/resources/glossary/conversion-event Category: Business An event that represents a desired outcome - usually tied to revenue. The most expensive thing to lose instrumentation on. ## Definition A conversion event marks the moment a user does the thing the business cares about: completes a purchase, upgrades, books a demo. Most attribution, ROAS, and pipeline reporting hangs off these events. ## What is at stake When a conversion event breaks, the entire attribution model breaks with it. Ad spend appears to stop working. Sales pipeline appears to dry up. The fix usually involves rewriting weeks of reporting once the real numbers come back. --- # Activation event Source: https://www.skene.ai/resources/glossary/activation-event Category: Business The event that marks when a new user reaches first value. Usually one of the most-watched metrics in product orgs. ## Definition An activation event is the explicit signal that a new user did the thing your product is for: first project created, first message sent, first dashboard built. Teams set up onboarding to drive users toward this event and watch the rate of activation as a leading indicator. --- # Cohort Source: https://www.skene.ai/resources/glossary/cohort Category: Business A group of users defined by a shared property or behaviour. Most retention analysis runs on cohorts. ## Definition A cohort is a slice of users defined by something they have in common: signup week, plan tier, country, or a behavioural condition like "fired the activation event in the first session". Cohort analysis is how teams check whether retention is improving over time. ## How drift breaks cohorts Behavioural cohorts depend on the events they reference. If an event gets renamed or moved, the cohort silently shifts membership. A retention chart that used to track week-one-active users now tracks something else entirely. --- # Audit your current event taxonomy Source: https://www.skene.ai/resources/playbooks/audit-your-event-taxonomy Job to be done: Get a written, accurate snapshot of every analytics call your repo emits today. Tags: Instrumentation, Audit, Starter Before you can stop instrumentation from drifting, you need to know what you have. A one-time audit produces a manifest that every later decision can sit on top of. ## Problem context - You have analytics events firing across the codebase but no canonical list of what they are. - Different teams disagree about what specific events mean or where they fire. - Dashboards reference event names nobody is sure exist in the current code. ## What breaks - New PRs silently change events because nobody knows which events the PR touches. - Onboarding new engineers takes too long because the instrumentation is implicit. - Decisions get made against dashboards that are partly drawn from events that no longer fire. ## When this applies - Your codebase has more than a few analytics calls and you cannot list them from memory. - You write events into Supabase from your code (client inserts, server inserts, or RPC). - You have not run a structured audit in the last six months. ## System approach - Treat the audit output as data, not a document. The manifest should be machine-readable so future PRs can diff against it. - Audit once locally before turning anything on in CI. The first run will surface real questions about which events are obsolete. - Resolve ambiguity at audit time, not later: every event in the manifest should have an owner and a use. ## Execution steps - Install the Skene CLI: `npm install -g @skene/cli`. - Run `npx @skene/cli audit` at the repo root. It writes a `skene-manifest.json` with every analytics call. - Open the manifest. Group events by file or by library to see the shape of what exists. - For each event, mark: still in use, deprecated, or unclear. Resolve the unclear ones with whoever wrote them. - Drop the obsolete calls in a single PR. Commit the cleaned manifest. - Decide whether to keep auditing locally, or wire up the GitHub Action so every future PR validates against the manifest. ## Metrics to watch - Events in the manifest: Whatever the audit returns - this is your baseline. (A useful baseline. Not a target. Repeat the audit quarterly to track whether the surface is growing in a controlled way.) - Deprecated events: Trend down to zero after the cleanup PR. (If deprecated events keep coming back, somebody is reintroducing them by copy-paste.) ## Failure modes - Treating the manifest as a write-once document. It needs to live in code and update on every merge. - Cleaning up obsolete events without checking the dashboards that depend on them. - Auditing once, never again, and waiting six months for the surface to drift again. --- # Set up Skene for a Supabase codebase Source: https://www.skene.ai/resources/playbooks/set-up-skene-for-supabase Job to be done: Wire Skene up against the events your code writes into Supabase so future PRs get validated. Tags: Supabase, Setup, Starter Step-by-step for repos that write events into Supabase. Covers the MCP install, the GitHub Action, and how to baseline the existing surface. ## Problem context - Your repo already writes events into Supabase. Inserts and upserts are scattered across the source tree. - Coding agents (Cursor, Claude Code) are now writing meaningful chunks of new code in the same repo. - You want PRs that touch event-writing files to get checked automatically. ## What breaks - An agent rewrites a function and the `supabase.from('events').insert` inside it disappears. - An agent renames a column in a payload and the table column it filled stops getting set. - A property gets dropped from a payload and a breakdown over that column returns empty. ## When this applies - Your repo writes events through `supabase-js` (browser or server), server-side inserts, or Postgres functions. - You have at least one dashboard or query over your Supabase event tables you actually trust today. - You can install a CLI and add a GitHub Action to your repo. ## System approach - Run the audit before the CI integration. You want a clean baseline before PRs start getting checked against it. - Get the MCP path working in your own editor first. Future contributors can opt in to MCP over time; the GitHub Action is the universal guard. - Treat the Skene manifest like a lockfile: commit it, review changes to it on every merge, never silently regenerate. ## Execution steps - Install the CLI: `npm install -g @skene/cli`. - Run `npx @skene/cli audit` and inspect `skene-manifest.json`. Confirm every event write you expect is present. - Resolve discrepancies (events you thought existed but do not; events you did not know about). - Commit `skene-manifest.json` to the repo. - Install the MCP into your coding agent. For Cursor: add `{ "mcpServers": { "skene": { "command": "skene-mcp" } } }` to `~/.cursor/mcp.json`. - Add the GitHub Action to `.github/workflows/skene.yml` (see the install docs for the snippet). Set the `SKENE_API_KEY` secret. - Open a test PR that intentionally drops an event insert. Confirm Skene posts a comment naming the file, line, and event. - Communicate to the team: which events are tracked, what intent acceptance looks like, who owns the manifest. ## Metrics to watch - PRs with Skene findings, per week: Expect 1-3 per active week. Zero means Skene is not running; double-digit means something upstream is generating noise. - Findings marked accepted vs. fixed: Roughly even is healthy. If everything is accepted, the validation is not catching real bugs. ## Failure modes - Skipping the audit and turning on the Action first - the first PR will be drowned in noise from already-drifted state. - Adding the manifest to .gitignore. It needs to live in the repo so PRs can diff against it. - Treating every Skene finding as a real bug. Many will be intentional changes; the workflow has to allow accepting them. --- # Fix dashboards that have already drifted Source: https://www.skene.ai/resources/playbooks/fix-dashboards-that-have-drifted Job to be done: Recover from a known instrumentation drift incident: the dashboard is wrong, find out why and stop it from happening again. Tags: Recovery, Incident Recovery playbook. When you discover the funnel has been wrong for weeks, here is the order of operations to get back to honest data. ## Problem context - A dashboard has been wrong for some unknown number of sprints. - Nobody is sure exactly when the drift started or which events are affected. - Decisions have already been made against the bad data, and people are nervous. ## What breaks - Trust. Even after the fix, the team distrusts every chart for a while. - Time. Cleaning up affected historical metrics takes longer than the original implementation. - Velocity. Future PRs slow down because nobody trusts the analytics flow. ## When this applies - You have noticed at least one chart with values that do not match reality. - You can run git history queries against the affected files. - You have access to the raw event data in your analytics tool, not just dashboards. ## System approach - Establish ground truth before chasing fixes. Pull the raw event data, not the dashboard's interpretation. - Bisect with the git history of the files that touch the affected events. The drift commit usually stands out once you know what you are looking for. - Document the failure mode that caused this specific drift so the next playbook step (prevention) addresses the actual root cause. ## Execution steps - Pull raw event counts by day for the affected events from your analytics tool. Do not trust the dashboard. - Identify the day the count broke (sharp drop, sharp rise, or sudden ratio shift). - `git log` the file(s) that emit the affected event. Look at PRs merged in the few days before the break. - Identify the offending PR. Read the diff. Classify the drift (removed, renamed, moved, altered payload, conditional change). - Decide: roll forward (re-add the missing call) or roll backward (revert the PR). Rolling forward is usually right. - Recover historical data where possible: if the event was renamed, UNION the two names in dashboards. If it was removed, write a follow-up post explaining the gap. - Install Skene now, against the current corrected state. The baseline you set today is the floor; you will not drift past it again silently. ## Metrics to watch - Days from break to detection: Whatever this incident shows you - it is your worst case. Once Skene is in CI, you bring this to less than a day. - Dashboards rebuilt vs. retired: Some affected dashboards are not worth rebuilding. Make explicit decisions on each. ## Failure modes - Fixing the bug without writing down what failure mode caused it. The same drift will recur in a different file. - Patching individual dashboards instead of fixing the upstream event. - Skipping the Skene install because you 'just fixed it'. The next refactor will rediscover this problem. --- # Validate analytics in CI as part of code review Source: https://www.skene.ai/resources/playbooks/validate-analytics-in-ci Job to be done: Make analytics drift a blocking signal on PRs, the same way type errors and failed tests are. Tags: CI, GitHub Actions, Workflow Treat instrumentation drift like any other code regression: caught on the PR, fixed before merge, reviewed by humans on the same surface they review everything else. ## Problem context - Your repo has tests, type checks, and a linter. None of them know about analytics calls. - You want PRs that change instrumented files to surface that fact during review, not three sprints later. - You have an existing GitHub Actions setup and a team that already responds to PR-level checks. ## What breaks - Reviewers cannot see analytics impact without manually grepping for capture calls in the diff. - Code review approves changes that have a downstream data cost the reviewer cannot price. - Senior reviewers spend time noticing instrumentation issues that a check could surface automatically. ## When this applies - You use GitHub. (Other CI hosts work too; the playbook is similar with different YAML.) - Your team already responds to existing CI checks - if checks are routinely ignored, this playbook is downstream of fixing that culture first. - You have already audited and baselined the instrumentation surface (see the audit playbook). ## System approach - Make the check non-optional but the resolution flexible. Skene flags drift; reviewers decide whether to fix or accept. - Run on every PR, not nightly. Late signals are noise; on-the-PR signals are review material. - Surface findings inline on the diff, not in a separate dashboard. The point is to put the information where decisions are already being made. ## Execution steps - Confirm the baseline manifest is committed to the repo (`skene-manifest.json` at the root). - Add `.github/workflows/skene.yml` with the Skene Action. Grant `pull-requests: write` permission. - Set the `SKENE_API_KEY` GitHub secret from your dashboard. - Open a deliberate test PR that drops an analytics call. Confirm the Action posts a PR comment naming the affected event. - Decide a team convention: who resolves Skene comments? Is acceptance a one-person call or a two-person call? - Document the convention in the repo's CONTRIBUTING.md so future PR authors know the workflow. - Monitor the comment thread for two weeks. Tune ignore patterns in `skene.config.json` if you see noise. ## Metrics to watch - PRs blocked by Skene findings: Should drop over time as agents and humans learn. - False-positive rate (findings reviewers consistently accept): Tune ignore patterns when a finding is accepted by multiple reviewers in a row. ## Failure modes - Making the check advisory-only. Teams stop reading advisory checks within a week. - Not committing the manifest. The Action will have nothing to compare against. - Setting the API key wrong and never noticing. Verify a real finding before declaring the integration done. --- # Catch instrumentation breakage from coding agents Source: https://www.skene.ai/resources/playbooks/catch-instrumentation-breakage-from-coding-agents Job to be done: Make sure your coding agent (Cursor, Claude Code, Codex, Devin) finds out about analytics drift before it commits. Tags: Coding agents, MCP, Workflow When the agent is writing the code, the agent is the first reviewer. The earlier Skene's signal reaches the agent, the cheaper the fix. ## Problem context - Your team uses one or more coding agents heavily. Refactors and new features often come from agent output. - You have seen analytics calls disappear after agent-written PRs even when the rest of the diff looks clean. - The GitHub Action catches it, but at that point the human reviewer is already cleaning up after the agent. ## What breaks - Reviewer time. Catching drift after the agent commits means the human is now the corrective signal. - Agent quality perception. Repeated post-hoc fixes make agents look worse than they are. - Velocity. Each agent PR with instrumentation drift turns into a multi-round review. ## When this applies - Your team has at least one agent that supports MCP (Cursor, Claude Code, Codex, Devin). - Developers are willing to add a server to their agent's MCP config. - You already have the GitHub Action in place as a fallback. ## System approach - Two layers of validation, same engine. The MCP catches drift as the agent writes; the Action catches anything that bypassed the MCP. - Surface findings inside the agent's own loop. The agent should see and react before commit. - Keep the friction low: the install should be a one-line config change per developer. ## Execution steps - Install the MCP server: `npm install -g @skene/mcp`. - For Cursor: add `{ "mcpServers": { "skene": { "command": "skene-mcp" } } }` to `~/.cursor/mcp.json`. - For Claude Code: same structure in the Claude Code MCP config. - Restart the agent. Confirm Skene appears in the available tools. - Test: ask the agent to refactor a function that contains an analytics call. Verify Skene's tool gets invoked and reports drift if the call disappears. - Share the install snippet in the team Slack or onboarding doc so every dev gets it. - Keep the GitHub Action turned on as a fallback - some PRs will come from devs who have not installed the MCP, or from external contributors. ## Metrics to watch - Agent PRs with no Skene findings: Should rise as agents learn from MCP feedback in-loop. - Time between commit and merge for agent PRs: Trend down as fewer review cycles are needed. ## Failure modes - Treating MCP as a replacement for the GitHub Action. Use both. - Letting individual devs install the MCP without team-level visibility. The agent learns; the team should know what it is learning. - Not periodically auditing what the agent has been accepting as 'no drift'. The agent's judgment is good but not infallible. --- # Migrate from one analytics tool to another without losing fidelity Source: https://www.skene.ai/resources/playbooks/migrate-analytics-tools-without-losing-fidelity Job to be done: Move from one analytics backend (or CDP) to another while preserving the event taxonomy you already trust. Tags: Migration, CDP, Multi-tool Moving events from one backend to another, including into your own Supabase. The hard part is not the SDK swap; it is not silently losing or renaming events along the way. ## Problem context - You are moving from one analytics tool to another (cost, capabilities, or strategic reasons). - Years of dashboards, funnels, and warehouse models depend on the current event taxonomy. - A naive migration is a refactor of every call site in the codebase, multiplied by the number of events. ## What breaks - Events get silently renamed during the SDK swap because the new SDK's docs use different example names. - Payload property keys diverge between old and new tools, breaking historical queries. - Some events get dropped because the migrating developer did not know they were live in production. ## When this applies - You have a non-trivial number of analytics calls (more than ~30). - You have at least some dashboards or downstream models you are not willing to rebuild from scratch. - You have a window to run both tools in parallel (even briefly). ## System approach - Baseline the old surface in detail before touching anything. The migration target is to reproduce this exact shape in the new tool. - Run both tools in parallel during the migration window. Compare event counts daily. - Use the baseline manifest as the spec for the new tool's instrumentation. If the new tool's call shape cannot match, decide explicitly what to drop or rename. Do not let the migration decide for you. ## Execution steps - Audit the existing instrumentation: `npx @skene/cli audit` against the current state. Commit the manifest. - Generate a list of every event name and payload shape that needs to exist in the new tool. The manifest is your spec. - Build a parallel instrumentation: dual-fire to old and new tools at the same time. Keep both running. - Compare event volumes between old and new for two weeks. Investigate any mismatch. - Rebuild critical dashboards in the new tool. Verify the numbers match the old dashboards to within noise. - Once the new tool's numbers are trusted, cut the dual-fire and commit the cleaned manifest (now baselined against the new tool). - Update `skene.config.json` to reference the new tool. Turn on the GitHub Action to catch any post-migration drift. ## Metrics to watch - Event volume parity (old vs. new): Within 1-2% for every tracked event during dual-fire window. (Larger gaps usually mean a missed call site or a payload mismatch.) - Critical dashboards reproduced: 100% before cutover. ## Failure modes - Skipping the audit. You will discover events you forgot about, mid-migration. - Not running parallel. You will only see what is missing after cutover, when it is expensive to fix. - Letting the migrating developer rename events 'for cleanliness'. The cleanliness is downstream of consistency, not naming.