Skip to content

docs(delegate): explain why git --no-pager is required in PTY-based agent environments #1059

Description

@AllenMuu

Issue Type

Incorrect information

Document Location

  • skills/open-code-review-delegate/SKILL.md, Step 3: Get Diffs
  • plugins/open-code-review/skills/open-code-review-delegate/SKILL.md, Step 3: Get Diffs

Description

Step 3 currently instructs agents to run git diff or git show directly. In an Agent Bash environment that provides a pseudo-terminal (PTY), Git can detect stdout as interactive and launch its configured pager, usually less.

Because the agent has no interactive input channel, less waits indefinitely. If the host tool enforces a command timeout and terminates the process group with SIGKILL, the observed result is exit code 137.

This is not caused by diff size or stdout pipe buffering. Large diffs may make the issue appear more frequent because they exceed one screen, but the triggering conditions are:

  1. The command runs with a PTY.
  2. Git selects an interactive pager such as less.
  3. The pager receives no user input.
  4. The host eventually terminates the hung command.

A deterministic local reproduction uses script to allocate a PTY:

TERM=xterm GIT_PAGER=less script -q /dev/null \
  git diff HEAD -- path/to/changed-file

With a sufficiently long diff, the command starts less and does not exit until input is provided or the process is terminated.

The same command completes immediately when the pager is disabled:

TERM=xterm GIT_PAGER=less script -q /dev/null \
  git --no-pager diff HEAD -- path/to/changed-file

I also reproduced this in Codex by forcing the same PTY and pager conditions: git --no-pager diff completed with exit 0, while the default-pager command remained blocked for four seconds and then exited 137 when the timeout harness sent SIGKILL.

Suggested Change

Add the following subsection before the Step 3 command examples:

Pager and large-output behavior in Agent and CI environments

Always pass --no-pager when obtaining diffs or file content through Git:

git --no-pager diff <ref> -- <path>
git --no-pager show <commit> -- <path>

Some Agent Bash tools allocate a pseudo-terminal. Without --no-pager, Git may start an interactive pager such as less, which waits for input that the agent cannot provide. A host-side timeout can then terminate the command and report exit code 137.

This is a pager and PTY interaction, not a Git diff size limitation.

For a potentially large diff, --no-pager alone does not bound the amount of stdout captured by the host tool. Redirect the diff to a temporary file, then read that file in bounded chunks:

git --no-pager diff --stat <ref> -- <path>
diff_file=$(mktemp /tmp/ocr-diff.XXXXXX)
git --no-pager diff <ref> -- <path> > "$diff_file"
# Read "$diff_file" with a file-reading tool in bounded chunks.

This avoids both an interactive pager waiting for input and an Agent or CI runner buffering the entire diff in memory.

Update the existing examples accordingly:

git --no-pager diff <merge_base>..<to> -- <path>
git --no-pager show <commit> -- <path>
git --no-pager diff HEAD -- <path>

The recommendation is intentionally local to each command. Environment-level alternatives such as GIT_PAGER=cat or core.pager=cat can be overridden by user configuration, while git --no-pager is explicit and reliable. For large diffs, use file redirection instead of streaming the full content to the host tool.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions