关于 run-posthog
run-posthog 是用于启动 PostHog 并验证实时应用变更的仓库技能,为开发者和 Agent 提供就绪检查及浏览器 QA 指引。
主要功能
- 01使用 hogli 启动 PostHog
- 02检查应用与进程就绪状态
- 03创建测试工作区和数据
- 04通过浏览器 MCP 验证变更
- 05将代码变更映射到应用路由
适用场景
- 01启动 PostHog 进行本地开发
- 02检查应用是否已就绪
- 03在实时浏览器中验证 UI 变更
MCP 相关
它使用 phrocs MCP 服务检查和管理进程状态,并使用 chrome-devtools-mcp、playwright 等浏览器 MCP 服务在验证期间操作应用。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ posthog/ posthog --skill run-posthog安装后在 Claude Code 中输入/run-posthog确认已加载。
详细介绍
PostHog 由 Django + Vite + Celery + plugin-server 构成,后端依赖 Docker 中的 Postgres、ClickHouse、Kafka、Redis 和 Temporal,前端由位于 http://localhost:8010 的 Envoy 风格代理提供服务。开发栈以分离模式运行在 phrocs 下,因此可以通过 phrocs MCP 服务从本次会话中检查正在运行的进程。浏览器 MCP 服务(chrome-devtools-mcp、playwright)负责驱动 UI;本技能自身不附带任何驱动。
对于 /run:让应用可访问,以便用户可以驱动它。成功 = http://localhost:8010 可以提供服务,并且核心单元为 ready。不要追查崩溃的迁移单元,除非被要求,否则不要注入数据。
对于 /verify:构建(前端由 Vite HMR 自动处理;后端更改无需构建),运行与 /run 相同的启动流程,然后通过浏览器 MCP 驱动实时应用以观察更改。观察本身就是验证——测试和类型检查不能替代。对于前端/UI 更改,此工作流的深度版本是仓库本地的 qa-frontend 技能在本地模式下运行:根据 diff 设计场景、可复现性重试,以及带注释的证据。
以下所有路径均相对于仓库根目录。
前提条件
- flox 1.16+ 提供工具链——
curl -L https://downloads.flox.dev/by-env/stable/install.sh | sudo bash - Docker——macOS 上首选 OrbStack(
brew install --cask orbstack) - 1Password CLI(可选)——
brew install 1password-cli,仅当.env.local包含op://引用时需要
启动
对于普通开发栈,使用已保存的交互式设置:
hogli dev:setup # first time only — interactive wizard picks which workers to run
hogli up -d -y # start the stack detached under phrocs
hogli services:ready -y # wait for Docker services (Postgres, CH, Kafka, Redis)
hogli wait -y # broad all-process signal; confirm with the checks below
hogli doctor # optional: stale migrations, zombie phrocs, disk pressure
对于 Agent 管理的 QA,除非用户要求调整服务,否则使用普通后台栈。在 devbox 上,对于新建/已停止的 box,优先使用 hogli devbox:start --start-app;如果它已在运行但没有应用,则在其中启动 PostHog:
hogli devbox:exec -- bash -lc 'cd ~/posthog && ./bin/hogli up -d -y'
仅使用 hogli dev:intents、hogli dev:explain <intent> 和 hogli dev:list-units <intent> 来了解特定路由的依赖关系;自定义生成的配置不是默认的 QA 启动路径。
首次启动需要 60-90 秒,因为 Django 需要导入且 Vite 需要预热。使用 hogli down -y 停止(会保持 Docker 服务运行,以便快速重启)。
栈是否就绪?
有两个就绪标准。不要将它们混为一谈。
/run 就绪——应用可访问且你可以驱动它:
curl -sf http://localhost:8010/_health # 200
curl -sf -o /dev/null -w '%{http_code}' http://localhost:8010/ # 200 or 302
curl -sS http://localhost:8010/api/projects/@current | grep -q '"code":"not_authenticated"' # API + DB reachable
对于 UI QA,backend 和 frontend 是硬性门槛;仅添加路由所需的单元,例如 mcp、feature-flags、nodejs、capture 或 ingestion。到此为止。当仅要求 /run 时,不要追查崩溃的 migrate-* 单元——无论迁移状态如何,栈都可用于启动、截图和大多数 UI 场景(首页、登录、设置、功能标志)。
HogQL 支撑场景的 /verify 就绪(洞察、仪表盘、Web 分析)以及 POST /api/setup_test/...:
- 还要求
mcp__phrocs__get_process_status process="migrate-clickhouse"显示status:"done" exit_code:0。如果它是crashed,请参阅下面的注意事项。
phrocs MCP 工具——适用于任一标准:
mcp__phrocs__get_process_status(无参数)——所有单元,包含ready、exit_code、内存、CPU。mcp__phrocs__get_process_status process="frontend"——单个单元。mcp__phrocs__get_process_logs process="backend"——查看最近的标准输出/标准错误。mcp__phrocs__toggle_process process="<unit>"——重启单个单元。自动模式会在共享栈上阻止此操作(被视为重启共享基础设施)。如果被阻止,请让用户批准,或运行phrocs stop && hogli up -d进行完全干净的重启。
驱动 UI 进行 /verify
每个空的 PostHog 场景看起来都像是坏掉了,因为没有任何事件存在。要验证 UI 改动,你需要一个带有真实数据的工作区。标准路径与 Playwright 测试套件使用的路径相同:POST /api/setup_test/organization_with_team/。其访问受 DEBUG=True | E2E_TESTING | CI | TEST 限制,本地开发通过 DEBUG=True 满足所有条件。实现:posthog/api/playwright_setup.py + posthog/test/playwright_setup_functions.py:create_organization_with_team —— 通过 HedgeboxMatrix 创建 3 个集群,端到端约 5-10s。参考调用位置:playwright/utils/playwright-setup.ts:251。
对于 /run 和 /verify,避免使用 hogli dev:demo-data —— 它调用 generate_demo_data 并传入 n_clusters=500(posthog/management/commands/generate_demo_data.py:59 处的默认值),需要 5-30 分钟。它是为那些想要一个大型真实数据集来把玩的人类而存在的;对于自动化的启动并截图来说,它是错误的工具。
完整的浏览器 MCP 配方:
-
new_page到http://localhost:8010/login。 -
evaluate_script执行工作区引导。每次调用使用不同的邮箱,以免重复运行时冲突;密码固定为12345678;响应会返回 team_id 和一个个人 API 密钥。const r = await fetch('/api/setup_test/organization_with_team/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ skip_onboarding: true, use_current_time: true }), }) const { result } = await r.json() // result: { user_email, team_id, personal_api_key, organization_id, ... } return result -
evaluate_script执行页面内登录。它在页面上下文中运行,因此 Django 的 CSRF 中间件能看到正确的 cookie(playwright/utils/playwright-setup.ts:282-291)。const r = await fetch('/api/login/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: workspace.user_email, password: '12345678' }), }) return r.status // 200 = logged in; 403 = you're not in-page; 400 = workspace setup didn't actually create the user -
navigate_page到http://localhost:8010/project/{team_id}{scene-path}。 -
wait_for文本或[data-attr]元素。PostHog 几乎为每个渲染的元素都附加了data-attr;用它作为"页面已完成水合"的信号。networkidle和load永远不会稳定下来,因为 PostHog.js 和 Vite HMR 一直在轮询。 -
take_screenshot。对于大多数"这个元素是否存在?"的验证,来自wait_for的可访问性快照本身就足够了 —— 无需进行像素对比。
对于仅 API 调用(创建 fixture、在没有浏览器的情况下访问端点),使用 setup_test 响应中的 personal_api_key 作为 Authorization: Bearer <key> —— 无需登录流程。
对于更深入的交互(点击、填写表单、检查控制台),同一套 MCP 工具包(chrome-devtools-mcp:* / playwright:*)即可覆盖。无需项目特定的封装。
对于 /verify:diff → URL 映射
前端使用 kea-router。映射规则:
| 编辑的路径 | 场景 URL(位于 /project/{team_id}/ 之下) |
|---|---|
frontend/src/scenes/<name>/** | 通常是 /<name>(例如 insights/ → /insights) |
frontend/src/scenes/activity/** | /activity/events(以及其他 ActivityTab) |
frontend/src/scenes/data-management/** | /data-management/<sub> |
frontend/src/scenes/settings/** | /settings/<section> |
frontend/src/scenes/authentication/** | /login、/signup、/preflight(无作用域) |
products/<name>/frontend/** | 依据 products/<name>/manifest.tsx 中的 urls: 块 |
frontend/src/layout/** | 到处都会渲染;可在任意场景中验证 |
frontend/src/lib/components/<X>.tsx | grep 查找使用位置,截图显示它的场景 |
当路径不明显时,可以 grep 的权威来源:
frontend/src/scenes/urls.ts—— 顶层 URL 辅助函数(urls.insights()、urls.dashboard(...)等)。frontend/src/scenes/scenes.ts—— 场景到路由的注册表。products/<name>/manifest.tsx—— 各产品的路由。
注意事项
migrate-clickhouse和migrate-persons-db在冷启动hogli up -d时常因启动竞态而崩溃。 它们与migrate-postgres并行启动,如果 Postgres 尚未就绪就会崩溃。这是POST /api/setup_test/...以及依赖 HogQL 的场景(洞察、仪表盘、Web 分析)的硬性前置条件 —— 但 不是/run的前置条件。除非任务需要 HogQL/setup_test,否则不要修复它。当你确实需要修复时,标准流程是:通过mcp__phrocs__get_process_status等待migrate-postgres显示status:"done",然后重启崩溃的迁移。mcp__phrocs__toggle_process是精准的工具,但 auto 模式会在共享 stack 上阻止它 —— 退而求其次可以用phrocs stop && hogli up -d,它会按顺序重新运行所有内容,或者直接运行python manage.py migrate_clickhouse(你需要先执行set -a; source .env.services; set +a,以便CLICKHOUSE_DATABASE=posthog,否则会指向default)。如果两者都不奏效(部分运行导致 ZooKeeper 中的 CH 副本状态损坏),hogli dev:reset是唯一的出路 —— 它会清除 Docker 卷,具有破坏性。hogli wait是一个粗粒度的全进程信号。 在判定 stack 不可用之前,请用进程特定的 phrocs 状态、curl探针和目标路由来确认。- Vite 在
:8234上提供服务,而不是你浏览的 URL。 你浏览的是http://localhost:8010(Envoy 风格的代理)。该代理将/static/*反向代理到 Vite,其余全部代理到 Django。直接访问:8234/会返回 404,因为 Vite 在开发服务器根路径上没有 index 路由。 - Worktree 共享 Docker 容器,但会争抢端口。 同一台机器上的所有 worktree 都解析到相同的
posthog-clickhouse-1/posthog-db-1容器,因此数据库状态是全局的。但端口 8000/8010/8234 一次只能被一个 worktree 占用 —— 在此处执行hogli up -d之前,请先杀掉另一个 worktree 的 granian/vite/phrocs。 - 浏览器控制台中的 CSP 警告和 401 在认证前是正常的。 预检/登录页面会尝试获取
/api/projects/@current、/api/users/@me/和 PostHog.js 远程配置 —— 在你注册之前全部返回 401。WASM/CSP 的 "Report Only" 警告来自开发环境的 CSP。 - 直接
curl -X POST /api/login/会返回 403(CSRF)。 会话登录必须通过browser_evaluate在页面内执行,以便 cookie 和 CSRF token 正常流转。对于非浏览器 API 调用,请使用setup_test响应中的personal_api_key作为Authorization: Bearer <key>—— token 认证没有 CSRF。 .env.local可能使用 1Password 引用。 如果没有安装op,引用会变成字面字符串(例如OPENAI_API_KEY=op://...),下游服务会因难以理解的认证错误而失败。请安装op或替换为字面值。
故障排查
hogli up -d退出并提示Another instance of bin/start is already running—— 上一次运行仍在进行,或崩溃后未清理。mcp__phrocs__get_process_status会显示当前有哪些进程;如果没有任何进程在运行,执行rm bin/start.lock后重试。docker info失败并提示dial unix /Users/<you>/.orbstack/run/docker.sock: ... no such file—— OrbStack 已停止。执行open -a OrbStack。/api/projects/@current返回 500 而不是 401 —— Postgres 或 ClickHouse 无法访问。执行docker ps | grep posthog-并查找不健康的容器;hogli services:ready会等待它们全部就绪。POST /api/login/返回 400invalid_credentials—— 你登录的用户实际上并非由setup_test工作区创建(通常是 CH 崩溃所致)。检查 setup_test 调用的响应;如果它返回了 500,请先修复 CH(参见migrate-clickhouse的注意事项)。POST /api/setup_test/organization_with_team/返回 404 ——DEBUG、E2E_TESTING、CI和TEST全部为 false。本地开发默认DEBUG=True;如果未设置,说明.env.local缺失,或DJANGO_SETTINGS_MODULE指向了类似生产环境的设置模块。POST /api/setup_test/organization_with_team/返回 500Table posthog.person does not exist——migrate-clickhouse在启动过程中崩溃。参见上面的注意事项。- 页面内
fetch('/api/login/')返回 403 —— 你是在页面上下文之外调用它(例如用page.request.post而不是page.evaluate)。使用evaluate_script/browser_evaluate,让调用从页面内发起。