Skip to main content
The context-packs mechanism installs versioned, pre-curated semantics//contracts//knowledge/ content for a known system. This guide runs the posthog pack (canonic-packs) end to end against a real (seeded) Postgres database, so you can see the whole story — install, validation, and querying — without a real PostHog instance.

Prerequisites

  • Docker with Compose
  • A checkout of the canonic repository (the compose file builds the daemon from scripts/posthog_pack_demo/Dockerfile)
  • Network access from inside the container to clone canonic-packs from GitHub at startup — no local checkout needed, see “Where the pack content comes from” below
  • An MCP client, for example the MCP Inspector, or plain curl

Start

From the repository root:
Wait for installing the posthog context pack..., a line listing the installed files, and then Uvicorn’s Uvicorn running on http://0.0.0.0:7474 line.

What happened

entrypoint.sh ran, non-interactively:
Before writing anything, this checked that posthog_exports.events/persons actually exist on the posthog_db connection (required_tables, a live introspection call). It then templated and wrote:
  • semantics/posthog_db/ph_events.yaml, ph_persons.yaml — one row per event, one row per (team_id, distinct_id), joined many-to-one.
  • contracts/metrics/active_users.yaml, new_users.yaml, activated_users.yaml, activation_rate.yaml.
  • contracts/guardrails/posthog-exclude-internal-traffic.yaml — a mandatory_filter built from the internal_email_domains: yourcompany.com param in pack-params.json, always AND-ed into any query against ph_events regardless of severity.
  • knowledge/global/activation-definition.md, internal-traffic-caveat.md.
Every file is stamped provenance: human_curated plus a pack_source: {pack: posthog, version, variant: postgres} tag, then validated with the project’s ordinary semantic/contract/knowledge checks — the same review posture as hand-written content, just starting from a known-good definition instead of an inferred one.

The seed data

postgres/init/02_seed.sql seeds one team (team_id = 1) with 30 persons over the last 30 days:
  • All 30 signed up (user_signed_up).
  • 3 are tagged with an internal @yourcompany.com email — excluded from every metric by exclude-internal-traffic.
  • 9 of the remaining 27 also fired report_created (the activation event).
  • Everyone gets a few $pageview/dashboard_viewed noise events spread across the window.
With the guardrail applied, that gives: The pack’s first_answer (active_users, 30d window) runs automatically right after install — its result is the first thing canonic pack add prints.

Query it

Or connect an MCP client to http://localhost:7474 with that same bearer token and query active_users, new_users, activated_users, or activation_rate via the query tool. posthog-demo-local-dev is canonic.docker.yaml’s single static demo token (mcp.auth.tokens) — --transport http refuses to start with no auth mechanism configured at all.

Stop

Add -v to also drop the seeded Postgres volume; without it, a later up reuses the same data (Postgres only runs its init scripts against a fresh volume) and reinstalls the pack fresh each time (install_pack overwrites unconditionally, so this is always safe).

Where the pack content comes from

No --repo is passed, so canonic pack add falls back to its own built-in default — the canonic-packs GitHub repo (canonic/cli/commands/pack.py::_DEFAULT_REPO) — shallow-cloned fresh into .canonic/packs-cache/ on every container start. That clone needs git on PATH, which the shared root Dockerfile doesn’t have (adding it there would grow every image built from it, not just this demo), so this demo builds from its own Dockerfile instead — an exact copy of the root one plus git.

Point this at a real PostHog instance

Nothing about the pack mechanism itself changes. Swap canonic.docker.yaml’s posthog_db connection for your real warehouse’s Postgres batch-export database, and either:
  • keep --params-file/--yes and edit pack-params.json’s signup_event/activation_event to your actual event names, or
  • drop both flags and run canonic pack add posthog interactively — choose_from then queries your live database for a top-50 custom-event picklist instead of using the seeded params.

Where to go next

  • canonic pack for every flag, and pack validate’s CI-friendly, connection-free path
  • canonic setup — the same install routine is also offered from the setup wizard’s pack branch
  • Marketplace with Keycloak for the same “Docker demo on top of a shipped example” pattern applied to OAuth/RBAC instead of context packs