How the Codex Plugin Collects Git Diff Context for Code Reviews

The Codex plugin gathers git diff context through the collectReviewContext function in plugins/codex/scripts/lib/git.mjs, which captures staged and unstaged changes, measures payload size against configurable limits, and returns either inline diff content or a lightweight summary depending on repository state.

The openai/codex-plugin-cc repository implements an intelligent diff collection system that determines what code changes to send to the LLM during automated reviews. This mechanism handles both clean repositories requiring branch comparisons and dirty working trees with local modifications, ensuring optimal token usage while preserving necessary context.

The Core Pipeline: collectReviewContext

The entry point for all diff collection is the collectReviewContext function exported from plugins/codex/scripts/lib/git.mjs (starting around line 300). This async function orchestrates the entire process of gathering repository state and preparing it for LLM consumption.

Resolving the Review Target

Before collecting diffs, the system must determine what to compare. The resolveReviewTarget function (lines 146-179 in git.mjs) analyzes the repository state to decide between two strategies:

  • Branch diff: Used when the working tree is clean (no staged or unstaged changes), comparing the current branch against its merge base
  • Working-tree diff: Used when local modifications exist, capturing staged and unstaged changes against HEAD

This decision ensures that reviews always reflect relevant changes, whether examining committed feature branches or uncommitted local work.

Capturing Staged and Unstaged Changes

When handling dirty working trees, collectReviewContext executes specific git commands via the gitChecked helper to capture patch data:


# Staged changes

git diff --cached --binary --no-ext-diff --submodule=diff

# Unstaged changes  

git diff --binary --no-ext-diff --submodule=diff

These commands run sequentially in git.mjs lines 232-233, storing raw output strings in stagedDiff and unstagedDiff variables. The --binary flag ensures binary file changes are included, while --submodule=diff provides detailed submodule change information.

Size-Aware Context Delivery

The plugin implements intelligent payload management to prevent exceeding LLM context limits or wasting tokens on excessive diff data.

Measuring Payload Size

After collecting raw diff strings, the function calls measureCombinedGitOutputBytes (line 307) to calculate the total byte size of both staged and unstaged diffs. This value compares against maxInlineDiffBytes, which defaults to 128 KB (configurable via options).

The size check appears in lines 307-314:

const diffBytes = measureCombinedGitOutputBytes(stagedDiff, unstagedDiff);
if (diffBytes > maxInlineDiffBytes) {
  // Trigger fallback mode
}

Selecting the Input Mode

Based on size and file count thresholds, collectReviewContext returns one of two input modes:

  • inline-diff (line 342): Returns when total bytes are under maxInlineDiffBytes and changed files are below maxInlineFiles. The raw diff content travels directly to the LLM within the prompt.
  • self-collect (around line 297): A lightweight fallback where the LLM receives only a "Diff Stat" summary and instructions to inspect the diff independently. This mode activates when repositories contain large generated files or extensive refactoring.

The function also preserves untracked file contents for small adversarial reviews, as verified by test cases in tests/git.test.mjs (lines 101-112).

Integration with codex-companion.mjs

The review flow triggers from plugins/codex/scripts/codex-companion.mjs (line 409), which calls collectReviewContext after resolveReviewTarget determines the comparison strategy:

// From codex-companion.mjs
const target = await resolveReviewTarget(cwd);
const context = await collectReviewContext(cwd, target, {
  maxInlineDiffBytes: 128 * 1024,
  maxInlineFiles: 50
});

This separation of concerns allows the companion script to handle LLM interaction while git.mjs manages repository introspection.

Code Examples

Command Line Usage

Run a review from your repository root to trigger automatic diff collection:

cd /path/to/your/repo
codex review

Programmatic Usage

Import the core functions directly for custom tooling:

import { collectReviewContext, resolveReviewTarget } from "./plugins/codex/scripts/lib/git.mjs";

const cwd = process.cwd();
const target = await resolveReviewTarget(cwd);

const reviewContext = await collectReviewContext(cwd, target, {
  maxInlineDiffBytes: 256 * 1024,  // 256 KB limit
  maxInlineFiles: 100
});

console.log(reviewContext.inputMode); // "inline-diff" or "self-collect"

Returned Context Object

The function returns a structured object containing:

{
  "label": "working tree diff",
  "diffBytes": 84231,
  "inputMode": "inline-diff",
  "stagedDiff": "diff --git a/src/foo.js b/src/foo.js...",
  "unstagedDiff": "diff --git a/src/bar.js b/src/bar.js...",
  "summary": "Diff Stat\n src/foo.js | 12 ++++++------\n 1 file changed, 6 insertions(+), 6 deletions(-)"
}

Summary

  • collectReviewContext in plugins/codex/scripts/lib/git.mjs serves as the primary entry point for diff collection
  • The system uses git diff --cached and git diff with binary and submodule support to capture complete change data
  • Size thresholds (default 128 KB) determine whether the LLM receives inline diffs or lightweight summaries
  • resolveReviewTarget automatically selects between branch comparisons and working-tree reviews based on repository cleanliness
  • The codex-companion.mjs script orchestrates the full review flow, calling these utilities at line 409

Frequently Asked Questions

What git commands does the Codex plugin use to capture diffs?

The plugin executes git diff --cached --binary --no-ext-diff --submodule=diff for staged changes and git diff --binary --no-ext-diff --submodule=diff for unstaged changes. These commands run through the gitChecked helper in git.mjs to ensure binary files and submodule changes appear in the output.

How does the Codex plugin handle large diffs that exceed size limits?

When measureCombinedGitOutputBytes detects that staged and unstaged diffs exceed maxInlineDiffBytes (default 128 KB), the plugin switches to inputMode: "self-collect". In this mode, the LLM receives a concise diff stat summary rather than full patch content, prompting the model to examine the diff independently.

What is the difference between "inline-diff" and "self-collect" modes?

Inline-diff mode sends the complete git patch content directly to the LLM prompt when the payload is small enough. Self-collect mode transmits only file statistics and instructs the LLM to inspect the diff separately, used when changes exceed size thresholds or file count limits.

Where is the review context collection logic located in the codebase?

The core logic resides in plugins/codex/scripts/lib/git.mjs, specifically the collectReviewContext function starting at line 300. The orchestration layer that calls this function exists in plugins/codex/scripts/codex-companion.mjs at line 409, while test coverage appears in tests/git.test.mjs.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →