Fast, exact diffing for modern apps. Fully open source, built on Shiki, insanely customizable, and packed with the features you need. Made with love by The Pierre Computer Company.
Currently v0.5.0
Choose from stacked (unified) or split (side-by-side). Both use CSS Grid and Shadow DOM under the hood, meaning fewer DOM nodes and faster rendering.
11 unmodified lines12 ThemesType,13} from '../types';1415export function createSpanFromToken(token: ThemedToken) {16 const element = document.createElement('div');17 const style = getTokenStyleObject(token);18 element.style = stringifyTokenStyle(style);19 return element;20}2122export function createRow(line: number) {23 const row = document.createElement('div');24 row.dataset.line = `${line}`;2526 const lineColumn = document.createElement('div');27 lineColumn.dataset.columnNumber = '';28 lineColumn.textContent = `${line}`;2930 const content = document.createElement('div');31 content.dataset.columnContent = '';3233 row.appendChild(lineColumn);34 row.appendChild(content);35 return { row, content };36}3729 unmodified lines11 unmodified lines12 ThemesType,13} from '../types';1415export function createSpanFromToken(token: ThemedToken) {16 const element = document.createElement('span');17 const style = token.htmlStyle ?? getTokenStyleObject(token);18 element.style = stringifyTokenStyle(style);19 element.textContent = token.content;20 element.dataset.span = ''21 return element;22}2324export function createRow(line: number) {25 const row = document.createElement('div');26 row.dataset.line = `${line}`;2728 const content = document.createElement('div');29 content.dataset.columnContent = '';3031 row.appendChild(content);32 return { row, content };33}3429 unmodified lines
Precision Diffs are built with Shiki for syntax highlighting and general theming. Our components automatically adapt to blend in with your theme selection, including across color modes.
1import * as 'react';2import IconSprite from './IconSprite';3import Header from './Header';45export default function Home() {6 return (7 <div>8 <Header />9 <IconSprite />10 </div>11 );12}1import IconSprite from './IconSprite';2import HeaderSimple from '../components/HeaderSimple';3import Hero from '../components/Hero';45export default function Home() {6 return (7 <div>8 <HeaderSimple />9 <IconSprite />10 <h1>Hello!</h1>11 </div>12 );13}
Love the Pierre themes? Install our Pierre VS Code Theme pack with light and dark flavors.
Your diffs, your choice. Render changed lines with classic diff indicators (+/–), full-width background colors, or vertical bars. You can even highlight inline changes—character or word based—and toggle line wrapping, hide numbers, and more.
1const std = @import("std");2const Allocator = std.heap.page_allocator;3const ArrayList = std.ArrayList;45pub fn main() !void {6 const stdout = std.io.getStdOut().writer();7 try stdout.print("Hi You, {s}!\n", .{"World"});89 var list = ArrayList(i32).init(allocator);10 defer list.deinit();11}1const std = @import("std");2const GeneralPurposeAllocator = std.heap.GeneralPurposeAllocator;3const ArrayList = std.ArrayList;45pub fn main() !void {6 var gpa = GeneralPurposeAllocator(.{}){};7 defer _ = gpa.deinit();8 const allocator = gpa.allocator();910 const stdout = std.io.getStdOut().writer();11 try stdout.print("Hello There, {s}!\n", .{"Zig"});1213 var list = ArrayList(i32).init(allocator);14 defer list.deinit();15 try list.append(42);16}
Precision Diffs adapts to any font, font-size, line-height, and even font-feature-settings you may have set. Configure font options with your preferred CSS method globally or on a per-component basis.
1function greet(name) {2 return "Hello, " + name + "!";1function greet(name: string): string {2 return `Hello, ${name}!`;3}4
5const message = greet("World");5const message: string = greet("World");6console.log(message);7
8export { greet };Precision Diffs provide a flexible annotation framework for injecting additional content and context. Use it to render your own line comments, annotations from CI jobs, and other third-party content.
1import * as 'react';1import IconSprite from './IconSprite';3import Header from './Header';2import HeaderSimple from '../components/HeaderSimple';3import Hero from '../components/Hero';4
5export default function Home() {6 return (7 <div>8 <h1>9 Code Storage is a fully managed version control system built to meet the highest standards of speed, scale, and reliability.10 </h1>11 <Header />11 <HeaderSimple />12 <IconSprite /> 13 <h1>Hello!</h1>14 </div>15 );16}Good lord, I refuse to look at diffs ever again after this.
Wait, how long have we been working on this?
*checks notes*… it’s not been a short amount of time.
Annotations can also be used to build interactive code review interfaces similar to AI-assisted coding tools like Cursor. Use it to track the state of each change, inject custom UI like accept/reject buttons, and provide immediate visual feedback.
1import * as 'react';2import IconSprite from './IconSprite';3import Header from './Header';4
5export default function Home() {6 return (7 <div>8 {/* todo: add header and icon sprite */}8 <Header />9 <IconSprite /> 10 <ul>11 <li>Item 1</li>12 <li>Item 2</li>13 <li>Item 3</li>14 </ul>15 </div>16 );Turn on line selection with enableLineSelection: true. When enabled, clicking a line number will select that line. Click and drag to select multiple lines, or hold Shift and click to extend your selection. You can also control the selection programmatically.
1 unmodified line23interface ButtonProps {4 onClick: () => void;5 children: React.ReactNode;6 variant?: 'primary' | 'secondary';7 disabled?: boolean;8}910export function Button({11 onClick,12 children,13 variant = 'primary',14 disabled = false15}: ButtonProps) {16 const baseStyles = 'px-4 py-2 rounded-md font-medium';1718 const variantStyles = {19 primary: 'bg-blue-500 text-white hover:bg-blue-600',20 secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300'21 };2223 return (24 <button25 onClick={onClick}26 disabled={disabled}27 className={`${baseStyles} ${variantStyles[variant]}`}28 >29 {children}30 </button>31 );1 unmodified line23interface ButtonProps {4 onClick: () => void;5 children: React.ReactNode;6 variant?: 'primary' | 'secondary' | 'danger';7 disabled?: boolean;8 size?: 'small' | 'medium' | 'large';9}1011export function Button({12 onClick,13 children,14 variant = 'primary',15 disabled = false,16 size = 'medium'17}: ButtonProps) {18 const baseStyles = 'rounded-md font-medium transition-colors';1920 const sizeStyles = {21 small: 'px-3 py-1 text-sm',22 medium: 'px-4 py-2',23 large: 'px-6 py-3 text-lg'24 };2526 const variantStyles = {27 primary: 'bg-blue-500 text-white hover:bg-blue-600',28 secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',29 danger: 'bg-red-500 text-white hover:bg-red-600'30 };3132 return (33 <button34 onClick={onClick}35 disabled={disabled}36 className={`${baseStyles} ${sizeStyles[size]} ${variantStyles[variant]}`}37 >38 {children}39 </button>40 );
In addition to rendering standard Git diffs and patches, you can pass any two files in Precision Diffs and get a diff between them. This is especially useful when comparing across generative snapshots where linear history isn't always available. Edit the css below to see the diff.
1.pizza {2 display: flex;3 justify-content: center;3}Our team has decades of cumulative experience in open source, developer tools, and more. We’ve worked on projects like Coinbase, GitHub, Bootstrap, Twitter, Medium, and more. This stuff is our bread and butter, and we’re happy to share it with you.