Task: Go core — Windows config paths and TTY reattach
Description
Two surgical Go fixes that together unblock revdiff on Windows. Both touch cmd/revdiff/main.go and are bundled into one task to avoid merge conflicts on that file.
Fix 1 — TTY reattach for --stdin mode. cmd/revdiff/main.go:329 hardcodes os.Open("/dev/tty"). On Windows the equivalent is os.Open("CONIN$"). Split the call site behind a build-tagged helper so each platform compiles cleanly.
Fix 2 — Config/themes/keybindings paths on Windows. defaultConfigPath() (line 272), defaultKeysPath() (line 300), and defaultThemesDir() (line 520) all build paths under ~/.config/revdiff/. On Windows, route through os.UserConfigDir() (returns %APPDATA%) so configs land at %APPDATA%\revdiff\. Unix paths are unchanged — macOS users currently using ~/.config/revdiff/ see no behavior shift.
Acceptance Criteria
Technical Details
Files to create
cmd/revdiff/tty_unix.go — ~10 lines, build tag //go:build !windows.
cmd/revdiff/tty_windows.go — ~10 lines, build tag //go:build windows.
Files to modify
cmd/revdiff/main.go — replace the body of openTTY() (or inline its callers) to use openInteractiveTTY(). Add runtime.GOOS == "windows" branch to the three default-path helpers. The os.UserConfigDir() call should be the only Windows-specific addition; everything else stays in runtime.GOOS == "windows" arms.
cmd/revdiff/main_test.go — add table-driven tests for the path helpers covering both windows and linux/darwin GOOS values. If using a real runtime.GOOS (not injected), build-tag a sibling file main_paths_windows_test.go for the Windows-only assertions.
Implementation notes
- Prefer dependency injection (a
goosFn func() string package var) over runtime.GOOS directly so tests can drive both branches without build tags. Default the var to func() string { return runtime.GOOS } and override in tests.
os.UserConfigDir() returns %APPDATA% on Windows (e.g., C:\Users\you\AppData\Roaming). Joining with "revdiff" gives C:\Users\you\AppData\Roaming\revdiff. Use filepath.Join, never string concat.
- Per CLAUDE.md, on Unix the existing
~/.config/revdiff/ layout must be preserved exactly — do not switch macOS to ~/Library/Application Support/revdiff/.
openInteractiveTTY() is a tiny helper; do not export it from another package — keep it in package main.
- The PowerShell launcher (task 003) and the validation step (task 006) depend on the
--dump-config output reflecting the new paths. Confirm via revdiff.exe --dump-config after building.
Audit references (line numbers from initial scan, may drift slightly)
cmd/revdiff/main.go:272 — defaultConfigPath
cmd/revdiff/main.go:300 — defaultKeysPath
cmd/revdiff/main.go:329 — hardcoded /dev/tty open
cmd/revdiff/main.go:520 — defaultThemesDir
cmd/revdiff/main_test.go:425–426 — existing path tests to update
Dependencies
- None. This task can start immediately.
- Blocks meaningful validation in tasks 002, 003, 004, 005, 006 (they need a working
revdiff.exe to test against), but does not block their creation.
Effort Estimate
- Size: S
- Scope: ~50 lines of Go across 3 files + ~30 lines of test. Single PR.
Definition of Done
Task: Go core — Windows config paths and TTY reattach
Description
Two surgical Go fixes that together unblock revdiff on Windows. Both touch
cmd/revdiff/main.goand are bundled into one task to avoid merge conflicts on that file.Fix 1 — TTY reattach for
--stdinmode.cmd/revdiff/main.go:329hardcodesos.Open("/dev/tty"). On Windows the equivalent isos.Open("CONIN$"). Split the call site behind a build-tagged helper so each platform compiles cleanly.Fix 2 — Config/themes/keybindings paths on Windows.
defaultConfigPath()(line 272),defaultKeysPath()(line 300), anddefaultThemesDir()(line 520) all build paths under~/.config/revdiff/. On Windows, route throughos.UserConfigDir()(returns%APPDATA%) so configs land at%APPDATA%\revdiff\. Unix paths are unchanged — macOS users currently using~/.config/revdiff/see no behavior shift.Acceptance Criteria
cmd/revdiff/tty_unix.gocreated with//go:build !windowsconstraint and a single exportedopenInteractiveTTY() (*os.File, error)returningos.Open("/dev/tty").cmd/revdiff/tty_windows.gocreated with//go:build windowsconstraint and the same signature returningos.Open("CONIN$").openTTY()incmd/revdiff/main.go(lines 328–334) is replaced/refactored to callopenInteractiveTTY()so the hardcoded/dev/ttyliteral is gone frommain.go.defaultConfigPath(),defaultKeysPath(),defaultThemesDir()consultruntime.GOOS. Onwindowsthey useos.UserConfigDir()joined withrevdiff/<config|keybindings|themes>. On all other platforms they keep returning the existingfilepath.Join(home, ".config", "revdiff", ...)paths verbatim.cmd/revdiff/main_test.gocovers both branches: existing tests still pass on Unix, new tests verify the Windows branch (use injectedruntime.GOOSor build-tag a sibling test filemain_windows_test.go).go build ./cmd/revdiffsucceeds on both Linux and Windows (validated viaGOOS=linux go buildandGOOS=windows go buildfrom any host).go test ./...passes on Linux/macOS with no behavior change.--dump-configon Windows shows paths under%APPDATA%\revdiff\; on Unix shows~/.config/revdiff/.go.mod— only standard library (os,runtime,path/filepath) used.//nolintdirectives required.Technical Details
Files to create
cmd/revdiff/tty_unix.go— ~10 lines, build tag//go:build !windows.cmd/revdiff/tty_windows.go— ~10 lines, build tag//go:build windows.Files to modify
cmd/revdiff/main.go— replace the body ofopenTTY()(or inline its callers) to useopenInteractiveTTY(). Addruntime.GOOS == "windows"branch to the three default-path helpers. Theos.UserConfigDir()call should be the only Windows-specific addition; everything else stays inruntime.GOOS == "windows"arms.cmd/revdiff/main_test.go— add table-driven tests for the path helpers covering bothwindowsandlinux/darwinGOOS values. If using a realruntime.GOOS(not injected), build-tag a sibling filemain_paths_windows_test.gofor the Windows-only assertions.Implementation notes
goosFn func() stringpackage var) overruntime.GOOSdirectly so tests can drive both branches without build tags. Default the var tofunc() string { return runtime.GOOS }and override in tests.os.UserConfigDir()returns%APPDATA%on Windows (e.g.,C:\Users\you\AppData\Roaming). Joining with"revdiff"givesC:\Users\you\AppData\Roaming\revdiff. Usefilepath.Join, never string concat.~/.config/revdiff/layout must be preserved exactly — do not switch macOS to~/Library/Application Support/revdiff/.openInteractiveTTY()is a tiny helper; do not export it from another package — keep it inpackage main.--dump-configoutput reflecting the new paths. Confirm viarevdiff.exe --dump-configafter building.Audit references (line numbers from initial scan, may drift slightly)
cmd/revdiff/main.go:272—defaultConfigPathcmd/revdiff/main.go:300—defaultKeysPathcmd/revdiff/main.go:329— hardcoded/dev/ttyopencmd/revdiff/main.go:520—defaultThemesDircmd/revdiff/main_test.go:425–426— existing path tests to updateDependencies
revdiff.exeto test against), but does not block their creation.Effort Estimate
Definition of Done
make test(Unix) green--dump-config/--init-themes/--list-themesflows on macOS or Linux