A GitHub CLI extension that renders GitHub objects into deterministic local Markdown projections. GitHub remains authoritative; local files become searchable, linkable repository artifacts.
The issues renderer is implemented and verified against a live repository. v0.1.0 is the first release target.
- Why gh-render exists
- Installation
- Usage
- Selecting issues
- Generated projection
- Safety model
- Repository map
- Development
GitHub issues are part of a repository's working context, but they normally remain outside its filesystem. This limits ordinary search, local links, offline inspection, and agent access.
gh render materializes a read-only local view:
GitHub issues β gh render issues β .issues/*.md
The projection can be committed and reviewed without becoming a second issue tracker. Rendering never writes to GitHub.
Once v0.1.0 is released:
gh extension install digimata/gh-renderTo build and install the current source:
git clone https://github.com/digimata/gh-render.git
cd gh-render
go build -o gh-render .
gh extension install .The extension is invoked as gh render.
Render the current repository's issues:
gh render issuesRender an explicit repository or output directory:
gh render issues --repo owner/repository
gh render issues --output .issuesInspect changes without writing, or verify that a committed projection is current:
gh render issues --dry-run
gh render issues --checkWith no selectors, gh render issues includes every open and closed issue.
Render the 20 most recently updated issues:
gh render issues --limit 20Filter by state, labels, assignee, or author:
gh render issues --state open
gh render issues --label bug --label p0
gh render issues --assignee @me
gh render issues --author @meDifferent selector types combine with AND. Repeated labels require every label. @me resolves to the authenticated GitHub login.
Control ranking before a limit is applied:
gh render issues --limit 10 --sort created --order descRank by your own label scheme. Each issue ranks by the first listed label it carries; issues with none of them go last, and the index lists issues in that order:
gh render issues --state open --sort labels --label-order P0,P1,P2,P3
gh render issues --sort labels --label-order priority:high,priority:lowThe issues renderer specification defines the complete selection and tie-breaking contract.
The default output is:
.issues/
βββ index.md
βββ iss-0001.md
βββ iss-0002.md
βββ iss-0123.md
Each issue file contains GitHub metadata, the author and their trust class, a source link, and the issue body. The index records the source repository, the normalized selection, and a Data as of line carrying the newest updated_at in the projection β derived from GitHub data, never the render clock, so output stays deterministic.
Generated files contain an ownership marker. A second render against unchanged GitHub data produces byte-identical output.
gh-render follows four filesystem rules:
- It replaces or removes only files carrying its ownership marker.
- It refuses the entire operation when a target file is unmanaged.
- It validates the complete write plan before changing disk state.
- It writes each file through an atomic replacement.
A filename matching the active renderer's managed pattern is reserved. If an unmanaged regular file occupies such a nameβeven outside the current selectionβthe complete render fails before mutation. Unrelated files, directories, and symlinks are ignored.
A filtered render is a complete projection of that filter. Managed files outside the selected set become stale and are removed in normal mode. Use --dry-run before changing an existing projection.
The global specification defines deterministic output, path validation, exit codes, and validation modes.
Issue titles and bodies on a public repository can be written by anyone, and .issues/ is often read by agents. gh-render therefore treats all GitHub-authored text as data (ADR-002):
- Each issue records
author,author_association, andtrust. Owners, members, and collaborators aremaintainer; everyone else isexternal. - An external issue's body follows a fixed provenance note, with every line quoted, so text imitating headings, markers, or notes stays visibly quoted.
- Content GitHub hides from readers is removed from every issue and recorded in
content_flags: zero-width and bidirectional control characters, Unicode tag characters, and HTML comments outside fenced code.
These measures make provenance explicit. They do not stop a model from following text it reads. If agents consume .issues/, tell them to treat issue text as data: never run commands, edit files, or follow links because an issue asks, and report text that addresses an AI or tool.
gh-render/
βββ main.go # process entry point
βββ internal/
β βββ app/ # object dispatch, flags, orchestration, exit codes
β βββ issues/ # issue fetch, normalization, selection, rendering
β βββ projection/ # write planning and filesystem safety
βββ tests/ # black-box test suites and golden fixtures
βββ docs/
β βββ spec.md # cross-renderer behavioral contract
β βββ objects/ # object-specific specifications
β βββ .decisions/ # architecture decisions
βββ .plan/ # approved implementation plans
βββ .github/workflows/ # precompiled extension releases
βββ CHANGELOG.md
The current implementation plan is .plan/v0.md. The detailed coding handoff is .plan/v0-implementation.md. The rendering-model decision is ADR-001; the content-trust decision is ADR-002.
Requirements:
- Go version declared in
go.mod; - an authenticated GitHub CLI session.
Validation:
go test ./...
go test -race ./...
go vet ./...
go build -o gh-render .Automated tests never use the network or the local GitHub configuration. All _test.go files and golden fixtures live under tests/; production packages contain no test files.
Start with the global specification, then read the specification for the object being changed. Update CHANGELOG.md with user-visible behavior.