Skip to content

Standardize property naming: snake_case for PostHog, camelCase for JSON #189

Description

@thecodedrift

The rule

  • PostHog properties are snake_case.
  • JSON payload fields are camelCase.

Two wire formats with two audiences: PostHog properties are read in insights and dashboards, JSON payloads are parsed by agents and scripts. Each follows its own ecosystem's convention. The same datum can therefore appear under both spellings, and that is correct rather than a mistake to reconcile.

Where we stand

JSON is already compliant. Every field across packages/cli/src/schemas/*.ts is camelCase; a scan for snake_case field names returns nothing. No change needed, and the rule is worth writing down so it stays that way.

PostHog is mixed. gh_owner (added in the #179 work) follows the rule; everything older does not.

Changes needed

Standard properties attached to every event, in packages/cli/src/telemetry.ts:

current should be
cliVersion cli_version
scaffoldVersion scaffold_version
cli unchanged (single word)
gh_owner unchanged (already correct)

Per-event properties passed by callers:

current should be
durationMs duration_ms
loggedIn logged_in
ruleCount rule_count
anonymous, command, meta, status, success unchanged (single word)

Not in scope: groupType and groupKey are parameters of the PostHog SDK's groupIdentify call, not properties we name.

What else has to move

The analytics spec names these properties normatively and would need a delta in the same change. openspec/specs/analytics/spec.md, requirement "All capture calls include standard properties", spells cliVersion and scaffoldVersion in the requirement text and in four scenarios. The "CLI version is the version the build reports as its own" requirement names cliVersion too.

Tests assert the current names, at minimum packages/cli/test/telemetry.test.ts.

The part that needs a decision

This breaks existing PostHog insights. Any saved insight, dashboard, funnel, or cohort filtering on cliVersion, scaffoldVersion, durationMs, loggedIn, or ruleCount stops matching at the rename, and historical events keep the old spelling forever. So the options are:

  1. Rename and accept the discontinuity. Simplest code, and every event after the release is consistent. Existing insights need updating by hand, and any query spanning the boundary needs both spellings.
  2. Dual-write for a period — emit both spellings, migrate insights, then drop the old. No discontinuity, at the cost of duplicated properties on every event and a second change later to finish it.
  3. Leave the legacy names and apply the rule only to new properties. Zero disruption; the inconsistency is permanent and every future reader has to learn which era a property comes from.

Worth noting the volume is low enough that option 1 is plausible: five properties, and the CLI's event taxonomy is small.

Notes

Found while adding gh_owner for #179. That property was written snake_case deliberately, so it is already on the right side of this and needs no follow-up. Nothing here blocks #179.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions