https://github.com/thiagokokada/gh-gfm-preview
A standalone/GitHub CLI extension to preview GitHub Flavored Markdown, even offline.
https://github.com/thiagokokada/gh-gfm-preview
cli gh-extension go golang markdown
Last synced: 3 months ago
JSON representation
A standalone/GitHub CLI extension to preview GitHub Flavored Markdown, even offline.
- Host: GitHub
- URL: https://github.com/thiagokokada/gh-gfm-preview
- Owner: thiagokokada
- License: mit
- Created: 2025-02-27T11:24:30.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2026-04-20T12:18:30.000Z (3 months ago)
- Last Synced: 2026-04-20T13:42:18.209Z (3 months ago)
- Topics: cli, gh-extension, go, golang, markdown
- Language: Go
- Homepage:
- Size: 2.81 MB
- Stars: 87
- Watchers: 1
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
- awesome-gh-extensions - thiagokokada/gh-gfm-preview - 01-16 | A standalone/GitHub CLI extension to preview GitHub Flavored Markdown, even offline. | (🧩 Categories / UI / Dashboard)
- gh-extension-atlas - gh-gfm-preview - gfm-preview` | Offline Markdown preview | Provides a standalone GitHub-flavored Markdown preview path. | active | (Dashboard/TUI)
README
# gh gfm-preview
A Go program to preview GitHub Flavored Markdown (GFM) :notebook:.
The `gh-gfm-preview` command start a local web server to serve the markdown
document. **gh gfm-preview** renders the HTML using
[yuin/goldmark](https://github.com/yuin/goldmark) and some extensions and
frontend tricks to have similar features and look to how GitHub renders a
markdown.
It may also be used as a [GitHub CLI](https://cli.github.com) extension.
This is a hard fork of
[yusukebe/gh-markdown-preview](https://github.com/yusukebe/gh-markdown-preview/),
that uses the [GitHub Markdown API](https://docs.github.com/en/rest/markdown),
but this means it doesn't work offline. The code of this repository tries to
emulate the look of GitHub Markdown rendering as close as possible, but the
original project will be even closer to the actual result if you don't need
offline rendering.
## Screenshots
Open your browser:

Live reloading:
https://github.com/user-attachments/assets/0219ac01-71d3-4568-bff4-c9de092ca4e3
## Highlights
- **Works offline** - You don't need an internet connection.
- **Fast** - Since it doesn't rely on external services it is really fast.
- **No-dependencies** - You can just run the standalone binary (or optionally
via `gh` as an extension).
- **Zero-configuration** - You don't have to set the GitHub access token.
- **Live reloading** - You don't need reload the browser.
- **Auto open browser** - Your browser will be opened automatically.
- **Auto find port** - You don't need find an available port if default is used.
- **Graceful degradation** - Basic functionality works even without JavaScript.
## Supported GFM features
- [x] : [Most (all?) of GitHub Flavored Markdown spec](https://github.github.com/gfm/)
- [x] : [Emojis](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#using-emojis)
+ not all of GitHub emojis are supported since a few of them are extensions
to the Unicode spec, but the majority of them works
- [x] : [Alerts](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts)
- [x] : [Code blocks with syntax
highlighting](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks)
+ highlighting is done via
[alecthomas/chroma](https://github.com/alecthomas/chroma); not all GitHub
languages are supported and there are slightly differences in highlighting
- [x] : [Section links](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#section-links)
- [x] : [Raw HTML](https://gist.github.com/seanh/13a93686bf4c2cb16e658b3cf96807f2)
+ no filtering is done so you can pass any arbitrary HTML, different from
GitHub where only a subset of HTML is allowed
- [x] : [MathJax](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/writing-mathematical-expressions)
- [x] : [Mermaid diagrams](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-diagrams)
- [x] : [GeoJSON/TopoJSON diagrams](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-diagrams)
+ rendered with Leaflet and online map tiles, so this feature does not work offline
+ the basemap will be OSM-style, not GitHub’s Azure/TomTom tiles, so it should be structurally similar rather than pixel-identical
- [ ] : [STL 3D diagrams](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-diagrams)
- [ ] : Mentioning people/Referencing issues and Pull Requests/Other features
that depends in GitHub access
## Installation
### GitHub Extension
You need to have [gh](https://github.com/cli/cli#installation) installed.
```console
gh extension install thiagokokada/gh-gfm-preview
```
Upgrade:
```console
gh extension upgrade gfm-preview
```
### Standalone
You need to have [Go](https://go.dev/) installed.
```console
go install github.com/thiagokokada/gh-gfm-preview@latest
```
### Nix
Assuming that you have [Flakes](https://wiki.nixos.org/wiki/Flakes) enabled:
```console
nix run github:thiagokokada/gh-gfm-preview
```
## Usage
The usage:
```console
gh gfm-preview README.md
```
Or this command will detect README file in the directory automatically.
```console
gh gfm-preview
```
You can also preview Markdown from stdin by piping or using `-`:
```
echo "# Hello" | gh gfm-preview
cat README.md | gh gfm-preview
gh gfm-preview - < README.md
```
Then access the local web server such as `http://localhost:3333` with Chrome,
Firefox, or Safari.
Available options:
```
-p, --port int TCP port number of this server (default 3333)
-H, --host string hostname this server will bind (default "localhost")
-R, --disable-reload disable live reloading
-A, --disable-auto-open disable auto opening your browser
-l, --light-mode force light mode
-d, --dark-mode force dark mode
-m, --markdown-mode force "markdown" mode (rather than default "gfm")
-D, --directory-listing enable directory browsing mode
--directory-listing-show-extensions string file extensions to show in directory listing (comma-separated, use '*' for all files) (default ".md,.txt")
--directory-listing-text-extensions string text file extensions for preview (comma-separated, others will be served as binary) (default ".md,.txt")
--no-color disable color for logs
-v, --verbose show verbose output
--version show program version
```
### Directory Listing
Enable directory browsing mode to navigate and preview files:
```console
# Enable with default settings
gh gfm-preview --directory-listing
# Or
gh gfm-preview -D
# Show all file types
gh gfm-preview --directory-listing --directory-listing-show-extensions="*"
# Custom file extensions
gh gfm-preview --directory-listing \
--directory-listing-show-extensions=".md,.rst,.adoc" \
--directory-listing-text-extensions=".md,.txt,.rst"
```
## Other usages
Since the binary is static and it works offline, this is a good program to
use to preview how a Markdown is looking in e.g.:
[neovim](https://github.com/neovim/neovim/). For example, you can add this
in your `$HOME/.config/nvim/init.lua`:
```lua
local function preview_markdown()
local file = vim.fn.expand("%")
local on_exit_cb = function(out)
print("Markdown preview process exited with code:", out.code)
end
local process = vim.system(
-- assuming that the extension were installed using gh
-- the reason we are not using `gh gfm-preview` instead is because this
-- can cause an issue where the gh process is killed but not the
-- gh-gfm-preview, since the kill signal will not reach the child process
{vim.fn.expand("$HOME/.local/share/gh/extensions/gh-gfm-preview/gh-gfm-preview"), file},
on_exit_cb
)
vim.api.nvim_create_autocmd({ "BufUnload", "BufDelete" }, {
buffer = vim.api.nvim_get_current_buf(),
callback = function()
process:kill("sigterm")
-- timeout (in ms), will call SIGKILL upon timeout
process:wait(500)
end,
})
end
-- create a shortcut only in Markdown files, mapped to `P`
vim.api.nvim_create_autocmd({ "FileType" }, {
pattern = { "markdown" },
callback = function()
vim.keymap.set("n", "P", preview_markdown, {
desc = "Markdown preview", buffer = true
})
end,
})
```
## Development
You can run the following command to (re-)generate assets:
```console
go generate ./...
```
And you can run the following command to build:
```console
go build
```
If you have `nix` with [Flakes](https://wiki.nixos.org/wiki/Flakes) enabled:
```console
nix develop
```
## Related projects
- GitHub CLI
- Grip
- github-markdown-css
- gh-markdown-preview