Skip to content

Commit 5124aeb

Browse files
committed
Initial documentation
1 parent 0287546 commit 5124aeb

14 files changed

Lines changed: 1140 additions & 0 deletions

File tree

‎.github/workflows/static-docs.yml‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Deploy static content to Pages
2+
3+
on:
4+
push:
5+
branches: ["main"]
6+
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
pages: write
12+
id-token: write
13+
14+
concurrency:
15+
group: "pages"
16+
cancel-in-progress: false
17+
18+
jobs:
19+
deploy:
20+
environment:
21+
name: github-pages
22+
url: ${{ steps.deployment.outputs.page_url }}
23+
env:
24+
VIRTUAL_ENV: /tmp/.venv
25+
runs-on: ubuntu-latest
26+
steps:
27+
- name: Checkout
28+
uses: actions/checkout@v4
29+
- name: Setup Pages
30+
uses: actions/configure-pages@v5
31+
- name: Install uv
32+
uses: astral-sh/setup-uv@v6
33+
- name: Install dependencies
34+
run: |
35+
uv venv $VIRTUAL_ENV
36+
uv sync --active --locked --dev
37+
- name: Build mkdocs documentation
38+
run: uv run --active mkdocs build
39+
- name: Replace docs with mkdocs site
40+
run: |
41+
rm -rf docs
42+
mv site docs
43+
- name: Upload artifact
44+
uses: actions/upload-pages-artifact@v3
45+
with:
46+
path: '.'
47+
- name: Deploy to GitHub Pages
48+
id: deployment
49+
uses: actions/deploy-pages@v4

‎.gitignore‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
gh-cached
22
!.agents/skills/gh-cached/
3+
site/
4+
.venv/
5+
__pycache__/

‎docs/index.md‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# gh-cached
2+
3+
A GitHub CLI that calls the GitHub GraphQL API to retrieve issues, pull requests, and comments, caching all results to disk to minimise API calls.
4+
5+
Cache lives at `~/.cache/gh-cached/<host>/<owner>/<repo>`.
6+
7+
## Quick start
8+
9+
```bash
10+
go install github.com/tomzxcode/gh-cached@main
11+
export GH_TOKEN=ghp_...
12+
gh-cached cache --repo cli/cli
13+
gh-cached issue list
14+
gh-cached pr list
15+
```
16+
17+
See the [User Guide](user-guide/installation.md) for detailed instructions.

‎docs/sdlc‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../.sdlc

‎docs/user-guide/authentication.md‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Authentication
2+
3+
gh-cached needs a GitHub personal access token to call the GitHub GraphQL API. It resolves a token in the following order:
4+
5+
1. **`GH_TOKEN`** environment variable
6+
2. **`GITHUB_TOKEN`** environment variable
7+
3. **`gh auth token --hostname <host>`** (GitHub CLI, host-specific)
8+
4. **`gh auth token`** (GitHub CLI, any host)
9+
10+
If none of these are available, gh-cached exits with an error.
11+
12+
## Personal access token
13+
14+
Create a token at [GitHub Settings > Developer settings > Personal access tokens](https://github.com/settings/tokens). The token needs the `repo` scope for private repositories.
15+
16+
Set it in your shell:
17+
18+
```bash
19+
export GH_TOKEN=ghp_...
20+
```
21+
22+
## GitHub CLI
23+
24+
If you already use [`gh`](https://cli.github.com/) and have run `gh auth login`, gh-cached will use it automatically as a fallback.
25+
26+
## GitHub Enterprise
27+
28+
For GitHub Enterprise hosts, pass the full repository path:
29+
30+
```bash
31+
gh-cached --repo ghe.example.com/org/repo cache
32+
```
33+
34+
gh-cached resolves the API endpoint as `https://ghe.example.com/api/graphql` and uses `gh auth token --hostname ghe.example.com` when looking for a token.

‎docs/user-guide/cache.md‎

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Cache
2+
3+
gh-cached caches GitHub data as individual JSON files on your local disk. After an initial fetch, subsequent commands serve results from cache without hitting the API.
4+
5+
## Cache location
6+
7+
```
8+
~/.cache/gh-cached/<host>/<owner>/<repo>/
9+
├── .cache_info.json
10+
├── issues/
11+
│ ├── 1.json
12+
│ ├── 2.json
13+
│ └── ...
14+
└── prs/
15+
├── 1.json
16+
├── 2.json
17+
└── ...
18+
```
19+
20+
Override the base directory with `--cache-dir`:
21+
22+
```bash
23+
gh-cached --cache-dir /tmp/gh-cache cache --repo cli/cli
24+
```
25+
26+
## Populate the cache
27+
28+
```bash
29+
gh-cached cache
30+
gh-cached cache --repo cli/cli
31+
gh-cached cache --cache-duration 120 # treat cache as fresh for 2 hours
32+
gh-cached cache --cache-duration 0 # always re-fetch (delta)
33+
gh-cached cache --force # force full re-fetch
34+
```
35+
36+
First run fetches everything. Example output:
37+
38+
```
39+
Caching issues for octocat/hello-world...
40+
Cached 42 issue(s).
41+
Caching pull requests for octocat/hello-world...
42+
Cached 15 pull request(s).
43+
Cache updated. Valid for 60 minute(s).
44+
```
45+
46+
Subsequent runs use a delta fetch, only retrieving items updated since the last cache write:
47+
48+
```
49+
Fetching issues updated since 2025-01-15 10:30 for octocat/hello-world...
50+
Cached 3 issue(s).
51+
Fetching PRs updated since 2025-01-15 10:30 for octocat/hello-world...
52+
Cached 1 pull request(s).
53+
Cache updated. Valid for 60 minute(s).
54+
```
55+
56+
## How freshness works
57+
58+
The `.cache_info.json` file tracks when the cache was last written and the configured duration:
59+
60+
```json
61+
{
62+
"cachedAt": "2025-01-15T10:30:00Z",
63+
"duration": 60
64+
}
65+
```
66+
67+
A cache is considered **fresh** when `time.Since(cachedAt) < duration × 1 minute`.
68+
69+
When the cache is fresh, `list` and `view` commands serve entirely from disk with no API calls. When stale, they fall back to the GitHub API.
70+
71+
## Cache behavior per command
72+
73+
| Command | Behavior |
74+
|---|---|
75+
| `cache` | Fetches all issues and PRs (all states, with comments). Skips if cache is younger than `--cache-duration`. Supports delta fetch. |
76+
| `issue list` / `pr list` | Reads cached files and filters in memory when cache is fresh. Falls back to the GitHub API when stale. Does not write to cache. |
77+
| `issue view` / `pr view` | Serves the individual cached file if the full cache is fresh, or if the file is less than 60 minutes old. Otherwise fetches from the API and saves to cache. `--refresh` bypasses all checks. |
78+
79+
## Notes
80+
81+
- Cache files are never automatically cleaned up. Delete directories under `~/.cache/gh-cached/` to free space.
82+
- The `--mention` and `--app` filters cannot be evaluated from cached data and are silently skipped when serving from cache.
83+
- Bulk cache operations fetch up to 100 comments per item.

‎docs/user-guide/flag-reference.md‎

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Flag Reference
2+
3+
## Global flags
4+
5+
These flags apply to all commands.
6+
7+
| Flag | Description |
8+
|---|---|
9+
| `--repo [HOST/]OWNER/REPO` | Target repository. When omitted, detected from `git remote origin` in the current directory. |
10+
| `--cache-dir string` | Override the cache directory (default `~/.cache/gh-cached/`). |
11+
| `--api-url string` | Override the GitHub GraphQL API endpoint (for testing). |
12+
| `--version`, `-v` | Print version. |
13+
| `--help`, `-h` | Show help. |
14+
15+
## cache
16+
17+
| Flag | Default | Description |
18+
|---|---|---|
19+
| `--cache-duration int` | `60` | Minutes before the cache is considered stale |
20+
| `--force` | `false` | Re-fetch even if the cache is still fresh (full fetch, not delta) |
21+
22+
## issue list
23+
24+
| Flag | Short | Default | Description |
25+
|---|---|---|---|
26+
| `--state string` | `-s` | `open` | Filter by state: `open`, `closed`, or `all` |
27+
| `--author string` | `-A` | | Filter by author |
28+
| `--assignee string` | `-a` | | Filter by assignee |
29+
| `--label strings` | `-l` | | Filter by label (repeat for AND logic) |
30+
| `--milestone string` | `-m` | | Filter by milestone number or title |
31+
| `--mention string` | | | Filter by mention |
32+
| `--app string` | | | Filter by GitHub App author |
33+
| `--search string` | `-S` | | Search query (case-insensitive substring match on title and body) |
34+
| `--limit int` | `-L` | `1000` | Maximum number of results |
35+
| `--json` | | `false` | Output as JSON |
36+
| `--no-truncate` | | `false` | Don't truncate long titles |
37+
38+
## issue view
39+
40+
| Flag | Short | Default | Description |
41+
|---|---|---|---|
42+
| `--comments` | `-c` | `false` | Show comments |
43+
| `--json` | | `false` | Output as JSON |
44+
| `--refresh` | | `false` | Force fetch from GitHub and update cache |
45+
46+
## pr list
47+
48+
| Flag | Short | Default | Description |
49+
|---|---|---|---|
50+
| `--state string` | `-s` | `open` | Filter by state: `open`, `closed`, `merged`, or `all` |
51+
| `--author string` | `-A` | | Filter by author |
52+
| `--assignee string` | `-a` | | Filter by assignee |
53+
| `--label strings` | `-l` | | Filter by label (repeat for AND logic) |
54+
| `--base string` | `-B` | | Filter by base branch name |
55+
| `--head string` | `-H` | | Filter by head branch name |
56+
| `--draft` | `-d` | `false` | Show only draft PRs |
57+
| `--app string` | | | Filter by GitHub App author |
58+
| `--search string` | `-S` | | Search query (case-insensitive substring match on title and body) |
59+
| `--limit int` | `-L` | `1000` | Maximum number of results |
60+
| `--json` | | `false` | Output as JSON |
61+
| `--no-truncate` | | `false` | Don't truncate long titles |
62+
63+
## pr view
64+
65+
| Flag | Short | Default | Description |
66+
|---|---|---|---|
67+
| `--comments` | `-c` | `false` | Show comments |
68+
| `--json` | | `false` | Output as JSON |
69+
| `--refresh` | | `false` | Force fetch from GitHub and update cache |
70+
71+
## repo list
72+
73+
No command-specific flags. Uses only the global `--cache-dir`.

‎docs/user-guide/installation.md‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Installation
2+
3+
## Binary download
4+
5+
Download the latest pre-built binary from the [releases page](https://github.com/TomzxCode/gh-cached/releases/tag/latest).
6+
7+
=== "darwin-amd64"
8+
```bash
9+
curl -LO https://github.com/TomzxCode/gh-cached/releases/latest/download/gh-cached-darwin-amd64
10+
chmod +x gh-cached-darwin-amd64
11+
mv gh-cached-darwin-amd64 /usr/local/bin/gh-cached
12+
```
13+
14+
=== "darwin-arm64"
15+
```bash
16+
curl -LO https://github.com/TomzxCode/gh-cached/releases/latest/download/gh-cached-darwin-arm64
17+
chmod +x gh-cached-darwin-arm64
18+
mv gh-cached-darwin-arm64 /usr/local/bin/gh-cached
19+
```
20+
21+
=== "linux-amd64"
22+
```bash
23+
curl -LO https://github.com/TomzxCode/gh-cached/releases/latest/download/gh-cached-linux-amd64
24+
chmod +x gh-cached-linux-amd64
25+
mv gh-cached-linux-amd64 /usr/local/bin/gh-cached
26+
```
27+
28+
=== "windows-amd64"
29+
```powershell
30+
curl -LO https://github.com/TomzxCode/gh-cached/releases/latest/download/gh-cached-windows-amd64.exe
31+
rename-item gh-cached-windows-amd64.exe gh-cached.exe
32+
```
33+
34+
## Build from source
35+
36+
Requires [Go](https://go.dev/) 1.21 or later.
37+
38+
```bash
39+
go install github.com/tomzxcode/gh-cached@main
40+
```
41+
42+
This places the binary at `$(go env GOPATH)/bin/gh-cached`. Make sure that directory is on your `PATH`.
43+
44+
## Verify
45+
46+
```bash
47+
gh-cached --version
48+
```

0 commit comments

Comments
 (0)