[activity] CLI filter + viewable Codex sessions#226
Conversation
Adds a CLI <select> to the activity tab (URL-synced as ?cli=...) so the mixed Claude/Codex feed can be filtered. Fixes the Codex "session not found" by extending the existing session route to fall back to ~/.codex/sessions/<…>.jsonl on ENOENT and parsing every Codex record type into the same LogEntry shapes the Claude viewer already renders. Codex transcript discovery (findCodexTranscript) is now in a shared lib/codex-sessions.ts; resolve-permission-mode imports from there instead of duplicating the walk. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
….mdx Activity tab section now lists the CLI filter and notes that the session detail link resolves Codex transcripts in addition to Claude. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Warning Rate limit exceeded
To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (11)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 0/1 reviews remaining, refill in 16 minutes and 42 seconds.Comment |
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Promotes the version from 0.0.9-beta.3 to 0.0.9 stable. The ## 0.0.9 — 2026-04-28 changelog section is already up to date with the contents below; no CHANGELOG churn required. 0.0.9 contents: Features: - OpenAI Codex hook integration via `failproofai policies --install --cli codex` (or --cli claude codex for both); supports all six Codex hook events, PermissionRequest wired through policy-evaluator, per-CLI telemetry tagging, interactive arrow-key CLI selector when both agents detected (#220, #222, #223) - Activity dashboard CLI filter alongside event-type, policy, and session-id filters; Codex sessions in the activity feed are now clickable, with the existing log viewer rendering Codex transcripts via lib/codex-sessions.ts (#226) - Surface Slack community link in CLI banner and Reach Us menu (#225) - Show OpenAI Codex projects on the /projects page alongside Claude Code projects, with CLI badges per row and per session; /project/[name] is Codex-aware and the session viewer renders the CLI badge beside the Session Log header (#232) Fixes: - Trailing blank line after enabled-policies summary in install output (#224) - Resolve hook bin via $CLAUDE_PROJECT_DIR (was relative path) (#219) - Mintlify validation of Arabic built-in-policies docs - Mintlify parse error in docs/de/dashboard.mdx (#229) - block-read-outside-cwd false-deny on globs and -v host:/path (#230) - Decouple hook chain from clsx/tailwind via lib/format-date.ts (#231) Docs: - Bump built-in policy count from 32 to 39 in README and translations (#207) Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* feat: add GitHub Copilot CLI integration (beta) Mirrors the Codex rollout (#220 + #226 + #232) for GitHub Copilot CLI: hook install/handler/path-protection, activity dashboard CLI filter + session viewer fallback, /projects listing + per-project sessions. Hooks install in Copilot's "VS Code compatible" PascalCase mode so the existing handler, snake_case payload parser, and hookSpecificOutput output shape all work unchanged. User scope writes ~/.copilot/hooks/failproofai.json; project scope writes <cwd>/.github/hooks/failproofai.json with version:1 and bash+powershell +timeoutSec entries (verified against Copilot CLI 1.0.39). Dashboard parser was rewritten against the real events.jsonl schema inspected from a live install — dotted-path record types (session.start, user.message, assistant.message, tool.execution_start/ _complete, …) rather than the camelCase hook payload format the docs hinted at. Project listing reads cwd from each session's workspace.yaml (always present, even pre-interaction). Adds lib/cli-registry.ts as the single source of truth for per-CLI metadata (label, badge classes, dashboard providers); future CLIs land with one registry entry instead of touching badge/filter/merge code. Marked beta because Copilot's events.jsonl schema is not publicly documented; parser is best-effort and falls open on unknown record types. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: green CI + uninstall prompt heading CI build failed with Turbopack "Module not found: Can't resolve 'fs/promises'" because lib/cli-registry.ts declared lazy `getProjects` / `loadSessionLog` providers via dynamic imports of codex-projects / copilot-projects. Even though no caller used them yet, Turbopack traced the dynamic-import expressions through the client-bundled CliBadge / project-list / hooks-client consumers and pulled Node-only modules into the client graph. Drop the providers from cli-registry; it's now a pure metadata module (label + badgeClasses). lib/projects.ts and the session viewer page already have their own targeted dynamic imports. Also: remove cross-module import in lib/copilot-projects.ts (was importing `getCopilotSessionStateRoot` from copilot-sessions); inline the trivial path computation so the two trees stay independent (mirrors how lib/codex-projects.ts and lib/codex-sessions.ts are arranged). Bug fix surfaced in conversation: `failproofai policies --uninstall` prompt heading said "Install Hooks" / "Choose where to install:" even though the action was uninstall. Add an `action: "install" | "uninstall"` parameter to resolveTargetClis + promptCliTargetSelection so the heading reads "Remove Hooks" / "Choose where to remove from:" during uninstall, and the non-interactive single-CLI log line says "removing hooks from <CLI>" instead of "installing hooks for <CLI>". Threaded through both bin/failproofai.mjs call sites. Tests: 1158 unit + 227 e2e pass; tsc clean; lint clean; bun run build clean (Turbopack no longer errors). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: address CodeRabbit review on PR #236 Critical / major: - lib/cli-registry.ts: isKnownCli now uses Object.prototype.hasOwnProperty.call instead of `in` so inherited prototype keys ("toString", "constructor", "hasOwnProperty") don't validate as known CLIs. - lib/copilot-sessions.ts: getCopilotSessionDir + findCopilotTranscript / findCopilotWorkspace reject path-traversal sessionIds (`../foo`, `..`, `/abs/path`) by `path.resolve`-ing the candidate and asserting it stays under getCopilotSessionStateRoot(). - lib/copilot-projects.ts: track `hasTranscript` per session-state dir and filter workspace-only sessions out of metasToSessionFiles — /project/[cwd] no longer renders clickable rows that lead to "Session log file not found." Workspace-only sessions still surface the project itself on /projects. - lib/copilot-projects.ts + lib/projects.ts: switch fs/promises, os, path imports to the `node:` specifier form (mirrors lib/codex- sessions.ts and is what Turbopack expects). - __tests__/e2e/hooks/copilot-integration.e2e.test.ts: pass FAILPROOFAI_BINARY_OVERRIDE in the --scope local rejection test so it doesn't depend on a global failproofai install in PATH. - __tests__/lib/projects.test.ts: add Copilot-aggregation assertions — Claude+Copilot merge, Claude+Codex+Copilot merge, Copilot-only surfacing, and graceful fall-through when getCopilotProjects() rejects. Minor: - CHANGELOG.md: shorten Copilot Features + Fixes entries to the repo's one-line + (#236) format. - docs/dashboard.mdx: rewrite Activity-tab Session viewer wording so the badge explanation lists all three CLIs and the click-through description includes Copilot CLI. Tests: 1165 unit + 227 e2e pass; tsc + bun run build + lint clean. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore: cleanups from self-review on PR #236 Three minor, no-behavior-change tidies surfaced during /review: - lib/copilot-projects.ts: replace `open(path).stat().close()` with direct `stat(path)` from node:fs/promises in `statMtime`. Halves the FD pressure (was opening two handles per session-state dir for mtime alone) and removes the try/finally close dance. The codex-projects equivalent uses open() because it reuses the handle for readFirstLine; we don't, so the simpler form is cleaner. - lib/copilot-sessions.ts: rename `CopilotToolToolTelemetry` (typo) to `CopilotToolTelemetry`. - lib/copilot-sessions.ts: inline `getMs(date)` — the wrapper was just `date.getTime()` and added indirection at four call sites. 1165 unit + 227 e2e + tsc + bun run build all green. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: use current GitHub Copilot mark with light/dark variants The previous copilot.svg used an older SimpleIcons path with a hard-coded fill="#000000", which rendered invisibly on GitHub's dark README theme. Replaced with the current canonical githubcopilot.svg path from simple-icons/simple-icons, split into copilot-light.svg and copilot-dark.svg, and switched the README block to <picture> with prefers-color-scheme — same pattern as the OpenAI logo. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs: changelog entry for Copilot logo fix Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: address remaining CodeRabbit nits on PR #236 - project-list CLI filter onChange now validates via isKnownCli, mirroring the URL-read path on line 54-57. Defends against <option> values drifting out of sync with KNOWN_CLI_IDS. - resolve-permission-mode fallback comment broadened to cover the codex without-sessionId case in addition to copilot / unknown. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: address CodeRabbit follow-up review on PR #236 Four findings from the latest CodeRabbit pass: - lib/copilot-projects.ts: filter `hasTranscript` in getCopilotProjects and getCopilotSessionsByEncodedName so workspace-only sessions don't surface as /projects rows whose detail page would show an empty session list. Mirrors the filter already in metasToSessionFiles. - lib/copilot-sessions.ts: wrap readFile + parseCopilotLog in try/catch in getCopilotSessionLog. findCopilotTranscript only proves existence at lookup time; the file can be removed/rotated before the async readFile lands. Preserve the nullable contract instead of throwing into the session page. - lib/codex-projects.ts: switch fs/promises, os, path imports to the node:-prefixed form for Turbopack resolver consistency. Other per-CLI modules already use this form. - __tests__/e2e/hooks/copilot-integration.e2e.test.ts: build the JWT-shaped fixture string at runtime via base64url Buffer encodes instead of embedding a contiguous JWT literal in source. Avoids tripping secret scanners (and this repo's own sanitize-jwt detector) on test code. Each segment is 10+ base64url chars so it still matches JWT_RE in builtin-policies.ts. Tests: existing copilot-projects tests that previously asserted workspace-only sessions surface as /projects rows are updated to match the new behavior; new positive tests cover the filter and the read-race path. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore: silence one Turbopack NFT warning in next.config.ts Replace `readFileSync(join(__dirname, "package.json"))` with a static JSON import. Turbopack's Node File Tracer was flagging the runtime filesystem call as a "could touch the whole project" operation, producing one of two "Encountered unexpected file in NFT list" warnings on `bun run build`. Static `import pkg from "./package.json"` resolves at compile time so NFT no longer treats the config as dynamic. This drops the build warning count from 2 → 1; the remaining warning is a Turbopack quirk where `next.config.ts` shows up transitively in the NFT trace from server components and doesn't have a clean user-code fix. `bun run dev` is unaffected and starts clean. tsconfig already has `resolveJsonModule: true` so the static import type-checks without changes. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat: dogfood Copilot hooks via .github/hooks/failproofai.json Mirror the existing .claude/settings.json and .codex/hooks.json contributor configs by shipping a project-scope Copilot hooks file so devs working on this repo with the GitHub Copilot CLI get failproofai hooks active automatically — no `policies --install` step required. The file lives at .github/hooks/failproofai.json (Copilot's project-scope path; .copilot/ is the user-scope path) and uses Copilot's "VS Code compatible" form: `version: 1`, PascalCase event names, and `bash` + `powershell` + `timeoutSec` per entry. All six COPILOT_HOOK_EVENT_TYPES are wired (SessionStart, SessionEnd, UserPromptSubmit, PreToolUse, PostToolUse, Stop) to `bun bin/failproofai.mjs --hook <Event> --cli copilot`. Path is relative since Copilot — like Codex — spawns hooks with the project root as cwd and exposes no $COPILOT_PROJECT_DIR equivalent. CLAUDE.md gains a `### Copilot hooks` subsection documenting the path choice, the relative-vs-absolute caveat, and the recommended production-user install command. CHANGELOG's existing Unreleased Copilot Features bullet is extended to call out the dogfood config. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Mirrors the Codex (#220, #226, #232) and Copilot (#236) rollouts for Cursor Agent CLI. Hook install/uninstall, handler canonicalization, policy-evaluator output adapter, path-protection, activity dashboard filter + per-CLI badge, /projects merge, and session viewer fallback. Cursor's hook protocol differs from Claude/Codex/Copilot: - camelCase event keys (preToolUse, beforeSubmitPrompt, …) — handler canonicalizes via CURSOR_EVENT_MAP before policy lookup. - Flat array of hook entries per event (no Claude-style {hooks: [...]} matcher wrapper); writeHookEntries / removeHooksFromFile / hooksInstalledInSettings all walk the flat structure directly. - Stdout decision shape is {permission, user_message, agent_message, additional_context, followup_message} (not hookSpecificOutput). policy-evaluator.ts now branches on session.cli === "cursor" for the deny / instruct / allow-with-info paths and emits the Cursor shape. - No documented permission-mode equivalent; resolve-permission-mode.ts falls into the existing "default" branch (same as Copilot). - Detected via cursor-agent (preferred) or agent (legacy alias). Settings paths: user → ~/.cursor/hooks.json project → <cwd>/.cursor/hooks.json Path-protection (isAgentInternalPath + isAgentSettingsFile) extended to cover ~/.cursor/ and .cursor/hooks.json so the agent can't disable its own hooks. Frontend: lib/cli-registry.ts adds a "Cursor Agent" entry with an emerald badge; lib/projects.ts merges cursor projects; the project page (app/project/[name]/page.tsx) and session viewer (app/project/[name]/session/[sessionId]/page.tsx) extend the external-CLI fallback chain. The activity feed (hooks-client.tsx) recognizes /.cursor/ transcript paths. Adds lib/cursor-projects.ts + lib/cursor-sessions.ts as scaffold parsers — Cursor's transcript layout is undocumented, so the modules probe candidate subdirs (agent-sessions/, conversations/, sessions/) and metadata files (meta.json/session.json/workspace.{json,yaml}) and gracefully return [] when the directory layout doesn't match. The parser handles dotted-path record types (session.start, user.message, …) and degrades to system entries for unknown types so nothing is silently dropped — same shape as the Copilot parser. Drops the .cursor/hooks.json file at the project root (mirrors the existing .codex/hooks.json and .github/hooks/failproofai.json) so contributors developing failproofai with Cursor get hooks active automatically. Adjusts .gitignore to track that single file while leaving the rest of .cursor/ ignored. Tests: 60 unit suites / 1228 tests pass; 9 e2e suites / 235 tests pass (including the new __tests__/e2e/hooks/cursor-integration.e2e.test.ts which covers PreToolUse deny + agent-settings guard + beforeSubmitPrompt allow + activity tagging + install/uninstall flows). Bumps version to 0.0.10-beta.1. Also fixes a pre-existing parity gap: the project detail page (app/project/[name]/page.tsx) only listed Claude + Codex sessions, missing Copilot (and now Cursor); it now merges all four sources. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* docs: note GitHub Copilot CLI testing is ongoing Update the README beta callout to clarify that GitHub Copilot CLI support is still under active testing. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * [luv-245] feat: add Cursor Agent CLI integration (beta) Mirrors the Codex (#220, #226, #232) and Copilot (#236) rollouts for Cursor Agent CLI. Hook install/uninstall, handler canonicalization, policy-evaluator output adapter, path-protection, activity dashboard filter + per-CLI badge, /projects merge, and session viewer fallback. Cursor's hook protocol differs from Claude/Codex/Copilot: - camelCase event keys (preToolUse, beforeSubmitPrompt, …) — handler canonicalizes via CURSOR_EVENT_MAP before policy lookup. - Flat array of hook entries per event (no Claude-style {hooks: [...]} matcher wrapper); writeHookEntries / removeHooksFromFile / hooksInstalledInSettings all walk the flat structure directly. - Stdout decision shape is {permission, user_message, agent_message, additional_context, followup_message} (not hookSpecificOutput). policy-evaluator.ts now branches on session.cli === "cursor" for the deny / instruct / allow-with-info paths and emits the Cursor shape. - No documented permission-mode equivalent; resolve-permission-mode.ts falls into the existing "default" branch (same as Copilot). - Detected via cursor-agent (preferred) or agent (legacy alias). Settings paths: user → ~/.cursor/hooks.json project → <cwd>/.cursor/hooks.json Path-protection (isAgentInternalPath + isAgentSettingsFile) extended to cover ~/.cursor/ and .cursor/hooks.json so the agent can't disable its own hooks. Frontend: lib/cli-registry.ts adds a "Cursor Agent" entry with an emerald badge; lib/projects.ts merges cursor projects; the project page (app/project/[name]/page.tsx) and session viewer (app/project/[name]/session/[sessionId]/page.tsx) extend the external-CLI fallback chain. The activity feed (hooks-client.tsx) recognizes /.cursor/ transcript paths. Adds lib/cursor-projects.ts + lib/cursor-sessions.ts as scaffold parsers — Cursor's transcript layout is undocumented, so the modules probe candidate subdirs (agent-sessions/, conversations/, sessions/) and metadata files (meta.json/session.json/workspace.{json,yaml}) and gracefully return [] when the directory layout doesn't match. The parser handles dotted-path record types (session.start, user.message, …) and degrades to system entries for unknown types so nothing is silently dropped — same shape as the Copilot parser. Drops the .cursor/hooks.json file at the project root (mirrors the existing .codex/hooks.json and .github/hooks/failproofai.json) so contributors developing failproofai with Cursor get hooks active automatically. Adjusts .gitignore to track that single file while leaving the rest of .cursor/ ignored. Tests: 60 unit suites / 1228 tests pass; 9 e2e suites / 235 tests pass (including the new __tests__/e2e/hooks/cursor-integration.e2e.test.ts which covers PreToolUse deny + agent-settings guard + beforeSubmitPrompt allow + activity tagging + install/uninstall flows). Bumps version to 0.0.10-beta.1. Also fixes a pre-existing parity gap: the project detail page (app/project/[name]/page.tsx) only listed Claude + Codex sessions, missing Copilot (and now Cursor); it now merges all four sources. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * [luv-245] fix: address CodeRabbit review feedback Five fixes from the bot review on PR #245: 1. .cursor/hooks.json: drop the `__failproofai_hook__` marker from the static dev config so the file matches Cursor's documented hook entry schema ({type, command, timeout}). The marker is still written by `cursor.buildHookEntry` for dynamically installed hooks; the legacy command-substring fallback in `isMarkedHook` identifies these static entries during uninstall. 2. CHANGELOG.md: fold the new Cursor entries into the existing Unreleased subsections (Features / Fixes / Docs) instead of creating a duplicate `### Features` heading. Resolves the MD024 markdownlint complaint. 3. lib/cursor-projects.ts: parse meta.json with `JSON.parse` first so escape sequences in JSON strings (Windows paths like `C:\\Users\\alice\\repo`) are decoded. Falls back to the YAML-ish regex only when the file isn't valid JSON. 4. lib/cursor-projects.ts: replace `findFirstExisting` (returns first existing path) with `findFirstUsableMeta` (returns first path whose parsed cwd is non-empty). Stops a stale `meta.json` from shadowing a valid `workspace.yaml` and dropping the session. 5. lib/cursor-sessions.ts: validate `data.content` / `data.text` with `typeof === "string"` before treating them as text in the user.message and assistant.message branches. Avoids surfacing non-string values via the `as string` casts. All 1228 unit + 235 e2e tests still pass. Lint clean (one pre-existing unrelated `<img>` warning). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…n top of each other (#587) * fix(dashboard): give log-viewer rows a stable unique key Rows in the virtualized session log were keyed `entry.uuid || entry.timestamp`. `baseEntry` leaves `uuid` as "" for every CLI that writes no per-record uuid (Codex, Copilot, Cursor, Pi), so the key degraded to the timestamp — which those CLIs reuse freely: one 771-record Codex session carries 93 timestamps shared by 2-5 records each. Duplicate React keys break reconciliation, and in a virtualized list the fallout is worse than a warning: orphaned DOM nodes are stranded at their old transform and never removed, so an unrelated message paints over the one you are reading and scrolling away and back does not clear it. Reproduced against a real Codex transcript — after one segment collapse, data-index 2 had two nodes and data-index 3 had three, one of them a message from 58 minutes later drawn across the two beneath it. Entries now take their identity from `buildEntryKeys` (lib/entry-keys.ts), which prefers the real uuid and disambiguates collisions by occurrence order. The same map is threaded into `getSegmentId` — queue-operation dividers are uuid-less even on Claude, so two sharing a millisecond collapsed into one segment — and into the virtualizer as `getItemKey`, which was absent entirely: TanStack defaults to keying its size and element caches by index, so collapsing a segment shifted every index and replayed one entry's cached height onto a different entry, misplacing rows independently of the key bug. The nested subagent list carried the same duplicate key. `buildEntryKeys` lives in its own dependency-free module rather than in log-entries.ts on purpose: that module reaches fs/promises through its project-resolution imports, so a *value* import of it from a client component pulls node:fs into the browser bundle and 500s the session page. Client code may only import types from there. Also fixes the Policies filter placeholder, which rendered the literal text `…` — a JSX attribute string is not a JS string literal, so the escape was painted verbatim beside a sibling input that had it right. Latent since before the open-source release but unreachable until #226 routed Codex transcripts into the Claude viewer. Known gap left open: EntryRow still anchors on entry.uuid, so #entry-… deep links stay inert for uuid-less transcripts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: fill in PR number in changelog entries Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(deps): pin brace-expansion to 5.0.7 to clear GHSA-3jxr-9vmj-r5cp The advisory published after main's last green scan, so every branch went red at once with no dependency change of its own — re-running main's last Supply Chain scan on its unchanged commit reproduced the failure. Both affected copies were transitive: 5.0.6 via minimatch@10, and three copies of 1.1.15 via the minimatch@3 that eslint-plugin-import, -jsx-a11y and -react still pull. `bun update brace-expansion` is the wrong tool: it adds the package as a direct dependency and lifts only the top-level copy, leaving the nested 5.0.6 and all three 1.1.15 copies vulnerable. Bun also ignores npm's range-keyed (`brace-expansion@^1.1.7`) and yarn's nested-path (`parent/child/pkg`) override forms — resolving nothing, silently — so the two majors cannot be pinned separately. Only the plain-key `overrides` form takes effect, as the existing postcss/vite/undici pins show. A single pin therefore also hands v5 to minimatch@3, which declares ^1.1.7. That is safe in practice: the package's entire surface is one `expand()` function whose signature is unchanged across these majors, and eslint exercises that path directly — lint runs clean with the same five pre-existing warnings. Verified with CI's own scanner image (ghcr.io/google/osv-scanner-action:v2.3.8) against the updated lockfile: "No issues found", exit 0. osv-scanner.toml keeps its zero ignored vulnerabilities. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
Claude Code/OpenAI Codex/All) to the/policies?tab=activitydashboard, URL-synced as?cli=claude|codex.~/.codex/sessions/<YYYY>/<MM>/<DD>/<…>.jsonlwhen the Claude lookup misses.lib/codex-sessions.ts) that maps every record type (session_meta,turn_context,response_itemmessage/function_call/function_call_output,event_msgtask_started/exec_command_end) into the existingLogEntryshapes, so the rich Claude log viewer renders Codex transcripts unchanged. Tool calls are paired withexec_command_endresults bycall_idfor stdout/stderr + duration.findCodexTranscriptSyncout ofsrc/hooks/resolve-permission-mode.tsinto the sharedlib/codex-sessions.tsso both the hook hot path and the dashboard reuse the same discovery (cache → today/yesterday → full tree scan)./project/<encoded-cwd>/session/<sid>; the[name]segment is purely a breadcrumb since the page auto-detects CLI by file location.Test plan
bun run test:run— 1078/1078 unit tests pass (includes new test for the integration filter and 11 new tests in__tests__/lib/codex-sessions.test.ts).bun run test:e2e— 217/217 pass.bun run lint && bun run build— clean (only the pre-existing<img>warning intool-input-output.tsx)./policies?tab=activityand confirm the new CLI<select>renders (All CLIs / Claude Code / OpenAI Codex).019dd672-68c9-7a30-8671-6242ee286af6from~/.codex/sessions/...— the page renders user prompts, assistant messages, andexec_commandtool calls with stdout/stderr + durations (no "session not found")./project/-home-nivedit-claudeye-evals/session/<sid>) still renders the existing Claude view including the Download Logs button.__tests__/hooks/handler.test.ts(29 tests) still passes after thefindCodexTranscriptrefactor.🤖 Generated with Claude Code