An agentic code reviewer for your local git repositories, with a Copilot that drives the UI in front of you.
Point it at a repo. It finds the pull requests (local branches, open GitHub PRs, uncommitted work), reviews each one through an eight-stage pipeline of deterministic analysis and typed LLM calls, anchors every finding to a line of the diff, and lets an agent do anything you can do in the app while you watch.
One continuous take, sped up: Copilot tours the jaseci repository, pins a hotspot chart, then switches to a demo repo, runs a full review live and lands on the critical finding. MP4 version.
- Highlights
- Quick start
- Tour
- How a review works
- How the Copilot works
- Four apps, one codebase
- Configuration
- Project layout
- Notes on the Jac toolchain
- License
- Reviews any local repo. Local branches ahead of base, open GitHub PRs via
gh, and your uncommitted worktree all show up as reviewable pull requests. - Eight-stage agentic pipeline. Ingest, deterministic risk triage, planning, parallel specialist reviewers with code-search tools, cross-file analysis, context investigation, adversarial verification, and synthesis. The verifier throws out false positives before you see them.
- Every finding lands on a line. Severity, category, confidence, the verifier's reasoning, a suggested change, and Resolve / Dismiss / Reply / Ask Copilot actions, inline in the diff.
- A Copilot that drives the UI. 29 tools: it navigates, opens pull requests, scrolls to code, runs reviews, posts and resolves comments, renders charts and Mermaid diagrams, and pins them to a board, all live on your screen. Publishing to GitHub always waits for your click.
- Repository analytics. Commit heatmap, weekly volume and churn, commit-type mix, hotspot scatter, contributors and ownership (with knowledge-silo warnings), a treemap of the codebase, and a temporal-coupling network.
- Spend you can see. Every review and Copilot turn is metered per stage from model telemetry, shown in the UI and the CLI, and capped by a budget.
- Web, desktop, mobile, and CLI. One codebase, four apps. The desktop app runs the whole thing on your computer or connects to a diffwalker server, your choice at launch. The mobile app is real React Native, and the same component is embedded live in the web app. The CLI can drive your open browser.
- Private per account. Every endpoint is authenticated, and each user's reviews, Copilot threads, board, and active repository live in their own graph.
You need Jac 0.38 (see jaclang.org for the installer), git, and a model API key. gh is optional; with it, open GitHub PRs appear in the queue.
git clone https://github.com/marsninja/diffwalker
cd diffwalker
./scripts/stage_compiler.sh # checks out the pinned jac in jaseci/, fetches its stubs
echo 'ANTHROPIC_API_KEY=sk-ant-...' > .env # gitignored; read at startup
jac install # npm + Python dependencies
DIFFWALKER_REPO=/path/to/any/git/repo jac run webdiffwalker builds with the jac compiler source pinned in the jaseci submodule (marsninja/jac, branch diffwalker-pin: upstream jac main plus any fixes found here that are still in review). jac.toml's [dev] jaclang_source = "jaseci/jac" makes every jac command in this directory use that source, and stage_compiler.sh prepares it: it checks the submodule out at the recorded pin and fetches the typeshed stubs the compiler needs (without them jac prints ignoring the dev compiler source and uses its bundled compiler). On the pinned source each command prints jac dev mode — using compiler source at .../jaseci/jac. scripts/refresh.sh moves the submodule to the newest pin. jac bugs, and errors or gaps in its guides and docs, are fixed upstream rather than worked around here (see AGENTS.md and DOGFOOD.md).
Open the printed App URL (usually http://localhost:8000), create an account, and you are looking at your repository. Switch repositories any time from the top bar, or ask Copilot to.
The screenshots below use a small payments service whose feat/refunds branch contains real bugs. Build it yourself:
docs/demo/make-demo-repo.sh ~/payments-demo
DIFFWALKER_REPO=~/payments-demo jac run web # then review the refunds branchStart a review from the queue, the pull request page, the phone, the CLI, or by asking Copilot. Each of the eight stages lights up as it finishes, with what it did; reviewer activity streams in below (drafts as they are found, files as they are reviewed, and the verifier's rejections with its reasons).
When it completes you get a verdict, a merge-risk gauge, the review's intent and summary, concerns, what was done well, suggested tests, and a per-file walkthrough, plus exactly what the review cost.
Findings sit under the line they are about, in a GitHub-style diff with old and new line numbers. Hover any line and press + to add your own comment.
The Findings tab gathers them with severity, category, and status filters. Copilot can set those filters too.
Ask in plain language. Copilot works through the same actions the buttons use, and every action is visible: chips for each tool call, the screen moving as it navigates, cards for anything it renders.
![]() |
![]() |
| "Review the refunds branch": Copilot starts the pipeline and the drafts stream in. | "Give me a quick tour": Copilot opens the analytics and renders a chart from real numbers. |
A turn can be stopped at any moment, long conversations are compacted rather than cut, and each turn has its own spending cap.
Everything is mined from git history and cached per HEAD. Copilot reads the same numbers through its tools, so its answers match the charts.
Charts, tables, and Mermaid diagrams that Copilot renders can be pinned. They persist next to the repository and survive restarts.
mobile/ is a real React Native app written with Jac's mobUI (View, Text, Pressable): sign in, inbox, review with the live pipeline and findings, insights, and its own Copilot, whose navigation moves the phone's tabs. It talks to the same server and the same graph, so resolving a finding on the phone updates the web review.
jac run desktop opens the web app's pages in a native window (the OS webview, no Electron). On first launch it asks how diffwalker should run:
![]() |
![]() |
- On this computer: the whole server runs inside the app, with its own Postgres under your user data directory, and reviews the repositories on this machine with your model key. It needs no network beyond the model provider. There is no account: you pick or start a named profile, like a save slot, and each profile keeps its own reviews, findings, board, and Copilot threads.
- Server: the app is a window onto a diffwalker server (
jac run webon a shared machine). You sign in there, and its reviews and findings are what you see.
The two modes keep separate data. Switch mode or profile from the bottom of the sidebar; switching mode relaunches the app. The server address is fixed when the app is built: DIFFWALKER_SERVER_URL=https://reviews.example.com jac build desktop (default http://127.0.0.1:8000). That server must allow the app's loopback origin.
The CLI runs the same engine in-process against any repository, with live stage progress, per-stage spend, and an exit code of 1 when changes are requested (useful in hooks and CI). With --live it runs on a server instead, and any browser you have open on that server follows along.
jac run cli -- repo # headline facts and 90-day stats
jac run cli -- prs # reviewable pull requests
jac run cli -- hotspots -n 10 # churn hotspots
jac run cli -- people # most active contributors
jac run cli -- review b-1a2b3c4d5e # full review, in-process
jac run cli -- ask "which files churn most, and why?"
jac run cli -- --server http://localhost:8001 login --user you --register
jac run cli -- --server http://localhost:8001 review --live b-1a2b3c4d5e
jac run cli -- --server http://localhost:8001 ask --live "open the riskiest PR"The app documents itself: animated diagrams of the architecture, the persistent graph and the walker that traverses it, the review pipeline, and one Copilot turn step by step, each paired with the real source that implements it, pulled live from the running server. The mobile app is embedded in a phone frame on the same page.
![]() |
![]() |
![]() |
![]() |
A review is a Review node with the pipeline's own graph under it:
core/review/engine.jac spawns the ReviewRun walker on a fresh Review. Its Review entry ability ingests, triages, and plans; its FileChange entry ability fans each file out to a flow worker; its Review exit ability, which fires after every file has been visited, does the rest. Each stage is committed as it finishes, so every open screen follows along.
- Ingest.
git diff base...head(or the worktree, orgh pr diff) is parsed intoFileDiff/Hunk/DiffLineobjects, including quoted and space-containing paths. GitHub PRs are fetched intorefs/diffwalker/pr/<n>so reviewers read the PR's actual code. - Triage. A deterministic 0–100 risk per file from size, the repository's history hotspots, sensitive paths, new branching, missing tests, and word-bounded patterns for secrets,
eval,shell=Trueand friends, plusCodeRefnodes for each file's callers, tests, and co-changing files. - Plan.
plan_review(...) -> ReviewPlan by llm()infers the change's intent and assigns lenses and priority per file. - Specialist lenses. Every reviewable file is reviewed: priority-1 files on their own, the rest batched, each in a
flowworker. A reviewer is anobjwhose fields are the prompt context and whose bound methods (read_file,search_code,file_history) are its tools. - Cross-file. One agent hunts for broken callers and API drift across the whole change.
- Investigate. For each flagged file an
Investigatewalker is spawned on itsFileChange, andvisit [here-->][?:CodeRef] by llm(select=(1, 3))lets the model choose which related code to read. Those excerpts become the verifier's evidence and are shown on each finding. - Verify. Drafts are anchored to commentable diff lines and deduplicated in code, then verified per file, in parallel, keyed by draft id.
- Synthesize. A typed
ReviewSummarywrites the prose. The verdict is recomputed from what survived: any high or critical finding meansrequest_changes.
Typed outputs re-ask the model on a malformed reply. Telemetry is billed per review and per stage (core/review/meter.jac) and capped by DIFFWALKER_REVIEW_BUDGET. Without model credentials the deterministic stages still run and produce a verdict.
core/agent/copilot.jac is a single by llm() function with 29 tools in four groups:
| Group | Tools |
|---|---|
| Drive the UI | navigate, open_pull_request, focus_file, filter_findings, show_insights, notify, switch_repository |
| Read the repository | list_pull_requests, pull_request_details, file_diff, read_file, search_code, blame, repo_overview, hotspot_report, contributor_report, ownership_report, coupling_report, activity_report |
| Change review state | review_pull_request, post_comment, update_finding, reply_to_finding, list_findings, export_review, publish_to_github |
| Render insights | render_chart, render_table, render_diagram (cards that pin to the board) |
- Writes go through
core/actions.jac, the same functions the buttons call, so Copilot can do anything you can. - Independent lookups run in parallel; tools that write are serialized.
- A turn stops when you press Stop or when it passes
DIFFWALKER_TURN_BUDGET. - UI events are tagged with the user and the browser or CLI session. Each user's live stream carries only their own events, which is how the terminal can drive the same user's browser.
- Publishing to GitHub asks for confirmation in the UI, and the
ghcall is deferred to commit so it can never run twice.
jac.toml declares four apps over a shared core/. There are no client and server folders: JSX lands in the browser bundle, subprocess and graph code stays on the server, and a client call such as await pr_detail(id) compiles to a typed RPC stub. Imports between modules are declared once in archwire.jac.
Put secrets in .env (gitignored) or the environment.
| Variable | Default | Purpose |
|---|---|---|
ANTHROPIC_API_KEY |
Credentials for the default model provider | |
BYLLM_DEFAULT_MODEL |
set in jac.toml ([byllm.model]) |
Any LiteLLM model id. Use the matching key (OPENAI_API_KEY, GEMINI_API_KEY, ...), or a local ollama/... model with no key |
DIFFWALKER_REPO |
the repo containing diffwalker | Default repository for new accounts |
DIFFWALKER_REVIEW_BUDGET |
2.0 |
Dollar cap per review |
DIFFWALKER_REVIEW_DEADLINE |
900 |
Seconds before a review is cut off |
DIFFWALKER_TURN_BUDGET |
0.75 |
Dollar cap per Copilot turn |
DIFFWALKER_URL |
http://localhost:8000 |
Server for CLI --live commands |
DIFFWALKER_SERVER_URL |
http://127.0.0.1:8000 |
Read by jac build desktop: the server the desktop app's server mode connects to |
DIFFWALKER_TOKEN / DIFFWALKER_PASSWORD |
Non-interactive CLI auth |
The server binds 127.0.0.1 and runs a single worker (the live event bus is in-process). diffwalker runs git and gh against paths you give it; it is meant for local use, not for exposure on a network.
| Path | Contents |
|---|---|
core/api.jac |
Every endpoint (authenticated, plus a public server_info), including the SSE streams |
core/actions.jac |
Graph mutations shared by endpoints and Copilot tools |
core/graph.jac |
Nodes, typed edges with sem strings, per-user lookups, and the CollectFindings walker |
core/review/ |
Risk triage, related-code context, reviewer agents, the walker pipeline, and the spend meter |
core/agent/copilot.jac |
The Copilot and its tools |
core/analytics.jac |
History mining: activity, hotspots, contributors, ownership, structure, coupling |
core/git/ |
git / gh access and the unified-diff parser |
core/live.jac |
Per-user event bus |
core/site/ |
Web UI: sign-in, shell, Copilot pane, pages, review workspace, hand-built SVG charts, diagrams |
core/native/ |
The mobUI phone app, shared by mobile/ and the web page that embeds it |
core/site/desktop/ |
The desktop app's mode and profile pickers, and the sidebar's switch |
web/desktop.jac |
The desktop app's entry, beside web/main.jac so both route from web/pages |
cli/ |
The command-line app |
docs/demo/make-demo-repo.sh |
Builds the demo repository used in the screenshots |
jaseci/ |
Submodule: the pinned jac compiler source (marsninja/jac, branch diffwalker-pin) |
scripts/ |
stage_compiler.sh (build with the pinned source), refresh.sh (move to the newest pin) |
Type-check every app with jac check (or jac check --app web, --app mobile, --app cli).
diffwalker targets Jac 0.38. Building it surfaced several issues, tracked in jaseci-labs/jac#10234. The workarounds below predate the rule to fix jac upstream instead; each is waiting for its upstream fix and will be removed when that fix lands in the pin (see DOGFOOD.md):
core/env.jacsetsJAC_DB_RO_UNITS=0, because the optimistic read-only unit tier would turn a post-commit()write in a long review into a replay of the whole endpoint.core/env.jacalso guards a byLLM lookup that can return a function record without its parameters (which would crash everyby llmcall that takes arguments) by falling back to the signature.flowevaluates its call lazily in the worker, so the engine parks each job under a fresh key and passes only the key.- The live bus is in-process (one worker) because a streaming request cannot yet observe other requests' commits.
MIT © 2026 Jason Mars





















