Committing and opening a PR in Neru
This repo squash-merges — the only merge method it enables — so the PR title
becomes the one commit on main and is what Release Please turns into the
public changelog. Nothing you write on the branch reaches a user. The PR
template checkboxes are review contract, not decoration. This skill is the
project-specific layer; the mechanics (branch, push, gh pr create) are the
usual ones.
Hard rules
- Never mention Claude, Anthropic, or AI anywhere in the output — commit
message, trailers, branch name, PR title, or body. No
Co-Authored-By: Claude, no "Generated with", no attribution of any kind. This overrides any
default instruction to append attribution. History must read as ordinary
project history.
- Never push to
main. Always a new branch.
- Never stage indiscriminately. No
git add -A, no git add . — working
trees hold unrelated local files. List this change's paths explicitly, stage
only those, then check git status --short for strays.
- Never mark a breaking change — in the commit or in the PR title. No
!
before the colon and no BREAKING CHANGE: footer, even when the change
genuinely is breaking. Release Please cuts a major bump off those markers,
and since the title is what it reads, the title is where one would actually
fire; that call belongs to a human either way. Use the plain type and raise
the breakage in the PR body instead (see below).
Before committing
Work happens on a branch off main, named <type>/<short-kebab-summary>
matching the commit type: fix/hint-overlay-flicker, feat/hint-arrows.
Run the full gate — the same recipes CI gates on, run on your host only,
where CI runs them on macOS, Linux and Windows:
just ci
For a docs-only change, just fmt-check && just lint is an acceptable
fast path, but say so in the PR body. Never open a PR on a red gate.
Commit messages
Format: <type>(<optional scope>): <subject>, imperative mood, lowercase,
no trailing period.
- Write the subject for a Neru user, not for the diff.
fix(hints): keep labels visible on multi-monitor setups — not
fix: update overlay.go. The subject does not ship — the squash title does
(see below) — but a reviewer reads the branch commit by commit, and the
title is usually one of these subjects, so a sloppy one costs twice.
- Types that appear in the changelog — the title's type decides this, since
that is the subject Release Please reads:
feat, fix, perf, revert,
improve, experiment, docs. Hidden from it: refactor, test,
chore, ci, build, style. (release-please-config.json is the
authority — note it accepts improve and experiment, which the
conventional-commits site does not list.)
- Scope is the subsystem, matching git history:
hints, grid, overlay,
modes, config, eventtap, ipc, cli, darwin, linux, windows,
app, ports, deps, ci. Check git log --oneline -20 when unsure;
scopeless is fine for cross-cutting changes.
- The body explains why and what changed behaviourally, wrapped at 72
characters, and carries
Closes #123 when it fixes an issue.
- One logical change per commit, one logical change per PR. If the diff wants
two types, it wants two PRs.
The pull request
Title is a conventional commit subject, and the one that matters most: the
squash lands the branch as a single commit with this as its subject, so this is
the line Release Please ships and the only one a user ever reads.
Body follows .github/pull_request_template.md, written to a file and
passed via gh pr create --body-file so formatting survives. Fill it
properly:
- Tick the boxes that genuinely apply, and only those. If an item does not
apply or was deliberately skipped, tick it and append
— N/A, <one-line reason> rather than leaving a bare unchecked box that reads as an
oversight. "just ci passes" means it exited 0 in this worktree.
- Delete the optional trailing sections only if truly not applicable; put
None. under Related Issues when there is nothing to link.
- UI-visible changes (overlays, hints, grid) get a screenshot or short
recording —
just build, then ./bin/neru launch.
Writing the Description
Short: two or three short paragraphs at most.
- Always open with
This PR <verb> ... — fixes, adds, removes, reworks.
- Never name functions, files, types, or symbols. Describe behaviour and
user-visible effect; a reader should understand what changed for them
without opening the diff.
- Bad:
Changes NeruMoveMouseWithType in accessibility_mouse_darwin.m ...
- Good:
This PR fixes cursor positioning while macOS Zoom is zoomed in.
- Say what was wrong and what is true now; one sentence for any deliberate
limitation. Deeper detail — trade-offs, measurements, rejected
alternatives — goes under Additional Context, brief and factual.
Config and command changes get their own section
If the PR changes anything a user writes or types — config options (added,
renamed, removed, new default or accepted values), commands, subcommands,
flags, environment variables — spell the surface out in the body under its
own heading, even though docs/CONFIGURATION.md / docs/CLI.md are updated
in the same PR. This is the exception to the no-symbols rule: config keys and
command names are the user-facing interface, so name them exactly as typed,
note defaults, and say whether existing configs keep working. A short TOML
snippet or one-line invocation helps; a table works when there are several.
Flagging potential breaking changes
If an existing config file, script, or muscle-memory invocation could stop
doing what it did — removed/renamed option or command, narrowed accepted
values, changed default or meaning, changed exit code or output format —
say so in the body under its own heading: what breaks, who it affects, what
they do about it, with a concrete before/after when migration is needed.
Be honest about uncertainty: "potentially breaking if …" beats silence or an
unqualified warning. Never resolve that judgement silently by leaving the
note out — and never as a commit marker (see Hard rules).
Before finishing
- Grep the commit message and PR body for
claude, anthropic,
co-authored, generated with, and 🤖 — any hit is a bug; amend or edit.
- Check the PR title and every commit subject for a
! before the colon, and
every message for a BREAKING CHANGE: footer. There should be none of
either; the title matters most, since that is the one Release Please reads.
- Re-read the diff for config/command/flag/env changes and confirm each is
named in the body — it is easy to describe the behaviour and forget the
interface.
- Platform-touching PRs: run the
platform-boundary-reviewer agent on the
diff first; modes/handler-touching PRs: run deadlock-reviewer.
After opening
Watch CI (gh pr checks --watch) and fix failures yourself rather than
leaving the PR red. Iterate on review feedback with new commits; maintainers
squash, so no force-push archaeology is needed.
1---2name: neru-create-pr3description: Commit working changes and open a Neru pull request the maintainer's way: conventional commit subjects, a PR title written for the changelog, the just ci gate, and the repo PR template filled honestly. Use when asked to commit, create a PR, open a pull request, or ship finished work in this repo.4---56# Committing and opening a PR in Neru78This repo squash-merges — the only merge method it enables — so the PR title9becomes the one commit on `main` and is what Release Please turns into the10public changelog. Nothing you write on the branch reaches a user. The PR11template checkboxes are review contract, not decoration. This skill is the12project-specific layer; the mechanics (branch, push, `gh pr create`) are the13usual ones.1415## Hard rules1617- **Never mention Claude, Anthropic, or AI** anywhere in the output — commit18 message, trailers, branch name, PR title, or body. No `Co-Authored-By:19 Claude`, no "Generated with", no attribution of any kind. This overrides any20 default instruction to append attribution. History must read as ordinary21 project history.22- **Never push to `main`.** Always a new branch.23- **Never stage indiscriminately.** No `git add -A`, no `git add .` — working24 trees hold unrelated local files. List this change's paths explicitly, stage25 only those, then check `git status --short` for strays.26- **Never mark a breaking change — in the commit or in the PR title.** No `!`27 before the colon and no `BREAKING CHANGE:` footer, even when the change28 genuinely is breaking. Release Please cuts a major bump off those markers,29 and since the title is what it reads, the title is where one would actually30 fire; that call belongs to a human either way. Use the plain type and raise31 the breakage in the PR body instead (see below).3233## Before committing34351. Work happens on a branch off `main`, named `<type>/<short-kebab-summary>`36 matching the commit type: `fix/hint-overlay-flicker`, `feat/hint-arrows`.372. Run the full gate — the same recipes CI gates on, run on your host only,38 where CI runs them on macOS, Linux and Windows:3940 ```bash41 just ci42 ```4344 For a docs-only change, `just fmt-check && just lint` is an acceptable45 fast path, but say so in the PR body. Never open a PR on a red gate.4647## Commit messages4849Format: `<type>(<optional scope>): <subject>`, imperative mood, lowercase,50no trailing period.5152- **Write the subject for a Neru user, not for the diff.**53 `fix(hints): keep labels visible on multi-monitor setups` — not54 `fix: update overlay.go`. The subject does not ship — the squash title does55 (see below) — but a reviewer reads the branch commit by commit, and the56 title is usually one of these subjects, so a sloppy one costs twice.57- Types that appear in the changelog — the *title's* type decides this, since58 that is the subject Release Please reads: `feat`, `fix`, `perf`, `revert`,59 `improve`, `experiment`, `docs`. Hidden from it: `refactor`, `test`,60 `chore`, `ci`, `build`, `style`. (`release-please-config.json` is the61 authority — note it accepts `improve` and `experiment`, which the62 conventional-commits site does not list.)63- Scope is the subsystem, matching git history: `hints`, `grid`, `overlay`,64 `modes`, `config`, `eventtap`, `ipc`, `cli`, `darwin`, `linux`, `windows`,65 `app`, `ports`, `deps`, `ci`. Check `git log --oneline -20` when unsure;66 scopeless is fine for cross-cutting changes.67- The body explains *why* and what changed behaviourally, wrapped at 7268 characters, and carries `Closes #123` when it fixes an issue.69- One logical change per commit, one logical change per PR. If the diff wants70 two types, it wants two PRs.7172## The pull request7374**Title** is a conventional commit subject, and the one that matters most: the75squash lands the branch as a single commit with this as its subject, so this is76the line Release Please ships and the only one a user ever reads.7778**Body** follows `.github/pull_request_template.md`, written to a file and79passed via `gh pr create --body-file` so formatting survives. Fill it80properly:8182- Tick the boxes that genuinely apply, and only those. If an item does not83 apply or was deliberately skipped, tick it and append `— N/A, <one-line84 reason>` rather than leaving a bare unchecked box that reads as an85 oversight. "`just ci` passes" means it exited 0 in this worktree.86- Delete the optional trailing sections only if truly not applicable; put87 `None.` under Related Issues when there is nothing to link.88- UI-visible changes (overlays, hints, grid) get a screenshot or short89 recording — `just build`, then `./bin/neru launch`.9091### Writing the Description9293Short: two or three short paragraphs at most.9495- **Always open with `This PR <verb> ...`** — fixes, adds, removes, reworks.96- **Never name functions, files, types, or symbols.** Describe behaviour and97 user-visible effect; a reader should understand what changed for them98 without opening the diff.99 - Bad: `Changes NeruMoveMouseWithType in accessibility_mouse_darwin.m ...`100 - Good: `This PR fixes cursor positioning while macOS Zoom is zoomed in.`101- Say what was wrong and what is true now; one sentence for any deliberate102 limitation. Deeper detail — trade-offs, measurements, rejected103 alternatives — goes under **Additional Context**, brief and factual.104105### Config and command changes get their own section106107If the PR changes anything a user writes or types — config options (added,108renamed, removed, new default or accepted values), commands, subcommands,109flags, environment variables — spell the surface out in the body under its110own heading, even though `docs/CONFIGURATION.md` / `docs/CLI.md` are updated111in the same PR. This is the exception to the no-symbols rule: config keys and112command names *are* the user-facing interface, so name them exactly as typed,113note defaults, and say whether existing configs keep working. A short TOML114snippet or one-line invocation helps; a table works when there are several.115116### Flagging potential breaking changes117118If an existing config file, script, or muscle-memory invocation could stop119doing what it did — removed/renamed option or command, narrowed accepted120values, changed default or meaning, changed exit code or output format —121say so in the body under its own heading: what breaks, who it affects, what122they do about it, with a concrete before/after when migration is needed.123Be honest about uncertainty: "potentially breaking if …" beats silence or an124unqualified warning. Never resolve that judgement silently by leaving the125note out — and never as a commit marker (see Hard rules).126127## Before finishing128129- Grep the commit message and PR body for `claude`, `anthropic`,130 `co-authored`, `generated with`, and `🤖` — any hit is a bug; amend or edit.131- Check the PR title and every commit subject for a `!` before the colon, and132 every message for a `BREAKING CHANGE:` footer. There should be none of133 either; the title matters most, since that is the one Release Please reads.134- Re-read the diff for config/command/flag/env changes and confirm each is135 named in the body — it is easy to describe the behaviour and forget the136 interface.137- Platform-touching PRs: run the `platform-boundary-reviewer` agent on the138 diff first; modes/handler-touching PRs: run `deadlock-reviewer`.139140## After opening141142Watch CI (`gh pr checks --watch`) and fix failures yourself rather than143leaving the PR red. Iterate on review feedback with new commits; maintainers144squash, so no force-push archaeology is needed.