quill-code

SkillMedia

Lets your agent edit the PostHog quill design system locally and preview changes in the desktop app.

Available today. Use it from your connected AI after setup.

Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

Then ask your AI: use the quill-code skill

About this skill

Edit the @posthog/quill design system locally and consume the change in products/desktop before it is published to npm. Use when changing quill components/primitives/tokens, when a quill change must be tested inside the Code app, or when the user mentions quill, the design system, the .local-quill t

What this skill tells your AI

The instructions your AI receives, as published by posthog/posthog in products/desktop/.claude/skills/quill-code/SKILL.md and read by ahel’s review.

@posthog/quill's source lives in this monorepo at packages/quill (repo root, two levels up from products/desktop). Desktop still consumes the published npm package via its nested workspace catalog — products/desktop is excluded from the root pnpm workspace, so workspace: linking cannot reach it. To test an unpublished quill change here, you build quill in-repo, pack it to a tarball, and point a pnpm overrides entry at that tarball. This is a temporary local-dev state — revert before merging (see below).

All commands below run from products/desktop/. Building quill uses the root workspace's install, so run pnpm install at the monorepo root once first.

Quill layout (where to edit)

packages/quill (from the monorepo root) is the workspace (@posthog/quill-workspace). It contains sub-packages, each a layer of the design system:

  • packages/primitives/src — base components (Card, Badge, Button, Progress, …)
  • packages/components/src — composed components (DataTable, DateTimePicker, Metric)
  • packages/blocks/src — product-level blocks (e.g. ExperimentCard). Add the file here and export it from packages/blocks/src/index.ts.
  • packages/quill/src — the aggregate that re-exports all layers as @posthog/quill.

A new export in any sub-package flows to @posthog/quill automatically on build.

The loop (every quill change)

  1. Edit/add the component in the right sub-package (above) and export it from that package's src/index.ts.

  2. Re-sync into products/desktop manually — build → pack → point the override → reinstall:

    # From products/desktop/
    DESKTOP_ROOT="$PWD"
    QUILL_DIR="${QUILL_DIR:-../../packages/quill/packages/quill}"
    
    # a. Build the WHOLE quill workspace (two levels up from the aggregate), so the
    #    sub-packages rebuild BEFORE the aggregate bundles them.
    ( cd "$QUILL_DIR/../.." && pnpm build )
    
    # b. Pack into .local-quill/ under a UNIQUE filename. pnpm pins a tarball by
    #    integrity, so a stable name caches stale across re-syncs — drop old local
    #    tarballs first, then rename the packed file to a unique local name.
    #    (Anchor on $DESKTOP_ROOT, not `git rev-parse --show-toplevel`: the git
    #    toplevel is the monorepo root, not this workspace.)
    rm -f .local-quill/posthog-quill-local-*.tgz
    ( cd "$QUILL_DIR" && npm pack --pack-destination "$DESKTOP_ROOT/.local-quill" )
    mv .local-quill/posthog-quill-[0-9]*.tgz ".local-quill/posthog-quill-local-$(git rev-parse --short HEAD)-$$.tgz"
    
    # c. Point the override at the new tarball, then reinstall.
    #    Edit pnpm-workspace.yaml so overrides['@posthog/quill'] = file:./.local-quill/<new file>
    pnpm install
    

    Building only the aggregate (packages/quill/packages/quill) re-bundles the sub-packages' stale dist/, so edits to primitives/components/blocks are silently dropped. Always build at the workspace root.

  3. Verify in the Code app (pnpm dev, or the test-electron-app skill). Repeat from 1.

After every quill edit you must re-run the sync — the app consumes the tarball, not the quill source, so unsynced edits are invisible here.

For an out-of-tree quill checkout, set QUILL_DIR=/abs/path/to/posthog/packages/quill/packages/quill.

Why a tarball, not link: or workspace:

workspace: cannot resolve across the nested-workspace boundary (products/desktop is excluded from the root pnpm workspace). link: symlinks into the root workspace's node_modules and drags in its React 18 types, colliding with this workspace's React 19 (dual-React → broken typecheck + invalid-hook-call at runtime). The tarball is copied into this workspace's store and deduped against React 19. The filename is content-hashed because pnpm pins a tarball by integrity, so a stable filename gets cached stale across re-syncs.

The override (what the script rewrites)

In pnpm-workspace.yaml, under overrides::

'@posthog/quill': file:./.local-quill/posthog-quill-local-<hash>.tgz

There is also a permanent pin you should leave alone:

'@posthog/quill>@base-ui/react': ^1.3.0   # quill ships a broken catalog: dep; do not remove

Reverting (before merge)

The override is local-dev only. Once the quill change is published to npm (quill publishes from this monorepo via the manual publish-quill-npm workflow dispatch):

  1. Bump the catalog version in pnpm-workspace.yaml ('@posthog/quill': 0.3.0-beta.x) to the published version.
  2. Restore the override line to point back at the catalog, or remove the file: override.
  3. pnpm install.

Do not commit a file:./.local-quill/... override or the .local-quill/ tarballs.

Signals

GitHub stars
40k
Forks
3k
Last commit
Sep 2026

ahel review

  • K1binfo
    installs-packages

Automated review, not a security audit. Ruleset v1+k2.

Others that do the same job

Advanced
Item type
skill
Key
quill-code
Source
github.com/posthog/posthog