Metadata-Version: 2.5
Name: ghp
Version: 0.3.1
Summary: Compact GitHub activity summary with repository-scoped checkpoints
Project-URL: Homepage, https://github.com/wakamex/ghp
Project-URL: Source, https://github.com/wakamex/ghp
License-Expression: MIT
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# ghp

Compact GitHub activity summary with repository-scoped checkpoints.

## Install

```bash
uv tool install ghp
# or
uvx ghp
```

## Dev

```bash
uv sync
uv run ghp --version
```

## Usage

```bash
ghp                                   # open issues + PRs snapshot
ghp upstream                          # use the GitHub repo from the upstream remote
ghp 1h                                # deltas since 1 hour ago
ghp upstream 1h                       # upstream deltas since 1 hour ago
ghp 2026-03-07T14:00:00Z              # deltas since timestamp
ghp --json                            # machine-readable output
ghp --me @clod                        # highlight mentions
ghp --repo owner/name                 # explicit repo
ghp inbox                             # unread notifications across all repositories
ghp inbox 1d                          # read and unread notifications since 1 day ago
ghp inbox --repo owner/name           # unread notifications for one repository
ghp owned                             # PRs awaiting workflow approval, unwatched repositories
```

## Behavior

- Cursor defaults to the saved checkpoint for the current GitHub repository when `--since` is
  omitted.
- `upstream` selects the repository configured as the Git remote named `upstream`.
- Checkpoints are stored under `$XDG_STATE_HOME/ghp/checkpoints/`. When `XDG_STATE_HOME` is unset or
  invalid, ghp uses `~/.local/state/ghp/checkpoints/`.
- Each repository has its own atomically replaced checkpoint file, so `origin`, `upstream`, and
  `--repo` queries do not advance each other's checkpoints.
- Saved checkpoints include a one-second margin because GitHub's `since` filters are strict and
  timestamps have second precision. Boundary activity may appear again on the next run.
- Tool installs and upgrades leave checkpoint state in place.
- Repository-keyed `.ghp-last-update-timestamp` files are migrated to XDG state and removed after
  successful writes. Older plaintext files require an explicit window such as `ghp 1h` once because
  they do not identify a repository.
- `--since` accepts relative shorthands (`30m`, `2h`, `1d`, `1w`) and normalizes timestamps to
  canonical UTC.
- Snapshot mode returns open issues and open PRs.
- Delta mode returns issues, PRs, issue comments, PR review comments, and recent commits since the cutoff.
- `inbox` lists the authenticated account's notifications, grouped by repository and newest first. It ignores the current checkout and reads and writes no checkpoint: GitHub's unread state is the cursor, and ghp never marks a notification as read.
- `inbox` alone returns unread notifications. With a TIME it returns read and unread notifications updated since then, and marks the read ones `read`.
- Each inbox line gives the issue or pull request number (or short commit hash), the subject type, the reason GitHub sent it (such as `mention`, `review_requested`, or `author`), the update time, and the title.
- `owned` checks every account you own: your user account and each organization where you are an admin. It ignores the current checkout and keeps no checkpoint.
- `owned` lists open pull requests whose [GitHub Actions](https://docs.github.com/actions) runs wait for maintainer approval, oldest first. GitHub holds runs from first-time and fork contributors this way, and sends no reminder while they wait. A pull request matches when its head commit has a run in the `action_required` state.
- `owned` also lists non-fork, non-archived repositories you own but do not watch. GitHub sends no notifications for those, so their new issues and pull requests never reach `ghp inbox`.
- `owned` prints an `awaiting-approval` section, with one `owner/repo#N @author created_at title` line per pull request, and an `unwatched` section with one `owner/repo` line per repository. It prints `none` when both are empty, and lists every match regardless of `--limit`.
- API or auth failures exit non-zero instead of silently pretending there was no activity.
- `--json` prints a machine-readable payload; on failure it emits a JSON object with an `error` field
  and exits non-zero.

## JSON output

`ghp inbox --json` prints `repo` (the `--repo` filter, or `null`), `timestamp`, `since` (the TIME cutoff, or `null`), and a `notifications` list. Each notification has:

| Field | Meaning |
|---|---|
| `id` | GitHub's notification thread ID |
| `repo` | `owner/repo` the notification belongs to |
| `type` | `issue`, `pr`, `commit`, `release`, `discussion`, `ci`, or GitHub's subject type in lowercase |
| `number` | issue or pull request number, or commit hash, as a string; `null` for other types |
| `title` | subject title |
| `reason` | why GitHub sent it, such as `mention`, `review_requested`, or `author` |
| `unread` | `true` while the notification is unread |
| `updated_at` | last update time, ISO 8601 UTC |
| `url` | website link to the issue, pull request, or commit; the repository page for other types |

`ghp owned --json` prints `timestamp`, `owners` (your login, then the organizations you administer), an `awaiting_approval` list, and `unwatched`, a list of `owner/repo` names. Each pull request in `awaiting_approval` has:

| Field | Meaning |
|---|---|
| `repo` | `owner/repo` the pull request targets |
| `number` | pull request number |
| `title` | pull request title |
| `user` | author login |
| `created_at` | when the pull request was opened, ISO 8601 UTC |
| `url` | website link to the pull request |

## Auth

Looks for tokens in this order:

1. `$GITHUB_PAT`
2. `$GITHUB_TOKEN`
3. `$GH_TOKEN`
4. `gh auth token` (gh CLI)

`ghp owned` always needs a token.

`ghp inbox` always needs a token, and GitHub's notifications API accepts only a `gh` CLI token or a classic personal access token with the `notifications` or `repo` scope. Fine-grained personal access tokens are rejected.

## Test

```bash
uv run python -m unittest discover -s tests
scripts/test-install.sh
```
