Skip to content

About

Session diff sidebar for Herdr: changed files with red/green hunks, click-to-jump, drag-to-send into the agent prompt

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

21 Commits

Folders and files

Repository files navigation

diff-viewer

CI License: MIT Platform Rust Themes

✨ Beautiful and ⚡ BLAZINGLY FAST ✨

Git diff sidebar for herdr: changed files with red/green hunks in a split pane. Click a file to jump, drag to send lines into the agent prompt. Written in Rust 🦀 btw.

diff-viewer screenshot

Usage

Run the toggle action from an agent pane (Diff viewer: toggle git diff sidebar).

Scope is per agent session, never per tab or pane cwd. Two sources feed it:

1. Agent journals (exact). The viewer reads the session's own transcript and adopts every repo the session edited — no cwd assumptions, works even when the agent writes to a repo it was not launched in.

agent journal what counts
claude $CLAUDE_CONFIG_DIR (else ~/.claude) /projects/<slug>/<session>.jsonl Edit/Write/MultiEdit/NotebookEdit + subagent journals; the root is read from the agent process's own env, and a session id that is not on disk scopes nothing — never another session's newest transcript
opencode ~/.local/share/opencode/opencode.db edit/write + apply_patch patch text, plus shell workdir (gated); legacy part and v2 session_message merged, subagent sessions included
kilo ~/.local/share/kilo/kilo.db same as opencode
codex ~/.codex/sessions/**.jsonl apply_patch / patch_apply_end changes
gemini ~/.gemini/tmp/<project>/chats/session-* write_file/replace tool calls
qwen ~/.qwen/projects/<slug>/chats/<session>.jsonl edit/write_file tool calls
pi ~/.pi/agent/sessions/<slug>/<session>.jsonl edit/write tool calls
omp ~/.omp/agent/sessions/<slug>/<session>.jsonl + every transcript nested under <session>/ (subagents, and subagents of subagents) edit/write tool calls in both call shapes — the path argument and the [file#hash] headers of a patch-form call; sessions resolve by transcript path, and a path that no longer exists scopes nothing rather than falling back to a neighbour's transcript
antigravity …/antigravity-cli/brain/<id>/.system_generated/logs/transcript.jsonl write_to_file/replace_file_content targets
cursor ~/.cursor/projects/<slug>/agent-transcripts/<conv>.jsonl + ai-tracking.db best-effort (no cwd in store)
aider <repo>/.aider.chat.history.md > Applied edit to <path>

2. Shell workdirs (gated). opencode and kilo record the working directory of every shell command; those directories join the scope as candidates and are adopted only once their working tree changes, so a repo the session merely reads stays out.

3. Process fallback (signature-gated). For agents without a journal (and for shell-only edits), a repo is adopted when a new process of the session's own tree runs with its cwd inside it and its working tree changes while the session is alive — so a dirty launch repo that the session never touched stays invisible. Sources marked best-effort above use the same gate. Agents that multiplex every session behind one shared daemon (opencode, kilo) never use the fallback: their pane's process tree spans unrelated sessions, so it is not walked.

The pane's own cwd repo is never assumed. Once a repo is in scope, all of its uncommitted changes are shown, whoever made them. Session id or agent change resets the scope; a new session starts empty; a confirmed pane close deletes it. The viewer follows its own agent pane live — neighbour panes never leak in. The header shows watching N so you always know the blast radius. Untracked files included. One broken repo never blanks the view.

Linked worktrees are repos of their own. A session that works in git worktree checkouts gets one entry per worktree, labelled <main>⎇<branch> (a detached head falls back to the short sha), and the files of a linked worktree send absolute paths when dragged — the agent usually runs in the main checkout, so a repo-relative path would point at the wrong tree. A removed worktree leaves the view within a tick and is forgotten from state.

Event-driven, not polling. The viewer subscribes to herdr's event stream (pane.updated/closed/moved, layout.updated, worktree.removed) and runs two timers: journal + process reads at most once a second while the agent is working, and a git-signature check every 3s when idle. A dropped socket is retried every second and the viewer keeps watching on that slow path. Plugin hooks (pane.agent_status_changed, pane.closed, pane.exited, pane.moved, tab.closed, workspace.closed) keep the record current even with no viewer open — toggling afterwards is instant — and prune it when a pane, tab or workspace goes away. Records are namespaced per herdr server ($HERDR_PLUGIN_STATE_DIR/srv-<socket>/session-<pane>.json), so a named session never reads or prunes another session's state.

Debug a journal reader from any shell:

diff-viewer journals claude "" <session-id>   # cwd + paths the viewer would adopt
CLAUDE_CONFIG_DIR=~/.claude-swap-backup/sessions/<profile> \
  diff-viewer journals claude <cwd> <session-id>   # same, for a swapped profile

Limitations: shell edits that finish between samples and agents with neither a journal nor visible child processes are not detected; cursor/aider/antigravity blob sources are heuristic and always gated.

Toggle resyncs pane sizes after open/close (resize --amount 0 is a no-op that still syncs pty winsizes), so neither the viewer nor the agent renders clipped until the next click.

Theme

Click ◑ in the header or press T for a theme menu — applies instantly, persists across toggles. j/k + Enter to pick, Esc to close.

cargo install --path .     # once: `diff-viewer` in ~/.cargo/bin
diff-viewer themes         # list
diff-viewer theme NAME     # set from any shell, picked up live, no re-toggle
diff-viewer theme auto     # back to claude-code dark/light auto-detect

transparent = same syntax colors as claude-code-dark, but the gray base stays unpainted (your terminal background / blur shows through) with juicier reds and greens. Also available: dark / light (follow claude-code themes), or any name from diff-viewer themes (catppuccin, dracula, nord, gruvbox, one-dark/light, solarized, kanagawa, rose-pine, vesper, tokyo-night…). Unset = auto-detect from terminal background.

Why not Claude Code /diff?

/diff diff-viewer
Multi-repo scope ❌ one repo ✅ own session's repos only, worktrees included
Live follow ❌ snapshot ✅ events + 1s ticks while the agent works
Click-to-jump file list ❌ ✅
Drag lines into prompt as file:line ❌ ✅
Transparent theme ❌ ✅ 👻
Speed fast ⚡ BLAZINGLY FAST (it's Rust 🦀)

About

Session diff sidebar for Herdr: changed files with red/green hunks, click-to-jump, drag-to-send into the agent prompt

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages