hunk Agent Skills & AI Rules

GitHub

Review-first terminal diff viewer for agentic coders

9,639 stars TypeScript TypeScript 1 file Β· ~134,911 tokens #agents#cli#code-review#diff#git#jj#jujutsu#sapling
RAW Rules
35 Discovered Rules β€’ ~41,646 Estimated Tokens
Quick:
Loading skill content...

AI Agent Protocol & Instructions

AGENTS.md root-instruction ~3,771 tokens
Raw
# hunk agent notes

## purpose

- Terminal-first diff viewer for understanding coding-agent changesets.
- Product target is "modern desktop diff tool in a terminal", not a pager-style TUI.

## architecture

### workspace map

```text
packages/hunk/                 published CLI, application, and public extension/OpenTUI facades
packages/hunk-vcs/             private dependency-bottom VCS helpers
packages/hunk-{git,jj,sapling}/ private bundled VCS providers
packages/hunk-gh/              private bundled GitHub review extension
packages/session-broker-core/  low-level broker protocol and state
packages/session-broker/       runtime-neutral broker, daemon, auth, and connection lifecycle
packages/session-broker-{bun,node}/ runtime listener adapters
packages/term-video/           private terminal capture tooling
website/                       product/documentation site, not the browser review client
```

### application flow

```text
main.tsx -> app/startup.ts -> app/cli.ts
  -> headless command/history plan returned to main.tsx, or
  -> app plan: extensionBootstrap.ts -> sessionBootstrap.ts -> normalized Changeset / DiffFile[]
     -> main.tsx lazy-loads runInteractiveApp.tsx -> HunkSessionHost -> AppHost -> App
     -> pane/diff planning -> Pierre-backed terminal rows
```

### shared review seam

Terminal, agent/session, broker/protocol, extension, and HTTP/SSE consumers share review semantics.
The browser client and UI remain planned. Do not recreate semantic review behavior in a surface:

```text
DiffFile[] -> projectReviewDocument -> ReviewDocumentV1 -> ReviewStore
ReviewIntent + caller facts -> planReviewIntent -> ReviewAction[] -> reducer -> surface projection
```

- **Model:** `packages/hunk/src/core/review/{types,document,identity}.ts` owns the ordered, JSON-safe document.
  File order is review/sidebar order; use `key` (referenced as `fileKey` elsewhere),
  `contentIdentity`, and `sourceIdentity` (cached source text additionally requires
  `sourceAttested`) β€” not runtime IDs or indexes β€” across reloads/surfaces.
- **Shared derivations:** `geometry.ts`, `expansion.ts`, `anchors.ts`, `stml.ts`, and
  `contentManifest.ts` own ranges, gaps, source splitting, note targets/ownership, tag roles, and
  parity manifests. Consume them; never re-derive those facts in a renderer.
- **State:** `state.ts` is semantic state; `actions.ts` transitions; `reducer.ts` pure/no-I/O;
  `selectors.ts` shared policies; `store.ts` synchronous observable storage. New cross-surface
  operations start as intents. Callers supply mutable-note IDs/timestamps; core derives identities.
- **Surfaces/publishers:** `useTerminalReview.ts` is the TUI adapter and
  `reviewNoteMapping.ts` is terminal-only. Rows, measurement, scrolling, layout, themes, DOM
  mechanics, and source I/O stay local. `useHunkSessionBridge.ts` publishes the current terminal
  session export; `registration.ts` builds its metadata/initial snapshot and `bridge.ts` receives
  agent commands. This broker export is not a full `ReviewState` mirror.
- **Other consumers:** Web/API consumers reuse the model, derivations, state, intents, and the
  producer/protocol tier. Never build a parallel protocol. Keep presentation/client-local state
  local; host/extension commands need explicit remote capabilities. See
  `docs/browser-review-rebuild.md` for the rollout and current boundaries.
- **Conformance:** `test/review-conformance/` has hand-authored semantic fixtures covering every
  registered core, terminal, producer, broker, protocol, and extension projection. Every new
  semantic consumer registers its real projection and runs the whole corpus.
  `scripts/quality/source-boundaries.test.ts` keeps the seam
  renderer/platform-free; its Node-debt list is shrink-only and tombstone lists append-only. A
  repaid seam finding deletes copies, adds a file or banned-symbol tombstone and adversarial
  fixture, registers consumers, and updates `docs/browser-review-seam-audit.md`.

- Bundled VCS implementations live in the private `packages/hunk-{git,jj,sapling}` workspaces and consume
  the public `hunkdiff/extension` contract plus explicit `@hunk/vcs/*` implementation leaves;
  `packages/hunk/src/app` composes their registrations into the
  provider-neutral core VCS catalog. Do not add provider commands, spawning, or source readers under `packages/hunk/src/core`.
- `hunk daemon serve` is the one loopback daemon for all live sessions; sessions auto-start and
  register with it rather than opening per-TUI ports. Reuse `classifyReviewPublication` and
  `ReviewChunkAssembler` for publication ordering and bounded, digest-verified resources. Browser
  review stays same-origin with no CORS; each session mints its capability and gives the daemon only
  its digest. Transport semantics come from the browser-safe review protocol modules and the
  existing intent path. See `docs/browser-review-rebuild.md` and the relevant module headers.
- User extensions, bundled VCS providers, bundled core commands, and bundled UI share one public
  registration API and registry model. VCS and UI use dedicated registries; bundled core commands
  load first into each session-owned extension registry so delegated resources share its lifecycle. `ExtensionSession` owns the
  user registry across routed surfaces. Keep `packages/hunk/src/extension-api/types.ts` import-free,
  bundled VCS renderer-free, repo-local extensions trust-gated, and bundled extensions active under
  `--no-extensions`. See `docs/extension-architecture.md`, `docs/extensions.md`, and
  `packages/hunk/skills/hunk-extensions/SKILL.md`.
- Sidecar file order is intentional sidebar and review-stream order.
- **Session wire:** the daemon and every window exchange `HUNK_SESSION_DAEMON_VERSION`
  (`packages/hunk/src/session/protocol.ts`) in the signed hello and require an exact match. Any
  change to what a session registers or snapshots β€” under `packages/hunk/src/session/**`,
  `packages/hunk/src/core/reviewDescriptor.ts`, `packages/hunk/src/app/session/registration.ts`, or
  anything else that appears in `packages/hunk/src/session/broker/fixtures/session-wire.v<N>.json`
  β€” requires a bump. `wire.snapshot.test.ts` enforces it; bump, run
  `bun run generate:session-wire`, and delete the previous fixture in the same change. The
  cross-revision admin scope (`status`/`stop`) is frozen separately and never grows in place.
- Derive shared rendering, navigation, scrolling, and note behavior from one planning layer. Make
  shared geometry explicit, and remove obsolete paths instead of retaining parallel implementations.

## architectural rules

- `bun run deps:check` enforces both the `packages/*` workspace graph and
  `packages/hunk/src/*` tiers; `.dependency-cruiser.cjs` is authoritative and
  `docs/module-boundaries.md` explains the model. Standalone packages do not import Hunk internals.
  Bundled providers use only provider-local modules, platform built-ins, `hunkdiff/extension`, and
  explicit `@hunk/vcs/*` leaves. The known-violations baseline is shrink-only: fix an edge, rerun
  `bun run deps:baseline`, and never add to it.
- Keep the app review-first: the main pane is a single top-to-bottom stream of all visible file diffs.
- The sidebar is for navigation. Selecting a file jumps to that file in the main review stream; it should not collapse the main pane to one file.
- Keep Pierre as the diff engine and renderer foundation. Do not switch the main renderer back to OpenTUI's built-in `<diff>` widget.
- Keep split and unified views terminal-native and driven from the same normalized diff model.
- Preserve mouse + keyboard parity for primary actions.
- Keep the chrome restrained: top menu bar, minimal borders, no redundant metadata headers.

## component guidance

- `HunkSessionHost` owns history/review routing in one React root. `AppHost` owns reload
  serialization, extension adoption, and broker/content/React commit ordering. `App` owns review
  interaction, navigation, layout, theme, filtering, and pane coordination. Pane and diff modules
  own rendering and geometry.
- `InteractiveSessionInitialization` in `packages/hunk/src/core/session/initialization.ts` carries
  finalized launch inputs whose lifetime spans routed surfaces. Add a concern there only when
  `HunkSessionHost` owns that cross-surface lifetime; keep surface-local bootstrap data out.
- Confirmation prompts with a small set of choices should reuse `ConfirmDialog` (body rows plus a clickable key-legend action row) instead of composing `ModalFrame` with a hand-rolled footer; keyboard handling for its actions stays in `useAppKeyboardShortcuts`.
- Extend existing components or add focused components rather than growing `App` into a monolith.
- Shared formatting, ids, and small derivations belong in helpers, not repeated inline.
- When refactoring logic that spans helpers and UI components, add tests at the level where the user-visible behavior actually lives, not only at the lowest helper layer.

## theme guidance

- Built-in theme ids and source metadata live in `packages/hunk/src/core/theme/catalog.ts`; `packages/hunk/src/ui/themes.ts`
  derives Hunk's semantic `AppTheme` values.
- When adding or renaming a built-in theme, update validation, public exports, docs/examples, the
  appropriate Changeset, and tests. Keep source palette tokens separate from semantic mappings and
  cover non-trivial derived colors.
- `BUNDLED_SHIKI_THEME_DIFF_COLORS` in `packages/hunk/src/core/theme/catalog.ts` is generated. Edit the sourcing policy in `scripts/generate/generate-theme-diff-colors.ts`, then run `bun run generate:theme-colors`.

## testing

- Colocate unit tests with the code they cover (`packages/hunk/src/core/foo.ts` + `packages/hunk/src/core/foo.test.ts`, `packages/hunk/src/ui/AppHost.*.test.tsx`, `packages/hunk/src/ui/lib/*.test.ts`).
- Put shared unit-test helpers in `test/helpers/`.
- Name test helpers so they explicitly include `Test` and are clearly test-only (`createTestDiffFile`).
- Use repo-level `test/` directories by intent:
  - `test/cli/` for black-box CLI contract coverage.
  - `test/session/` for daemon/session integration and end-to-end flows.
  - `test/pty/` for PTY-backed live UI integration tests.
  - `test/review-conformance/` for the shared review model's golden fixtures and per-consumer conformance suites.
  - `test/session-broker-node/` for real Node listener/adapter conformance.
  - `test/session-broker-runtime/` for shared Bun/Node broker fixtures.
  - `test/smoke/` for opt-in terminal transcript smoke coverage.
- `bun run test` does not include review conformance, PTY, TTY smoke, or real-Node adapter
  conformance under `test/session-broker-node/`. Run the dedicated command documented in
  `test/README.md` when changing those areas.

## source formatting

- Separate functions, class methods, nested helpers, and test declarations with a blank line; keep JSDoc and test-specific comments attached to their declaration.
- Use blank lines between logical phases inside functions. Keep related statements grouped rather than packing an entire workflow into one dense block.

## code comments

- Add short JSDoc-style comments to functions and helpers.
- Write header comments in active voice: the first sentence says what the module or function
  does ("Applies one action to the review state and returns the next state."), followed by its
  invariants. Avoid passive or self-important framing ("The one place where…", "the single
  source of truth for…") β€” name the behavior, not the architecture's opinion of itself.
- For orchestration and controller modules, explain the product workflow before the mechanics:
  name the user-visible triggers that converge there, state what the module owns, identify the
  neighboring authority it deliberately leaves elsewhere, and call out preservation or
  non-reloadable invariants. Prefer concrete flows ("watch changes and manual refresh both rebuild
  the mounted review") over abstract labels ("handles refresh").
- Add inline comments for intent, invariants, ownership, or non-obvious tradeoffs. Do not narrate
  syntax, praise the implementation, address the reader conversationally, or record temporary
  implementation history that belongs in Git or maintainer docs.

## naming

- Prefer names that match the role the code plays in the product and architecture.
- Use `layout` for structural placement or arrangement data.
- Use `geometry` for aggregate spatial data used by rendering, scrolling, or interaction.
- Use `bounds` for one concrete visible extent within a larger structure.

## review behavior

- Default behavior is a multi-file review stream in sidebar order.
- Layout modes are `auto`, `split`, and `unified`. `auto` chooses split on wide terminals and unified
  on narrow ones; explicit modes override it.
- `[` and `]` navigate hunks across the full review stream. Do not reintroduce `j`/`k` hunk navigation unless the user asks.
- Agent context belongs beside the code, not hidden in a separate mode or workflow.
- Agent notes are hunk-specific: show notes for the selected hunk, render them in the diff flow near the annotated row, and keep a clear spatial relationship to the code they explain.
- Keep note behavior explicit. If the UI intentionally prioritizes one note, one selection, or one active target, encode that as a named policy rather than scattering array-index assumptions through the codebase.
- STML markup notes (experimental) live in `packages/hunk/src/ui/lib/stml/`. The layout engine is deliberately a deterministic line layout, not OpenTUI flexbox: the row-windowed review stream needs exact note heights before mount, so `(markup, width)` must always produce the same lines. Colors stay symbolic until render time so measurement never needs a theme. Do not "simplify" this into flexbox renderables, and keep note-card geometry in `agentNoteGeometry` as the single source for rendering, measurement, and agent-facing width reporting.
- Keep temporary sidecars concise and review-oriented. Their file order is intentional, while the
  visible note UI remains hunk-note driven rather than showing generic explainer cards.
- Agents review via `packages/hunk/skills/hunk-review/SKILL.md` using `hunk session *` commands; do not run interactive TUI commands directly.
- `packages/hunk/skills/hunk-review/SKILL.md` is generated. Edit `packages/hunk/src/hunk-review/skillDocument.ts`, `packages/hunk/src/session/agent/surface.ts`, or `packages/hunk/src/session/agent/errors.ts`, then run `bun run generate:skill`; never hand-edit the skill file.

## binary notes

- Installed `hunk` is a compiled snapshot, not linked to source.
- After source changes, rebuild/reinstall with `bun run install:bin`.
- For rendering verification, prefer a real TTY smoke run over redirected stdout capture.

## verification

- For rendering changes: run `bun run typecheck`, `bun run test`, `bun run test:integration`,
  `bun run test:tty-smoke`, and do one real TTY smoke run on an actual diff.
- For interaction, layout, scrolling, navigation, windowing, or other terminal-native behavior: add or update PTY integration coverage in `test/pty/*-integration.test.ts` and run it with `bun run test:integration`.
- For broker/runtime changes, run `bun run test:session-broker-node` in addition to the relevant
  Bun tests.
- For CLI, config, or pager work: make sure the relevant source invocation still works (`diff`, `show`, `patch`, or `pager`).
- Preserve current interaction model unless the user asks to change it explicitly.

## cross-platform support

- Hunk should work on macOS, Linux, and Windows. Keep tests and CI portable unless a case is explicitly Unix-only (PTY/TTY smoke coverage is Unix-only).
- In tests, avoid hard-coded POSIX paths, separators, shell syntax, and filenames invalid on Windows; use Node path helpers for real filesystem paths while preserving user-provided/protocol paths when pass-through is intentional.
- If Windows-only Bun behavior appears around timers, sockets, or line endings, prefer a small compatibility fix or a narrowly scoped skip with a comment over broadening Unix assumptions.

## releases

- User-visible changes require a Changeset; maintenance-only changes require an empty Changeset.
  Follow `.changeset/README.md` and do not edit `CHANGELOG.md` directly.
- For release preparation, publishing, backports, and post-release verification, read `skills/hunk-release/SKILL.md`.
- Never push a release tag or trigger publishing without explicit user confirmation.
- `hunk.dev/changelog` is generated from `CHANGELOG.md` by `bun run generate:changelog`; hand-author only `website/releases/notes.json`, and never edit its output. `docs/changelog-on-hunk-dev.md` explains how release dates and the pre-tag window work.

## repo notes

- Local review artifacts are ignored on purpose. Leave them alone unless the user explicitly wants them updated, and do not commit them.
- Before committing or preparing a PR, follow `CONTRIBUTING.md`.