Skip to content

Reviewing changes ​

hiarky review answers "what actually changed here?" for a branch, a commit range, or the last two snapshots.

sh
hiarky review main..HEAD

Endpoints that already have a clean snapshot reuse it. The rest are analysed in a temporary git worktree, so your working tree is never touched and the project's own git hooks never fire. The review is then narrowed to files the range touched (--all-files to opt out).

What the report contains ​

  • Field-level deltas. props: +subtitle, signature: (a) → (a, b), members: +tier, not just "changed". Long lists are truncated in the report and complete in --format json.
  • Move and rename detection. A removal and an addition with the same body hash are reported as one move, so moving a directory does not read as a rewrite.
  • Impact ranking. Export, kind, route and signature changes outrank edge and hook changes, which outrank body-only edits. Anything on the public surface is weighted up. Migrations, models, routes and procedures count as public whatever their file exports. Each entry lists the reasons for its score.
  • Grouping that matches how code is read. New files summarise as one line each, test changes get their own section listing cases added and removed, and body-only changes collapse into a closing section.

Test coverage ​

changed  routers/company.ts#companyRouter.update  [procedure · mutation · protected]  (no test change)
           input: +tier

Coverage follows the dependency graph two hops, so a suite that exercises a root router also covers the procedures it mounts. Each changed symbol is in one of three states:

  • a covering suite changed (no marker)
  • suites cover it but none changed (no test change)
  • nothing references it (no tests reference this)

The headline counts them: 12 added · 20 changed · 5 without a test change.

Schema, migrations and config are exempt, since no test imports a Prisma model or package.json. Browser-driven tests (Playwright and similar) import nothing from the app, so they register no coverage.

A visual summary for pull requests ​

--format github puts a summary a reviewer can take in at a glance above the report, using only what GitHub renders natively in a comment or job summary: tables and a Mermaid diagram, no images to host.

  • Three tiles. How the changes split across impact tiers, how many touched files changed what they export, and how many changes a test moved with.
  • What changed, by kind. Migrations, models, routes and procedures first, since a reviewer reads "1 migration" differently from "26 functions".
  • Blast radius. The highest-ranked changes grouped by file, the edges between them, and the unchanged files that depend on them, collapsed to one node per file so a widely used type does not drag in every caller. Test files are marked. It appears only when something depends on something else in the change set.
  • Render tree. For a React project, the pages and components that render what changed, top down: the screens an edit reaches, with the changed components marked on the path.
  • Public surface. Signatures and members before and after, for exported symbols.
  • Files. Ranked by their most important change and flagged surface, new or n untested: a reading order for the diff.

The full report follows, folded. Sections drop from the bottom up when the whole would not fit in a GitHub comment. With --per-commit, an overview table of the commits leads. The dependency data behind the graphs is in --format json as graph.

Posting it on pull requests ​

The kosminog/hiarky action runs the review on every pull request and posts it as one comment, updated in place on each push, as the run's job summary, and as annotations on the changed lines of the diff:

yaml
name: Review
on:
  pull_request:
permissions:
  contents: read
  pull-requests: write
jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
        with:
          fetch-depth: 0 # both ends of the range must be reachable
      - uses: kosminog/hiarky@v0.2.0

It runs the hiarky release it was tagged with; version overrides that.

InputDefaultWhat it does
commenttruePost the review as one pull request comment, updated in place
summarytrueWrite the review to the job summary
annotatetrueAnnotate the changed lines of the diff with the changes worth a look
viewerfalseSnapshot every commit of the range and upload the interactive viewer as an artifact, linked from the comment and the summary
artifact-namehiarky-viewerName of the viewer artifact, when viewer is on
rangethe pull request's branch since it divergedAny git range, for other events
working-directory.The project, when it is not at the repository root
versionthe release the action was tagged withThe hiarky version to run from npm
commandA command that runs hiarky in place of the npm release, such as node dist/index.js from a checkout of hiarky itself
tokengithub.tokenToken for the comment; needs pull-requests: write

A pull request from a fork gets a read-only token, so the comment step is allowed to fail and the rest remains. The action is action.yml at the root of the repository; the same steps by hand:

yaml
name: Review
on:
  pull_request:
permissions:
  contents: read
  pull-requests: write
jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
        with:
          fetch-depth: 0 # both ends of the range must be reachable
      - uses: actions/setup-node@v6
        with:
          node-version: '24'
      - name: Review the pull request
        env:
          BASE: ${{ github.event.pull_request.base.sha }}
          HEAD: ${{ github.event.pull_request.head.sha }}
        run: |
          npx hiarky review "$BASE...$HEAD" --format github > hiarky-review.md
          cat hiarky-review.md >> "$GITHUB_STEP_SUMMARY"
      - name: Annotate the diff
        env:
          BASE: ${{ github.event.pull_request.base.sha }}
          HEAD: ${{ github.event.pull_request.head.sha }}
        run: npx hiarky review "$BASE...$HEAD" --format actions
      - name: Post it as a comment
        continue-on-error: true # a fork's token is read-only; the summary remains
        env:
          GH_TOKEN: ${{ github.token }}
          REPO: ${{ github.repository }}
          PR: ${{ github.event.pull_request.number }}
        run: |
          marker='<!-- hiarky-review -->'
          { echo "$marker"; cat hiarky-review.md; } > hiarky-comment.md
          existing="$(gh api "repos/$REPO/issues/$PR/comments" --paginate \
            --jq "first(.[] | select(.body | startswith(\"$marker\")) | .id)" | head -n 1)"
          if [ -n "$existing" ]; then
            gh api -X PATCH "repos/$REPO/issues/comments/$existing" -F body=@hiarky-comment.md > /dev/null
          else
            gh api "repos/$REPO/issues/$PR/comments" -F body=@hiarky-comment.md > /dev/null
          fi

The comment is found again by the marker on its first line, so each push edits it rather than adding another. A pull request from a fork gets a read-only token, so the comment step is allowed to fail and the job summary remains.

--format actions prints one workflow command per change worth a look, so the same findings appear as annotations on the changed lines of the diff: a warning where no test moved with the change, a notice otherwise. The runner shows ten of each per step, so the most important ten go out and the comment has the rest.

The hiarky repository reviews its own pull requests from the checkout's build, and runs the published action beside it; see its workflow.

Output formats ​

FlagUse
(default)Terminal text
--format mdMarkdown, for a PR comment
--format githubMarkdown with a visual summary on top, for a PR comment or job summary
--format actionsGitHub Actions workflow commands: one annotation per change worth a look, on its line
--format jsonThe full data, for tooling
--per-commitOne section per commit in the range

Released under the MIT License.