Skip to content

feat(codex): connect a chatgpt plan on web and bill codex runs to it - #108909

Open
puemos wants to merge 14 commits into
masterfrom
posthog/codex-personal-integration
Open

puemos wants to merge 14 commits into
masterfrom
posthog/codex-personal-integration

Conversation

@puemos

@puemos puemos commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Problem

  • Users can connect a ChatGPT account for Codex cloud tasks only in PostHog Desktop. Web settings do not have this option.
  • Desktop runs codex login in its own terminal. Web cannot do that, so the user must run a command on their computer and bring the result back.
  • The web task composer always bills Codex runs to PostHog credits. A user with a ChatGPT plan cannot pay with it.

Changes

Settings: Project > AI > Subscriptions > Codex

  • A new Subscriptions section in the AI group, below Model preferences, has a Codex row. It shows the connected ChatGPT account, the plan, and when the user connected it. The connection belongs to the user and applies in every project.
  • The row reads the existing /api/users/@me/integrations/codex/ record, so a connection made in Desktop shows up on web. The row reloads when the window gets focus.
  • When OpenAI rejects the stored refresh token, the row shows an error and a Connect again button.

Connect dialog (device code flow only)

  • One command for macOS, Linux, or Windows. A picker selects it, and the browser's platform is the default.
  • The command signs in with codex login --device-auth in a temporary CODEX_HOME, forces file credential storage, copies auth.json to the clipboard, and deletes the folder, also on Ctrl+C. The sign-in never shows in the terminal, nothing stays on the computer, and ~/.codex is never touched, so the local Codex sign-in keeps working.
  • The paste field never shows the sign-in. A paste connects at once, Paste from clipboard does the same in one click, and the page clears the clipboard after a valid paste.
  • The dialog opens only for the surface that asked for it, so settings and a composer on screen together do not both open it.

Task composer billing

  • On the Codex harness, the model menu has a Billing row: PostHog credits or OpenAI (ChatGPT plan). The trigger shows "ChatGPT plan" when it is chosen.
  • The plan needs a connected account. Otherwise the row offers Connect your ChatGPT account, which opens the connect dialog in place and selects the plan after the connect.
  • The choice is kept in the browser. A live run shows its billing locked, as the harness is.
  • New tasks and resumed runs send codex_model_access. A run on the plan pins the Codex model and skips warm reuse, because a warm sandbox holds no ChatGPT token. When the flag is on, the choice is always sent: a resume otherwise keeps the old billing, and the backend refuses the plan on Claude.
  • Only a wrapper that renders behind the flag mounts codexBillingLogic, so users without the flag never load their ChatGPT connection.

Rollout: the posthog-code-codex-own-subscription-cloud flag gates the settings section and the billing row. The backend already checks the same flag on connect and on run start. There is no backend change.

Subscriptions section
Sign-in needs renewal
Connect dialog
After a paste
Windows command
Billing row
ChatGPT plan chosen
Connect from the composer
Settings at 900px

Note

Desktop's "Cloud tasks" toggle still decides if a Desktop run uses the ChatGPT plan. The web choice applies to runs started on web.

How did you test this code?

  • codexAuthFile.test.ts checks the paste parser. It catches a parser that accepts an API-key auth.json, or that fails to read the tokens.
  • codexLoginCommands.test.ts checks the platform detection. It catches a macOS browser that gets the Windows command, because darwin contains win.
  • ComposerModelEffortPickers.test.tsx checks that Billing is absent on Claude, that the plan is disabled until an account is connected, and that a connected account can switch to it.
  • The three commands ran against a fake codex in bash, zsh, fish, and PowerShell 7. Each put the token on the clipboard, printed only "Copied", and deleted the folder after success, failure, and a real Ctrl+C in a pseudo-terminal. PowerShell also restores the previous CODEX_HOME. The real Codex CLI 0.154.0 accepted -c cli_auth_credentials_store=file and wrote only a login log before sign-in.
  • In Chromium, a paste showed "Sign-in received" and started the connect, and the token was in no page text and no input value.
  • In Storybook with the flag on, choosing the plan and sending a task made a task create without a branch key (no warm reuse) and a run create with codex_model_access: "own-subscription" and the pinned Codex model.
  • The screenshots come from the stories in SettingsEnvironment.stories.tsx and from Storybook with the flag on.
  • The frontend TypeScript check, oxlint, and oxfmt pass.
  • Not tested: a real connect against OpenAI, a real run on the plan, a resume in a browser, the command on a real Windows machine (PowerShell 5.1 and the npm .cmd launcher), Wayland wl-copy, and a sync with a real Desktop app.

Release status

  • No feature flag controls this change
  • This change is behind a feature flag and is not available to users
  • This change makes a previously flagged feature available to everyone

Automatic notifications

  • Publish to changelog?

Docs update

None.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Agent: PostHog Desktop, Claude Opus 5.5 (claude-opus-5-5)

  • The person compared mocked placements, then asked for the Codex row under Personal integrations, and later moved it to an AI Subscriptions section. They asked for the device code flow only, no mention of PostHog Desktop in the UI copy, a command that leaves nothing on the computer and never shows the sign-in, and a billing choice in the web composer.
  • Claude is out of scope. Desktop keeps the Claude token only on the computer, and a web version needs a legal review first.
  • Skills: /writing-ui-components, /adopting-generated-api-types, /writing-user-facing-copy, /writing-tests, /using-kea-disposables, /setting-feature-flags-in-storybook, /writing-pr-descriptions.
  • Search for duplicate PRs: none found.
  • All sample data (jane@example.com, fake tokens) is invented.

Created with PostHog Desktop

🤖 Generated with Claude Code

@puemos puemos self-assigned this Sep 30, 2026
@trunk-io

trunk-io Bot commented Sep 30, 2026

Copy link
Copy Markdown

Merging to master in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

🤖 CI report

✅ Trunk lane — non-backend lane

This PR is assigned to the non-backend lane. It does not run backend Python tests and may merge in parallel with PRs in other lanes.

⚠️ Complexity (TypeScript) — 9 functions above the limit (max 56)

Cyclomatic complexity above the limit in changed typescript files (10 for production files, 15 for test files). Warn only: worth simplifying when you next touch these functions.

Function Location Complexity Limit
submitNewTask products/posthog_ai/frontend/scenes/TaskTracker/taskTrackerSceneLogic.ts:706 56 10
sendNow products/posthog_ai/frontend/logics/runInteractionLogic.ts:1298 44 10
ComposerModelEffortPickers products/posthog_ai/frontend/components/composer/ComposerModelEffortPickers.tsx:127 22 10
startNewRun products/posthog_ai/frontend/logics/runInteractionLogic.ts:1504 21 10
TaskRunComposer products/posthog_ai/frontend/scenes/TaskTracker/components/TaskRunComposer.tsx:34 20 10
submit products/posthog_ai/frontend/logics/runInteractionLogic.ts:911 13 10
TaskRunChat products/posthog_ai/frontend/scenes/TaskTracker/components/TaskRunChat.tsx:47 13 10
<anonymous> products/posthog_ai/frontend/logics/runInteractionLogic.ts:1076 12 10
TaskComposer products/posthog_ai/frontend/scenes/TaskTracker/components/TaskComposer.tsx:48 11 10
✅ Duplication (Python) — clean

New Python code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

✅ Duplication (TypeScript) — clean

New TypeScript code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

⚠️ Comment density — 3% of added code lines are comments (46 of 1389)

This section warns when comments are more than 3% of the code lines a PR adds, and alerts above 6%. Before agent-assisted PRs, the typical share was about 2%. Only full-line comments count. Docstrings, generated files, snapshots, migrations, and workflow files are left out.

Comments that restate the code, record how the change came about, or narrate the next line add noise for the next reader. Keep the comments that explain a reason the code cannot show, and remove the rest. See .agents/skills/writing-code-comments/SKILL.md for the house rules.

Files with the most added comment lines:

File Comment lines Added lines
products/posthog_ai/frontend/logics/codexBillingLogic.ts 19 174
frontend/src/scenes/settings/user/personalCodexIntegrationLogic.ts 5 287
products/posthog_ai/frontend/components/composer/ComposerCodexBillingPickers.tsx 5 42
products/posthog_ai/frontend/scenes/TaskTracker/taskTrackerSceneLogic.ts 5 40
products/posthog_ai/frontend/scenes/TaskTracker/components/TaskComposer.tsx 4 37
products/posthog_ai/frontend/components/composer/ComposerModelEffortPickers.tsx 3 60
products/posthog_ai/frontend/logics/runInteractionLogic.ts 2 11
products/posthog_ai/frontend/scenes/TaskTracker/components/TaskRunComposer.tsx 2 34

This check does not block merging. It updates on every push and clears when the share drops.

⚠️ Bundle size — 🔺 +12.6 KiB (+0.0%)

Uncompressed size of every built .js bundle, compared against the base branch.

Total: 69.23 MiB · 🔺 +12.6 KiB (+0.0%)

File Size Δ vs base
render-query/src/render-query/render-query.js 20.20 MiB 🔺 +7.1 KiB (+0.0%)
posthog-app/src/scenes/AuthenticatedShell.js 276.9 KiB 🔺 +4.4 KiB (+1.6%)

Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report

✅ Eager graph — within budget

How much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy import() / React.lazy chunks are not counted.

Root Eager (shipped) Δ vs base Budget
entry (logged-out pages, app bootstrap)
src/index.tsx
1.60 MiB · 22 files no change █████████░ 86.9% of 1.84 MiB
logged-out boot: index + App + bootApp (preloaded by every page, including /login)
src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
3.54 MiB · 629 files 🔺 +573 B (+0.0%) █████████░ 87.9% of 4.03 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
7.46 MiB · 2,395 files 🔺 +15.5 KiB (+0.2%) █████████░ 89.5% of 8.34 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/layout/navigation-3000/navigationLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/scenes/dashboard/dashboardLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/lemon-ui/LemonMarkdown/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/RichContentEditor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/CodeSnippet/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/taxonomy/core-filter-definitions-by-group.json stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx

Largest files eagerly shipped from src/index.tsx
Size File
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
24.6 KiB ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js
6.3 KiB ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js
4.5 KiB ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js
3.9 KiB ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js
1.4 KiB ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js
1.3 KiB src/index.tsx
1.3 KiB src/RootErrorBoundary.tsx
912 B ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js
854 B src/scenes/ChunkLoadErrorBoundary.tsx
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
Size File
301.8 KiB ../node_modules/.pnpm/posthog-js@1.434.14_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
216.9 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
100.5 KiB src/lib/api.ts
89.6 KiB src/products.tsx
69.4 KiB src/lib/lemon-ui/icons/icons.tsx
40.1 KiB src/lib/utils/eventUsageLogic.ts
38.7 KiB ../node_modules/.pnpm/@dnd-kit+core@6.0.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js
33.9 KiB ../node_modules/.pnpm/kea@4.0.0-pre.6_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js
28.5 KiB src/scenes/scenes.ts
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
301.8 KiB ../node_modules/.pnpm/posthog-js@1.434.14_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
279.7 KiB src/taxonomy/core-filter-definitions-by-group.json
216.9 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.7 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
102.8 KiB ../packages/quill/packages/quill/dist/index.js
100.5 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
90.6 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js
89.6 KiB src/products.tsx

Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479

✅ Toolbar bundle — eager 2.17 MiB within budget

What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.

Metric Size Δ vs base Budget
Eager (shipped)
entry + static imports
2.17 MiB · 19 files 🔺 +86 B (+0.0%) ████░░░░░░ 38.0% of 5.72 MiB
Deferred (lazy) 2.10 MiB · 44 files no change n/a — loads on demand
Loader dist/toolbar.js 1.2 KiB no change █░░░░░░░░░ 6.0% of 19.5 KiB
Largest eagerly-shipped chunks
Size File
813.3 KiB dist/toolbar/toolbar-app-BW77XXDE.css
651.9 KiB dist/toolbar/chunk-chunk-DJWLUZ3R.js
259.4 KiB dist/toolbar/chunk-chunk-4EKE7GSM.js
138.3 KiB dist/toolbar/chunk-chunk-QQ7R6XBZ.js
131.8 KiB dist/toolbar/chunk-chunk-FDH2IBXT.js
75.2 KiB dist/toolbar/toolbar-app-NPMWAVD2.js
69.0 KiB dist/toolbar/chunk-chunk-TSAL54PB.js
35.6 KiB dist/toolbar/chunk-chunk-YL3B42H2.js
21.0 KiB dist/toolbar/chunk-chunk-KGGZKL3I.js
6.8 KiB dist/toolbar/chunk-chunk-DV7IWQNF.js

Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile

✅ Dist folder size — 🔺 +367.4 KiB (+0.0%)

Total size of the built frontend/dist folder (all assets), compared against the base branch.

Total: 952.09 MiB · 🔺 +367.4 KiB (+0.0%)

✅ Playwright — all passed

All tests passed.

View test results →

@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a feature-flagged Codex subscription setting with account connection and disconnection flows. Adds billing controls for selecting PostHog credits or a ChatGPT plan. Task creation and run interaction logic resolve Codex model access, include it in run requests, and retain it in run state. Draft warming and warm reuse are adjusted for ChatGPT-plan runs. Adds tests, stories, and snapshot updates.

🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The description is complete and matches the required template. It clearly explains the problem, user-visible changes, feature-flag rollout, screenshots, test coverage, known test gaps, release status,…
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (2)
frontend/src/scenes/settings/user/CodexConnectModal.tsx-17-19 (1)

17-19: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Block modal dismissal while a connection is in flight.

The Cancel button is disabled while connecting is true. onClose still lets the user close the modal with Esc, an overlay click, or the X button. If the user closes the modal and the request then fails, connectError is set for a modal that is no longer visible, so the user never sees the error. Pass closable={!connecting}.

frontend/src/scenes/settings/user/personalCodexIntegrationLogic.ts-122-122 (1)

122-122: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Prevent focus loads from overwriting Codex mutations.

These three operations share codexIntegration, and the Codex loader functions do not use the repository’s cooperative cancellation pattern. A focus GET can therefore settle after a successful connect or disconnect and replace the UI with an older response.

The focus guard is necessary, but it is not sufficient. The connect button and modal submit can start a connect while a GET is already running. Guard those controls, and guard the disconnect confirmation callback or serialize all three operations at the logic boundary.

The impact is limited to stale UI state. The server-side mutation remains successful, and a later reload restores the correct state.

Suggested focus and connect guards
-    events(({ actions, cache }) => ({
+    events(({ actions, values, cache }) => ({
         afterMount: () => {
             actions.loadCodexIntegration()
             cache.disposables.add(
                 () => {
-                    const onFocus = (): void => actions.loadCodexIntegration()
+                    const onFocus = (): void => {
+                        if (!values.connecting && !values.codexIntegrationLoading) {
+                            actions.loadCodexIntegration()
+                        }
+                    }
                     window.addEventListener('focus', onFocus)
                     return () => window.removeEventListener('focus', onFocus)
                 },
-    const { codexIntegration, codexIntegrationLoadFailed, connecting } = useValues(personalCodexIntegrationLogic)
+    const { codexIntegration, codexIntegrationLoadFailed, codexIntegrationLoading, connecting } = useValues(
+        personalCodexIntegrationLogic
+    )
...
-                            disabledReason={connecting ? 'Connecting…' : undefined}
+                            disabledReason={connecting ? 'Connecting…' : codexIntegrationLoading ? 'Loading…' : undefined}

Apply the same codexIntegrationLoading guard to the modal submit and the disconnect confirmation callback.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: PostHog/posthog/.coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: d6fb1870-6bf0-4805-94d3-68674ede5ce8

📥 Commits

Reviewing files that changed from the base of the PR and between 1c66a26 and d9cd689.

📒 Files selected for processing (9)
  • frontend/src/lib/constants.tsx
  • frontend/src/scenes/settings/SettingsMap.tsx
  • frontend/src/scenes/settings/stories/SettingsUser.stories.tsx
  • frontend/src/scenes/settings/types.ts
  • frontend/src/scenes/settings/user/CodexConnectModal.tsx
  • frontend/src/scenes/settings/user/PersonalCodexIntegration.tsx
  • frontend/src/scenes/settings/user/codexAuthFile.test.ts
  • frontend/src/scenes/settings/user/codexAuthFile.ts
  • frontend/src/scenes/settings/user/personalCodexIntegrationLogic.ts

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 8 remain after this review.

@posthog

posthog Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

🕓 This approval covered an earlier revision. There are new visual changes to review in the newer comment below.

✅ Visual changes approved by @puemos — baseline updated in 4386abe.

View this run in PostHog

6 new.

Install the Visual Review Chrome extension to see visual review results at the top of your pull requests.

@trunk-io

trunk-io Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Static Badge   Static Badge   Static Badge

View Full Report ↗︎ ⋅ Docs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (2)
frontend/src/scenes/settings/user/personalCodexIntegrationLogic.ts-24-25 (1)

24-25: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Report clipboard-clear failures.

When clipboard writes are denied, writeText rejects. This helper discards the rejection, so the sign-in remains on the clipboard without a warning. The modal nevertheless promises that PostHog clears it. Clipboard write permission can fail independently of a keyboard paste. (w3.org)

Return an observable result. If clearing fails, tell the user to overwrite the clipboard manually. Change the privacy notice to describe the attempted cleanup rather than guarantee it.

Based on learnings: async clipboard helpers should not “silently catch and swallow errors internally.”

Source: Learnings

frontend/src/scenes/settings/user/CodexConnectModal.tsx-75-75 (1)

75-75: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Wrap the changing platform hint.

PLATFORM_HINTS[loginPlatform] changes beside a static text sibling. This is the text-node shape prohibited by the frontend translation guideline.

Wrap the changing hint in its own element. Keep the surrounding instructions translatable.

Proposed fix
-                        {PLATFORM_HINTS[loginPlatform]} Open the link that it shows, sign in, and enter the one-time
+                        <span>{PLATFORM_HINTS[loginPlatform]}</span> Open the link that it shows, sign in, and enter the one-time

As per coding guidelines: “Don't leave a changing bare text node next to siblings.”

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: PostHog/posthog/.coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: 5ea444c3-62c2-457b-8c25-85f2919bb2c4

📥 Commits

Reviewing files that changed from the base of the PR and between 6806c2e and d359376.

📒 Files selected for processing (6)
  • frontend/src/scenes/settings/user/CodexConnectModal.tsx
  • frontend/src/scenes/settings/user/codexAuthFile.test.ts
  • frontend/src/scenes/settings/user/codexAuthFile.ts
  • frontend/src/scenes/settings/user/codexLoginCommands.test.ts
  • frontend/src/scenes/settings/user/codexLoginCommands.ts
  • frontend/src/scenes/settings/user/personalCodexIntegrationLogic.ts

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 9 remain after this review.

Comment thread frontend/src/scenes/settings/user/personalCodexIntegrationLogic.ts Outdated
@puemos puemos changed the title feat(settings): connect codex as a personal integration on web feat(codex): connect a chatgpt plan on web and bill codex runs to it Sep 30, 2026
@puemos
puemos marked this pull request as ready for review September 30, 2026 14:22
@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested a review from a team September 30, 2026 14:23
@puemos
puemos force-pushed the posthog/codex-personal-integration branch from 190e19e to 90ed2f3 Compare September 30, 2026 14:33
@github-actions
github-actions Bot requested a deployment to preview-pr-108909 September 30, 2026 14:34 In progress
@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

🦔 Hogbox preview · ✅ ready

▶ Open the preview

🔑 Login test@posthog.com / 12345678 (demo data)
🧩 Running this PR's backend and frontend, on the PostHog :master base
🔗 Link stable across rebuilds — a re-push swaps the box underneath, the URL stays
🔒 Access tailnet only (PostHog VPN)
🛠️ Admin inspect & debug state in hogland
💤 Idle sleeps after ~30 min idle (snapshot to S3, zero node cost) and wakes on your next visit in ~30s, behind a brief "waking up" screen

commit f427526 · box box-d517fc324706 · ready in 998s (push → usable) · build log · rebuilds on every push, torn down on close

puemos commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

puemos commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai review

@puemos puemos added the reviewhog ($$$) Reviews pull requests before humans do label Sep 30, 2026 — with PostHog
@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Pull request base or head changed.

@posthog

posthog Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

🦔 PostHog Review reviewed this pull request

Found 0 must fix, 4 should fix, 1 consider.

Published 5 findings (view the review).

@greptile-apps

greptile-apps Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Retrigger

[Medium risk] Adds ChatGPT account connection for Codex billing.

The PR is not safe to merge until connecting from the composer selects the requested ChatGPT plan.

Reviews (1) · Last reviewed commit: "fix(settings): close codex connect races..."

Comment thread products/posthog_ai/frontend/logics/codexBillingLogic.ts Outdated
Comment thread frontend/src/scenes/settings/user/personalCodexIntegrationLogic.ts
@posthog

posthog Bot commented Sep 30, 2026

Copy link
Copy Markdown
Contributor

PostHog Review alpha 🦔 If you find any issues helpful - please reply "valid", "invalid", etc., for evaluation purposes 🙏

@posthog posthog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PostHog Review

Found 4 should fix, 1 consider.

Comment thread frontend/src/scenes/settings/user/CodexConnectModal.tsx
Comment thread frontend/src/scenes/settings/user/CodexConnectModal.tsx
Comment thread products/posthog_ai/frontend/logics/codexBillingLogic.ts Outdated
Comment thread frontend/src/scenes/settings/user/personalCodexIntegrationLogic.ts
@posthog posthog Bot removed the reviewhog ($$$) Reviews pull requests before humans do label Sep 30, 2026
@posthog

posthog Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

🕓 This approval covered an earlier revision. There are new visual changes to review in the newer comment below.

✅ Visual changes approved by @puemos — baseline updated in f61ba53.

View this run in PostHog

128 changed, 6 new, 6 removed.

Install the Visual Review Chrome extension to see visual review results at the top of your pull requests.

Users can connect the ChatGPT account for Codex cloud tasks from web settings, next to GitHub and Slack. They run codex login in their own terminal and paste auth.json. The row reads the same backend record as PostHog Desktop, so a Desktop connection shows up on web. Gated by posthog-code-codex-own-subscription-cloud.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: 59c79143-386a-4043-9109-6e3a2e4fa61f
puemos and others added 12 commits September 30, 2026 17:58
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: 59c79143-386a-4043-9109-6e3a2e4fa61f
The connect dialog now tells users to run codex login --device-auth, and to turn on device code login in ChatGPT first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: 59c79143-386a-4043-9109-6e3a2e4fa61f
The section description above the row already says the same thing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: 59c79143-386a-4043-9109-6e3a2e4fa61f
6 updated
Run: 65463936-b6cb-403c-bdb4-3eb9f126f932

Co-authored-by: puemos <13174025+puemos@users.noreply.github.com>
The inline logic types did not match what kea-typegen writes, so the frontend typecheck job failed its typegen diff check. Type the disconnect loader so typegen infers the same shape as the other loaders.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: 59c79143-386a-4043-9109-6e3a2e4fa61f
…n paste

The connect dialog now gives one command for macOS, Linux, or Windows, picked from the browser. The command signs in with a device code in a temporary CODEX_HOME, forces file credential storage, copies auth.json to the clipboard, and deletes the folder, also on Ctrl+C. The paste field never shows the sign-in, connects on paste, and clears the clipboard.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: 59c79143-386a-4043-9109-6e3a2e4fa61f
The web task composer's model menu gets a Billing row on the Codex harness: PostHog credits or the user's ChatGPT plan. The choice is kept per browser, the plan needs a connected ChatGPT account, and the menu can open the connect dialog in place. New tasks and resumed runs send codex_model_access, and a run on the plan pins the Codex model and skips warm reuse. Behind posthog-code-codex-own-subscription-cloud.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: 59c79143-386a-4043-9109-6e3a2e4fa61f
The Codex row leaves Personal integrations for a new Subscriptions section in the AI settings group, next to Model preferences, under the same flag. The Codex stories move to the environment settings stories.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: 59c79143-386a-4043-9109-6e3a2e4fa61f
A clipboard read that ends after the dialog closes no longer connects. A focus reload that ends after a connect or disconnect no longer overwrites it. The dialog cannot close while a connect is in flight, a failed clipboard clear shows a warning, and the platform hint is its own element for page translation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: 59c79143-386a-4043-9109-6e3a2e4fa61f
…mposer

Kea runs reducers before listeners, so connectCodexSuccess cleared the pending plan pick before the listener could read it, and billing stayed on PostHog credits. The pick is now cleared by the plan selection itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: 59c79143-386a-4043-9109-6e3a2e4fa61f
…e warms

A seeded task can submit before the billing picker mounts, so the new-task submit now reads the saved choice and the ChatGPT connection itself. A draft on the ChatGPT plan no longer boots a warm sandbox it can't use, and switching to the plan releases one. The connect dialog names the Codex CLI, drops an invalid paste, and ignores a second clipboard read while a connect runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: 59c79143-386a-4043-9109-6e3a2e4fa61f
134 updated, 6 removed
Run: 00913d73-94ab-47ff-b7ab-9ea9cbdd6d40

Co-authored-by: puemos <13174025+puemos@users.noreply.github.com>
@posthog

posthog Bot commented Sep 30, 2026

Copy link
Copy Markdown
Contributor

👋 Visual changes detected for this PR.

Review and approve in PostHog Visual Review

If these changes are unexpected, they may be caused by a flaky test or a broken snapshot on master. Don't approve — rerun the job or wait for a fix.

Install the Visual Review Chrome extension to see visual review results at the top of your pull requests.

puemos commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Deferred architecture/priority summary could not be published.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (1)
products/posthog_ai/frontend/scenes/TaskTracker/taskTrackerSceneLogic.ts-760-760 (1)

760-760: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Derive currentCodexModelAccess from the resolved access.

When a seeded task submits before the Codex billing picker mounts, usesChatGptPlan(composerAdapter) returns false because it reads only the mounted billing logic. codexModelAccessForRun can then resolve OwnSubscription from the saved preference and connected integration. The optimistic interaction starts with null, and the fallback preserves that value when the run state omits codex_model_access. The UI can therefore show “PostHog credits” for a run billed to the ChatGPT plan.

Resolve codexModelAccessForRun before constructing runInteractionLogic, or update the interaction after resolution.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: PostHog/posthog/.coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: ba9830f2-61a0-4a76-8855-e59bc248174a

📥 Commits

Reviewing files that changed from the base of the PR and between 59714f0 and 2706704.

📒 Files selected for processing (23)
  • frontend/snapshots.yml
  • frontend/src/lib/constants.tsx
  • frontend/src/scenes/settings/SettingsMap.tsx
  • frontend/src/scenes/settings/stories/SettingsEnvironment.stories.tsx
  • frontend/src/scenes/settings/types.ts
  • frontend/src/scenes/settings/user/CodexConnectModal.tsx
  • frontend/src/scenes/settings/user/PersonalCodexIntegration.tsx
  • frontend/src/scenes/settings/user/codexAuthFile.test.ts
  • frontend/src/scenes/settings/user/codexAuthFile.ts
  • frontend/src/scenes/settings/user/codexLoginCommands.test.ts
  • frontend/src/scenes/settings/user/codexLoginCommands.ts
  • frontend/src/scenes/settings/user/personalCodexIntegrationLogic.test.ts
  • frontend/src/scenes/settings/user/personalCodexIntegrationLogic.ts
  • products/posthog_ai/frontend/components/composer/ComposerCodexBillingPickers.tsx
  • products/posthog_ai/frontend/components/composer/ComposerModelEffortPickers.test.tsx
  • products/posthog_ai/frontend/components/composer/ComposerModelEffortPickers.tsx
  • products/posthog_ai/frontend/logics/codexBillingLogic.test.ts
  • products/posthog_ai/frontend/logics/codexBillingLogic.ts
  • products/posthog_ai/frontend/logics/runInteractionLogic.ts
  • products/posthog_ai/frontend/scenes/TaskTracker/components/TaskComposer.tsx
  • products/posthog_ai/frontend/scenes/TaskTracker/components/TaskRunChat.tsx
  • products/posthog_ai/frontend/scenes/TaskTracker/components/TaskRunComposer.tsx
  • products/posthog_ai/frontend/scenes/TaskTracker/taskTrackerSceneLogic.ts

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 6 remain after this review.

Comment thread products/posthog_ai/frontend/logics/runInteractionLogic.ts
…ion loads

A resume sent before the ChatGPT connection loaded stated PostHog credits and moved a plan run off the plan. With a saved plan and an unknown connection, the resume now leaves the field off so the run keeps its billing. A seeded task also shows the billing it resolved when the run state omits it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: 59c79143-386a-4043-9109-6e3a2e4fa61f

This branch was successfully deployed

1 active deployment
preview-pr-108909 — f4275261 Deployed Sep 30, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants