Local Code Review (lcr)

Local code review tool for AI-assisted development. Review uncommitted changes with a GitHub PR-like interface — inline comments, suggestions, questions — then approve (and commit in git, or simply approve in jj) or send feedback to AI for another round. Works with git and Jujutsu (jj) repositories.

Local Code Review demo

Why?

When developing with AI (vibe-coding), AI makes many changes at once. There’s no good way to review those changes and give structured feedback before committing. Diff tools show changes but don’t let you write comments. Chat interfaces take one comment at a time. This tool gives you the full PR review experience locally:

  • See diffs like a GitHub PR (unified or split view, syntax highlighted)
  • Write inline comments on any line — comments, suggestions, questions
  • Approve individual files to stage them for commit
  • Toggle between full diff and unstaged-only to focus on what still needs review
  • Submit a structured review with all your feedback at once
  • Send to AI — export review as JSON/Markdown, copy to clipboard, or send directly to Claude Code via built-in terminal
  • Outdated detection — comments are automatically flagged when the underlying code changes
  • Approve & commit when you’re satisfied (in jj repos, just approve — changes are autocommitted)

Install

npm install -g local-code-review

Requires Node.js 18+.

Nix / devenv

lcr is also installable as a Nix flake. It builds from source with pnpm run build and exposes bin/lcr as the lcr executable:

nix run git+https://git.kilimanjaro.io/local-code-review -- /path/to/repo

To add it to a devenv environment, add the source as an input in devenv.yaml:

inputs:
  local-code-review:
    url: git+https://git.kilimanjaro.io/local-code-review

and the package in devenv.nix:

{ inputs, pkgs, ... }:
{
  packages = [ inputs.local-code-review.packages.${pkgs.system}.default ];
}

lcr uses the git / jj binaries from your environment (they are not bundled into the package).

Quick Start

cd your-project
lcr

Opens a web UI at http://localhost:5678 showing all uncommitted changes.

Usage

Reviewing a project

Run from inside any git or jj repository:

lcr                    # Review current directory
lcr /path/to/project   # Review a different project

The repository type is auto-detected: if a .jj/ directory is present (and the jj CLI is available), the Jujutsu client is used; otherwise git is used. This works for colocated repos too.

Running multiple instances

Each instance needs its own port:

lcr                          # First project on default port 5678
PORT=5679 lcr /path/to/other # Second project on port 5679

Review flow

  1. Browse changed files in the sidebar
  2. Click the + button on any line to add a comment
  3. Choose comment type: comment, suggestion, or question
  4. Add comments across multiple files
  5. Approve individual files (checkbox in sidebar) — in git repos approved files are staged; in jj repos approval is tracked by the tool
  6. When done, click Review and choose:
    • Request Changes — sends your review to Claude Code for another iteration
    • Approve & Commit (git) / Approve (jj) — in git, opens the commit dialog; in jj, moves the main bookmark forward to the reviewed change (see Stacked changes below)

Diff scope

  • Uncommitted (default) — git: uncommitted changes vs HEAD; jj: changes in the working-copy commit @ vs its parent (jj diff -r @). If @ is a merge, jj diffs against the auto-merge of all parents.
  • Worktree — git: the full branch diff (all commits since the branch diverged from main/master/development, plus uncommitted changes); jj: the diff from the main bookmark to the change being viewed

Diff modes

  • Full Diff — shows all changes in the current scope (staged + unstaged, or full branch)
  • Needs Review — git: shows only unstaged changes; jj: shows only files that haven’t been approved yet

Export options

Click Export in the toolbar:

  • Send to Claude Code — sends review to Claude via the built-in terminal
  • Copy to Clipboard — paste into any AI chat
  • Export as JSON — saves .lcr-review.json in the project root
  • Export as Markdown — saves .lcr-review.md in the project root

Built-in terminal

The tool includes an embedded terminal that runs an interactive Claude session in your project directory. When you click “Request Changes” or “Send to Claude Code”, your review is sent directly to this terminal session. Claude can then make changes, and you can review the next round without leaving the tool.

The terminal uses a WebSocket connection on a separate port (main port + 1000 by default).

Outdated comments

When AI makes changes after you’ve submitted a review, comments on lines that changed are automatically marked as Outdated with a yellow badge. This happens whenever the diff is refreshed, so you can see which of your comments have already been addressed.

File approval

Click the checkbox next to any file in the sidebar to approve it. Approved files are: - git: staged (git add); jj: tracked as approved in memory (jj has no staging area) - Shown with a strikethrough in the sidebar - Excluded from the “Needs Review” diff mode

If an approved file is modified again, its approval status is reset.

Stacked changes (jj)

In jj repositories the sidebar shows a Changes panel below the file tree, listing every change that descends from the main bookmark (newest first). This supports a feature-by-feature session workflow:

  • The agent stacks changes on top of main (squashing as it goes); the panel tracks them and refreshes automatically as work lands.
  • Click a change to review only that change’s diff against its parents. Selecting is view-only — it does not move your working copy @, so the agent is never disrupted.
  • Click Approve to move the main bookmark forward to the change you are reviewing, marking the feature as accepted. The view then advances to the next change above it. main can only move forward.
  • At the end of the session, push the accepted work yourself, e.g. jj git push --bookmark main.

The local main bookmark is the source of truth (not trunk()/main@origin), so approvals are reflected immediately, even before you push.

Keyboard shortcuts

Key Action
j / k Navigate files
b Toggle sidebar
Cmd/Ctrl+Enter Submit comment / commit
Escape Cancel comment

Configuration

Environment variables

Variable Default Description
PORT 5678 HTTP server port
LCR_REPO_DIR Current directory Path to the git or jj repository to review
VITE_LCR_WS_PORT PORT + 1000 WebSocket port for the terminal (dev mode only)

Claude Code integration

The “Send to Claude Code” feature requires Claude Code CLI to be installed. The tool uses whatever model your Claude Code is configured with. To change the default model:

claude config set model claude-sonnet-4-6
# or
claude config set model claude-opus-4-6

Development

Setup

git clone <repo>
cd local-code-review
npm install
npm run dev

The dev server starts at http://localhost:5173 by default.

Testing with another project

Point LCR_REPO_DIR at a different git repository:

LCR_REPO_DIR=/path/to/your/project npm run dev

To run multiple dev instances simultaneously, each needs its own port and WebSocket port:

# Instance 1 (default ports: 5173 + WS on 6173)
LCR_REPO_DIR=/path/to/project-a npm run dev

# Instance 2 (custom ports: 5174 + WS on 6174)
LCR_REPO_DIR=/path/to/project-b VITE_LCR_WS_PORT=6174 npm run dev -- --port 5174

Building

npm run build

Test the production build locally:

node bin/lcr.js /path/to/project

Project structure

src/
  lib/
    components/    # Svelte UI components (DiffView, FileTree, Terminal, etc.)
    server/        # Server-side code (VCS abstraction, git/jj clients, review store, terminal)
    stores/        # Svelte stores (files, review, UI state)
    types/         # TypeScript interfaces
  routes/
    api/           # REST API endpoints (diff, comments, export, commit, etc.)
    +page.svelte   # Main page
bin/
  lcr.js           # CLI entry point

Notes

  • Jujutsu repos are auto-detected by the presence of a .jj/ directory and require the jj CLI on PATH. In jj repos there is no commit step: the working copy is autocommitted, so Approve moves the local main bookmark forward to the reviewed change (main@origin is left untouched)
  • Comments are stored in memory and reset when the server restarts
  • The .lcr-review.json and .lcr-review.md export files are created in the project root — add them to .gitignore if needed
  • Syntax highlighting is powered by Shiki (same engine as VS Code)
  • The terminal feature requires node-pty which needs a C++ compiler to build (usually available by default on macOS/Linux)

License

MIT