Model or dataset
yz671/viewllm avatar
yz671/viewllm

viewllm: a single Go binary that serves LLM-generated HTML and Markdown reports

Single-binary HTML report viewer for LLM-generated artifacts

826 stars113 forksHTMLMIT

At a glance

What is it?
viewllm is a read-only local web server for the HTML and Markdown files that coding agents produce. It solves a real gap (GitHub will not render HTML, VS Code Live Preview breaks over SSH) but it is a viewer, not a report generator, and its sharing model is deliberately ephemeral.
Who is it for?
Adopt viewllm if you already have agents writing .html or .md files into a project folder and you work over SSH, WSL or a remote box where a browser preview extension is unreliable. Skip it if you need authenticated multi-user access, durable share links, or a hosted archive, because the tunnel URL is regenerated on every start and anyone holding the link can read every report in the served directory.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 83 days ago.
What is it written in?
Mainly HTML, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap viewllm fills: agents write HTML, and nothing renders it

The README frames the problem with a list of four failures. VS Code Live Preview breaks over SSH and WSL. GitHub renders Markdown but not HTML. Running python -m http.server gives a raw directory listing with no preview, no search and no unread state. Sharing means downloading files and emailing them. Those four cases describe the same underlying situation: an agent has produced a self-contained HTML artifact, and the developer has no cheap way to look at it in place. The project is aimed at people running Claude Code, Codex or Cursor in a terminal, particularly on a remote machine. The README also quotes Thariq Shihipar, an engineering lead on Claude Code at Anthropic, saying he has stopped writing Markdown files and switched to having Claude Code generate HTML. That quote is the thesis viewllm is built around, and it is worth noting the tool takes no position on whether HTML reports are a good idea. It only assumes the files exist.

What actually runs: a Go binary, a watcher and a browser-rendered file tree

The README describes a single Go binary of about 9MB with no dependencies, no database and no config files, and states it is read-only. Startup is listed at roughly 100ms with about 7MB of memory. The mechanism is a local HTTP server: run it in a directory and it serves that directory, watching for new and modified files and surfacing them with unread indicators as an agent writes them. The UI is a file tree with a search bar, hover previews, thumbnails and text snippets, plus Light, Dark and Solarized themes. Unread tracking is per device rather than per server, which matters because it means the server holds no user state at all. Settings live in the browser's localStorage, so stopping the process leaves nothing behind. The GitHub browsing mode changes the data flow meaningfully: the full file list is fetched in a single GitHub API call, and individual reports are downloaded on demand and rendered in the browser with nothing written to disk. The repo and token are also kept in localStorage, so the connection is re-established on the next visit without re-entering credentials.

Getting it running, and the four flags that matter

The zero-install path is one command: npx viewllm@latest. The binary path downloads a release asset, for example curl -fsSL https://github.com/yz671/viewllm/releases/latest/download/viewllm-linux-amd64 -o viewllm followed by chmod +x viewllm and ./viewllm. Building from source is a two-step clone and go build -o viewllm ., then ./viewllm. The usage line is viewllm [directory] [-p port] [-exclude dir]... [-exclude-file name]... [-tunnel]. It serves the current directory by default and finds an open port automatically if the default 8090 is taken. The two exclude flags are repeatable, which is the practical way to keep a node_modules or .git directory out of the tree. The -tunnel flag is the one that changes the security posture, and it is covered below. A detail worth flagging: the README states that the flags use single dashes, so -tunnel and -p, not the double-dash GNU style that many Go tools accept. If you copy a command from another tool's documentation, check the dash count before assuming it parses.

The tunnel is a convenience with a short half-life

Running npx viewllm@latest -tunnel prints a Cloudflare-hosted URL of the form https://random-words.trycloudflare.com. The README is explicit about the trade: anyone with that link can view your reports, and the link expires when you stop viewllm, with a new one created each time. There are no accounts. That combination is coherent for a demo or a quick handoff to a colleague, and it is the wrong shape for anything durable. You cannot put the link in a ticket and expect it to resolve tomorrow. You also cannot revoke access for one person without stopping the server for everyone. The README does not describe any password, allowlist or per-link scoping, so the served directory is the access boundary. If a folder contains one report you would not send to a client, that folder should not be the one you pass to -tunnel. The per-device unread tracking is a nice side effect of this design, since there are no accounts to tie read state to, but it also means you cannot tell who has read what.

GitHub mode, tokens, and the rate limit that shapes it

The GitHub browsing path is the most interesting part of the design because it decouples the report from the machine that produced it. The README gives three scenarios where the generating machine is gone: a CI job, a short-lived cloud instance, or a teammate's laptop. The flow is to start viewllm with no directory, open the gear icon, choose Browse GitHub repository under Source, and enter owner/repo or paste the URL, adding a token for private repos. Public repositories work without a token, subject to an unauthenticated limit of 60 requests per hour. An authenticated token raises that to 5,000 per hour. The README recommends a fine-grained token scoped to Only select repositories with Contents: Read-only, and notes that Metadata: Read-only is added automatically. It warns that a classic token with the repo scope grants full read and write access to all private repositories, which is a much larger grant than this tool needs. The token is sent only to GitHub's API from the browser, according to the README, and never to the viewllm server.

Where viewllm is the wrong tool

The read-only design is a hard boundary, not a limitation to work around. There is no editing, no annotation, no commenting and no way to leave feedback on a report from inside the viewer. If your workflow needs a reviewer to mark up a generated analysis, viewllm serves the file and stops there. The second boundary is persistence. Nothing is written to disk in GitHub mode, and in local mode the settings and read state live in each browser's localStorage. Clear your browser data and your unread state is gone. The third is access control: the README describes no authentication layer for locally served files, so binding to a network interface exposes the directory to anyone who can reach the port. The fourth is that viewllm does not generate anything. It has no prompt interface, no agent, no templating. The README's quick start tells you to ask your existing agent for a report and only then run viewllm. If you were looking for a tool that turns a prompt into a rendered report, this is one layer below that.

Against python -m http.server and a static site generator

The README names python -m http.server as one of the things viewllm replaces, and the comparison is fair but narrower than it first appears. Both serve a directory over HTTP. The difference is everything layered on top: file watching with unread indicators, search across the tree, hover previews, thumbnail renders, Markdown formatting in GitHub style, and the tunnel flag. If you only need to fetch one file over HTTP, the Python one-liner is already installed and viewllm adds a download. A static site generator such as Hugo or MkDocs sits at a different point in the pipeline. It owns the build step, produces a navigable site with a permanent structure, and is the right answer if the reports are a long-lived documentation set that should be versioned and published. viewllm deliberately has no build step and no output directory. It is a viewer over whatever is on disk right now, which is why it fits a loop where an agent writes a file and you want to see it seconds later. Choose the generator when the artifact is the deliverable. Choose viewllm when the artifact is a byproduct of a session you are still in.

Maintenance cost, licence and what to check first

The licence is MIT, which permits commercial use and modification with the usual requirement to keep the copyright notice and permission text. That is a permissive baseline, not legal advice, and the GitHub token you paste into the settings dialog is a separate question from the licence: it is a credential stored in browser localStorage on whatever machine you use. Treat it accordingly and prefer the fine-grained, single-repo, Contents: Read-only token the README recommends. On maintenance, the release cadence visible here is three patch releases on a single day (v0.6.1, v0.6.2, v0.6.3 on 2026-06-24), which suggests active but still pre-1.0 development. The npx path always pulls the latest version, so a patch release reaches you on the next run without any action; the binary path requires re-downloading from the releases page. There are no config files to migrate between versions, which keeps upgrade cost low, but it also means there is no version pinning mechanism described in the README. If reproducibility matters, pin the binary rather than using npx, and check the release notes for the version you pin.

Editorial conclusion

Adopt viewllm if you already have agents writing .html or .md files into a project folder and you work over SSH, WSL or a remote box where a browser preview extension is unreliable. Skip it if you need authenticated multi-user access, durable share links, or a hosted archive, because the tunnel URL is regenerated on every start and anyone holding the link can read every report in the served directory. Before trusting it with private repositories, verify what the fine-grained token actually grants: the README asks for Contents: Read-only on one selected repo, and that is the configuration to test against first.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. yz671/viewllm on GitHub
Community notes

Community notes