Review the diff.
Redline it.
Hand it back to your agent.
nittle opens your local git diff in the browser like a pull request. Comment on exact lines, then hand the comments back to your coding agent as one structured prompt. No forge, no account, no hosted AI.
curl -fsSL https://nittle.dev/install | shWindows (PowerShell 7+):pwsh -c "irm https://nittle.dev/install.ps1 | iex"
- local-first
- durable review records
- MCP handoff
- macOS · Linux · Windows
export function resolveRef(ref: string) { const base = ref || "HEAD"; return runGit(["rev-parse", base]); const sha = runGit(["rev-parse", "--verify", base]); if (!sha) throw new NoSuchRef(base); return sha.trim();}From diff to approval, on your machine.
- inspectRender a live git comparison in the browser.
- commentAnchor notes to a line, a range, or a file.
- returnCompile the redline into agent-ready feedback.
- refreshRe-run the diff after the agent edits.
- resolveReply, reopen, and clear threads.
- approveSign off on a durable Review Record.
Read the code. Still.
Agents write code faster than you can read it in a terminal. nittle makes the read cheap enough to do every time.
Your name is on the commit.
When the change breaks in production, the bug is yours, whoever typed it. Read it before it merges.
Unread code is unknown code.
A diff you skip is code you can't explain later, and you need that picture of the system to decide what to refactor or delete.
Only you know what it's for.
An agent stops when the tests pass. Intent, naming, boundaries and what shouldn't exist at all still come from you.
Writing got cheap. Reading didn't.
An agent can produce a 600-line diff in minutes. Deciding whether it's right still takes a person reading it.
Watch a review happen.
Open a diff, redline the exact code, and send the feedback straight back to the agent that wrote it.
Keyboard-first
A line cursor with vim keys: j and k, ] and [ for hunks, c to comment. g/ searches every changed file.
Suggested changes
Ctrl+G in a comment drops in the lines to edit. The agent gets the original and suggested text as data.
Scorecard
gc bands size, tests, public API, dependencies and hotspots from fixed rules. No AI, same diff, same score.
Code navigation
gd, gh and gA go to definitions, hover docs and references, once a language server is installed for TypeScript, C#, Python, Go, Rust, Vue or Svelte.
Review any comparison
Working tree, staged changes, a branch, a commit range, or the whole codebase, rendered in your browser with a file tree and syntax highlighting, not scrolled past in the terminal. Unified or side-by-side, your choice.
nittle show reviews one commit with its message, author and hash above the files, pinned to the full hash so it reopens the same diff later.
$ nittle# working tree vs HEAD$ nittle staged# staged changes only$ nittle main# this branch vs main$ nittle v1.0..v1.1# a commit range$ nittle browse src/# the whole subtree$ nittle show# the last commit, message and author on top$ nittle --wait# block until you send feedback
Comment on the exact code
Click a line, or drag across line numbers for a range. Press c on the cursor line if you'd rather keep your hands on the keys. Tag a note nit, issue, question or praise, and press Ctrl+G to suggest the replacement lines. Every note is saved to a durable Review Record that survives restarts and re-runs, and an unsent draft comes back after a reload.
const res = await fetch(url, opts);No timeout here, so an agent hangs on a dead dev server.
Added an AbortController with a 10s timeout. Marked addressed; it's yours to resolve.
Close the loop with your agent
Return the whole redline as one prompt, each comment with its file, line and the code around it. Over the local MCP server, Claude Code, Codex or any MCP client fixes the code, replies inline, marks comments addressed and asks for a re-review. You refresh, check the work, and resolve the thread. Agents can't.
No MCP? nittle --wait blocks until you send feedback, then prints the prompt on stdout. Any agent that can run a shell command can drive it.
## Code Review — fix/fetch-timeout → main — 2026-10-29---### client/src/lib/api.ts — Line 88```86 | export async function getJson(url: string) {87 | const opts = { headers: JSON_HEADERS };> 88 | + const res = await fetch(url, opts);89 | return res.json();```No timeout here, so an agent hangs on a dead dev server.---### src/utils/git.ts — Line 43```41 | const base = ref || "HEAD";42 | const sha = runGit(["rev-parse", "--verify", base]);> 43 | + if (!sha) throw new NoSuchRef(base);44 | return sha.trim();45 | }```**[issue]** Throws on a fresh repo where HEAD has no commits. Guard the empty case first.---## Summary: 2 comment(s) across 2 file(s)
Triage before you read
A deterministic scorecard flags what deserves your attention: size, untested code, public API and dependency changes, hotspots, and risky leftovers. Files come in review order, grouped by project with dependencies first. Lockfiles and generated code collapse, and moved code is marked. Same diff, same score, no AI. C# is first-class. When the agent sends changes back, files it touched since your last round get a chip, and you can show only what's new.
How the scorecard works- mediumSize412 effective lines across 9 files
- mediumTestsOrders/OrderService.cs: code change with no matching test in this diff
- highPublic APIUsers/UserService.cs: removed public method `GetUser(int id)`
- mediumDependenciesApi/Api.csproj: changed dependency Serilog from 3.0.0 to 3.1.1
- lowHotspotsno frequently changed files
- lowFlagsno sensitive paths, leftovers, or oversized files
Install nittle
One self-contained binary. It embeds its own web client and needs no checkout, no Node, and no sidecar files. git on your PATH is the only prerequisite.
curl -fsSL https://nittle.dev/install | shpwsh -c "irm https://nittle.dev/install.ps1 | iex"- No forge, no database, no hosted AI service.
nittle updatechecks the SHA-256 and swaps the binary in place.- Review Records stay in
~/.nittleon your machine.
Throws on a fresh repo where HEAD has no commits. Guard the empty case first.