[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-92308":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":20,"hasPages":20,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":32,"readmeContent":33,"aiSummary":34,"trendingCount":16,"starSnapshotCount":16,"syncStatus":35,"lastSyncTime":36,"discoverSource":37},92308,"herdr-file-viewer","smarzban\u002Fherdr-file-viewer","smarzban","A git-aware, read-only file viewer for herdr. Mouse friendly,  keyboard-driven TUI: tree + content pane with diffs, rendered markdown, and syntax highlighting.","",null,"Rust",80,4,52,3,0,27,44.8,"MIT License",false,"main",[23,24,25,26,27,28,29,30,31],"file-viewer","git","herdr","herdr-plugin","ratatui","rust","terminal","terminal-file-explorer","tui","2026-07-22 04:02:05","# herdr-file-viewer\n\n[![CI](https:\u002F\u002Fgithub.com\u002Fsmarzban\u002Fherdr-file-viewer\u002Factions\u002Fworkflows\u002Fci.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Fsmarzban\u002Fherdr-file-viewer\u002Factions\u002Fworkflows\u002Fci.yml)\n[![License: MIT](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicense-MIT-blue.svg)](LICENSE)\n![Rust 1.96+](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Frust-1.96%2B-orange.svg)\n![herdr 0.7+](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fherdr-0.7%2B-8a2be2)\n![platforms: linux • macOS • Windows (preview)](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fplatforms-linux%20%E2%80%A2%20macOS%20%E2%80%A2%20Windows%20(preview)-informational)\n\n**Browse your repo without leaving your terminal session — a git-aware, read-only file viewer\nthat lives in a herdr pane.** A keyboard-driven TUI with a directory tree\non the left and, on the right, exactly the view each file deserves: a **diff** if it changed,\n**rendered markdown** if it's markdown, **syntax-highlighted code** otherwise. Git status is woven\nright into the tree. It opens beside whatever you're doing and never touches your files.\n\n![herdr-file-viewer open in a herdr split beside your work — the directory tree on the left, syntax-highlighted content on the right](assets\u002FFile-viewer.png)\n\n*The right view per file — here a markdown file rendered (headings, inline code, tables) in your terminal's theme:*\n\n![herdr-file-viewer rendering a markdown file — colored headings and styled inline code on the right, the git-status tree on the left](assets\u002FMarkdown-view.png)\n\n*…and running full-screen — the same tree + content, filling the terminal:*\n\n![herdr-file-viewer running full-screen](assets\u002FFile-Viewer-FS.png)\n\n\u003C!-- TODO: swap these stills for a short GIF (open → arrow to a changed file (diff) → `v` rendered markdown → `z` zoom). asciinema + agg → gif. -->\n\n## Why you'd want it\n\n- **The right view, automatically.** Stop `cat`-ing files and squinting at raw diffs. A changed\n  file shows its diff; a README renders; code is highlighted — no mode-switching, no commands.\n- **Git at a glance.** `M`\u002F`A`\u002F`D`\u002F`?` markers, colored so changes pop, a changed-files-only\n  filter, and a baseline you can flip between your branch's merge-base and `HEAD` — all in the\n  tree, not a separate mode.\n- **It sits beside your work.** Opens in a herdr split (or its own tab) with one keypress, and\n  toggles away just as fast. Great next to an agent, a build, or an editor.\n- **Safe on anything.** Read-only by construction and hardened to open *untrusted* repos (an\n  agent's worktree, a fresh clone) without running repo-controlled code or letting hostile file\n  content drive your terminal. See [SECURITY.md](SECURITY.md).\n- **Keyboard-first**, mouse-optional, and it never reinvents rendering — it delegates to\n  `glow` \u002F `delta` \u002F `bat` and degrades gracefully when they're absent.\n\n## What it does\n\n- **Tree, scoped to your work** — rooted at the worktree root inside a git repo, else the\n  launch directory. Honors `.gitignore` (toggle to reveal ignored files), and a separate toggle\n  (`.`) hides dot-prefixed \"hidden\" files when a directory is full of them. The tree's top border\n  names the root directory and its bottom border shows the current branch, so you always know\n  *where* and *on what branch* you're looking.\n- **Jump to any file** — press `f` to open a fuzzy finder over every file in the tree\n  (`.gitignore`-aware); type to filter, `↑` \u002F `↓` to move, and `Enter` to open — far faster than\n  scrolling the tree in a large repo.\n- **Go to a line** — press `:` and type a line number to jump the content pane straight there;\n  in a rendered-markdown or diff view it switches to the line-numbered content view to make the\n  jump. Out-of-range clamps to the last line.\n- **Search in a file** — press `\u002F` to search the open file's content: every match highlights as\n  you type, `Enter` commits, and `n` \u002F `N` cycle through matches (wrapping at the ends). Smartcase —\n  a lowercase query matches any case, add a capital to go case-sensitive — and it works in every\n  view (code, markdown, or diff); `Esc` clears it.\n- **Switch worktree on the fly** — press `W` to re-root the viewer at another git worktree of\n  the repo without relaunching; it pre-selects the worktree a herdr agent is working in, so you\n  can jump straight to it. Read-only — it changes only *what you're viewing*, never the branch\n  or any files.\n- **In-app help** — press `?` to open a view-only help overlay showing What's New (the latest\n  changelog entries, rendered as markdown) and About (version, repo, license, and update status).\n  Keyboard and mouse; `Esc` or `q` closes it. A `? help` hint rides the content pane's bottom\n  border so the overlay is discoverable without already knowing the key.\n- **Git woven in** — per-file status markers (`M`\u002F`A`\u002F`D`\u002F`?`), and a `●` on a directory that\n  contains any change; **colored** so changes read at a glance (changed files and dirty folders\n  are red, new files green), with the glyph as a non-color cue so it survives a colorblind palette\n  or a non-default theme. A changed-files-only filter; and a baseline you can switch between the\n  merge-base of your branch and `HEAD`.\n- **The right view per file** — a changed file shows its **diff**; a markdown file renders;\n  anything else is shown as syntax-highlighted content with line numbers. Cycle the view\n  (`v`) to override — a changed file can also show a **full-file diff**: the whole file with\n  line numbers and the diff shown inline.\n- **Navigable content** — scroll the content pane in all four directions, toggle line\n  wrapping, resize the tree\u002Fcontent split, or zoom (`z`) to hide the tree and read a file\n  full-screen; the layout reflows when the pane is resized. The tree scrolls to keep the\n  selection in view (and sideways, for long names), and a scrollbar appears on the tree or\n  content pane whenever there is more to see than fits — drag it with the mouse to scroll.\n- **Keyboard-first** — every function has a key; no mouse required. The tree's horizontal\n  scroll (for long \u002F deeply-nested rows) is reachable with `H` \u002F `L`, the same way the content\n  pane scrolls with `←` \u002F `→` when focused.\n\n## Quick start\n\n```bash\n# 1. Install the plugin (downloads a prebuilt binary for released versions; otherwise builds from source):\nherdr plugin install smarzban\u002Fherdr-file-viewer\n\n# 2. (recommended) install the renderers, so markdown \u002F diffs \u002F code are styled, not plain text:\nbrew install glow git-delta bat     # macOS — or use your package manager\n#   Linux \u002F cross-platform: run scripts\u002Finstall-renderers.sh from the plugin dir (`herdr plugin list`)\n```\n\nThen **bind a key** in your herdr config (`~\u002F.config\u002Fherdr\u002Fconfig.toml`) so one press summons it:\n\n```toml\n[[keys.command]]              # open in a split beside your work\nkey = \"prefix+f\"\ntype = \"shell\"\ncommand = \"herdr plugin action invoke open-file-viewer --plugin herdr-file-viewer\"\n\n[[keys.command]]              # …or in its own tab\nkey = \"prefix+shift+f\"\ntype = \"shell\"\ncommand = \"herdr plugin action invoke open-file-viewer-tab --plugin herdr-file-viewer\"\n```\n\nRun `herdr server reload-config`, then press your key. That's the whole setup — the split-pane\nviewer and its open actions ship **inside** the plugin and register automatically on install, so\nyou only add the keybinding. The [keys](#keys) are below; deeper detail lives in the docs:\n[install & updating](docs\u002Finstall.md), [external renderers](docs\u002Frenderers.md), and\n[summoning & keybindings](docs\u002Fusage.md).\n\n## Windows (preview)\n\nNative Windows (`x86_64-pc-windows-msvc`) is supported as a **preview**, mirroring herdr's own\nposture there: the crate builds, the test suite runs (advisory) on `windows-latest` CI, and\ninstall works the same way as Linux\u002FmacOS — `herdr plugin install` downloads a SHA-256-verified\nprebuilt binary (via `scripts\u002Ffetch-or-build.ps1`) or falls back to `cargo build --release`, no\nextra tooling required beyond the in-box Windows PowerShell 5.1. The open\u002Ftoggle actions work via\nPowerShell launcher scripts.\n\n- **On Windows, bind the `-windows` action ids.** herdr requires every action id to be unique, so\n  the Windows launchers register as **`open-file-viewer-windows`** and\n  **`open-file-viewer-tab-windows`** (the unqualified `open-file-viewer` \u002F `open-file-viewer-tab`\n  ids are the Linux\u002FmacOS variants). Point your herdr keybinding at the `-windows` id:\n  `command = \"herdr plugin action invoke open-file-viewer-windows --plugin herdr-file-viewer\"`.\n- **A `prefix+f` keybinding needs herdr v0.7.2 or newer.** herdr runs custom-command\n  (`[[keys.command]]`) keybindings through the platform shell; before v0.7.2 that was `\u002Fbin\u002Fsh` —\n  absent on Windows — so the binding silently did nothing there. herdr **v0.7.2** runs them through\n  `cmd.exe \u002Fd \u002Fc`, so the `prefix+f` binding above fires normally. On older herdr, summon the viewer\n  by invoking the action **directly** (`herdr plugin action invoke open-file-viewer-windows\n  --plugin herdr-file-viewer` from a shell, or via herdr's action menu) rather than through a\n  keybinding.\n- **Requires herdr's preview channel.** Windows herdr binaries ship only on herdr's pre-release\n  update channel, so you need to be on it before installing this plugin on Windows.\n- **Preview means best-effort, not a parity guarantee.** There's no Windows host in this\n  project's CI gate (the `windows-latest` job is advisory, not required), so a Windows-specific\n  regression can land between releases. Full feature parity with Linux\u002FmacOS is the goal, not a\n  promise — please [open an issue](https:\u002F\u002Fgithub.com\u002Fsmarzban\u002Fherdr-file-viewer\u002Fissues) if you\n  hit a Windows-specific problem.\n- **WSL works today, with zero extra setup.** If you'd rather not wait on native-Windows preview\n  maturity, the existing Linux (`x86_64-unknown-linux-musl`) binary already runs unmodified\n  inside WSL — install herdr and this plugin from within your WSL distro exactly as you would on\n  native Linux.\n\n## Keys\n\n| Key | Action |\n| --- | --- |\n| `↑` \u002F `k`, `↓` \u002F `j` | Move the tree cursor — or **scroll the content pane** vertically when it is focused |\n| `→` \u002F `l` | Expand the selected directory — or **scroll the content pane right** when it is focused |\n| `←` \u002F `h` | Collapse the selected directory — or **scroll the content pane left** when it is focused |\n| `H` (Shift+`h`) | Scroll the **tree** pane left (long \u002F deeply-nested rows) — inert unless the tree is focused |\n| `L` (Shift+`l`) | Focus-gated: with the **tree** focused, scroll it right (long \u002F deeply-nested rows); with the **content pane** focused (or zoomed), enter **line-select mode** to select lines and copy either a `file:line` reference or the content itself (see below) |\n| _line-select mode_ | `j`\u002F`k` (or `↑`\u002F`↓`) move the marker, `Shift`+move (`J`\u002F`K`, Shift+`↑`\u002F`↓`) extends a line selection; **click-drag** with the mouse selects **text** (character-granular); `Enter` copies the `path:line` \u002F `path:start-end` **reference**, `y`\u002F`Y` copies the selected **content**, `Esc` exits |\n| `Enter` | Activate the selection — expand\u002Fcollapse a directory, or open a file in **zoom mode** (content full-screen) |\n| `i` | Toggle gitignored files |\n| `.` | Toggle hidden (dot-prefixed) files and folders |\n| `c` | Toggle changed-files-only |\n| `b` | Toggle the diff baseline (base branch ⇄ `HEAD`) |\n| `v` | Cycle the content view mode |\n| `e` | Open the selected file in `$EDITOR` |\n| `O` (Shift+`o`) | **Open with default app** — hand the selected file or directory to the OS default application (e.g. an image opens in the system viewer). Read-only hand-off; non-blocking (the viewer keeps running) |\n| `R` (Shift+`r`) | **Reveal in file manager** — open the OS file manager (Finder \u002F Explorer \u002F a Linux file manager) with the selected entry highlighted where supported, so you can drag it out (e.g. into Slack). Read-only hand-off |\n| `f` | **Go to file** — open a fuzzy finder over every file in the tree; type to filter, `↑` \u002F `↓` move, `Enter` opens the selected file, `Esc` cancels (`←` \u002F `→` scroll long paths) |\n| `:` | **Go to line** — open a prompt and jump the content pane to a source line by number (`Enter` jumps, `Esc` cancels; out-of-range clamps to the last line). Works in any view; in a rendered-markdown or diff view, confirming switches to the line-numbered content view and jumps there |\n| `\u002F` | **Search in file** — open a prompt and highlight every match in the content pane as you type; `Enter` commits the search (highlights persist), `Esc` clears it and restores the scroll. Smartcase (a lowercase query is case-insensitive; a capital makes it case-sensitive). Works in any view |\n| `n` \u002F `N` (Shift+`n`) | After a committed search, jump to the **next** \u002F **previous** match and scroll it into view — wrapping at the ends with a notice |\n| `y` | Copy the selected file's **repo-relative** path to the clipboard (e.g. `src\u002Fapp.rs`) |\n| `Y` | Copy the selected file's **absolute** path to the clipboard |\n| `Tab` | Move focus between the tree and content columns |\n| `\u003C` \u002F `>` | Narrow \u002F widen the tree column (move the divider) |\n| `w` | Toggle line wrapping for the content pane |\n| `z` | Zoom — hide the tree so the content pane fills the frame; press again (or `q`\u002F`Esc`) to restore the two-column layout |\n| `r` | Refresh git state — pick up changes made outside the viewer (a merge \u002F pull \u002F commit elsewhere) |\n| `W` (Shift+`w`) | **Switch worktree** — open a picker of the repo's git worktrees and re-root the viewer to the one you pick (read-only; no branch checkout). Marks the current worktree and pre-selects the one with an active herdr agent; `↑`\u002F`↓` move, `←`\u002F`→` scroll long paths, `Enter` switches, `Esc` cancels |\n| `?` (Shift+`\u002F`) | Open the **help overlay** — What's New (latest changelog, rendered markdown) + About (version, repo, license, update status); `Esc` \u002F `q` closes it |\n| `u` | Dismiss the \"update available\" banner for this session |\n| `q` \u002F `Esc` | Back out of zoom if zoomed; otherwise close the viewer and return to the prior pane |\n\n`Tab` to the content pane, then the arrow keys (or `h`\u002F`j`\u002F`k`\u002F`l`) scroll it in all four\ndirections; `Tab` back to the tree to move between files. Long lines wrap in prose (markdown \u002F\nplain text); diffs and code keep their original lines so columns stay aligned — scroll\nsideways with `←`\u002F`→`, or press `w` to wrap them instead. The layout reflows automatically\nwhen the pane is resized.\n\n**Git state stays current.** The viewer re-reads git status when the pane **regains focus**, so\nchanges you make outside it (a merge, pull, or commit in another pane) show up automatically; `r`\nforces a full refresh on demand. (Focus-refresh updates the tree's status without disturbing your\ncontent scroll.)\n\nCharacter keys act only when no control chord is held (so terminal chords like `Ctrl+C` are\nnever intercepted); `Shift` is permitted, for keys such as `\u003C` and `>` (and `y`\u002F`Y`, `W`, `N`,\n`O`, `R`, `?`, `H`\u002F`L`, and `J`\u002F`K` in line-select mode).\n\n**Copy a path (`y` \u002F `Y`).** `y` copies the selected file's repo-relative path; `Y` copies its\nabsolute path — handy for pasting into a prompt, a command, or an agent. The copy uses the\nterminal's **OSC 52** clipboard escape, so it travels through herdr (and SSH) to your real\nclipboard with no extra tooling. A confirmation appears in the notices strip. If nothing lands\non your clipboard, your terminal likely needs OSC 52 \u002F clipboard-write enabled (e.g. in tmux,\n`set -g set-clipboard on`).\n\n**Copy a line reference or line content (`L`).** With the content pane focused (or zoomed), `L`\nenters **line-select mode**: a marker lands on the top visible line, `j`\u002F`k` (or `↑`\u002F`↓`) move it,\nand holding `Shift` (`J`\u002F`K`, or Shift+`↑`\u002F`↓`) extends a whole-line selection. Or **click-drag\nwith the mouse** to select **text** character-by-character — press where the selection starts,\ndrag to where it ends (the pane scrolls if you drag past an edge), release; the selected\ncharacters are highlighted as you go. One selection, two products:\n\n- **`Enter` copies a repo-relative reference** — `src\u002Fapp.rs:42` for a single line,\n  `src\u002Fapp.rs:42-58` for a range (a mouse selection references the lines it spans) — ready to\n  paste into an agent chat or an issue to point at exact lines.\n- **`y` \u002F `Y` copy the content itself** — for a line selection, the lines joined by newlines; for\n  a mouse text selection, exactly the characters you dragged over. The syntax view's line-number\n  gutter is stripped and indentation is preserved, so it pastes as real code.\n\nA confirmation notice names what was copied. Both copies use the same **OSC 52** path as the\ntree's `y`\u002F`Y`. `Esc` leaves the mode.\n\n`Shift`+mouse is deliberately left alone so your terminal's own native selection\u002Fcopy still works\n— most terminals reserve `Shift`+drag for exactly that. Selection works in wrapped views too (the\n`w` toggle): the click maps through the same wrapping the pane draws with, so the caret lands on\nthe character under the cursor. Because selection only maps onto the source, entering line-select\nfrom a rendered-markdown or diff view first switches that file to the line-numbered content view. With the **tree** focused, `L` keeps its tree horizontal-scroll\nbehavior instead — the mode is gated on which pane has focus.\n\n### Mouse\n\nThe viewer is keyboard-first; the mouse is additive and on by default:\n\n| Gesture | Action |\n| --- | --- |\n| **Click** a tree row | Select it (focus the tree) |\n| **Double-click** a folder | Expand \u002F collapse it (same as `Enter`) |\n| **Double-click** a file | Open it in **zoom mode** — content full-screen (same as `Enter`); the editor is the `e` key |\n| **Wheel** over the content pane | Scroll it vertically; over the tree, move the selection |\n| **Horizontal wheel \u002F swipe** | Scroll the content — or the tree — sideways (terminal-dependent — see below) |\n| **Drag** a scrollbar | Scroll that pane — drag ↕ on a vertical bar, ↔ on a horizontal bar; pressing the track jumps there |\n| **Drag** the divider | Resize the tree \u002F content split |\n| **Drag** over the content text | **Select and copy text** — the selection highlights character-by-character as you drag (auto-scrolling past an edge) and is copied to the clipboard on release; no mode needed. Works in wrapped views (prose\u002Fmarkdown) too. `Esc`, a click elsewhere, or switching files clears the highlight |\n\n**`Shift`+drag is left to your terminal**, so its native select-and-copy still works while the\nviewer owns ordinary clicks — herdr reserves `Shift`+mouse for exactly this. (herdr forwards\nmouse events to the pane because the viewer requests capture.)\n\n**Horizontal mouse scroll is terminal-dependent** — it works only where your terminal emits\nhorizontal-scroll events (`ScrollLeft` \u002F `ScrollRight`); many terminals send nothing for a\nsideways trackpad swipe. The `←` \u002F `→` keys always scroll the content sideways, and `H` \u002F `L`\nalways scroll the tree sideways, regardless of terminal.\n\n### Opening in an editor\n\n`e` hands the selected file to the editor named by the **`$EDITOR`** environment variable\n(e.g. `vim`, or `\"code --wait\"` for editors that fork). The viewer suspends, runs the editor,\nand resumes when it exits. If `$EDITOR` is unset, a notice is shown — the viewer never edits a\nfile itself.\n\n**`e` does nothing, or says \"no editor configured\"?** The viewer reads `$EDITOR` from the\n**herdr server's** environment — the server spawns every pane — *not* from the shell you happen to\nbe attached from. So if `$EDITOR` is set in your interactive shell but the server was started\nwithout it (common with `mosh`, `systemd`, or any login manager that doesn't source your shell\nstartup files), the viewer won't see it. To fix it:\n\n1. **Export `$EDITOR` in the startup file your server's launch actually reads.** Pick the line(s)\n   that match how herdr starts on your machine:\n\n   ```bash\n   # zsh — interactive shells read ~\u002F.zshrc; ~\u002F.zshenv is read by *every* zsh invocation\n   echo 'export EDITOR=vim' >> ~\u002F.zshrc\n\n   # bash — add to both, so interactive and login shells agree\n   echo 'export EDITOR=vim' >> ~\u002F.bashrc\n   echo 'export EDITOR=vim' >> ~\u002F.profile\n\n   # mosh \u002F `sh -lc` \u002F any POSIX login-shell launch (e.g. herdr started over SSH+mosh)\n   echo 'export EDITOR=vim' >> ~\u002F.profile\n   ```\n\n   If you're unsure which applies, adding it to **`~\u002F.profile`** covers the login-shell launch\n   paths; keep it in your shell's rc too for interactive use.\n\n2. **Restart the herdr server** so it re-reads the environment — `reload-config` and `prefix+q`\n   are **not** enough (the first doesn't re-read env; the second only quits the client and leaves\n   the detached server running with its old environment):\n\n   ```bash\n   herdr server stop   # stops the background daemon — ends all panes, so finish in-flight work first\n   herdr               # relaunch from a shell where `echo $EDITOR` already prints your editor\n   ```\n\n3. **Verify:** open any shell pane *inside* herdr and run `echo $EDITOR`. Once that prints your\n   editor (it was empty before), `e` will open it. (A future settings file will also let you set\n   the editor command directly — see [Roadmap](#roadmap).)\n\n## Documentation\n\n- **[Install & updating](docs\u002Finstall.md)** — prebuilt vs. source, pinning a version, local-dev linking, and how updates surface (the in-app \"update available\" banner).\n- **[External renderers](docs\u002Frenderers.md)** — the optional `glow` \u002F `delta` \u002F `bat` integrations and the plain-text fallback when they're absent.\n- **[Summoning & keybindings](docs\u002Fusage.md)** — the open actions, the idempotent launcher, split vs. tab, and the `--remote` caveat.\n- **[Architecture](ARCHITECTURE.md)** — one in-process TUI owning both columns, the component map, off-thread rendering, and the load-bearing decisions (read-only, delegate rendering, git-first).\n- **[Security](SECURITY.md)** — the threat model and mitigations for opening untrusted content, and how to report a vulnerability.\n\n## Roadmap\n\nA few things on the way:\n\n- **Settings & customization** — a config file for keymaps, the default split, themes, and your own renderer\u002Feditor commands.\n\n**Hit a bug, or want a feature?** Please [open an issue](https:\u002F\u002Fgithub.com\u002Fsmarzban\u002Fherdr-file-viewer\u002Fissues) — bug reports and feature requests are very welcome.\n\n## Development\n\nThis crate is a library (`src\u002Flib.rs` + modules) plus a thin binary (`src\u002Fmain.rs` →\n`run()`), so the components are unit-testable.\n\n```bash\ncargo test                 # unit + integration + e2e (pty) tests\ncargo build --release      # what herdr's [[build]] step runs\ncargo run                  # run the viewer locally, outside herdr\n```\n\nThe e2e tests drive the real binary over a pseudo-terminal; they stub the editor via\n`$EDITOR` and run in temporary directories, so they need neither glow\u002Fdelta\u002Fbat nor a live\nherdr.\n\n## License\n\n[MIT](LICENSE) © Saeed Marzban\n","herdr-file-viewer 是一款专为 herdr 终端环境设计的 Git 感知型只读文件查看器。它采用 Rust 编写，提供键盘驱动的 TUI 界面，左侧为带 Git 状态标记（M\u002FA\u002FD\u002F?）的目录树，右侧根据文件类型自动渲染：修改文件显示 diff（依赖 delta），Markdown 文件渲染为富文本（依赖 glow），源码文件支持语法高亮（依赖 bat）。支持跨平台运行，可嵌入 herdr 分屏或全屏使用，全程不修改文件、不执行任意代码，保障安全性。适用于开发者在终端中快速浏览代码库结构、审查变更、预览文档，尤其适合与构建、调试或 AI 代理协同工作的轻量级开发场景。",2,"2026-07-08 04:30:02","CREATED_QUERY"]