Skip to content

CodeDiff

CodeDiff shows a proposed change to one file the way a code review tool would: removed lines tinted red, added lines tinted green, under a header naming the file.

The plan author pastes ordinary git diff output for that file into the component, and the reader gets a unified diff with optional line numbers, change counts, and anchored notes. With the viewer script active, a pressed-state segmented control switches between unified and side-by-side views and remembers the choice for this exact plan revision. With scripts disabled, the complete unified view remains readable and no dormant control appears.

A unified diff with an annotation card beneath its line range and an accent spine on the covered linesA unified diff with an annotation card beneath its line range and an accent spine on the covered lines

Use CodeDiff whenever a plan proposes a concrete change to existing code, so the reviewer approves the exact lines rather than a prose description of them.

  • Code that is not a change - a plain fenced code block presents it without diff framing
  • Decisions that are architectural rather than line-level - prose or a diagram carries those better
  • Changes too large to read line by line - summarize them in prose and reserve CodeDiff for the risky excerpts
  • Show the exact edit an agent intends to make before it touches the file
  • Explain a risky or subtle change with annotations anchored to the specific lines they discuss
  • Make additions and removals scannable through line markers, gutters, and color
<CodeDiff file="src/cache.ts" showLineNumbers showLineCounts>
```diff
@@ -12 +12 @@
-const ttl = 30;
+const ttl = 60;
```
</CodeDiff>
Attribute Type Required Behavior
file string (non-empty) Yes Shown in the header with the directory muted and filename bold.
showLineNumbers bare boolean No Renders old/new line-number gutters computed from @@ hunk headers.
showLineCounts bare boolean No Shows the computed +added -removed summary in the header.

Attributes take the bare form (showLineNumbers, never showLineNumbers="true"). Any other attribute, an empty file, or showLineNumbers on a diff without @@ headers is a positional authoring error.

The component takes exactly one fenced ```diff code block, plus zero or more direct Annotation children, and nothing else.

The fenced diff block accepts:

  • One file’s unified git diff output, verbatim - the file preamble (diff --git, index, ---, +++, mode, rename, and copy lines) may appear before the first hunk
  • Headerless diffs of bare +/-/context lines, when line numbers are not requested
  • A blank line inside a hunk as empty context, even when an editor has stripped its leading space

Combined and multi-file diffs are not supported; use one CodeDiff per file.

Validation is strict, and a malformed line fails the render with both the document position and the fence-relative line number:

  • Each @@ header’s declared old and new line counts must match the hunk content
  • Hunk coordinates and the line-number ranges they produce cannot exceed 9007199254740991

Nest Annotation directly inside CodeDiff to anchor a markdown note to specific lines:

<Annotation lines="45-46" side="new">
Slug allocation must follow component rendering.
</Annotation>
Attribute Type Required Behavior
lines string Yes One canonical positive integer (N) or a strictly ascending inclusive range (N-M); zero and leading zeros are invalid.
side "old" | "new" No Which side of the diff the range addresses; defaults to new.

Every referenced line must exist on the chosen side, and annotations require @@ hunk headers. Annotation bodies accept prose, lists, inline formatting, and plain fenced code, but reject headings, footnotes, and typed components (each with a positional diagnostic). An Annotation anywhere other than a direct CodeDiff child is an unknown component. Annotation is a scoped child component; CodeSnippet reuses the concept with file-absolute line anchors.

An annotation renders as a prose card after the final line of its range, with a comment glyph, a Line N / Lines N-M badge, and role="note":

  • The card spans the component immediately after the last line in its range.
  • Covered lines carry the annotation accent as a left spine and a subtle wash blended over their add/remove tints, so ranges read at a glance.
  • Multiple annotations may target the same line or range and render in authored order.
  • Hovering an annotation or any of its anchored lines highlights both, so the pairing reads at a glance.
  • Long cards remain fully visible so no annotation detail is hidden.

Added and removed lines are tinted, carry +/- markers, and include visually hidden Added line: / Removed line: prefixes so the change kind survives without color.