Glow can render markdown from various sources, making it flexible for different workflows.
Local Files
Render any markdown file by providing its path:
glow /path/to/document.md
glow ~/Documents/notes.md
Glow supports both relative and absolute paths, with automatic expansion of ~ and environment variables.
Directories
When you provide a directory path, Glow searches for README files:
glow .
glow /path/to/project
README Discovery
Glow searches for these filenames in order (main.go:35):
readmeNames = []string{"README.md", "README", "Readme.md", "Readme", "readme.md", "readme"}
The discovery process (main.go:112-131):
st, err := os.Stat(arg)
if err == nil && st.IsDir() {
var src *source
_ = filepath.Walk(arg, func(path string, _ os.FileInfo, err error) error {
if err != nil {
return err
}
for _, v := range readmeNames {
if strings.EqualFold(filepath.Base(path), v) {
r, err := os.Open(path)
if err != nil {
continue
}
u, _ := filepath.Abs(path)
src = &source{r, u}
// abort filepath.Walk
return errors.New("source found")
}
}
return nil
})
Glow walks through the directory and renders the first matching README file found.
Read markdown from stdin using - or by piping content:
Explicit stdin with Dash
echo "# Hello World" | glow -
Automatic Pipe Detection
Glow automatically detects piped input:
curl https://example.com/doc.md | glow
The pipe detection logic (main.go:211-220):
func stdinIsPipe() (bool, error) {
stat, err := os.Stdin.Stat()
if err != nil {
return false, fmt.Errorf("unable to open file: %w", err)
}
if stat.Mode()&os.ModeCharDevice == 0 || stat.Size() > 0 {
return true, nil
}
return false, nil
}
HTTP/HTTPS URLs
Fetch and render markdown from any HTTP(S) URL:
glow https://raw.githubusercontent.com/charmbracelet/glow/main/README.md
glow https://example.com/documentation.md
The URL handling (main.go:87-102):
// HTTP(S) URLs:
if u, err := url.ParseRequestURI(arg); err == nil && strings.Contains(arg, "://") {
if u.Scheme != "" {
if u.Scheme != "http" && u.Scheme != "https" {
return nil, fmt.Errorf("%s is not a supported protocol", u.Scheme)
}
resp, err := http.Get(u.String())
if err != nil {
return nil, fmt.Errorf("unable to get url: %w", err)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("HTTP status %d", resp.StatusCode)
}
return &source{resp.Body, u.String()}, nil
}
}
Only http:// and https:// protocols are supported. Other schemes will return an error.
GitHub Repositories
Glow provides convenient shortcuts for GitHub repositories:
GitHub URL Patterns
# Standard GitHub URL
glow https://github.com/charmbracelet/glow
# Without protocol
glow github.com/charmbracelet/glow
# Using github:// protocol
glow github://charmbracelet/glow
All three formats fetch the repository’s README using the GitHub API.
GitHub API Integration
Glow uses the GitHub API to find the README (github.go:14-57):
func findGitHubREADME(u *url.URL) (*source, error) {
owner, repo, ok := strings.Cut(strings.TrimPrefix(u.Path, "/"), "/")
if !ok {
return nil, fmt.Errorf("invalid url: %s", u.String())
}
type readme struct {
DownloadURL string `json:"download_url"`
}
apiURL := fmt.Sprintf("https://api.%s/repos/%s/%s/readme", u.Hostname(), owner, repo)
res, err := http.Get(apiURL)
if err != nil {
return nil, fmt.Errorf("unable to get url: %w", err)
}
This approach:
- Parses owner and repository from the URL
- Calls GitHub’s README API endpoint
- Downloads the README content
- Works regardless of README filename (README.md, readme.md, etc.)
GitLab Repositories
Similar to GitHub, Glow supports GitLab repository shortcuts:
GitLab URL Patterns
# Standard GitLab URL
glow https://gitlab.com/owner/project
# Without protocol
glow gitlab.com/owner/project
# Using gitlab:// protocol
glow gitlab://owner/project
GitLab API Integration
Glow uses the GitLab API v4 (gitlab.go:14-61):
func findGitLabREADME(u *url.URL) (*source, error) {
owner, repo, ok := strings.Cut(strings.TrimPrefix(u.Path, "/"), "/")
if !ok {
return nil, fmt.Errorf("invalid url: %s", u.String())
}
projectPath := url.QueryEscape(owner + "/" + repo)
type readme struct {
ReadmeURL string `json:"readme_url"`
}
apiURL := fmt.Sprintf("https://%s/api/v4/projects/%s", u.Hostname(), projectPath)
The process:
- Extracts owner and project name
- URL-encodes the project path
- Calls GitLab’s projects API
- Converts blob URL to raw URL for content
- Downloads the README
Source Resolution Order
Glow resolves sources in this order (main.go:72-148):
Check for stdin (-)
If argument is -, read from standard input
Try GitHub/GitLab URL
Attempt to parse as GitHub or GitLab repository
Try HTTP(S) URL
Parse as regular HTTP/HTTPS URL
Try Directory
Check if path is directory and search for README
Try Local File
Attempt to open as local file
Examples
Local Files and Directories
# Current directory's README
glow
# Specific file
glow CHANGELOG.md
# Directory with README
glow ~/projects/myapp
Remote Sources
# GitHub shortcut
glow github.com/charmbracelet/glow
# GitLab project
glow gitlab.com/gitlab-org/gitlab
# Direct markdown URL
glow https://raw.githubusercontent.com/owner/repo/main/docs/guide.md
# From pipe
cat notes.md | glow
# From heredoc
glow <<EOF
# Quick Note
This is **important**!
EOF
# From curl
curl -s https://example.com/api/docs.md | glow
Combining with Other Flags
# GitHub repo with custom style
glow github.com/charmbracelet/glow --style pink
# URL with pager
glow https://example.com/doc.md --pager
# Stdin with custom width
echo "# Test" | glow --width 60
When working with GitHub or GitLab repositories, using the URL shortcuts is faster than navigating to the raw file URL, as Glow handles README discovery automatically.