Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
fb4348d
replace REST API with HTML/Atom scraper, rename binary to github
tamnd Jun 15, 2026
b37197e
chore: upgrade GitHub Actions to latest versions
tamnd Jun 19, 2026
9013920
gh: keyless core, repository reader, and the nine search types
tamnd Jul 25, 2026
d0d8bb0
gh: user and organization profiles
tamnd Jul 25, 2026
7aeba8f
gh: issues, pull requests, discussions, and timelines
tamnd Jul 25, 2026
0744d8c
gh: trees, blobs, raw content, and archives
tamnd Jul 25, 2026
dca357d
gh: commits, refs, releases, and ranges
tamnd Jul 25, 2026
8135c60
Wire the whole command surface onto the gh client
tamnd Jul 25, 2026
17cd105
gh: people, gists, activity, trending, and repository statistics
tamnd Jul 25, 2026
7fcae27
gh: the graph plane, plus the dependency graph pages
tamnd Jul 25, 2026
a8ab53e
gh: the page plane and doctor
tamnd Jul 25, 2026
71339d1
Update kit to v0.4.7
tamnd Jul 25, 2026
ed7a0a4
gh: fix package URLs, and reword the reference errors
tamnd Jul 25, 2026
2d4ff52
gh: give every error message a word to lead with
tamnd Jul 25, 2026
d02c052
gh: fail the build if a credential ever appears
tamnd Jul 25, 2026
e85a209
gh: read a blob from the page, in one request
tamnd Jul 25, 2026
9f4bbbb
gh: make -o url work, and narrow the author column
tamnd Jul 25, 2026
9114bcc
gh: refuse to hand back a page when a diff was asked for
tamnd Jul 25, 2026
1fe6926
Point the release at the right names
tamnd Jul 25, 2026
64c773e
Rewrite the README, with a demo
tamnd Jul 25, 2026
8c21028
docs: write the site for the tool that exists
tamnd Jul 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.2
- uses: actions/checkout@v7.0.0
with:
submodules: true
# Sitemap lastmod comes from the latest content commit.
fetch-depth: 0

- name: Checkout tago
uses: actions/checkout@v6.0.2
uses: actions/checkout@v7.0.0
with:
repository: tamnd/tago
path: .tago-src
Expand Down Expand Up @@ -107,7 +107,7 @@ jobs:
group: cloudflare-pages-github-cli
cancel-in-progress: true
steps:
- uses: actions/checkout@v6.0.2
- uses: actions/checkout@v7.0.0
with:
fetch-depth: 1
sparse-checkout: scripts/
Expand Down
58 changes: 35 additions & 23 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@
# entries for the package managers (Homebrew, Scoop). `git tag vX.Y.Z && git
# push --tags` fans out to all of them through .github/workflows/release.yml.
#
# Publish steps that push to a repository you do not own yet (the Homebrew tap,
# Publish steps that push to a repository we do not own yet (the Homebrew tap,
# the Scoop bucket) self-disable when their token is absent. A release with no
# extra secrets still produces every downloadable artifact and the container
# image; each manager lights up the moment its repository and token exist.
version: 2

project_name: ghb
project_name: github-cli

before:
hooks:
- go mod download

builds:
- id: ghb
binary: ghb
main: ./cmd/ghb
- id: github
binary: github
main: ./cmd/github
env:
- CGO_ENABLED=0
flags:
Expand All @@ -43,7 +43,7 @@ builds:

archives:
- id: default
name_template: "ghb_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}"
name_template: "github_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}"
format_overrides:
- goos: windows
formats: [zip]
Expand All @@ -53,12 +53,12 @@ archives:

nfpms:
- id: linux-packages
package_name: ghb
package_name: github-cli
file_name_template: "{{ .ConventionalFileName }}"
vendor: tamnd
homepage: https://github.com/tamnd/github-cli
maintainer: Duc-Tam Nguyen <tamnd87@gmail.com>
description: Browse GitHub repositories, users and releases
description: "A command-line for GitHub: scrapes HTML, no API key needed."
license: Apache-2.0
formats:
- deb
Expand All @@ -68,11 +68,17 @@ nfpms:
section: utils
contents:
- src: ./LICENSE
dst: /usr/share/doc/ghb/LICENSE
dst: /usr/share/doc/github-cli/LICENSE

dockers_v2:
# The image is named for the repository, not for the binary. A short name in a
# user-owned GHCR namespace belongs to whichever repository pushed it first,
# and the workflow token only has write access to packages linked to the
# repository it is running in. A sibling project taking the short name is how
# a release fails at the last step with a 403 that reads like a permissions
# bug, which already happened once on hf-cli.
- images:
- ghcr.io/tamnd/ghb
- ghcr.io/tamnd/github-cli
tags:
- "{{ .Version }}"
- latest
Expand All @@ -82,34 +88,49 @@ dockers_v2:
- linux/arm64
labels:
org.opencontainers.image.title: "{{ .ProjectName }}"
org.opencontainers.image.description: "Browse GitHub repositories, users and releases"
org.opencontainers.image.description: "A command-line for GitHub: scrapes HTML, no API key needed."
org.opencontainers.image.url: "https://github.com/tamnd/github-cli"
org.opencontainers.image.source: "https://github.com/tamnd/github-cli"
org.opencontainers.image.version: "{{ .Version }}"
org.opencontainers.image.revision: "{{ .FullCommit }}"
org.opencontainers.image.licenses: "Apache-2.0"

homebrew_casks:
- name: ghb
# Pushed to the tap repository. It self-disables until
# HOMEBREW_TAP_GITHUB_TOKEN (a PAT with write access to tamnd/homebrew-tap) is
# set, so a tokenless release still writes the cask into dist for inspection.
#
# The cask is github-cli rather than github because homebrew-cask already has
# a cask called github, which is GitHub Desktop.
- name: github-cli
repository:
owner: tamnd
name: homebrew-tap
token: '{{ envOrDefault "HOMEBREW_TAP_GITHUB_TOKEN" "" }}'
directory: Casks
homepage: https://github.com/tamnd/github-cli
description: Browse GitHub repositories, users and releases
description: "A command-line for GitHub: scrapes HTML, no API key needed."
skip_upload: '{{ if envOrDefault "HOMEBREW_TAP_GITHUB_TOKEN" "" }}false{{ else }}true{{ end }}'
commit_author:
name: Duc-Tam Nguyen
email: tamnd87@gmail.com
# Homebrew quarantines cask artifacts, and Gatekeeper kills a quarantined
# binary that is only ad-hoc signed, which is what a cross-compiled Go
# binary is. Strip the attribute at install so github runs on the first try.
hooks:
post:
install: |
if system_command("/usr/bin/xattr", args: ["-h"]).exit_status.zero?
system_command "/usr/bin/xattr", args: ["-dr", "com.apple.quarantine", "#{staged_path}/github"]
end

scoops:
- repository:
owner: tamnd
name: scoop-bucket
token: '{{ envOrDefault "SCOOP_BUCKET_GITHUB_TOKEN" "" }}'
homepage: https://github.com/tamnd/github-cli
description: Browse GitHub repositories, users and releases
description: "A command-line for GitHub: scrapes HTML, no API key needed."
license: Apache-2.0
skip_upload: '{{ if envOrDefault "SCOOP_BUCKET_GITHUB_TOKEN" "" }}false{{ else }}true{{ end }}'
commit_author:
Expand Down Expand Up @@ -155,15 +176,6 @@ changelog:
- "^ci:"
- Merge pull request
- Merge branch
groups:
- title: Features
regexp: '^.*?feat(\(.+\))??!?:.+$'
order: 0
- title: Fixes
regexp: '^.*?fix(\(.+\))??!?:.+$'
order: 1
- title: Other
order: 999

release:
github:
Expand Down
8 changes: 4 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ ARG TARGETPLATFORM

# ca-certificates for HTTPS; tzdata for sane timestamps.
RUN apk add --no-cache ca-certificates tzdata \
&& adduser -D -H -u 10001 ghb
&& adduser -D -H -u 10001 github

COPY $TARGETPLATFORM/ghb /usr/bin/ghb
COPY $TARGETPLATFORM/github /usr/bin/github

USER ghb
USER github

ENTRYPOINT ["/usr/bin/ghb"]
ENTRYPOINT ["/usr/bin/github"]
15 changes: 12 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Build into bin/ (gitignored) so the binary never collides with the github/
# source package at the repo root.
BINARY := bin/ghb
PKG := ./cmd/ghb
BINARY := bin/github
PKG := ./cmd/github
VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo dev)
COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo none)
DATE := $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
Expand All @@ -10,7 +10,7 @@ LDFLAGS := -s -w \
-X github.com/tamnd/github-cli/cli.Commit=$(COMMIT) \
-X github.com/tamnd/github-cli/cli.Date=$(DATE)

.PHONY: build install test vet fmt clean run
.PHONY: build install test live vet fmt lint clean run

build:
@mkdir -p $(dir $(BINARY))
Expand All @@ -19,15 +19,24 @@ build:
install:
CGO_ENABLED=0 go install -trimpath -ldflags "$(LDFLAGS)" $(PKG)

# The default run is offline and deterministic.
test:
go test ./...

# live talks to github.com. It answers the one question no offline test can:
# does the site still look the way the readers think it does.
live:
GITHUB_LIVE=1 go test ./gh/ -run Live -count=1 -v

vet:
go vet ./...

fmt:
gofmt -w -s .

lint:
golangci-lint run

clean:
rm -rf bin dist

Expand Down
Loading
Loading