Skip to content

Add open-in-editor feature with Cmd+O shortcut#2

Merged
t3dotgg merged 5 commits intomainfrom
juliusmarminge/open-in-editor
Feb 9, 2026
Merged

Add open-in-editor feature with Cmd+O shortcut#2
t3dotgg merged 5 commits intomainfrom
juliusmarminge/open-in-editor

Conversation

@juliusmarminge
Copy link
Copy Markdown
Member

@juliusmarminge juliusmarminge commented Feb 9, 2026

CleanShot 2026-02-08 at 20 49 41@2x

Summary

Add a header dropdown to open the workspace in Cursor or the system file manager (Finder on macOS, Explorer on Windows, Files on Linux). Includes a global Cmd+O / Ctrl+O keyboard shortcut that opens in the last-used editor, with persistence via localStorage.

Changes

  • Add IPC channel shell:open-in-editor in contracts
  • Main process handler that spawns editor CLI or uses shell.openPath() for cross-platform file manager support
  • Header dropdown with editor options between status indicator and Diff button
  • Global keyboard shortcut listener for Cmd+O / Ctrl+O
  • Last-used editor tracked in localStorage with intelligent platform-aware naming (Finder/Explorer/Files)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added an "Open in…" dropdown in the top bar to open the active project in a chosen editor or the file manager.
    • Added Cmd/Ctrl+O shortcut to open the project with your last-selected editor; selection is persisted across sessions.
    • Editor menu closes on outside clicks and after choosing an editor.
  • Platform Integration

    • Desktop app now launches external editors or the file manager to open project folders.

Add dropdown in header to open workspace in Cursor or system file manager (Finder/Explorer/Files). Include Cmd+O/Ctrl+O global keyboard shortcut to open in last-used editor, persisted to localStorage.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 9, 2026

Walkthrough

Adds an "open in editor" feature: new EDITORS and EditorId types, IPC_CHANNELS.shellOpenInEditor plus main-process handler, nativeApi.shell.openInEditor in preload, and renderer UI/shortcut to invoke and persist the chosen editor.

Changes

Cohort / File(s) Summary
Main / IPC handler
apps/desktop/src/main.ts
Imports shell and EDITORS; registers IPC_CHANNELS.shellOpenInEditor handler that looks up editor by id, throws on unknown, uses shell.openPath(cwd) for file-manager or spawn (detached, stdio ignored) and unref() for editor commands.
Preload / Renderer bridge
apps/desktop/src/preload.ts
Adds nativeApi.shell.openInEditor(cwd: string, editor: EditorId) which invokes IPC_CHANNELS.shellOpenInEditor via ipcRenderer.invoke.
Renderer UI
apps/renderer/src/components/ChatView.tsx
Adds editor dropdown, isEditorMenuOpen and lastEditor state with localStorage persistence, outside-click handling, Cmd/Ctrl+O shortcut to open last editor, and calls api.shell.openInEditor.
Contracts / Types
packages/contracts/src/ipc.ts
Exports new EDITORS array and EditorId type, adds IPC_CHANNELS.shellOpenInEditor, and extends NativeApi with shell.openInEditor(cwd: string, editor: EditorId): Promise<void>.
Manifests / Package
manifest_file, package.json
Small manifest/package updates referenced by diff (lines changed +25/-1 and +4/-0 respectively).

Sequence Diagram

sequenceDiagram
    actor User
    participant ChatView as Renderer (ChatView.tsx)
    participant Preload as Preload (preload.ts)
    participant Main as Main Process (main.ts)
    participant OS as Operating System Shell

    User->>ChatView: Click "Open in…" or press Cmd/Ctrl+O
    ChatView->>ChatView: openInEditor(editorId) and persist lastEditor
    ChatView->>Preload: invoke 'shell:open-in-editor' (cwd, editorId)
    Preload->>Main: Forward IPC invoke
    Main->>Main: Lookup editor in EDITORS
    alt editor == 'file-manager'
        Main->>OS: shell.openPath(cwd)
    else editor has command
        Main->>OS: spawn(editorCommand, [cwd], {detached, stdio:'ignore'}) and unref()
    end
    OS-->>Main: process/path opened
    Main-->>Preload: resolve Promise<void>
    Preload-->>ChatView: invoke resolves
    ChatView->>ChatView: close editor menu
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main feature added: an open-in-editor capability triggered by a Cmd+O keyboard shortcut, which is the primary change across all modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch juliusmarminge/open-in-editor

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
apps/renderer/src/components/ChatView.tsx (3)

36-40: navigator.platform is deprecated but acceptable here.

While navigator.platform is technically deprecated in favor of navigator.userAgentData, it remains well-supported in Electron's renderer process. This is a reasonable choice for platform detection in this context.


203-220: Consider extracting click-outside logic to a reusable hook.

This pattern is duplicated with the model menu handler (lines 184-201). A useOnClickOutside(ref, callback) hook would reduce duplication.

♻️ Example hook extraction
function useOnClickOutside(
  ref: React.RefObject<HTMLElement>,
  handler: () => void,
  enabled: boolean,
) {
  useEffect(() => {
    if (!enabled) return;
    const handleClickOutside = (event: MouseEvent) => {
      if (
        ref.current &&
        event.target instanceof Node &&
        !ref.current.contains(event.target)
      ) {
        handler();
      }
    };
    window.addEventListener("mousedown", handleClickOutside);
    return () => window.removeEventListener("mousedown", handleClickOutside);
  }, [ref, handler, enabled]);
}

Then use:

useOnClickOutside(editorMenuRef, () => setIsEditorMenuOpen(false), isEditorMenuOpen);
useOnClickOutside(modelMenuRef, () => setIsModelMenuOpen(false), isModelMenuOpen);

378-410: Add aria attributes for accessibility.

The dropdown trigger is missing aria-expanded and aria-haspopup attributes that improve screen reader experience.

♿ Suggested accessibility improvement
               <button
                 type="button"
                 className="rounded-md px-2 py-1 text-[10px] text-[`#a0a0a0`]/40 transition-colors duration-150 hover:text-[`#a0a0a0`]/60"
                 onClick={() => setIsEditorMenuOpen((v) => !v)}
+                aria-expanded={isEditorMenuOpen}
+                aria-haspopup="menu"
               >
                 Open in&hellip;
               </button>

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

@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp bot commented Feb 9, 2026

Add Cmd+O/Ctrl+O open-in-editor action in chat view and handle IPC_CHANNELS.shellOpenInEditor in main process

Implement window.nativeApi.shell.openInEditor and a main-process IPC_CHANNELS.shellOpenInEditor handler that opens the active project's cwd in a selected editor from EDITORS, plus add an 'Open in…' menu and Cmd+O/Ctrl+O shortcut in the chat view.

📍Where to Start

Start with the IPC handler in registerIpcHandlers in main.ts, then review the preload API in preload.ts, and the UI wiring in ChatView.tsx.


📊 Macroscope summarized ff34d2c. 98 files reviewed, 10 issues evaluated, 8 issues filtered, 0 comments posted. View details

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@apps/desktop/src/main.ts`:
- Around line 143-145: The CI formatter flagged the EDITOR_COMMANDS block — run
the project formatter (e.g., run the formatter or execute `bun run lint`) to
reformat the object literal; specifically ensure the EDITOR_COMMANDS constant
and its entry for "cursor" follow the project's formatting rules (spacing,
trailing commas, and indentation) so the object shape Record<string, { command:
string; args: (cwd: string) => string[] }> and the cursor entry { command:
"cursor", args: (p) => [p] } are formatted exactly as the linter expects.
- Around line 135-153: The IPC handler for ipcMain.handle should validate cwd is
non-empty, await shell.openPath(cwd) and check its returned string for an error
(log/throw when non-empty) instead of assuming success, and protect the spawn
path by wrapping the spawn call in try/catch and attaching an 'error' listener
to the returned child (e.g., child.on('error', ...) to log/throw when the CLI
cannot be spawned); reference EDITOR_COMMANDS and entry (from editor) to locate
the spawn logic, and ensure you handle and surface errors for both
shell.openPath and spawn so the handler doesn't crash or fail silently.

In `@apps/renderer/src/components/ChatView.tsx`:
- Around line 66-69: Validate the value read from localStorage under
LAST_EDITOR_KEY against the known EDITORS list before using it as the initial
state for lastEditor; replace the current initializer (() =>
localStorage.getItem(LAST_EDITOR_KEY) ?? EDITORS[0].id) with logic that reads
localStorage, checks EDITORS.some(e => e.id === stored), and falls back to
EDITORS[0].id when the stored id is missing or not found; also ensure any places
that write to lastEditor (setLastEditor) persist only validated ids to
localStorage.
- Around line 183-191: The keydown handler currently calls e.preventDefault()
unconditionally for Cmd/Ctrl+O even when the action won't run; update the
handler in the useEffect (function handler used for the KeyboardEvent) to only
call e.preventDefault() when api and activeProject are truthy and you are about
to call api.shell.openInEditor(activeProject.cwd, lastEditor), i.e. move or
guard preventDefault() behind the same condition that checks api and
activeProject so the key event is not swallowed when no activeProject exists.

Comment on lines +135 to +153
// Shell handlers
ipcMain.handle(
IPC_CHANNELS.shellOpenInEditor,
async (_event, cwd: string, editor: string) => {
if (editor === "file-manager") {
await shell.openPath(cwd);
return;
}
const EDITOR_COMMANDS: Record<string, { command: string; args: (cwd: string) => string[] }> = {
cursor: { command: "cursor", args: (p) => [p] },
};
const entry = EDITOR_COMMANDS[editor];
if (!entry) throw new Error(`Unknown editor: ${editor}`);
const child = spawn(entry.command, entry.args(cwd), {
detached: true,
stdio: "ignore",
});
child.unref();
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n apps/desktop/src/main.ts | sed -n '135,153p'

Repository: pingdotgg/codething-mvp

Length of output: 848


🌐 Web query:

Electron shell.openPath() return value error handling

💡 Result:

shell.openPath(path) returns a Promise<string> that resolves (not rejects) to:

  • "" (empty string) on success
  • a non-empty error message string on failure (electronjs.org)

So error handling is typically:

import { shell } from "electron";

async function openFile(p: string) {
  try {
    const err = await shell.openPath(p);
    if (err) {
      // open failed; Electron returns an error message string
      console.error("openPath failed:", err);
      // show UI / log / fallback here
    }
  } catch (e) {
    // for unexpected exceptions (e.g., bad argument types, other runtime issues)
    console.error("openPath threw:", e);
  }
}

Key point: check the resolved string—don’t rely only on catch. (electronjs.org)

Citations:


🌐 Web query:

Node.js child_process spawn error event handling

💡 Result:

In Node.js, child_process.spawn() can fail asynchronously, so you should always attach an 'error' handler to the returned ChildProcess:

  • 'error' event is emitted when the process could not be spawned (e.g., ENOENT, EACCES), could not be killed, or IPC send failed. The 'exit' event may or may not fire after an 'error', so don’t rely on 'exit' alone. [1]
  • 'close' event fires after the process ends and all stdio streams are closed; it will emit after 'exit', or after 'error' if the child failed to spawn. [2]

A common safe pattern is to funnel both 'error' and 'close' into a single “done once” handler:

import { spawn } from 'node:child_process';

function spawnChecked(cmd, args, opts) {
  const child = spawn(cmd, args, opts);

  let settled = false;
  const done = (err, result) => {
    if (settled) return;
    settled = true;
    if (err) throw err;              // or reject a Promise / call cb(err)
    return result;
  };

  child.once('error', (err) => done(err));                  // spawn/kill/IPC failure
  child.once('close', (code, signal) => {                   // stdio fully closed
    if (code === 0) return done(null, { code, signal });
    done(Object.assign(new Error(`exit ${code ?? 'null'} (${signal ?? 'no-signal'})`), { code, signal }));
  });

  return child;
}

Sources: Node.js ChildProcess event docs for 'error' and 'close'. [1] [2]

References
[1] Node.js docs — ChildProcess event: 'error' (nodejs.org)
[2] Node.js v22 docs — ChildProcess event: 'close' (nodejs.org)

Citations:


Add error handling for shell.openPath() and spawn() to prevent crashes and silent failures.
shell.openPath() returns a Promise that resolves to an error string (not thrown), and spawn() emits an 'error' event asynchronously when the process cannot be spawned (e.g., missing CLI). Without handling these, the IPC handler silently fails or crashes. Also guard against empty cwd.

🛠️ Suggested fix
-    async (_event, cwd: string, editor: string) => {
-      if (editor === "file-manager") {
-        await shell.openPath(cwd);
-        return;
-      }
+    async (_event, cwd: string, editor: string) => {
+      if (!cwd) {
+        throw new Error("cwd is required");
+      }
+      if (editor === "file-manager") {
+        const error = await shell.openPath(cwd);
+        if (error) {
+          throw new Error(error);
+        }
+        return;
+      }
       const EDITOR_COMMANDS: Record<string, { command: string; args: (cwd: string) => string[] }> = {
         cursor: { command: "cursor", args: (p) => [p] },
       };
       const entry = EDITOR_COMMANDS[editor];
       if (!entry) throw new Error(`Unknown editor: ${editor}`);
-      const child = spawn(entry.command, entry.args(cwd), {
-        detached: true,
-        stdio: "ignore",
-      });
-      child.unref();
+      await new Promise<void>((resolve, reject) => {
+        const child = spawn(entry.command, entry.args(cwd), {
+          detached: true,
+          stdio: "ignore",
+        });
+        child.once("error", reject);
+        child.once("spawn", () => {
+          child.unref();
+          resolve();
+        });
+      });
     },
   );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Shell handlers
ipcMain.handle(
IPC_CHANNELS.shellOpenInEditor,
async (_event, cwd: string, editor: string) => {
if (editor === "file-manager") {
await shell.openPath(cwd);
return;
}
const EDITOR_COMMANDS: Record<string, { command: string; args: (cwd: string) => string[] }> = {
cursor: { command: "cursor", args: (p) => [p] },
};
const entry = EDITOR_COMMANDS[editor];
if (!entry) throw new Error(`Unknown editor: ${editor}`);
const child = spawn(entry.command, entry.args(cwd), {
detached: true,
stdio: "ignore",
});
child.unref();
},
// Shell handlers
ipcMain.handle(
IPC_CHANNELS.shellOpenInEditor,
async (_event, cwd: string, editor: string) => {
if (!cwd) {
throw new Error("cwd is required");
}
if (editor === "file-manager") {
const error = await shell.openPath(cwd);
if (error) {
throw new Error(error);
}
return;
}
const EDITOR_COMMANDS: Record<string, { command: string; args: (cwd: string) => string[] }> = {
cursor: { command: "cursor", args: (p) => [p] },
};
const entry = EDITOR_COMMANDS[editor];
if (!entry) throw new Error(`Unknown editor: ${editor}`);
await new Promise<void>((resolve, reject) => {
const child = spawn(entry.command, entry.args(cwd), {
detached: true,
stdio: "ignore",
});
child.once("error", reject);
child.once("spawn", () => {
child.unref();
resolve();
});
});
},
);
🤖 Prompt for AI Agents
In `@apps/desktop/src/main.ts` around lines 135 - 153, The IPC handler for
ipcMain.handle should validate cwd is non-empty, await shell.openPath(cwd) and
check its returned string for an error (log/throw when non-empty) instead of
assuming success, and protect the spawn path by wrapping the spawn call in
try/catch and attaching an 'error' listener to the returned child (e.g.,
child.on('error', ...) to log/throw when the CLI cannot be spawned); reference
EDITOR_COMMANDS and entry (from editor) to locate the spawn logic, and ensure
you handle and surface errors for both shell.openPath and spawn so the handler
doesn't crash or fail silently.

Comment on lines +66 to +69
const [isEditorMenuOpen, setIsEditorMenuOpen] = useState(false);
const [lastEditor, setLastEditor] = useState(
() => localStorage.getItem(LAST_EDITOR_KEY) ?? EDITORS[0].id,
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Guard against stale lastEditor values in localStorage.
If localStorage contains an unknown editor id (older versions, manual edits), the IPC handler will throw. Prefer validating against EDITORS and falling back.

🧩 Suggested fix
-  const [lastEditor, setLastEditor] = useState(
-    () => localStorage.getItem(LAST_EDITOR_KEY) ?? EDITORS[0].id,
-  );
+  const [lastEditor, setLastEditor] = useState(() => {
+    const stored = localStorage.getItem(LAST_EDITOR_KEY);
+    return EDITORS.some((editor) => editor.id === stored)
+      ? stored
+      : EDITORS[0].id;
+  });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const [isEditorMenuOpen, setIsEditorMenuOpen] = useState(false);
const [lastEditor, setLastEditor] = useState(
() => localStorage.getItem(LAST_EDITOR_KEY) ?? EDITORS[0].id,
);
const [isEditorMenuOpen, setIsEditorMenuOpen] = useState(false);
const [lastEditor, setLastEditor] = useState(() => {
const stored = localStorage.getItem(LAST_EDITOR_KEY);
return EDITORS.some((editor) => editor.id === stored)
? stored
: EDITORS[0].id;
});
🤖 Prompt for AI Agents
In `@apps/renderer/src/components/ChatView.tsx` around lines 66 - 69, Validate the
value read from localStorage under LAST_EDITOR_KEY against the known EDITORS
list before using it as the initial state for lastEditor; replace the current
initializer (() => localStorage.getItem(LAST_EDITOR_KEY) ?? EDITORS[0].id) with
logic that reads localStorage, checks EDITORS.some(e => e.id === stored), and
falls back to EDITORS[0].id when the stored id is missing or not found; also
ensure any places that write to lastEditor (setLastEditor) persist only
validated ids to localStorage.

@juliusmarminge
Copy link
Copy Markdown
Member Author

@cursor fix ci pls

@cursor
Copy link
Copy Markdown
Contributor

cursor bot commented Feb 9, 2026

All done. Here's what I fixed:

apps/desktop/src/main.ts - IPC handler hardening:

  • Added cwd validation (throw if empty)
  • Check shell.openPath() return value and throw on error (it resolves to an error string, not rejects)
  • Added child.on('error', ...) listener on the spawned process to prevent crashes if the editor CLI is missing

apps/renderer/src/components/ChatView.tsx - Review feedback:

  • Validate localStorage value against the known EDITORS list before using as initial state, falling back to EDITORS[0].id for stale/unknown values
  • Moved e.preventDefault() inside the api && activeProject guard so Cmd/Ctrl+O isn't swallowed when no active project exists

Lint passes cleanly across all three packages. Changes pushed to juliusmarminge/open-in-editor.

Open in Cursor Open in Web

juliusmarminge and others added 4 commits February 8, 2026 21:15
EDITORS config and EditorId type now live in @acme/contracts so the
shell.openInEditor IPC channel is strictly typed end-to-end. The main
process uses the contract's command field (null = file manager via
shell.openPath).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Validate cwd is non-empty in shell:open-in-editor IPC handler
- Check shell.openPath() return value and throw on error
- Attach spawn error listener to prevent crashes from missing CLI
- Validate localStorage lastEditor against known EDITORS list
- Only call preventDefault() for Cmd+O when action will run

Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
Keep open-in-editor dropdown, accept main's removal of status indicator
from header.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@t3dotgg t3dotgg merged commit eef57db into main Feb 9, 2026
3 checks passed
@Xenoifyteam Xenoifyteam mentioned this pull request Mar 7, 2026
@kimkhoi2202 kimkhoi2202 mentioned this pull request Mar 7, 2026
jjalangtry pushed a commit to jjalangtry/t3code that referenced this pull request Mar 16, 2026
* Add open-in-editor feature with Cmd+O shortcut

Add dropdown in header to open workspace in Cursor or system file manager (Finder/Explorer/Files). Include Cmd+O/Ctrl+O global keyboard shortcut to open in last-used editor, persisted to localStorage.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* Move editor definitions to contracts for strict IPC typing

EDITORS config and EditorId type now live in @acme/contracts so the
shell.openInEditor IPC channel is strictly typed end-to-end. The main
process uses the contract's command field (null = file manager via
shell.openPath).

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

* Fix biome formatting issues

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

* fix: add error handling and address review feedback

- Validate cwd is non-empty in shell:open-in-editor IPC handler
- Check shell.openPath() return value and throw on error
- Attach spawn error listener to prevent crashes from missing CLI
- Validate localStorage lastEditor against known EDITORS list
- Only call preventDefault() for Cmd+O when action will run

Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
hameltomor added a commit to hameltomor/t3code that referenced this pull request Mar 19, 2026
Add file attachments and inline projector
MacGyver-Assistant pushed a commit to MacGyver-Assistant/t3code that referenced this pull request Mar 22, 2026
- Store: index files by cwd+relativePath to avoid cross-worktree
  collisions; never overwrite dirty buffer on refetch/reopen
- EditorPanel: reorder render branches so error state is tested
  before empty state (was unreachable)
- A11y: separate tab activation (div[role=tab]) from close button
  (proper button element) — no nested interactive elements
- Extract shared RightPanelInlineSidebar, RightPanelSheet, and
  shouldAcceptPanelWidth into RightPanelPrimitives.tsx so PR pingdotgg#2
  (Browser panel) only needs to add a config block
praveenperera pushed a commit to praveenperera/t3code that referenced this pull request Mar 23, 2026
Add thread header tabs and persistent thread notes
BarretoDiego added a commit to BarretoDiego/t3code that referenced this pull request Mar 28, 2026
- Add CODEX_INTEGRATION_ANALYSIS.md with detailed protocol flow analysis
  * Protocol flow architecture and high-level overview
  * Request-response JSON-RPC sequence diagrams
  * Event streaming and transformation pipeline
  * Session state machine and lifecycle events
  * Provider dispatch routing analysis
  * 5 critical improvements ranked by priority
  * Failure scenarios and recovery analysis
  * Testing and deployment recommendations

- Add CODEX_IMPROVEMENTS_GUIDE.md with step-by-step implementation guide
  * Improvement pingdotgg#1: Method-specific timeout configuration
  * Improvement pingdotgg#2: Partial stream recovery buffer
  * Improvement pingdotgg#3: Circuit breaker pattern implementation
  * Improvement pingdotgg#4: Graceful shutdown with timeout
  * Improvement pingdotgg#5: Structured observability logging
  * Integration checklist and testing procedures
  * 5-week rollout strategy

Architecture grade: B+ (strong foundation, operational concerns remain)
Expected impact: 10x reduction in false timeouts, 99.9% → 99.99% availability

These guides provide actionable recommendations for improving connection
robustness, timeout strategies, error recovery, and observability in the
Codex App Server integration.
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.

3 participants