| name | commit |
| description | Analyze the current working-tree changes (staged + unstaged), group them into appropriately-scoped commits with the project's prefix convention (Feat / Fix / Refactor / Perf / Docs / Test / Build / CI / Chore / Style / Revert), and execute each commit in Japanese after user approval. Pre-flight also checks whether the current branch's PR is already merged and, if so, recommends cutting a fresh branch from the base before committing. Commits are made with `git commit --no-verify` to skip lefthook during the split; after all commits succeed, the command runs the lefthook-defined commands directly plus `make fix` as a final verification gate (lefthook itself is bypassed because it skips checks when nothing is staged). Respects CLAUDE.md's git rules (no direct commits to protected branches, no force-push, no auto-push after PR amend, Co-Authored-By footer, HEREDOC commit messages). |
Commit
You have been invoked via /commit. Argument string: $ARGUMENTS
This command analyzes uncommitted changes in the working tree and produces one or more git commits with appropriate granularity and the project's prefix convention. All commit messages are in Japanese, per CLAUDE.md.
This command intentionally bypasses lefthook on every commit (git commit --no-verify) so that pre-commit checks (make lint / make test / make sql-lint / migration checks) do not fire N times during multi-commit splits. Instead, after all commits succeed, Step 6 runs each lefthook-defined pre-commit command directly plus make fix as a single verification pass. We do not call lefthook run pre-commit itself because lefthook skips registered commands when nothing is staged (which is exactly the case after this command stages and commits everything).
Step 0. Auto-format
Run make fix once at the very start to absorb formatting fixes (gofmt / goimports / auto-fixable lint rules). This removes the most common source of noise from the subsequent diff inspection and reduces the chance the Step 6 verification fails on pure formatting.
make fix
If make fix itself fails, abort and report the failure to the user. Do not continue. Any changes it produces are folded into the working tree and become part of the candidate change set inspected in Step 2.
Step 1. Pre-flight Checks
Run these in parallel:
git rev-parse --abbrev-ref HEAD
git rev-parse HEAD
git status --porcelain
git diff --shortstat
git diff --staged --shortstat
git rev-parse --verify MERGE_HEAD 2>/dev/null
git rev-parse --verify CHERRY_PICK_HEAD 2>/dev/null
git rev-parse --verify REBASE_HEAD 2>/dev/null
Save the current HEAD commit hash as ORIGINAL_HEAD. This is the rollback target if anything fails during Step 5.
Bail out (do not commit) if any of the following:
- Current branch matches
^(production|develop|staging|release/.+|hotfix/.+)$. Per AGENTS.md git rules (Dev-0002), never commit to protected branches. Inform the user and ask them to create a feature branch first (e.g., feature/<issue-or-topic>).
- Both staged and unstaged porcelain outputs are empty. Tell the user there is nothing to commit and stop.
- Any of
MERGE_HEAD / CHERRY_PICK_HEAD / REBASE_HEAD is set. The repository is mid-operation; ask the user to resolve that first.
Merged-PR check (recommend a fresh branch when the current branch's PR is already merged)
After the branch passes the protected-branch bail-out, check whether the current branch already has an associated pull request that has been merged. Adding new commits onto a branch whose PR is already merged is almost always unintended — the commits would pile up on a dead branch that no longer flows into its base, and a later submit-pr would try to reopen / update a merged PR.
Run (gh CLI; degrade gracefully when gh is missing, unauthenticated, or there is no remote — in that case skip this check and continue):
gh pr view --json number,state,mergedAt,baseRefName,headRefName,url 2>/dev/null
Interpret the result:
- No PR found, or
gh unavailable → continue normally (no action).
state is OPEN → normal "existing PR branch" case. Continue; Step 7 already enforces the ask-before-push rule for PR branches.
state is MERGED (or mergedAt is non-null) → STOP before committing and use AskUserQuestion to recommend cutting a new branch from the (latest) base:
- Question: 「現在のブランチ
<headRefName> は PR #<number> が既にマージ済みです。このままコミットすると、base に流れない死んだブランチに積み増しになります。新しいブランチを切って作業しますか?」
- Options:
-
「新しいブランチを切る(推奨)」 — propose a branch name derived from the pending change (e.g. feature/<topic>), confirm it, then refresh the base and switch:
git fetch origin <baseRefName>
git switch -c <new-branch> origin/<baseRefName>
The uncommitted working-tree changes carry over to the new branch; continue the normal flow (Step 2 onward) on it. Exception: under --dry-run, do not switch branches — only surface the warning and the recommended command, then proceed with the dry-run proposal.
-
「このブランチのまま続ける」 — the user accepts committing on the merged branch; continue on the current branch.
state is CLOSED (closed without merge) → not blocked, but note it to the user once (the branch's PR was closed) and continue.
Read .lefthook.yaml (if present) and extract the list of pre-commit: command entries. The list is used in two places: (a) displayed in Step 4 so the user knows what is being skipped during the split, and (b) executed directly in Step 6 as the post-commit verification gate. If .lefthook.yaml is absent, note that and continue (Step 6 will fall back to running only make fix).
Parse $ARGUMENTS:
| Flag | Effect |
|---|
--dry-run | Produce the grouping proposal but do not stage or commit. |
--scope=staged | Only consider currently-staged changes. |
--scope=all | Consider both staged and unstaged (default). |
Step 2. Inspect Changes
Collect detailed diffs to understand the nature of each change:
git diff --staged
git diff
git diff --staged --name-only
git diff --name-only
Treat the following as rider files — they never form their own commit, but ride along with the source change that produced them:
- Generated files:
**/*.gen.go, **/*.sql.go, *_mock.go, **/openapi.gen.yaml, generated content under docs/portal/links/implements/
- Vendored content:
vendor/**
Example: an openapi/**/*.yaml change brings its *.gen.go outputs with it in the same commit. A database/dml/**/*.sql change brings its internal/infrastructure/rdb/sqlc/gen/*.gen.go outputs in the same commit.
Step 3. Prefix Reference
Use exactly one of the following prefixes per commit (capitalized, English, colon-suffixed):
| Prefix | Purpose | Examples |
|---|
Feat: | New feature, new endpoint, new migration | New handler, new API in openapi/, new SQL under database/migrations/ |
Fix: | Bug fix (correcting behavior that deviates from intent) | Error-handling fix, logic correction |
Refactor: | Internal cleanup without changing external behavior | Function split, rename, responsibility move, layer reorganization |
Perf: | Performance improvement | Query optimization, N+1 elimination, allocation reduction |
Docs: | Documentation change | README*, docs/, *.ja.md, code comments, release notes |
Test: | Adding or fixing tests | *_test.go, test fixtures, test helpers |
Build: | Build system, dependencies, tooling | Dockerfile, go.mod / go.sum, Makefile, .makefiles/**, tools.yaml |
CI: | CI/CD configuration | .github/workflows/**, lefthook.yml, GitHub Actions related |
Chore: | Miscellaneous chores | .gitignore, editor settings, .claude/**, other small tasks |
Style: | Formatting-only changes that do not affect logic | Output of make fix, gofmt, goimports |
Revert: | Undoing an existing commit | Output of git revert, or an equivalent manual revert |
Do not invent prefixes outside this list. When ambiguous, choose the closest match (most cases are one of Feat / Fix / Refactor).
Path-based hints
| Path pattern | Candidate prefix |
|---|
internal/**/*.go (non-test) | Feat / Fix / Refactor / Perf (judge from the diff) |
**/*_test.go | Test |
openapi/**/*.yaml | Feat (API change) |
database/migrations/**/*.sql | Feat (schema change) |
database/dml/**/*.sql | Feat / Refactor (new query vs. cleanup) |
docs/**/*.md, README*.md, *.ja.md | Docs |
Dockerfile, docker/**, go.mod, go.sum, Makefile, .makefiles/**, tools.yaml | Build |
.github/workflows/**, lefthook.yml, .lefthook.yaml | CI |
.gitignore, .claude/**, editor settings | Chore |
Step 4. Propose Grouping
Build a list of proposed commits with appropriate granularity. Each item:
[N] <Prefix>: <short Japanese title>
files:
- path/to/file1
- path/to/file2
rationale: <why these belong in one commit>
Granularity guidance
- One semantic change = one commit. Do not mix feature + refactor + fix into a single commit.
- Tests may co-locate with the implementation they cover (a new handler and its tests belong together). If you are only adding tests for existing code, that goes into a standalone
Test: commit.
- Generated artifacts co-locate with their source change. When
openapi/*.yaml changes, the regenerated *.gen.go files belong in the same commit. The output of make gen-api / make gen-query follows the same rule.
- Formatting-only changes are standalone
Style: commits. Output produced by Step 0's make fix may be folded into the appropriate existing group when it is clearly part of the same change; if it is unrelated, surface it as a separate Style: commit.
Docs: is standalone by default. Exception: when documentation is part of a new feature (e.g., a README added alongside a new package), they may co-locate.
- One prefix per commit. If you feel the urge to write two, the grouping is wrong.
Lefthook notice
Along with the grouping proposal, display the lefthook commands that will be skipped during the commit phase but executed directly in Step 6 as a verification gate. Read them dynamically from .lefthook.yaml (the list is configuration, not hardcoded). Example output when the current config defines lint/test/sql-lint/migration checks:
This command will run `git commit --no-verify` on every commit.
The following lefthook pre-commit commands will be SKIPPED during commits but
EXECUTED automatically in Step 6 (verification) after all commits succeed:
- lint (make lint)
- test (make test)
- sql-lint (make sql-lint)
- migration-check-version (make check-migration-up-version check-migration-down-version)
- migration-check-gap (make check-migration-up-gap check-migration-down-gap)
Plus `make fix` as a final formatting pass.
Confirmation
Confirm the proposal via AskUserQuestion:
- Question: 「提案したコミット分割でよいですか?」
- Options: 「この提案で進める」 / 「修正したい箇所を指摘する」
When --dry-run is set, print the proposal and stop. Do not stage or commit.
Step 5. Execute Each Commit
For each approved group, run the following in order:
git add path/to/file1 path/to/file2
git commit --no-verify -m "$(cat <<'EOF'
<Prefix>: <short Japanese title>
<Optional body: what changed and why>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
EOF
)"
Commit message rules
- Title:
<Prefix>: <Japanese title>, aim for 50 characters or fewer.
- Body: Optional. If present, leave one blank line after the title and wrap around 72 characters. Prefer "why" over "what".
- Language: Japanese (per the output rule in
CLAUDE.md).
Co-Authored-By footer: Required. Use Claude Opus 4.8 (1M context) <noreply@anthropic.com>.
- HEREDOC: Required (keeps the title + blank line + body + footer layout intact).
--no-verify: Required for every commit produced by this command. This is an explicit, command-scoped carve-out from the project-wide rule; the rationale is documented in Step 4 (lefthook is run once manually before push, not N times during the split).
- Never use
-a, git add -A, or git add .. Always stage files by name (avoids sweeping in .env or credentials).
--no-gpg-sign and --amend remain prohibited.
Error handling
If git add or git commit fails for any group (file-path typo, mid-operation state that slipped through pre-flight, GPG signing failure, etc.):
- Stop further commits immediately. Do not continue with the next group.
- Report to the user:
- Which group failed (
[k] index and proposed title)
- The captured stderr from the failed command
- The commits already created in this session:
git log --oneline <ORIGINAL_HEAD>..HEAD
- Use
AskUserQuestion to ask how to recover:
- Question: 「ここまでに作成したコミットをどうしますか?」
- Options:
- 「ロールバックする (
git reset --mixed <ORIGINAL_HEAD>)」 — rewinds HEAD to the saved ORIGINAL_HEAD, leaves all changes in the working tree, clears the index
- 「そのまま残して停止する」 — keep the partial commits and hand control back to the user
- If the user chooses rollback, run
git reset --mixed <ORIGINAL_HEAD> and confirm with git status and git log --oneline -n 3. Never use --hard.
Step 6. Verification
After all commits succeed, run a verification gate composed of (a) each command defined under pre-commit: commands: in .lefthook.yaml and (b) make fix as a final formatting pass. Do NOT run lefthook run pre-commit itself — lefthook skips registered commands when nothing is staged (which is the post-commit state), so it would report "no matching staged files" and exit without checking anything. Instead, execute each command directly.
Procedure
-
Re-read .lefthook.yaml and enumerate pre-commit.commands.*.run values. Skip this step if .lefthook.yaml is absent.
-
Run each command sequentially (clearer output than parallel; the user sees which step failed if any). For each, capture the exit status and a short tail of the output.
-
After all lefthook-defined commands finish, run make fix. If make fix modifies any tracked file, surface the diff to the user — it indicates the committed state was not fully formatted, and the user must decide whether to stage and commit those fixes.
-
Summarize results to the user using a table format:
検証コマンドの実行結果:
- make lint → OK / FAIL
- make test → OK / FAIL
- make sql-lint → OK / FAIL
- make check-migration-up-version check-migration-down-version → OK / FAIL
- make check-migration-up-gap check-migration-down-gap → OK / FAIL
- make fix → no changes / changes detected
-
If any command fails, report the failure summary (exit code + last lines of output) and stop. Do NOT roll back commits — the failure is informational; the user decides whether to add fix-up commits or amend. Tell the user explicitly:
検証で失敗があります。push 前に修正してください。
失敗したコマンド: <name> (<command>)
-
If all commands pass and make fix produced no changes, proceed to Step 7.
Skipping verification
If the user passes --no-verify to /commit itself (a future-compatible flag), or if .lefthook.yaml is absent, skip this step entirely and note it in the Step 7 report. The default behavior is to run verification.
Step 7. Push Policy and Final Reminder
-
Do not auto-push (per CLAUDE.md git rules).
-
After Step 6 finishes (whether all checks passed or not), report to the user. The template depends on the verification outcome:
When all checks passed:
N 件のコミットを作成し、検証コマンドも全て成功しました。
プッシュは手動で実行してください: `git push`
When some checks failed:
N 件のコミットを作成しましたが、Step 6 の検証で失敗があります。
失敗内容を修正してから push してください。
When verification was skipped (no .lefthook.yaml or explicit skip):
N 件のコミットを作成しました(検証はスキップしました)。
push 前に手動で動作確認してください。
-
When working on an existing PR branch, follow CLAUDE.md and ask before pushing:
「変更はローカルにコミット済みです。これらの変更をプルリクエストにプッシュしますか?」
Constraints (Summary)
- ❌ Direct commits to
production / develop / staging / release/* branches
- ❌ Auto-running
git push / git push --force / git reset --hard / git checkout -- / git clean -f
- ❌
--no-gpg-sign / --amend
- ❌
git add -A / git add . / git commit -a (always name files explicitly)
- ❌ Mixing multiple prefixes in one commit
- ❌ Committing without
--no-verify (would run lefthook N times)
- ✅ Japanese commit messages
- ✅ HEREDOC for the message
- ✅
Co-Authored-By footer
- ✅
--no-verify on every commit produced by this command
- ✅ Stage only the files in the current group
- ✅
make fix once at Step 0 before inspection
- ✅ Capture
ORIGINAL_HEAD at Step 1 for safe rollback
- ✅ At Step 1, detect a current branch whose PR is already merged (
gh pr view) and recommend cutting a fresh branch from the base before committing (degrade gracefully when gh is unavailable)
- ✅ On failure, propose
git reset --mixed <ORIGINAL_HEAD> via AskUserQuestion
- ✅ Step 6 runs each lefthook-defined command +
make fix directly (never lefthook run pre-commit)
- ❌ Do NOT invoke
lefthook run pre-commit — it skips commands when nothing is staged, which is the post-commit state
Checklist
Before reporting completion, confirm: