https://github.com/loping151/gitshelf
Self-hosted, read-only Git repository browser — read your bare/mirror repos in place (zero copy) with GitHub-style previews for code, Markdown, PDF, images, CSV and more.
https://github.com/loping151/gitshelf
devtools git gitea-alternative go golang read-only repository-browser self-hosted
Last synced: about 11 hours ago
JSON representation
Self-hosted, read-only Git repository browser — read your bare/mirror repos in place (zero copy) with GitHub-style previews for code, Markdown, PDF, images, CSV and more.
- Host: GitHub
- URL: https://github.com/loping151/gitshelf
- Owner: Loping151
- License: mit
- Created: 2026-06-30T23:14:31.000Z (about 14 hours ago)
- Default Branch: main
- Last Pushed: 2026-07-01T00:43:35.000Z (about 12 hours ago)
- Last Synced: 2026-07-01T01:14:44.076Z (about 11 hours ago)
- Topics: devtools, git, gitea-alternative, go, golang, read-only, repository-browser, self-hosted
- Language: Go
- Size: 2.28 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
README

# GitShelf
**English** · [简体中文](README.zh-CN.md)
A self-hosted, read-only Git browser. Point it at a folder of bare/mirror
repos and read them like GitHub — no import, no copy.

[Features](#features) · [Quick start](#quick-start) · [Config](#configuration) · [Screenshots](#screenshots)
Typical use: browsing your nightly **GitHub mirror backups** (`git clone --mirror`) offline.
GitShelf reads existing `*.git` mirrors in place and gives you file trees,
rich previews (code, Markdown, PDF, images, audio/video, CSV, JSON), commit
history and diffs, blame, code search, and — if you export them — the
issues, PRs and releases that go with the code. It's deliberately read-only:
no pushing, no CI, no issue editing. Just the browsing layer.
## Why
cgit is bare-bones; Gitea and GitLab are heavy and insist on importing repos
into their own storage first. GitShelf sits in between — it reads what's
already on disk.
| | Gitea / Forgejo | cgit | GitLab CE | GitShelf |
|---|---|---|---|---|
| Reads existing bare repos in place | needs import | yes | needs import | **yes** |
| File previews (code, PDF, images…) | good | minimal | great | **good** |
| Shows exported issues / PRs | no | no | no | **yes** |
| Footprint | low | tiny | heavy | **single binary** |
| Scope | full forge | minimal | full forge | **read-only** |
## Features
- Reads your existing bare/mirror repos directly — nothing is imported or duplicated.
- File previews: syntax highlighting (Chroma), GitHub-flavored Markdown, images, PDF, audio/video, CSV/TSV, JSON. Renderers are pluggable.
- Branch/tag switching, commit history, diffs, compare, blame, `git grep` search, zip/tar.gz downloads.
- Optional issues / PRs / releases from exported JSON, shown next to the code.
- Auth is on by default — the first visit walks you through creating an admin account.
- Dark / light / auto theme, responsive, keyboard-friendly.
- One static binary, config-driven, binds `127.0.0.1` by default, no database.
## Quick start
Grab a prebuilt binary for your platform from the
[Releases](https://github.com/Loping151/GitShelf/releases) page (no Go needed —
just `git` on PATH):
```bash
cp gitshelf.example.toml gitshelf.toml # then edit repo_source.path
./gitshelf -config gitshelf.toml # http://127.0.0.1:8888
```
Or build from source (Go 1.26+):
```bash
go build -o gitshelf ./cmd/gitshelf
./gitshelf -config gitshelf.toml
```
Or Docker:
```bash
docker run -p 8888:8888 \
-v /path/to/mirrors:/mirrors:ro \
-v /path/to/gitshelf.toml:/etc/gitshelf.toml:ro \
ghcr.io/loping151/gitshelf
```
A repo source is just a directory of bare repos:
```
/path/to/mirrors/
project-a.git/ # from: git clone --mirror
project-b.git/
```
## Configuration
One TOML file drives everything; there are no hard-coded paths. Full reference
in [`gitshelf.example.toml`](gitshelf.example.toml).
```toml
[server]
bind = "127.0.0.1:8888" # 0.0.0.0:8888 to expose on the LAN
theme = "auto"
[[repo_source]]
path = "/path/to/mirrors"
glob = "*.git"
namespace = "flat" # flat: / owner: //
[metadata] # optional
provider = "json-export"
path = "/path/to/meta"
[auth]
enabled = true # first visit creates the admin account
```
**Auth** is enabled by default. On first launch GitShelf sends you to a one-time
`/setup` page to pick an admin username and password (stored as a bcrypt hash —
never in the config). Turn it off only behind a trusted reverse proxy or for a
purely local instance.
The metadata JSON layout is one folder per repo (`//{summary.json,
issues/.json, prs/.json, releases/.json}`). Missing fields and files
are tolerated — a repo with no metadata just shows no issues tab.
## Screenshots
Browsing the bundled demo repo, dark and light:

| Code | Commit diff |
|---|---|
|  |  |
| Issue timeline | CSV as a table |
|  |  |
## URLs
```
/ repo list
/ repo home (README + tree)
//src// tree or file
//raw// raw file
//archive/. zip / tar.gz
//commits/ history /commit/ diff
//compare/... compare /blame//
//branches /tags /search?q=
//issues[/] /pulls[/] /releases[/]
```
## Architecture
```
web routing · templates · static · auth · CSP
├─ git Adapter interface → git CLI (argument arrays, never shell)
├─ render Registry → pluggable Renderer{code, markdown, image, pdf, …}
├─ metadata Provider interface → json-export
└─ config TOML load + validation
```
The git layer shells out to `git`, so any mirror/bare/worktree works; a
`go-git` backend can slot in behind the same interface later. See
[CONTRIBUTING.md](CONTRIBUTING.md).
## Development
```bash
go test ./...
go vet ./...
make build
```
## License
[MIT](LICENSE) © 2026 Loping151