From 133c678b4fdd896a49bdf399f063ddc9da8ff450 Mon Sep 17 00:00:00 2001 From: shilpijc Date: Mon, 3 Aug 2026 00:43:17 +0530 Subject: [PATCH] Rename package to code-explainer 3.0 with pr and repo modes. Ship @shilpi1958/code-explainer with explicit subcommands, keep pr-explainer as a legacy alias, document Graphify for repo mode, and refresh the site without the Product Hunt badge. Co-authored-by: Cursor --- README.md | 223 ++++++++------------------ action.yml | 8 +- docs/index.html | 132 ++++----------- package-lock.json | 9 +- package.json | 11 +- src/cli.js | 157 +++++++++++++----- src/github.js | 6 +- src/posthog.js | 20 ++- templates/learning-profile.example.md | 7 +- test/posthog.test.js | 2 + 10 files changed, 259 insertions(+), 316 deletions(-) diff --git a/README.md b/README.md index 1755bb3..9db52e1 100644 --- a/README.md +++ b/README.md @@ -1,192 +1,111 @@ -# pr-explainer - -Point it at any merged pull request, anywhere on GitHub. Get back a -plain explainer of what it did and why it matters — pitched at *you*, -whoever you are — plus a couple of quick questions to check it stuck. - -You don't need to have written the PR, or even read code. A product -analyst can point it at an engineer's PR and get a stakeholder-ready -explanation with zero jargon. An engineer can point it at a teammate's -PR and get the reasoning, not just the diff. Same tool — the only -input that changes is a one-time profile describing who's reading. - -## How it works - -1. Run `pr-explainer init` once — it creates - `~/.pr-explainer/learning-profile.md`. Edit it with your role and - what you're currently trying to understand better. Not a skills - checklist, just a couple of sentences. That one file applies - everywhere you run the CLI. -2. Point the CLI at any merged PR — a number, a URL, whatever `gh pr - view` accepts. It reads the PR's diff and description, combines it - with your profile, and asks Claude to write one plain-language - explainer: what changed, why it was done this way, why it matters - to you — followed by a multiple-choice Quick check. -3. The explainer lands in `~/.pr-explainer/explainers/`, and gets added - to a running `index.md` of every PR you've explained so far. A readable - summary (title, Ships, What changed, Why it was done this way, Why it - matters) prints to the terminal first. In an interactive terminal, press - Enter for a CHECK IT STUCK quiz (pick A/B/C, Enter to skip, `q` to quit), - then optionally open the saved file. - -## Quick start (CLI) +# code-explainer + +Plain-language explainers for **merged GitHub PRs** or a **whole repository** — +pitched at *you*, via a one-time learning profile. Optional interactive quiz +so it sticks. ```bash -npm install -g @shilpi1958/pr-explainer -pr-explainer init -# edit ~/.pr-explainer/learning-profile.md to describe yourself - -pr-explainer 42 # current repo only -pr-explainer https://github.com/some-org/some-repo/pull/42 # any repo -pr-explainer some-org/some-repo#42 -pr-explainer https://github.com/some-org/some-repo/pull/42 --no-quiz - -# Explain a whole local checkout (needs Graphify — see below) -pr-explainer repo -pr-explainer repo /path/to/checkout --no-quiz +npm install -g @shilpi1958/code-explainer + +code-explainer init +# edit ~/.code-explainer/learning-profile.md (or legacy ~/.pr-explainer/) + +code-explainer pr https://github.com/org/repo/pull/42 +code-explainer repo # explain the checkout you're in ``` -### Repo mode +The `pr-explainer` binary is still installed as an alias (legacy shorthand: +`pr-explainer ` without the `pr` subcommand). -`pr-explainer repo` orients you to what a **repository** does — for non-engineers -or engineers outside that domain — using the same learning profile as PR mode. +## Modes -It builds a local [Graphify](https://graphify.com/) knowledge graph of the -checkout (structure, hubs, communities), combines that with recent merged PRs -and your profile, and writes a concise plain-language explainer. Output lands -in `~/.pr-explainer/explainers/repos/`. +### `pr` — what just shipped -Requires a **local git checkout** with a GitHub remote (not a bare `owner/repo` -URL yet), plus Graphify: +Point it at any merged PR (number, URL, or `owner/repo#N`). Reads the diff + +description, combines it with your profile, and asks Claude Code for a +plain-language explainer. ```bash -uv tool install graphifyy # or: pipx install graphifyy +code-explainer pr 42 +code-explainer pr https://github.com/org/repo/pull/42 +code-explainer pr org/repo#42 --no-quiz ``` -If `graphify` is missing, repo mode exits with install instructions. - -> **Note:** a bare number resolves against the GitHub repo of your current -> directory. To explain a PR elsewhere, pass the full URL or `owner/repo#N`. -> Only **merged** PRs are supported. - -After the explainer is saved, a summary of the key sections prints to stderr -(title, Ships, What changed, Why it was done this way, Why it matters — Quick -check is left for the quiz). In an interactive terminal you’re prompted -`Press Enter for CHECK IT STUCK…`, then the multiple-choice quiz runs -(`a`/`b`/`c` or `1`/`2`/`3`, Enter to skip, `q` to quit early). Correct picks -get a green ✓; wrong picks show the right option. Then you’re offered -`Open explainer? [y/N]`. The Markdown file still keeps the questions with -options and collapsed answers for later. Pass `--no-quiz` (or set -`PR_EXPLAINER_NO_QUIZ=1`) to skip the quiz; it’s also skipped when stdin -isn’t a TTY (CI, pipes). The summary still prints unless -`PR_EXPLAINER_QUIET=1`. The only stdout line is the saved file path (for -scripting). - -No API key needed if you already have [Claude Code](https://claude.com/claude-code) -installed and logged in — `pr-explainer` calls the local `claude` CLI, so it -rides on whatever auth you already use there (subscription or key). Run `claude` -once to log in if you haven't. - -Also requires the [GitHub CLI](https://cli.github.com/) (`gh`), authenticated -(`gh auth login`). - -**Repo mode** additionally requires [Graphify](https://graphify.com/docs) -(`uv tool install graphifyy`). -## GitHub Action (optional) - -The CLI is the main way to use this — point it at any PR, any time. The -Action is for the narrower case of auto-generating an explainer for your -*own* repo's PRs as they merge, committed automatically. +### `repo` — what this codebase is -CI runners don't have access to your local `claude` login, so the Action -needs a credential. If you have a Claude subscription, generate a -long-lived token once, locally: +Orients non-engineers (or engineers in another domain) to a **local** checkout. +Builds a [Graphify](https://graphify.com/) knowledge graph, adds recent merges + +your profile, and writes a concise orientation. ```bash -claude setup-token -gh secret set CLAUDE_CODE_OAUTH_TOKEN +# also required for repo mode: +uv tool install graphifyy # or: pipx install graphifyy + +cd /path/to/checkout +code-explainer repo +code-explainer repo --no-quiz ``` -Then drop this into `.github/workflows/explainer.yml`: +If `graphify` is missing, repo mode exits with install instructions. -```yaml -on: - pull_request: - types: [closed] - -jobs: - explainer: - if: github.event.pull_request.merged == true - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.base.ref }} - - uses: shilpi1958/pr-explainer@v1 - with: - claude-code-oauth-token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} -``` +## Requirements -No subscription? Pass `anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}` -instead (Console API key, billed separately). +- [Claude Code](https://claude.com/claude-code) CLI (`claude`), logged in +- [GitHub CLI](https://cli.github.com/) (`gh`), authenticated +- **Repo mode only:** [Graphify](https://graphify.com/docs) (`uv tool install graphifyy`) -Every merge gets you a commit with a fresh explainer. Put a -`learning-profile.md` in the repo root for the Action (or pass -`profile-path`); explainers are written to `docs/explainers/` by default. +No separate Anthropic API key for local use — the tool shells out to `claude`. -## Configuration +## Profile + +```bash +code-explainer init +``` -Profile lookup (first hit wins): +Creates `~/.code-explainer/learning-profile.md` (or keeps using +`~/.pr-explainer/` if you already have one). Override with `LEARNING_PROFILE` +or a local `./learning-profile.md`. -1. `LEARNING_PROFILE` env -2. `./learning-profile.md` (repo override — useful for the Action) -3. `~/.pr-explainer/learning-profile.md` (default for local CLI) +## Output -| Env var | Default | Purpose | -|---|---|---| -| `LEARNING_PROFILE` | `~/.pr-explainer/learning-profile.md` | path to your profile | -| `EXPLAINER_DIR` | `~/.pr-explainer/explainers` | output directory | -| `PR_EXPLAINER_NO_QUIZ` | unset | set to `1` to skip the interactive quiz | -| `PR_EXPLAINER_QUIET` | unset | set to `1` to skip printing the summary to stderr | -| `POSTHOG_API_KEY` | unset | enables product analytics + `$ai_generation` for [PostHog AI Evals](https://posthog.com/docs/ai-evals). Alias: `POSTHOG_PROJECT_TOKEN` | -| `POSTHOG_HOST` | PostHog default | e.g. `https://us.i.posthog.com` | -| `POSTHOG_DEBUG` | unset | set to `1` to log when PostHog is unconfigured | +- PR explainers → `~/.code-explainer/explainers/` (or legacy path) +- Repo explainers → `…/explainers/repos/` +- Summary prints to stderr; quiz is interactive unless `--no-quiz` / + `PR_EXPLAINER_NO_QUIZ=1` -Copy [`.env.example`](.env.example) to `.env` for local runs (loaded automatically from cwd or package root). For the GitHub Action, pass `posthog-api-key` / `posthog-host` inputs (see `action.yml`) via repo secrets — not only a local `.env`. +## GitHub Action (optional) -When configured, the CLI emits `profile_initialized`, `explainer_generation_started`, `explainer_generated`, plus `$ai_generation` (for evals) and mode-specific `pr_explained` / `repo_explained`. +Auto-generate a PR explainer on merge. Pass Claude credentials and optional +PostHog secrets: -See [`templates/learning-profile.example.md`](templates/learning-profile.example.md) -for the profile format. +```yaml +- uses: shilpi1958/pr-explainer@v1 + with: + claude-code-oauth-token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + posthog-api-key: ${{ secrets.POSTHOG_API_KEY }} + posthog-host: ${{ secrets.POSTHOG_HOST }} +``` -## Why this needs no separate API key (locally) +## Analytics (optional) -`pr-explainer` shells out to the `claude` CLI instead of calling the -Anthropic API directly. If you already use Claude Code, you already have -auth configured — nothing new to sign up for, no data leaving your -machine except what `claude` itself sends. +Copy [`.env.example`](.env.example) to `.env` for local PostHog capture +(`POSTHOG_API_KEY` / `POSTHOG_PROJECT_TOKEN` + `POSTHOG_HOST`). Enables +funnel events and `$ai_generation` for [AI Evals](https://posthog.com/docs/ai-evals). ## Troubleshooting | Symptom | Fix | |---|---| -| `No profile found` | Run `pr-explainer init`, then edit `~/.pr-explainer/learning-profile.md` | -| `Could not resolve to a PullRequest` / PR not found | A bare number only looks in the **current** repo. Pass a URL or `owner/repo#42` | -| `PR … is not merged yet` | Only merged PRs are supported — pick one that already shipped | -| `claude -p failed` / spending cap / usage limit | Wait for the Claude Code reset, raise your cap, or retry later. Confirm `claude` works on its own | -| Claude Code CLI not found | Install from https://claude.com/claude-code and run `claude` once to log in | -| `gh` auth / forbidden errors | Run `gh auth login` | -| GitHub CLI not found | Install from https://cli.github.com/ | -| Graphify CLI not found / repo mode | Install with `uv tool install graphifyy`, then retry `pr-explainer repo` | - -Quick sanity checks: +| `No profile found` | `code-explainer init`, then edit the profile file | +| Bare PR number not found | `cd` into the repo, or pass a URL / `owner/repo#N` | +| PR not merged | Only merged PRs are supported | +| Graphify not found | `uv tool install graphifyy` | +| Claude / gh auth | Run `claude` once; `gh auth login` | ```bash gh auth status claude -p --output-format text <<< "Say hi in one word" -pr-explainer --help +code-explainer --help ``` ## License diff --git a/action.yml b/action.yml index 556d081..b9ea6df 100644 --- a/action.yml +++ b/action.yml @@ -45,10 +45,10 @@ runs: with: node-version: "20" - - name: Install pr-explainer and Claude Code CLI + - name: Install code-explainer and Claude Code CLI shell: bash run: | - npm install --no-save @shilpi1958/pr-explainer @anthropic-ai/claude-code + npm install --no-save @shilpi1958/code-explainer @anthropic-ai/claude-code - name: Generate explainer id: generate @@ -62,14 +62,14 @@ runs: POSTHOG_API_KEY: ${{ inputs.posthog-api-key }} POSTHOG_HOST: ${{ inputs.posthog-host }} run: | - OUT_PATH=$(npx pr-explainer "${{ github.event.pull_request.number }}") + OUT_PATH=$(npx code-explainer pr "${{ github.event.pull_request.number }}") echo "path=$OUT_PATH" >> "$GITHUB_OUTPUT" - name: Commit entry if: ${{ inputs.commit == 'true' }} shell: bash run: | - git config user.name "pr-explainer[bot]" + git config user.name "code-explainer[bot]" git config user.email "actions@github.com" git add "${{ steps.generate.outputs.path }}" "$(dirname "${{ steps.generate.outputs.path }}")/index.md" git commit -m "docs: explainer for #${{ github.event.pull_request.number }}" diff --git a/docs/index.html b/docs/index.html index d1e25af..96a20d5 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3,11 +3,11 @@ -pr-explainer — plain-English explainers for any GitHub PR - +code-explainer — plain-English explainers for PRs and repos + - - + + @@ -136,66 +136,6 @@ .btn-secondary { border: 1px solid var(--border-strong); color: var(--text); } .btn-secondary:hover { border-color: var(--text-muted); } - .ph-badge { - margin: 36px auto 0; - max-width: 500px; - text-align: left; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; - border: 1px solid rgb(224, 224, 224); - border-radius: 12px; - padding: 20px; - background: rgb(255, 255, 255); - box-shadow: rgba(0, 0, 0, 0.05) 0px 2px 8px; - } - .ph-badge-top { - display: flex; - align-items: center; - gap: 12px; - margin-bottom: 12px; - } - .ph-badge-top img { - width: 64px; - height: 64px; - border-radius: 8px; - object-fit: cover; - flex-shrink: 0; - } - .ph-badge-copy { flex: 1 1 0%; min-width: 0; } - .ph-badge-copy h3 { - margin: 0; - font-size: 18px; - font-weight: 600; - color: rgb(26, 26, 26); - line-height: 1.3; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - .ph-badge-copy p { - margin: 4px 0 0; - font-size: 14px; - color: rgb(102, 102, 102); - line-height: 1.4; - overflow: hidden; - text-overflow: ellipsis; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - } - .ph-badge a.ph-cta { - display: inline-flex; - align-items: center; - gap: 4px; - margin-top: 12px; - padding: 8px 16px; - background: rgb(255, 97, 84); - color: rgb(255, 255, 255); - text-decoration: none; - border-radius: 8px; - font-size: 14px; - font-weight: 600; - } - /* section shared */ section.block { padding: 70px 40px; @@ -372,7 +312,7 @@ - pr-explainer + code-explainer