# How the Codex Plugin Collects Git Diff Context for Code Reviews

> Discover how the Codex plugin collects git diff context for code reviews. Learn about its `collectReviewContext` function and how it optimizes payload size for efficient reviews.

- Repository: [OpenAI/codex-plugin-cc](https://github.com/openai/codex-plugin-cc)
- Tags: how-to-guide
- Published: 2026-07-12

---

**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:

```bash

# 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:

```javascript
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:

```javascript
// 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:

```bash
cd /path/to/your/repo
codex review

```

### Programmatic Usage

Import the core functions directly for custom tooling:

```javascript
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:

```json
{
  "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`.