Posthog Product Health Audit
boardsesh/boardsesh
Mine Boardsesh's PostHog telemetry (error tracking, session recordings, product analytics) with a multi-agent workflow, then file verified, deduplicated, severity-labelled GitHub issues.
Get PostHog data into a canvas correctly: the host-injected ph SDK (loadInsight, query, capture, state, connectors, openExternal, navigate), the data hierarchy (saved insights first, typed query…
$ npx skills add PostHog/posthog-foss --skill querying-canvas-data -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install PostHog/posthog-foss querying-canvas-data --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/PostHog/posthog-foss.git skills-src && mkdir -p .claude/skills && cp -r skills-src/products/canvas/skills/querying-canvas-data .claude/skills/querying-canvas-data && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "querying-canvas-data" agent skill from https://github.com/PostHog/posthog-foss/tree/master/products/canvas/skills/querying-canvas-data into .claude/skills/querying-canvas-data/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "querying-canvas-data", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/PostHog/posthog-foss/tree/master/products/canvas/skills/querying-canvas-dataType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add PostHog/posthog-foss --skill querying-canvas-data -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install PostHog/posthog-foss querying-canvas-data --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/PostHog/posthog-foss.git skills-src && mkdir -p .agents/skills && cp -r skills-src/products/canvas/skills/querying-canvas-data .agents/skills/querying-canvas-data && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "querying-canvas-data" agent skill from https://github.com/PostHog/posthog-foss/tree/master/products/canvas/skills/querying-canvas-data into .agents/skills/querying-canvas-data/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "querying-canvas-data", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add PostHog/posthog-foss --skill querying-canvas-data -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install PostHog/posthog-foss querying-canvas-data --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/PostHog/posthog-foss.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/products/canvas/skills/querying-canvas-data .cursor/skills/querying-canvas-data && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "querying-canvas-data" agent skill from https://github.com/PostHog/posthog-foss/tree/master/products/canvas/skills/querying-canvas-data into .cursor/skills/querying-canvas-data/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "querying-canvas-data", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/PostHog/posthog-foss.git --path products/canvas/skills/querying-canvas-data--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add PostHog/posthog-foss --skill querying-canvas-data -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install PostHog/posthog-foss querying-canvas-data --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/PostHog/posthog-foss.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/products/canvas/skills/querying-canvas-data .gemini/skills/querying-canvas-data && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "querying-canvas-data" agent skill from https://github.com/PostHog/posthog-foss/tree/master/products/canvas/skills/querying-canvas-data into .gemini/skills/querying-canvas-data/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "querying-canvas-data", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install PostHog/posthog-foss querying-canvas-dataInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add PostHog/posthog-foss --skill querying-canvas-data -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/PostHog/posthog-foss.git skills-src && mkdir -p .github/skills && cp -r skills-src/products/canvas/skills/querying-canvas-data .github/skills/querying-canvas-data && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "querying-canvas-data" agent skill from https://github.com/PostHog/posthog-foss/tree/master/products/canvas/skills/querying-canvas-data into .github/skills/querying-canvas-data/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "querying-canvas-data", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add PostHog/posthog-foss --skill querying-canvas-data -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install PostHog/posthog-foss querying-canvas-data --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/PostHog/posthog-foss.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/products/canvas/skills/querying-canvas-data .opencode/skills/querying-canvas-data && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "querying-canvas-data" agent skill from https://github.com/PostHog/posthog-foss/tree/master/products/canvas/skills/querying-canvas-data into .opencode/skills/querying-canvas-data/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "querying-canvas-data", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
querying-canvas-dataGet PostHog data into a canvas correctly: the host-injected ph SDK (loadInsight, query, capture, state, connectors, openExternal, navigate), the data hierarchy (saved insights first, typed query…
Querying Canvas Data is an agent skill from PostHog/posthog-foss, published by the product's own GitHub organization. Get PostHog data into a canvas correctly: the host-injected ph SDK (loadInsight, query, capture, state, connectors, openExternal, navigate), the data hierarchy (saved insights first, typed query nodes second, inline HogQL last), verifiability (insight-backed metrics link their saved insight in PostHog; ad-hoc queries expose the exact query that ran), per-insight-type result shapes, progressive per-query loading, date-range wiring, live third-party data through the viewer's own connections (ph.connectors), and…
Its SKILL.md is about 5k tokens, which your agent loads only when the skill is triggered. The skill folder holds 2 other files, including reference files (for example `references/canvas-sdk.d.ts`).
It sits in Agent Workflows. It works with PostHog, Model Context Protocol and GitHub. The repository describes itself as: PostHog FOSS is a read-only mirror of PostHog, with all proprietary code removed. NOTE: This repo is synced automatically from the main PostHog repo. Please raise any issues and… The licence is MIT.
3 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 2c48221. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships script files (TypeScript), which the agent can run.
From the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
github.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Querying Canvas Data loads about 5k tokens when it runs, and up to ~7.1k if it reads all its reference files. Until then it costs about 178 tokens; SKILL.md has 2,550 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from PostHog/posthog-foss at commit 2c48221, republished under its MIT licence (© PostHog). 2,550 words, ~5,000 tokens.
.claude/skills/querying-canvas-data/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.The ph bridge is the only way a canvas talks to PostHog. Import it with
import { ph } from "@posthog/canvas-sdk" — a platform-provided module, so it needs no
dependencies entry. The same object is also installed as the window.ph global, which existing
canvases use; prefer the import in new code. Its typed surface is
references/canvas-sdk.d.ts. Never initialize it: credentials stay in
the host, and fetch(), posthog-js, and hand-rolled clients cannot reach PostHog from the sandbox.
External requests and resources require a non-PostHog origin declared in
capabilities.network.origins, and work only in the published canvas — the edit-mode preview
blocks all direct network access. This includes external stylesheets; remote scripts remain
blocked.
short_id, and render it with
await ph.loadInsight(shortId, { dateRange }). These are proven queries — numbers match the
PostHog UI exactly (sessionization, unique users, breakdowns, bounce rate). Never fabricate a
query or guess event/property names; discover and save them via MCP first.ph.query({ kind: "TrendsQuery", series: [...], dateRange: {...} })
when saving an insight genuinely doesn't fit.ph.query("SELECT …"), only when no insight kind can express
the metric; you then own the SQL and its date window.For web-analytics boards specifically, use the web-analytics query kinds — raw HogQL subtly gets bounce rate, sessionization, channel attribution, and unique-visitor counts wrong.
Whatever tier you use, declare it in the project's capabilities before publishing: every
ph.loadInsight short id in capabilities.posthog.insights, every ph.capture event name in
captureEvents, and inlineQueries: true for any ph.query use. The host rejects undeclared
calls at runtime, and validation fails on undeclared literals.
A number a viewer cannot verify is a number they cannot trust. Every data-backed figure a canvas shows — a KPI, a chart, a table, a stated conclusion — must carry the verification affordance for its tier:
ph.openExternal(insightUrl) from a click. Mint the URL at authoring time with the
generate-app-url MCP tool (path template /insights/{id} with the insight's short id) and
bake the returned URL into the source verbatim — never hand-build one. ph.openExternal only
opens https://*.posthog.com URLs and only from a user gesture, so wire it to a button or
link, never to load or render. Do not also bake the insight's saved query text into the
source: canvas source is readable by every canvas viewer, while access to the insight itself
is enforced by PostHog — the link is where a viewer inspects the query, with their own
permissions applied.ph.query (a typed node or inline HogQL), show the query behind it — the HogQL text, or
the typed query node pretty-printed as JSON — in a modal or a collapsed disclosure attached to
the card (a Quill Dialog or Collapsible in a React canvas, a <details> element in an
HTML one). Render it from the same constant or builder you pass to ph.query, so the
displayed query can never drift from the executed one. This discloses nothing beyond what the
viewer already runs: ph.query executes as the signed-in viewer.These are not optional polish: a canvas that presents PostHog data without them is incomplete. Keep the affordances compact — a small link icon per insight-backed card, a "View query" disclosure per ad-hoc card, or one shared modal listing every ad-hoc query the canvas runs, each labeled with the figure it backs.
For a status board, set refresh to the cache lifetime in seconds. Use a whole number from 30 to
86400 (one day); values outside that range, or fractional ones, fail at runtime:
await ph.loadInsight(shortId, { refresh: 30 })
await ph.query(queryNode, {}, { refresh: 30 })ph.loadInsight or a typed node): results
is an array of series objects, not rows. Each series has data: number[] (per interval),
days: string[] (ISO), labels: string[], count (sum), aggregated_value (single-value
total), label, and optional compare_label: "current" | "previous". A KPI total is
results[0].count (or .aggregated_value); a line chart plots results[0].data over
results[0].days. count sums the per-interval values, which double-counts a unique-users
series (math: "dau") for anyone active on several days — for a period-unique KPI, set
trendsFilter: { display: "BoldNumber" } on the query and read aggregated_value instead.
With a compare period, find the prior series by compare_label === "previous"
— never by index. columns is empty here.{ columns: string[], results: rows[][] } — each row an array of cell values in
columns order.PostHog queries can take several seconds each, and a board usually runs several. Never gate rendering on all of them:
awaits. The host runs 8 data requests at a time and makes the rest wait in a 32-deep queue,
so a board with more sections than slots still loads, section by section. A board wide enough to
outlast the queue gets its extra requests refused, with the reason in the error message, and the
runtime sends each one again after a backoff before it gives up; a board that wide consolidates
its queries (one query returning every row, sliced client-side), still one state per section.{ loading, error, data } state and let each card, chart, or table
swap its skeleton for data the moment its own result arrives. One shared loading flag or a
single Promise.all across independent queries makes the fastest metric wait for the slowest —
the canvas must fill in progressively, not appear all at once.Load data in useEffect with useState, and aggregate in the query; never
fetch raw event dumps. Treat a rejected query and an empty result as different states: .catch
must set an error state that renders visibly (message + retry), never fall through to zeros, an
empty chart, or a "no data" message — a swallowed error makes real breakage (a missing table, an
auth failure) look like missing data. Reserve the empty state for a query that succeeded with no
rows.
dateRange:
ph.loadInsight(shortId, { dateRange: { date_from: win.start.toISOString(), date_to: win.end.toISOString() } })
— the saved insight re-scopes to the window with no time SQL. Typed nodes take the same
dateRange. Re-run every query when the window changes.dateRange (its window lives inside the SQL) — a reason to
prefer insight query types. If its window comes from a {variables.…} placeholder, drive it
through variables (below) instead; dateRange will never reach it.now() or a hardcoded INTERVAL. Compute unix bounds
(Math.floor(win.start.getTime() / 1000)) and write half-open
timestamp >= toDateTime(fromUnix) AND timestamp < toDateTime(toUnix). Prior period = the
equal-length window immediately before; bucket with toStartOfDay/toStartOfHour.A saved SQL insight whose HogQL contains {variables.name} placeholders takes its values per call,
keyed by the variable's code name (not its uuid):
await ph.loadInsight(shortId, { variables: { product: 'surveys', month: '2026-07-01' } })This is how one saved insight fills a whole board — the same per-product insight loaded once per product — rather than every tile resolving the insight's saved default.
insight-get over MCP). The host rejects a
variable the insight doesn't use, and rejects one whose value didn't take effect, instead of
silently falling back to the saved value — so a variable mismatch surfaces as a visible error, not
as another product's numbers.For a task inbox, queue, or status board, query system.tasks and system.task_runs through
ph.query. Do not call posthog:tasks-list while authoring and embed its response: that produces a
snapshot, while the system tables keep the rendered canvas live.
The tables run as the signed-in viewer. They are project-scoped and require access to the Tasks
resource. system.tasks includes only non-internal tasks filed in live public spaces; it excludes
private, personal, unfiled, and internal tasks. Always exclude soft-deleted tasks explicitly.
Join a task to its latest run when the canvas needs current status:
const data = await ph.query(`
SELECT
t.id,
t.task_number,
t.title,
t.repository,
t.created_by_id,
t.created_at,
t.updated_at,
latest.status AS latest_run_status
FROM system.tasks AS t
LEFT JOIN (
SELECT
task_id,
argMax(status, tuple(created_at, id)) AS status
FROM system.task_runs
GROUP BY task_id
) AS latest ON latest.task_id = t.id
WHERE t.deleted = 0
ORDER BY t.updated_at DESC
LIMIT 100
`)This is inline HogQL, so declare capabilities.posthog.inlineQueries: true. Render links with
ph.navigate.toTask(id) rather than constructing task URLs.
Do not promise filters the tables cannot express. channel_id is not queryable, so a canvas cannot
currently restrict this query to its own space. Filtering to the current viewer also requires a
known numeric user id; the canvas runtime does not inject one. State these limits when the request
depends on “this space” or “my tasks” instead of silently showing project-wide public tasks.
Durable key-value storage per canvas. Declare every scope you use in capabilities.posthog.state
(["user"], ["shared"], or both) — undeclared scopes fail validation and the host refuses them
at runtime. Scope "user" (the default when no scope is passed) is private to each viewer;
"shared" is one value per canvas, visible to the whole team.
const draft = await ph.state.get('draft') // user scope by default; null when unset
await ph.state.set('draft', { text }) // JSON value, capped at 64 KB serialized
await ph.state.set('draft', null) // null deletes the key
await ph.state.set('board', { columns }, { scope: 'shared' }) // team-visible
const entries = await ph.state.list({ scope: 'shared' }) // [{ scope, key, value, updatedAt }]When a user asks about a canvas's current progress or settings, do not infer them from source alone.
Call canvas-state-retrieve with the canvas id after reading its source. It returns shared state plus
the authenticated user's own user-scoped state for canvases in public channels or their personal
channel. Use canvas-state-set when the user asks to change those values; read first, preserve
unrelated keys, and use the scope the canvas source expects.
Canvas discussions use the generic comment tools. Read them with comments-list filtered to
scope=canvas and the canvas id as item_id. Create a root comment or reply with
comments-create, using the same scope and item id. A thread belongs to the canvas, so a task id is
optional. Put one in item_context.taskId only when that task generated or published the canvas;
the API refuses any other task. The space of the canvas controls access: a user who can see the
space can read and write its comments.
ph.actions.invoke(verb, payload) writes into PostHog as the viewer. Declare every verb in
capabilities.posthog.actions; undeclared or unregistered verbs fail validation and the host
refuses them at runtime. Invocations must be wired to an explicit user gesture (a button the
viewer clicks) — the host rejects calls made on load or render.
Render the result or the thrown error visibly, and disable the button while the call is in flight — every invocation is a real PostHog write.
The registry is the source of truth for verbs. Before wiring one, list it with the
canvases-actions-retrieve tool: each entry carries verb, summary, destructive, and
usage — the payload and result shape, what invoking it actually does, and the confirmation
copy it warrants. Follow a verb's usage exactly, including what the success message may claim.
Do not infer a verb's payload from the matching product's own MCP tools or skills — an MCP tool
call (you, now, with your credentials) and a canvas verb (the viewer, later, in the published
canvas) differ in payload shape, auth, and behavior. Invoking looks like:
const { result } = await ph.actions.invoke('tasks.create', { title, description })ph.connectors.call(provider, tool, args, { refresh? }) reads data from a third-party service
with the viewer's own connection, at view time. Use it for anything that must stay fresh
per person: open pull requests, today's meetings, assigned issues. Never fetch such data
yourself while authoring and bake the result into the source — that snapshot is stale the moment
it is published, and it shows every viewer the author's data.
github (native, over the viewer's personal GitHub connection) or
mcp:<server host> for any server the viewer has connected in the MCP store (for example
mcp:mcp.calendly.com). Discover providers, tools, argument schemas, and per-tool usage
with the canvas-connectors-retrieve tool; pass mcp_hosts to inspect a server the current
user has not connected. Call only tools whose catalog entry has is_read_only: true.
MCP tools need an explicit read-only hint and a name that passes the local read-verb check.capabilities.connectors as
[{ "provider": "github", "tools": ["list_pull_requests"] }]. Validation rejects an
undeclared ph.connectors.call literal, and the host refuses undeclared calls at runtime.{ status, result, detail, truncated, connect_path }. Branch on status:ok — result holds the tool output. Native tools return their documented shape; MCP
tools return { content, structured_content, is_error } (MCP content blocks).not_connected / needs_reauth — this viewer has no usable connection. Render a
"Connect GitHub" (or the server's name) button that calls ph.connectors.connect(provider)
from the click; the host opens the right settings page. Never treat this as empty data.blocked, write_blocked, tool_missing, upstream_error — show detail with a retry.truncated: true means the result exceeded 256 KB and was cut to a preview; narrow the call
(a smaller limit, one repository) instead of paging client-side.refresh seconds (default 60, range 30–86400).
Account, organization, and project changes clear both results and consent.ph.state scope "user".
A canvas with connectors cannot declare shared state. Validation and the API reject this combination.const [prs, setPrs] = useState<{ loading: boolean; status?: string; rows?: PullRequest[] }>({ loading: true })
useEffect(() => {
ph.connectors
.call('github', 'list_pull_requests', { repository: 'example/app', state: 'open' }, { refresh: 60 })
.then((res) => setPrs({ loading: false, status: res.status, rows: res.result?.pull_requests ?? [] }))
.catch((error) => setPrs({ loading: false, status: 'error', rows: [] }))
}, [])ph.capture(event, properties?, distinctId?) — analytics events for interactions
(fire-and-forget). Session replay, $session_id, and person attribution are handled by the
host automatically; never initialize recording, set session ids, or roll your own capture.ph.openExternal(url) — opens PostHog HTTPS URLs and https://github.com/<owner>/<repo>/pull/<number>
links from a user click. GitHub PR links open without a confirmation dialog. Files, commits, checks,
and fragment links are allowed; credentials, custom ports, query strings, and other domains are not.
Sandboxed target="_blank" navigation is blocked, so use the bridge rather than a browser fallback.ph.navigate.toTask(id) / .toNewTask() / .toCanvas(id) / .toNewCanvas() — in-app
navigation within the canvas's own channel.ph.navigate.toNewTask({ prompt, repository }) — opens a prefilled task form in a new tab from
a user click. prompt is at most 16,000 characters; repository is an owner/repo name. Both are
optional. Setting a repository selects cloud mode for this task without changing the space.
The viewer reviews and sends the prompt; opening the form does not start a run. Check for
ph.navigate in older published artifacts and ask for a rebuild after deployment if it is missing.© PostHog, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file (references) in products/canvas/skills/querying-canvas-data of PostHog/posthog-foss.
Open the folder on GitHubat commit 2c48221
Querying Canvas Data next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Querying Canvas Data this skillPostHog/posthog-foss | 721 | — | ~5k | Automated safety check: Pass | MIT | |
| Posthog Product Health Auditboardsesh/boardsesh | 163 | — | ~2.1k | Automated safety check: Pass | Apache-2.0 | |
| Skill Seekers Builderyusufkaraaslan/Skill_Seekers | 15k | — | ~760 | Automated safety check: Pass | MIT | |
| Helmor CLIdohooo/helmor | 1.3k | — | ~1.3k | Automated safety check: Pass | Apache-2.0 | |
| Spec Driven Developzhu1090093659/deepseek-pp | 1.9k | — | ~6.9k | Automated safety check: Pass | Apache-2.0 | |
| MCP Apps Builderawslabs/cli-agent-orchestrator | 1.4k | — | ~1.7k | Automated safety check: Pass | Apache-2.0 |
boardsesh/boardsesh
Mine Boardsesh's PostHog telemetry (error tracking, session recordings, product analytics) with a multi-agent workflow, then file verified, deduplicated, severity-labelled GitHub issues.
yusufkaraaslan/Skill_Seekers
Detects the type of a knowledge source and uses the Skill Seekers MCP tools to turn docs, repos, PDFs or videos into packaged AI skills.
dohooo/helmor
Use the Helmor CLI to remote-control Helmor from the terminal.
zhu1090093659/deepseek-pp
Automates pre-development workflow for large-scale complex tasks.
awslabs/cli-agent-orchestrator
Load the official MCP Apps builder skills (create-mcp-app, migrate-oai-app, add-app-to-server, convert-web-app) from github.com/modelcontextprotocol/ext-apps.
jgravelle/jcodemunch-mcp
Publishing a jMunch release (jcodemunch-mcp, jdocmunch-mcp, jdatamunch-mcp, jragmunch-cli), reviewing/merging/closing PRs, and responding to the community.
PostHog/posthog-foss
Author useful, low-noise log alerts on services in a PostHog project.
PostHog/posthog-foss
Operating procedure for the conflict-autoresolver agent: sweep open PostHog/posthog PRs that conflict with master, resolve the trivial conflicts (generated artifacts deterministically, source…
PostHog/posthog-foss
Help users debug PostHog Error Tracking stack-trace symbolication for any supported platform — JavaScript/TypeScript web, React Native (Hermes), Android (Proguard / R8), or iOS / macOS (dSYM).
PostHog/posthog-foss
Investigates distributed application performance using PostHog APM (OpenTelemetry span) data via MCP.
PostHog/posthog-foss
Debug and inspect LLM/AI agent traces using PostHog's MCP tools.
PostHog/posthog-foss
Diagnose why a product metric changed (dropped, spiked, or plateaued) by orchestrating breakdowns, actors, paths, lifecycle, retention, and annotations queries.
Works with
Categories
Get PostHog data into a canvas correctly: the host-injected ph SDK (loadInsight, query, capture, state, connectors, openExternal, navigate), the data hierarchy (saved insights first, typed query…. Querying Canvas Data is an agent skill from PostHog/posthog-foss, published by the product's own GitHub organization.
Querying Canvas Data fits situations like: A canvas shows metrics; any PostHog data; data from GitHub; needs to send analytics events.
Run `npx skills add PostHog/posthog-foss --skill querying-canvas-data -a claude-code`. Or copy the skill folder (products/canvas/skills/querying-canvas-data in PostHog/posthog-foss) into .claude/skills/querying-canvas-data in your project. Claude Code loads it when a task matches its description.
Run `npx skills add PostHog/posthog-foss --skill querying-canvas-data -a codex`. Or copy the skill folder (products/canvas/skills/querying-canvas-data in PostHog/posthog-foss) into .agents/skills/querying-canvas-data in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add PostHog/posthog-foss --skill querying-canvas-data -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/querying-canvas-data, .gemini/skills/querying-canvas-data, .github/skills/querying-canvas-data and .opencode/skills/querying-canvas-data in your project.
Going by SKILL.md and its folder, Querying Canvas Data needs TypeScript for the scripts in its folder. Our summary lists: Node.js.
SKILL.md names 1 domain. In commands or code: github.com; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Querying Canvas Data is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 5k tokens (SKILL.md is roughly 20k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 2.1k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Querying Canvas Data: Posthog Product Health Audit (boardsesh/boardsesh, 163 stars), Skill Seekers Builder (yusufkaraaslan/Skill_Seekers, 15k stars), Helmor CLI (dohooo/helmor, 1.3k stars) and Spec Driven Develop (zhu1090093659/deepseek-pp, 1.9k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
PostHog (a GitHub organization, an official publisher) maintains it in PostHog/posthog-foss, which has 721 GitHub stars. The repository holds 213 skills in this directory. The repository was last updated on October 7, 2026.
Source: PostHog/posthog-foss on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.