From 4cb1852ad354302aa21b5abc17bae2c8a3e710a0 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 20 Jul 2026 12:23:04 +0000 Subject: [PATCH 1/5] Add design doc for dirview, a lightweight local directory viewer server Research and design (no implementation) for a single-file web server that serves a two-pane directory browser with GitHub-flavored markdown, Shiki code highlighting, git status/diff integration, live file watching, and Catppuccin Latte/Mocha theming. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01DJieA2dNDXVv7P3Q6HpCNB --- docs/dirview-design.md | 275 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 docs/dirview-design.md diff --git a/docs/dirview-design.md b/docs/dirview-design.md new file mode 100644 index 0000000..48b5f7a --- /dev/null +++ b/docs/dirview-design.md @@ -0,0 +1,275 @@ +# dirview — Design for a Lightweight Local Directory Viewer + +**Status:** Design only — not yet implemented. + +A small web server you run in any local directory that gives you a two-column +browsing UI: directory tree on the left, rendered file on the right, with +first-class markdown rendering, syntax-highlighted code, git status awareness, +inline change indicators with click-through diffs, and live updates as files +change on disk. Catppuccin themed (Latte light / Mocha dark). + +``` +uv run dirview.py # serve the current directory at http://127.0.0.1:7440 +``` + +--- + +## 1. Requirements + +1. Two-column layout: directory tree (left), viewed file (right) +2. GOOD markdown rendering (GitHub-flavored) +3. GOOD code rendering (real syntax highlighting, not an afterthought) +4. Git status shown in the tree; filter to changed/new files +5. For changed files, a *subtle* indication of *where* changes are, with + click-through to a standard diff representation +6. Watches the directory tree and keeps open views up to date + +Constraints: as little code as possible — assemble best-in-class existing +solutions rather than building anything from scratch. Catppuccin light + dark. + +## 2. Research: what already exists + +No single existing tool covers all six requirements; each covers a slice: + +| Tool | Tree | Markdown | Code | Git status | Inline diffs | Watch | Verdict | +|---|---|---|---|---|---|---|---| +| [markserv](https://github.com/markserv/markserv) / [mdserver](https://github.com/deepdadou/mdserver) / [gh-markdown-preview](https://github.com/yusukebe/gh-markdown-preview) | dir index only | ✅ | partial | ❌ | ❌ | ✅ | Markdown + live reload, no git at all | +| [difit](https://github.com/yoshiko-pg/difit) | changed files only | ❌ | ✅ | ✅ | ✅ (GitHub-style) | partial | Excellent diff review UI, but not a directory *browser* — no markdown, no unchanged files | +| [diffhub](https://github.com/mblode/diffhub) | changed files only | ❌ | ✅ | ✅ | ✅ | ❌ | Same category as difit | +| `code serve-web` / code-server | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | Covers everything but is a full IDE: heavyweight, editing-oriented, not a calm reading view | +| [Ferrite](https://github.com/OlaProeis/Ferrite) | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | Native desktop app (Rust/egui), not a web server | +| klaus / gitweb / Gitea | ✅ | ✅ | ✅ | commit-oriented | commit-oriented | ❌ | Browse *commits*, not the live working tree | + +**Conclusion:** the gap is real but narrow — every individual capability is a +solved problem with a clear best-in-class library. The right build is a thin +glue server (~200–300 lines) plus one HTML page that composes those libraries, +not a new app. + +## 3. Recommended architecture + +**A single-file Python server + a single static HTML page.** All rendering +happens in the browser; the server only serves files, answers git questions, +and pushes change events. Total new code target: **under ~800 lines.** + +### Why this shape + +- The server stays trivial (static files + 4 JSON endpoints + 1 SSE stream) — + no template engine, no server-side rendering, no build step. +- The heavy lifting (markdown, highlighting, diff HTML) is done by mature JS + libraries loaded as ES modules — exactly the "pull from best-in-class" + requirement. +- Python + `uv` matches this repo's existing tooling. With + [PEP 723 inline script metadata](https://packaging.python.org/en/latest/specifications/inline-script-metadata/), + `dirview.py` declares its own dependencies and `uv run dirview.py` just works + in any directory, no venv setup. + +### Component choices (all best-in-class, all boring) + +| Concern | Choice | Why | +|---|---|---| +| HTTP server | **Starlette + uvicorn** (Python) | Minimal async framework; SSE and static files out of the box. (FastAPI works too but adds nothing we need.) | +| File watching | **[watchfiles](https://github.com/samuelcolvin/watchfiles)** | Rust `notify`-based, the watcher behind `uvicorn --reload`; `awatch()` gives an async iterator of debounced change batches — feeds SSE directly | +| Git interrogation | **`git` subprocess** (`status --porcelain=v2`, `diff`) | Zero dependencies, always agrees with the user's git; porcelain v2 is a stable machine format. GitPython/pygit2 add weight for no benefit here | +| Markdown | **[markdown-it](https://github.com/markdown-it/markdown-it)** (client-side) + task-list/anchor plugins | The de-facto standard CommonMark+GFM renderer (VS Code uses it). Critically, its token `map` gives **source line ranges per block** — which is what makes requirement 5 work on *rendered* markdown | +| Code highlighting | **[Shiki](https://shiki.style)** | TextMate-grammar highlighting (identical quality to VS Code). Ships **Catppuccin Latte/Frappé/Macchiato/Mocha as bundled themes**, and its [dual-theme mode](https://shiki.style/guide/dual-themes) emits CSS-variable output so light/dark switching is pure CSS | +| Diff rendering | **[diff2html](https://github.com/rtfpessoa/diff2html)** | The standard "GitHub-style diff from raw `git diff` text" library; line-by-line and side-by-side; colors overridable via CSS variables → Catppuccin-able | +| UI reactivity | **Alpine.js** | Already used by this repo's viewer; no build step; a recursive `