必须先安装并登录一个受支持的 LLM CLI,否则无法生成讲解;首次运行需在交互中选择语言和 LLM;生成一次讲解需 2 到 5 分钟,且 Gemini、Copilot、Pi 支持仍属实验性。
diff-tour
init-co-jpMIT活跃维护把 git diff 变成带讲解的引导式浏览,用只读 TUI 像资深工程师那样逐段读懂代码改动,适合新人上手和代码评审。
Walk through a diff the way a senior engineer reads it. A read-only TUI that turns a git change into a guided tour.
curl -fsSL https://raw.githubusercontent.com/init-co-jp/diff-tour/main/install.sh | sh
cd your-repo
tourREADME 未说明硬件要求;需已安装并登录 git 及 Claude Code、Codex CLI、Gemini CLI、OpenCode 2、Copilot CLI 或 Pi 之一。
把 git 变更变成资深工程师视角的引导式讲解,用方向键逐步走读 diff
把 git diff 变成带讲解的引导式浏览,用只读 TUI 像资深工程师那样逐段读懂代码改动,适合新人上手和代码评审。
核心能力
- 用 git archive/diff/log 导出变更,交给本地已登录的 LLM 写讲解
- 讲解 JSON 中的文件与行号会逐条校验,错误最多回修两次
- 屏幕代码直接从 git 对应提交读取,非仓库代码标注 Example
- 按资深工程师的读法组织:改动目的、风险点、该问的问题与结论
- 只读运行,不修改文件与仓库,无服务端、无遥测
容易踩的坑
- v0.6.1最新正式版2026-10-29 · 2026-10-29 07:12 UTC
The Russian screens now read the way a Russian speaker would say them.
What changed
- More natural Russian screens. The title of the change picker, the safety refusal, the welcome line on first run and the title of the step question are reworded. "More below" is now «▼ Ещё», so it no longer reads like «→ Далее» (next step). (#4) Thanks @Bosun18!
- More natural Russian example tour. The chapter titles and a few lines of the Russian example tour are reworded, and the weight of small findings is «Мелочь» instead of the untranslated «Nit». (#4)
The prompts did not change, so tours you saved with v0.6.0 open as they are.
Install or update
curl -fsSL https://raw.githubusercontent.com/init-co-jp/diff-tour/main/install.sh | sh - v0.6.02026-10-24 · 2026-10-24 08:11 UTC
查看更新说明
The screens and the tours now come in Russian, and
tourno longer hangs on Windows while reading the code.What changed
- Russian (
ru). The screens, the tours and the answers to your questions can now be in Russian. Anyru_*locale picks it, andtour --lang rupicks it for one run. The example tour is in Russian too. (#4) Thanks @Bosun18! - No more hang on Windows.
tourcould stop at "reading the code" on Windows and never go on. It now reads everything git sends while exporting the code, so git finishes. (#3) Thanks @qwer112358! - Long prompts with Claude Code on Windows. Claude Code now gets the prompt on stdin, as Codex, OpenCode and Copilot already did. On Windows, Claude Code installed with npm runs through
cmd.exe, which cut long prompts and failed with "The command line is too long". The read-only flags passed to Claude Code did not change. (#3)
The prompts for the other languages did not change, so tours you saved with v0.5.0 open as they are.
Install or update
curl -fsSL https://raw.githubusercontent.com/init-co-jp/diff-tour/main/install.sh | sh - Russian (
- v0.5.02026-10-15 · 2026-10-15 15:46 UTC
查看更新说明
The screens and the tours now come in Simplified Chinese, Traditional Chinese and Spanish, as well as English and Japanese.
What changed
- Simplified Chinese (
zh). Builds on the work in #1 by @shangjinyu012-gif. Thank you! - Traditional Chinese (
zh-Hant). Worded for readers in Taiwan (程式碼, 檔案, 資料表). Locales for Taiwan, Hong Kong and Macau pick it, and other Chinese locales pick Simplified Chinese. - Spanish (
es). Neutral Spanish, picked by anyes_*locale. - Choosing a language. The language is detected from your locale the first time you run
tour.tour setupchanges it, andtour --lang zh,--lang zh-Hantor--lang eschanges it for one run. The tours and the answers to your questions are written in the same language. - Example tours. The example tour is now in Simplified Chinese, Traditional Chinese and Spanish too.
- Requests as issues. We now take requests as issues and write the changes ourselves, instead of accepting pull requests. CONTRIBUTING.md explains why. If something in your language sounds unnatural, please open an issue.
Prompts for English and Japanese did not change, so tours you saved with v0.4.0 open as they are.
Install or update
curl -fsSL https://raw.githubusercontent.com/init-co-jp/diff-tour/main/install.sh | sh - Simplified Chinese (
- v0.4.02026-10-15 · 2026-10-15 13:12 UTC
查看更新说明
Tours can now be written with OpenCode 2 or GitHub Copilot CLI, as well as Claude Code, Codex CLI and Gemini CLI.
What changed
- OpenCode 2. Choose OpenCode in
tour setup.tourfindsopencode2, or anopencodethat is version 2 or later. It runs its own agent that can only read and search inside the export directory, and does not load your plugins, MCP servers, agents orAGENTS.md. Your model and provider settings are used as they are. A full tour was written with OpenCode 2.0.29 on Linux. (#2) - Copilot CLI (experimental). Choose Copilot CLI in
tour setup. The model gets only theview,grepandglobtools, and none of your Copilot hooks, plugins, extensions, MCP servers or custom instructions are loaded. The read-only setup was tested against the real Copilot CLI 1.0.98, but a full tour has not yet been written with a real Copilot model. If it fails, please open an issue.
The prompts did not change, so tours you saved with v0.3.0 open as they are.
Install or update
curl -fsSL https://raw.githubusercontent.com/init-co-jp/diff-tour/main/install.sh | sh - OpenCode 2. Choose OpenCode in
- v0.3.02026-10-11 · 2026-10-11 16:54 UTC
查看更新说明
You can now ask a tour about the step you are reading, and diagrams are drawn by the tool instead of the LLM.
What changed
- Ask about a step. Press ? to pick one of the questions the tour expects at that step, or type your own. The LLM answers from the same files the tour was written from, and the answer becomes the next step. For a tour that
tourgenerated, answers are saved with it. For a tour file you open, they last until you quit. - Diagrams drawn by the tool. The LLM describes a flow, a timeline or the map of changed files, and
tourdraws it. Shapes and colors stay the same from tour to tour, and changed and new parts stand out. Notes on code are attached to the line they talk about. - Easier to read on the screen. Long lines of code wrap instead of being cut off. Tables and code too wide for the right column move below at full width. Flows that start separately, such as a timer job next to a request, are kept apart.
- Judgments grounded in the repository. The LLM now gets the senior engineers' lessons as reference files. A finding is marked "must fix" only when the tour can show an input from this repository that breaks it, and code the repository controls is checked before a problem is blamed on an outside service. In blind reviews on changes the prompts were not tuned on, the average score went from 3.94 to 4.38 out of 5.
- New example tours and demo GIFs.
Tours you saved with v0.2.0 are written again the next time you open the same change, because the prompts changed. With Claude Code, one tour now uses the equivalent of about $1.10 to $1.50 at API prices, a little more than before, because the LLM reads the lessons too.
Install or update
curl -fsSL https://raw.githubusercontent.com/init-co-jp/diff-tour/main/install.sh | sh - Ask about a step. Press ? to pick one of the questions the tour expects at that step, or type your own. The LLM answers from the same files the tour was written from, and the answer becomes the next step. For a tour that
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
diff-tour
Walk through a diff the way a senior engineer reads it.
English | 日本語

A tour of a branch that adds coupons: what the change is for, how the usage limit is enforced, a question to think about, and the answer: applying a coupon twice to one order uses it up twice.
[!NOTE] diff-tour is growing fast. The tour format and the screens may still change from release to release.
Quick start
You need git and one of Claude Code, Codex CLI, Gemini CLI, OpenCode 2, Copilot CLI or Pi, signed in.
curl -fsSL https://raw.githubusercontent.com/init-co-jp/diff-tour/main/install.sh | sh
cd your-repo
tour
Then it goes like this:
- Setup (first time only): choose the display language and the LLM that writes the tour. Both have a recommended choice selected, so press Enter twice.
- Pick a change: the changes you can tour are listed, with your current branch selected. Press Enter.
- Writing: the LLM writes the tour. This takes 2 to 5 minutes.
- The tour: → goes forward, ← goes back, q quits.
If tour is not found, add the line the install script printed to your shell profile.
To see a finished tour first, with no LLM and no sign-in, play the one from the GIF. It opens at once:
git clone https://github.com/init-co-jp/diff-tour-example && cd diff-tour-example
curl -fsSLO https://raw.githubusercontent.com/init-co-jp/diff-tour/main/tours/example-coupons.en.json
tour example-coupons.en.json
Other ways to install are in Install, and an example repository to try is in First run.
What it is
AI can write code that works. It does not teach you why the code is written that way, or what a reviewer would worry about.
tour turns a git change into a guided tour you step through with two keys, → and ←. The tour shows what a senior engineer looks at when they read the change:
- How they read it. What the change is for, where to spend time, and which files to jump to next, including files that did not change.
- What they ask. Does it keep the promises the old code kept? What happens when something fails, or runs twice? Can it be rolled out and rolled back safely? Who can call it, and with what input? What happens at 100 times the data? Is the next change easier or harder? Would the tests fail if the code broke?
- How they judge. Which findings must be fixed and which are only suggestions or nits, what looks risky but is fine and why, what is done well, and whether the change makes the codebase better overall.
- Where they stop and say "wait". These come as questions, so you can predict the answer before you see it.
This view comes from what experienced engineers have written down about reading and reviewing code, collected in internal/generate/lessons (in Japanese). The LLM reads it before every tour.
The tour is written by an LLM you already use: Claude Code, Codex CLI, Gemini CLI, OpenCode, Copilot CLI or Pi. tour is read-only. It never changes your files or your repository.
How it works
your repository cache directory (deleted after writing)
─────────────── ──────────────────────────────────────
git archive <base> ──────────────────▶ base/ files before the change
git archive <head> ──────────────────▶ head/ files after the change
git diff ──────────────────▶ change.diff
git log ──────────────────▶ commits.txt
(built into tour) ──────────────────▶ lessons/ what senior engineers have learned
│
▼
Claude Code / Codex / Gemini / OpenCode / Copilot / Pi, started in that directory
with read-only permissions. It reads, then writes the
tour as JSON.
│
▼
tour checks every file and line the JSON points to. If something is wrong,
it asks the LLM to fix only that (up to 2 times). The tour is saved.
│
▼
tour shows the tour. The code on screen is read from git at the right commit,
never copied from the LLM's reply.
- Export.
tourreads your repository withgit archive,git diffandgit log, and writes the files into a new directory in your cache. Only files that git tracks are exported. When you tour uncommitted changes, untracked files that are not ignored are exported too. Files in.gitignore, such as.env, are never exported. - Write.
tourstarts the LLM's command-line tool in that directory with a fixed prompt and read-only permissions (see below). This takes 2 to 5 minutes, and the screen shows which files the LLM is reading. - Check. The tour is JSON that points to files and line numbers.
tourchecks that each one exists, and sends mistakes back to the LLM to fix, at most twice. - Show. Code, diffs and schemas on screen come from git, so the code you see is always the real code at that commit. Code that is not in the repository, such as a naive version or a possible fix, is always labeled Example.
The export directory is deleted once the tour is written. The finished tour is saved in your cache, so opening it again is instant.
What the LLM can and cannot do
Sending your code to an LLM is a real decision, so here is exactly what happens.
Sent to the LLM you chose:
- the files of your repository at the two commits being compared, the diff, and the commit messages. Only tracked files, plus untracked files that are not ignored when you tour uncommitted changes
- the prompt in
internal/generate/prompts - when you press ?: your question and the whole tour, with the same files
They go to the provider of that tool (Anthropic, OpenAI, Google or GitHub; with OpenCode and Pi, the provider of the model you use), under the terms of your account with them. tour itself makes no network requests, has no server, and collects no telemetry.
Not possible for the LLM:
- reading files outside the export directory, including your real working tree,
.gitand your home directory - reading files ignored by
.gitignore, because they are never exported - writing, editing or deleting any file
- running commands that change anything, or reaching the network
- using MCP servers, plugins, extensions or web search
This is enforced by the flags tour passes to each tool, not only by the prompt.
claude -p --restricted --strict-mcp-config --tools Read,Grep,Glob
--permission-mode dontAsk --permission-prompts none --no-session-persistence
--restrictedremoves the command and web tools, and keeps file tools inside the working directory--strict-mcp-configloads no MCP servers--tools Read,Grep,Globleaves only the three read-only tools--permission-mode dontAskrefuses anything that would need permission, without asking--no-session-persistencesaves no session
Source: internal/generate/claude.go
Codex reads files by running commands such as cat and rg, so the protection is the sandbox those commands run in. tour defines its own permission profile on the command line. Commands may read the export directory and system paths such as /usr and /etc. Nothing is writable, and the network is off.
--ignore-user-configand--ignore-rulesskip your~/.codexsettings and rules, so your MCP servers and plugins are not loaded-c approval_policy="never"makes blocked actions fail instead of asking-c web_search="disabled"and--disablefor apps, plugins, multi_agent, browser_use and others remove web search, connectors, sub-agents and browser tools--ephemeraland-c history.persistence="none"save no session or history
Tested on Linux, where Codex uses bubblewrap. On macOS, Codex uses its Seatbelt sandbox instead, which is not tested yet.
Source: internal/generate/codex.go
--admin-policypoints to a temporary file that allowsread_file,glob,grep_searchandlist_directoryonly inside the export directory, and denies every other tool. Admin policies take priority over your own policies.- Temporary settings in the export directory register only those four tools, and turn off MCP discovery, sub-agents, hooks, checkpoints and telemetry.
--extensions noneloads no extensions.--allowed-mcp-server-namesis set to a name no server has, so no MCP server starts.
Gemini CLI always saves the session to ~/.gemini/tmp, and deletes it after 30 days by default. This cannot be turned off from the command line.
Source: internal/generate/gemini.go
opencode run --standalone --format json --agent diff-tour
tourpasses its own config inOPENCODE_CONFIG_CONTENT, which outranks yours. It denies every tool and then allows onlyread,globandgrep, and the agentdiff-tourends with the same rules. Reading outside the export directory is denied.- Policies, which can only take permissions away, block every other tool too, and every MCP server, skill and plugin.
OPENCODE_CONFIG_DIRpoints to an empty directory and project config is turned off, so nothing in~/.config/opencode(plugins, MCP servers, agents,AGENTS.md) and noopencode.jsonorAGENTS.mdin the repository is loaded. Onlymodeland the provider settings are copied from your config, so your model and sign-ins still work.--standaloneruns a private server instead of the background service.
OpenCode keeps the session in its database (~/.local/share/opencode/opencode.db), like any other session. A system config in /etc/opencode outranks these settings.
Only OpenCode 2 is supported. If opencode is OpenCode 1, tour looks for opencode2, which OpenCode 2 also installs.
Source: internal/generate/opencode.go
copilot --available-tools=view,grep,rg,glob --deny-tool=shell --deny-tool=write
--disallow-temp-dir --disable-builtin-mcps --no-custom-instructions --no-ask-user
--no-remote --no-remote-export --no-auto-update --output-format json
--available-toolsleaves onlyview,grepandglob. The model cannot ask for any other tool: no shell, no file changes, no web, no sub-agents, no skills--deny-tooldenies shell and write again; deny rules win over every allow rule--allow-all-toolsis not passed, so anything that needs approval, such as reading outside the export directory, is refused at once.--disallow-temp-dirkeeps the system temporary directory out too--disable-builtin-mcpsturns off the GitHub MCP server, and--no-custom-instructionsskipsAGENTS.md,.github/copilot-instructions.mdand the likeCOPILOT_HOMEpoints to a temporary directory holding only your sign-in from~/.copilot/config.json, so your hooks, plugins, extensions, MCP servers, skills, trusted folders and saved approvals are not loaded. Your model setting is passed with--model. The session and logs are written there and deleted afterwards.COPILOT_ALLOW_ALLis set tofalse
Settings managed by your organization still apply.
Source: internal/generate/copilot.go
pi -p --mode json --tools read,grep,find,ls --no-extensions -e <tour's guard>
--no-mcp --no-skills --no-context-files --no-prompt-templates --no-themes
--no-session --no-approve --offline
--toolsleaves onlyread,grep,findandls: no shell, no file changes- Pi has no permissions or sandbox of its own, and its read tools accept any path. So
tourloads its own small extension with-e(pi-guard.ts). It refuses every other tool, and every path outside the export directory (.., absolute paths,~, symlinks). If it cannot check a call, it refuses it --no-extensionsloads none of your extensions or Pi's built-in ones (MCP, codemode, tool search); onlytour's guard.--no-mcp,--no-skillsand--no-prompt-templateskeep the rest of your Pi add-ons out, and--no-context-filesskipsAGENTS.mdandCLAUDE.md--no-approvedoes not trust the repository's.pidirectory, so its settings, extensions and MCP servers are not loaded.--no-sessionsaves nothing.--offlineandPI_TELEMETRY=0turn off update checks, downloads and telemetry- Your sign-in and chosen model are read from your Pi directory (
~/.pi/agent) as usual
Only Pi 1.5 and later 1.x versions are used. Older versions lack some of these flags, and Pi ignores long flags it does not know; a new major version may change the extension API the guard relies on.
Source: internal/generate/pi.go
The LLM still reads your code, so text in the code can try to steer what it writes (prompt injection). With these permissions it cannot act on that. Still, a tour is an explanation, not a guarantee: check what it says against the code it shows.
Install
macOS and Linux
curl -fsSL https://raw.githubusercontent.com/init-co-jp/diff-tour/main/install.sh | sh
This downloads the latest release for your OS and CPU, checks it against checksums.txt, and puts tour in ~/.local/bin. If that directory is not on your PATH, it prints the line to add. To choose the place or the version:
curl -fsSL https://raw.githubusercontent.com/init-co-jp/diff-tour/main/install.sh | TOUR_INSTALL_DIR=/usr/local/bin TOUR_VERSION=v0.1.0 sh
With Go 1.27 or later (any OS)
go install github.com/init-co-jp/diff-tour/cmd/tour@latest
This puts tour in $(go env GOPATH)/bin, usually ~/go/bin.
Windows (PowerShell; not tested on Windows yet)
$tag = (Invoke-RestMethod https://api.github.com/repos/init-co-jp/diff-tour/releases/latest).tag_name
$zip = "diff-tour_$($tag.TrimStart('v'))_windows_amd64.zip"
$dir = "$env:LOCALAPPDATA\Programs\tour"
Invoke-WebRequest "https://github.com/init-co-jp/diff-tour/releases/download/$tag/$zip" -OutFile "$env:TEMP\$zip"
Expand-Archive "$env:TEMP\$zip" -DestinationPath $dir -Force
[Environment]::SetEnvironmentVariable("Path", [Environment]::GetEnvironmentVariable("Path", "User") + ";$dir", "User")
Open a new terminal afterwards. On ARM, use windows_arm64.
Check the install with tour --version.
First run
You need git and one of these, installed and signed in:
| LLM | Check | Sign in |
|---|---|---|
| Claude Code | claude --version | run claude once |
| Codex CLI | codex --version | codex login |
| Gemini CLI | gemini --version | run gemini once |
| OpenCode 2 | opencode --version (2.0 or later), or opencode2 --version | opencode auth login |
| Copilot CLI | copilot --version | copilot login |
| Pi | pi --version (1.5 or a later 1.x) | run pi, then /login |
Gemini CLI support is experimental. Its read-only setup was tested against the real Gemini CLI, but a full tour has not yet been written with a real Gemini model. If it fails, please open an issue.
OpenCode support is new. A full tour was written with OpenCode 2.0.29 and one of its free models on Linux, but not yet on macOS or Windows.
Copilot CLI support is experimental. Its read-only setup was tested against the real Copilot CLI 1.0.98 on Linux, driven by a scripted stand-in model, but a full tour has not yet been written with a real Copilot model. If it fails, please open an issue.
Pi support is experimental. Its read-only setup was tested against the real Pi 1.5.0 on Linux, driven by a scripted stand-in model that tried to read outside the export directory in every way the read tools allow, but a full tour has not yet been written with a real model through Pi. If it fails, please open an issue.
Then, in a repository:
cd your-repo
tour
The first time, tour asks for the language (detected from your terminal) and the LLM. Then it lists the changes you can tour. Your current branch is already selected, so press Enter.
To try it without your own code, use the example repository from the GIF:
git clone https://github.com/init-co-jp/diff-tour-example
cd diff-tour-example
git checkout feature/coupons
tour
Choosing what to tour
| Command | Tours |
|---|---|
tour | a branch you pick from a list, compared with the default branch. If you have uncommitted changes, the current branch with them comes first |
tour <branch> | that branch, e.g. feature/x, or origin/feature/x to review someone else's branch |
tour <commit> | that single commit |
tour <base>..<head> | that range |
tour <file>.json | a saved tour file, e.g. tours/example-coupons.en.json |
tour setup | choose the language and the LLM again |
Keys
| Key | Action |
|---|---|
| → Space Enter | Next step |
| ← Backspace | Previous step |
| ? | Ask about this step: pick a suggested question or type your own. The answer becomes the next step |
| o | Open the code of this step in your editor |
| ↑ ↓ | Scroll, when a step does not fit on the screen |
| q | Quit |
What a step can show
- code and diffs, read from git at the right commit, with syntax highlighting
- code that is not in the repository, such as a naive version or a possible fix, labeled Example
- flow and timeline diagrams
- database schemas before and after the change, computed by applying the migrations to an in-memory SQLite database (SQLite migrations only for now)
- tables of example data
- questions to think about before the answer appears on the next step
- answers to your own questions about a step, saved with the tour (when you play a tour file, they last only until you quit)
Every explanation is labeled with how it is known:
| Label | Meaning |
|---|---|
| Verified | backed by code, tests or commit messages in this repository |
| From the code | inferred from how the code is structured |
| Senior view | general design judgment, not checked against this repository |
Configuration
| Linux | macOS | Windows | |
|---|---|---|---|
| Settings | ~/.config/tour/config.json | ~/Library/Application Support/tour/config.json | %AppData%\tour\config.json |
| Saved tours | ~/.cache/tour/tours/ | ~/Library/Caches/tour/tours/ | %LocalAppData%\tour\tours\ |
On Linux, XDG_CONFIG_HOME and XDG_CACHE_HOME are respected. The cache is safe to delete. Tours are written again when needed.
Editor. o uses $VISUAL or $EDITOR, and knows how to jump to a line in vim, Neovim, Emacs, nano, VS Code, Cursor, Zed, Helix, Sublime Text and others. For any other editor, set a template:
export TOUR_EDITOR='code -g {file}:{line}'
If the file on disk differs from the commit being toured, tour opens a read-only copy from the cache instead, so you see the code the tour talks about.
Language. English, Japanese, Simplified Chinese (zh), Traditional Chinese (zh-Hant, worded for Taiwan), Spanish (es), Russian (ru) and Brazilian Portuguese (pt-BR). The screens and the tours use it. tour setup changes it, and tour --lang ja changes it for one run. In Taiwan, Hong Kong and Macau, Traditional Chinese is picked from your locale.
FAQ
How much does a tour cost? It runs on your own Claude Code, Codex, Gemini, OpenCode, Copilot or Pi plan. With Claude Code, one tour of a change of about 250 lines used the equivalent of $1.00 to $1.50 at API prices. Opening a saved tour again costs nothing.
Why does it take minutes? Before writing, the LLM reads the files around the change, not only the diff. That reading is what lets the tour explain code that did not change.
Can I share a tour?
Yes. A tour is a JSON file in the cache directory, and anyone with the same repository can open it with tour <file>.json.
When is tour not the right tool?
For a one-line fix, reading the diff is faster. tour is for changes where the "why" is not obvious from the diff: new features, refactors, and code written by AI that you are now expected to own.
Development
go test ./...
go run ./cmd/tour tours/example-coupons.en.json --repo path/to/diff-tour-example --dump --cols 140 --rows 44 --plain
--dump prints every step at a fixed screen size, which is handy for checking layouts without a terminal. demo/ records the GIFs, and experiments/generate has the notes from tuning the prompts.
Contributing
Requests and bug reports are very welcome as issues, in English or Japanese. We don't accept pull requests. We write the changes ourselves, so that every change gets the same review of what the LLM can read and do. CONTRIBUTING.md has the details.