ワンクリックで
commit
Stage changes, run tests, and write a commit message. Use when work is ready to commit, push, or checkpoint.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Stage changes, run tests, and write a commit message. Use when work is ready to commit, push, or checkpoint.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Merge an approved change request once its gates are green — waiting on the pipeline if needed — then clean up the branch. Use when merging or landing a PR/MR.
Rebase on the default branch, push, open the PR/MR, and draft a description that tells reviewers WHY the change exists. Use when opening an MR/PR or creating a review.
File a new forge issue (or update an existing one) that leads with WHY the work is needed. Use when filing, creating, drafting, or updating a single issue or ticket. To find, browse, or pick which issue to work on next, use the `issues` skill instead.
List and rank the forge issues assigned to you so you can pick what to work on next — ranked by soonest due date, then most recently updated. Use whenever finding, browsing, surveying, or choosing the next issue/ticket to pick up, even when the user doesn't say "issues" — e.g. "what's next?", "what should I work on?", "anything due soon?", "show my open tickets". For filing or updating a single issue, use the `issue` skill instead.
Fetch an open CR's review feedback and drive each thread to resolution — fix, reply, resolve. Use when addressing review feedback or resolving comment threads on an open PR/MR.
Report a commit's forge pipeline state, or watch until it settles. Use when checking the status of a pipeline, build, CI, or GitHub Actions run — or watching one to completion.
| name | commit |
| description | Stage changes, run tests, and write a commit message. Use when work is ready to commit, push, or checkpoint. |
Confirm the target repo, run tests, stage all changes, and generate a commit message.
Don't narrate your work. Every step below is an operating instruction, not a script to read aloud — follow the execute-quietly discipline: ${CLAUDE_PLUGIN_ROOT}/guides/execute-quietly.md. For /commit, the only things worth surfacing are the resolved repo in one line, a failing test, the drafted message with its options, and the final review verdict; where a step prescribes exact output (e.g. Committed [short-sha]), emit that and nothing more.
%%{ init: { 'look': 'handDrawn' } }%%
flowchart TD
Start(["/commit"]) --> Preview{"--preview flag?"}
Preview -->|"Yes (cr)"| PreviewFull["Difftool on full branch diff, read verdict, stop"]
Preview -->|Yes| PreviewDiff["Difftool on working tree, read verdict, stop"]
Preview -->|No| Repo["Confirm target repo"] --> Tests
subgraph "Step 0: Tests"
Tests["Run test suite"] --> TestResult{Tests pass?}
TestResult -->|No| Fix["Fix failures"] --> Tests
TestResult -->|Yes| Stage
end
subgraph "Step 1: Stage & Read"
Stage["git add -A"] --> Staged{Changes staged?}
Staged -->|Yes| ReadDiff["Read staged diff"]
Staged -->|No| CheckHead{HEAD pushed?}
CheckHead -->|Yes| Stop([No local changes])
CheckHead -->|No| ReadHead["Diff HEAD~1"]
end
subgraph "Step 2-3: Write & Confirm"
ReadDiff --> Draft["Draft commit message"]
ReadHead --> Draft
Draft --> OnDefault{On default branch?}
OnDefault -->|Yes| Branch["Offer feature branch"] --> Confirm
OnDefault -->|No| Confirm{User choice?}
Confirm -->|Yes| Commit["git commit"]
Confirm -->|Merge| Amend["git commit --amend"]
Confirm -->|Edit| Revise["Revise message"] --> Confirm
end
subgraph "Step 4: Visual Diff"
Commit --> DiffTool["Launch difftool"]
Amend --> DiffTool
DiffTool --> Review{Review result?}
Review -->|Accepted| Done([Done])
Review -->|fix-now comments| Fix["Address fix-now comments"] --> Tests
end
--preview)When invoked with --preview, this is a look-only path: open a diff in the difftool for review, then stop. Do not run tests, stage, draft a message, or commit — none of the steps below apply. Resolve the target repo the same way (see "Target repo"), pick the diff scope from the argument, and launch the shared wrapper as a background Bash call (run_in_background: true), exactly as Step 4 does for the post-commit review:
--preview — the working tree vs HEAD (--local), to look over uncommitted work before committing. If the working tree is clean there's nothing uncommitted to show — but the branch may still hold unpushed commits worth a look before pushing. Check the unpushed-commit count:
bash "${CLAUDE_PLUGIN_ROOT}/scripts/look-ahead.sh"
If the count is 1 or more, offer the branch review — the whole branch vs the default branch, the same diff --preview cr shows — and run it when the user accepts:
bash "${CLAUDE_PLUGIN_ROOT}/scripts/review-diff.sh" --full
If the count is 0 or empty (nothing uncommitted and nothing unpushed), say so and stop rather than opening an empty diff.
--preview cr (or mr / pr) — the whole branch vs the default branch (--full), the way a reviewer sees the change request. Useful for a self-review of the full changeset before you open or update the CR.
bash "${CLAUDE_PLUGIN_ROOT}/scripts/review-diff.sh" --local # or --full for `cr` / `mr` / `pr`
Read the verdict back with the BashOutput tool (the REVIEW_VERDICT / REVIEW_OUTPUT contract and the command -v moor split are identical to Step 4 below). When moor is on PATH, map the verdict to a one-line result — Previewed — clean, Previewed — fix-now comments (list them), Previewed — unreviewed hunks, or Previewed — review closed without a verdict — and surface any advisory fix-later / consider comments. When moor isn't on PATH, the diff was shown in your git-configured difftool and the verdict comes back absent; report Previewed in your difftool rather than reading the silence as a failed review.
At the very start, call TaskList. If any task is already in_progress, this
skill is running inside an orchestrator (e.g. a release workflow) — run silently
and do not create your own tasks; the orchestrator's list is the source of
truth. If nothing is in_progress, /commit is the entry point; enumerate these
steps as tasks. Label them by what happens, not by the ## Step N headings
(the headings start at Step 0, so a numbered task list drifts one off) — and
don't split out a "read the diff" task, since reading is the input to drafting,
not a step of its own:
Run testsStage changesDraft commit messageCommit the checkpointReview the commit (amend on fix-now)The last two read commit-then-review on purpose: the commit is a durable,
re-reviewable checkpoint, and a fix-now amends that still-unpushed commit and
re-reviews. (To review before committing, that's --preview — see below.)
If the diff is empty and the skill exits early, mark remaining tasks deleted
rather than leaving them pending.
Before anything else, resolve which repo this operates on — the working directory isn't a reliable proxy (edits may have landed in a sibling repo). Re-resolve on every invocation; don't assume the previous target carries forward.
/anchor:commit <name>): resolve the name through tack's repo db — bash "${CLAUDE_PLUGIN_ROOT}/scripts/resolve-target.sh" <name> (see the cookbook's "Resolving a named target repo"). On TARGET_VIA=tack, use TARGET_LOCAL as the checkout; committing needs a work tree, so if TARGET_LOCAL is empty (a known remote with no checkout) say so and stop rather than committing to the wrong place. ambiguous → prompt with TARGET_CANDIDATES. cwd (no tack, or no match) → fall back to a case-insensitive substring-match of <name> against the basename of every git repo the session has touched; one match → use it (confirm in one line), zero/multiple → ask.git rev-parse --show-toplevel from the working directory. If the session touched more than one repo, or edits landed outside it, state the resolved path and ask which to target.Run git with -C <checkout> when the working directory isn't the target, rather than cd. The test runner in Step 0 and every git command below operate on the resolved checkout. The helper scripts this skill launches — look-ahead.sh, squash-check.sh, review-diff.sh — read their own origin/git state, so pass them the same target: --repo <checkout> for a checkout you operate on directly, or --worktree <path> for a flow-owned isolated worktree. On its own each would otherwise fall back to the cwd repo. When the target is a different repo than the session cwd and the work will mutate it, isolate that work in a worktree first — see scripts/worktree.sh and prepare-review's "Operating against a non-cwd repo" for the setup/teardown lifecycle.
Before reading changes, look for a test runner in the project (e.g., just test, npm test, dotnet test, pytest, go test ./..., a Makefile test target). Run the test suite.
If tests pass, proceed to Step 1.
If tests fail, stop and fix them. Present the failures and help the user resolve them. Do NOT proceed to Step 1 until the test suite exits cleanly. No exceptions — "pre-existing" failures still block the commit.
If no test suite is found, skip this step silently.
First, stage all changes:
git add -A
Then read what's staged:
git diff --cached --stat
git diff --cached
If nothing is staged after git add -A, fall back to describing the most recent commit. But first, verify HEAD hasn't already been pushed — otherwise you'd just be describing an already-published commit:
bash "${CLAUDE_PLUGIN_ROOT}/scripts/look-ahead.sh"
The helper prints the ahead-count (unpushed commits) or empty if no upstream is configured. If the count is 0, HEAD equals the remote tracking branch — warn the user that there are no local changes (staged or committed) and stop.
Otherwise, diff the most recent commit:
git diff HEAD~1 --stat
git diff HEAD~1
If both staged and HEAD~1 are empty, say so and stop.
Write the message following the format in templates/commit-message.md — it owns the shape (the cbea.ms rules and the trailer). Spend your effort on the why; the code already shows the how. If the change is trivial (typo fix, one-liner), a subject-only message is fine.
Keep the body free of loaded framing — temporal blame, size-minimizers, self-congratulatory adverbs, defensive softeners. The tone discipline lives in ${CLAUDE_PLUGIN_ROOT}/guides/loaded-framing.md (shared with prepare-review and issue); consult it while drafting.
anchor.* configRead the project + global anchor keys once:
git config --get-regexp '^anchor\.' 2>/dev/null
--get-regexp returns the names lowercased (anchor.worktrackerbaseuri); match them case-insensitively. Apply the keys relevant to a commit; absent keys keep anchor's defaults — never invent a value:
anchor.workTrackerBaseUri — when the user mentions a ticket (a full tracker URL, or a bare id), append a Refs: trailer (a footer line after a blank line, below the body): use a full URL as-is, or build <base-uri><id> from a bare id. Don't scrape the branch or prompt for a ticket — no mention, no trailer. Skip it for a trivial subject-only commit unless the user asks.anchor.commitRules — an extra rule layered onto the default commit-message rules for this message (the escape hatch for anything without a dedicated key).See ${CLAUDE_PLUGIN_ROOT}/guides/configuring.md for the full key set.
First, display the --stat summary from Step 1 so the user can see what's being committed. Then output the commit message in a fenced code block:
Subject line here
Body paragraph explaining why this change was made,
wrapped at 72 characters. Focus on context that isn't
obvious from the diff.
Before committing, check whether HEAD is the default branch:
git branch --show-current
Compare it to the default (git symbolic-ref --short refs/remotes/origin/HEAD | sed 's@^origin/@@', falling back to main/master). If they match, don't just commit onto the default branch — a commit meant for review belongs on a feature branch, and committing to the default branch directly is how work lands unreviewable (and how the leaked "commit on main, then try to open an MR from main" dead-end happens). Offer the branch, named from the subject you just drafted:
Add retry to checkout → add-retry-to-checkout.AskUserQuestion (header Branch), recommended option first so the default lands on branch creation:
<slug> (recommended) — git checkout -b <slug>, then commit onto it.<default> — the deliberate direct-to-default case (a release commit, a docs typo on main); proceed as normal.git checkout -b <that>.Create the branch (when chosen) before the commit below, so the commit lands on the feature branch. When /anchor:prepare-review chained here, the recommended branch path is exactly what it needs — it re-gathers afterward and opens the CR from the new branch.
Committing directly to the default branch is never a squash target — the gate below returns SQUASH=blocked, so even the "commit to <default>" path lands as a new commit rather than amending the published tip.
Before presenting options, decide whether squashing the staged changes into HEAD (via git commit --amend) is on the table. The gate is "is HEAD out for review?" — the helper decides it and returns only what you act on, one launch-and-read:
bash "${CLAUDE_PLUGIN_ROOT}/scripts/squash-check.sh"
The contract it prints:
| Key | What to do with it |
|---|---|
SQUASH | allowed → amending HEAD is safe; offer squash (gated further by relatedness below). blocked → the ordinary new commit (below) |
SQUASH_FORCE_PUSH | meaningful only when allowed: 1 → HEAD is pushed (a draft CR, or no CR), so the amend must be followed by git push --force-with-lease |
ALLOW_MESSAGE_AMEND | 1 → squash is blocked, but a message-only amend is permitted (the ready-CR case); gates the exception below. 0 → no amend of any kind |
PRIOR_SUBJECT | HEAD's subject, for the squash option text |
The helper folds the push-state probe (including the no-upstream origin/<default>..HEAD fallback), the author guard, and the CR-draft probe into that decision — don't re-run them. It deliberately does not emit why squash is blocked: the block reason, push count, CR state, and author identity stay inside the script, so there's nothing here to narrate or keep quiet by hand — the gate is silent by construction (${CLAUDE_PLUGIN_ROOT}/guides/execute-quietly.md).
SQUASH=blocked — the ordinary commitThe vanilla path, and the common one: HEAD isn't yours to rewrite or it's out for review, so a plain new commit is the only sensible outcome — exactly what the user asked for when they said "commit." The helper already withheld why, so there's nothing to keep quiet: present the drafted message with two choices and commit. The user never raised squashing; don't mention it.
On Accept, run git commit.
Narrow exception — message-only amend (ALLOW_MESSAGE_AMEND=1). When the helper permits a message-only amend and the user reports the message (not the code) is demonstrably wrong — pasted from a different repo, references identifiers that don't exist here, doesn't match what the diff does — the tree is unchanged, so the reviewer-protection motivation doesn't apply. Offer git commit --amend -F <msg-file> to fix the message, then surface "force-push (--force-with-lease) affects only the message; the tree is unchanged" as an explicit choice and let the user decide. The flag fires only where this is safe (a ready CR whose tree a message fix leaves untouched); when it's 0, no amend — a new commit is the only path. Do not extend it to content rewrites; the moment any file content moves, the standard gate applies again.
SQUASH=allowed — apply the relatedness judgmentThe gate is open; now your judgment decides squash vs new commit. Decide whether the staged changes are related to the prior commit (continuation, fix, or refinement of the same work) or unrelated (different topic, different files, new task):
When SQUASH_FORCE_PUSH=1 (pushed draft CR), annotate the squash option so the user knows the follow-up push is a force-push — e.g. _(CR is draft — mutable history is the norm; amend force-pushes with lease)_. Don't let it flip the recommendation; a draft's history is expected to move.
Present options in recommended-first order:
If recommending a new commit:
If recommending squash:
If they choose New commit (or Accept when no squash option), run git commit with the message.
If they choose Squash, write a combined commit message covering both the prior commit and the new changes, present it for confirmation, then run git commit --amend with the new message. If SQUASH_FORCE_PUSH=1, follow the amend with git push --force-with-lease so the open draft CR updates to the rewritten history.
If they choose Edit, commit with the drafted message then immediately open the editor:
git commit -m "..." && git commit --amend
Some hooks pattern-match on bash command substrings — destructive-operation gates (npm install -g, git push --force), secret-scanning regexes (secret/token/password/api.?key), or other safety guards. These can false-positive when the same string appears inside a heredoc'd commit message body — the hook sees the literal text and blocks the commit before git ever parses the heredoc. The trigger is often natural-language wording in the body that overlaps with the hook's keyword set.
If a commit attempt is rejected by a PreToolUse hook citing a substring that's actually inside the message body (not the executed command), stop and surface the conflict to the user. Do not reach for a temp-file workaround (Write to /tmp/... then git commit -F) — splitting the commit into a separate Write plus Bash doubles the permission prompts, hides the message body from the bash command preview, and introduces cross-session collision risk on predictable paths. The message wording is the right thing for the diff; the hook's matcher is the limitation. The user can approve the bypass for this commit or adjust the hook.
After committing, open the change in a visual review. First check whether moor — the difftool that speaks the sidecar contract — is on PATH, since that decides how you read the outcome (the same probe prepare-review and issue use):
command -v moor
Launch the wrapper in --commit mode — not raw git difftool. The wrapper determines the diff range from the unpushed-commit count (@{upstream}...HEAD for the first commit, HEAD~1...HEAD when earlier commits were already reviewed, an origin/... fallback when there's no upstream), pre-populates the commit subject / body / author / hash as a header, drives git's configured difftool (moor when it's installed and set as diff.tool, otherwise whatever diff.tool names), and — once it closes — prints the verdict on its own stdout. Raw git difftool bypasses the header and the verdict.
Launch as a background call (run_in_background: true): the wrapper blocks until the difftool closes, so a foreground call would hold the turn open until the Bash timeout.
bash "${CLAUDE_PLUGIN_ROOT}/scripts/review-diff.sh" --commit
When the background command completes, read its stdout with the BashOutput tool — not tail / $(...), which trip the command-substitution gate. The last lines carry the verdict (no separate file read):
REVIEW_VERDICT — 0 clean · 1 one-or-more fix-now · 2 unreviewed · 3 closed early · absent (no sidecar was written — either moor closed without one, or a non-moor difftool ran)REVIEW_OUTPUT — compact JSON; when the verdict is 1, read .comments from here. Each comment is {body, action, file?, startLine?, endLine?}: action is fix-now (the blocker), fix-later, or consider; body is the reviewer's inline feedback; the optional file / startLine / endLine anchor it to a line range (a comment may target a file, a line range, or the whole changeset with no line). The verdict and comments come from the difftool's sidecar contract, defined normatively in moor's SPEC.md (IM.OUT-*).If moor is on PATH, it drove the review and the sidecar carries a real verdict. Map it to exactly this output and nothing more:
0 → Committed [short-sha]. If .comments carries advisory comments (action fix-later or consider), surface them — they don't gate the commit, but the user may want to act on them.1 → Committed [short-sha] — fix-now comments, list the fix-now comments (the .comments entries where action == "fix-now"), then loop back to Step 0 (re-run tests after the fix). Surface any advisory (fix-later / consider) comments too. If a comment's body is short (e.g. "I don't get what this flag means") and the cited line range contains more than one distinct change (e.g. two flag additions in a usage block, two unrelated lines in the same range), ask the user which token the comment refers to before fixing — a one-second clarification beats several minutes of guessing wrong and re-amending. Fix the commented lines themselves; don't expand into adjacent pre-existing code (${CLAUDE_PLUGIN_ROOT}/guides/changeset-scope.md).2 → Committed [short-sha] — unreviewed hunks, what do you want to change?3 or absent → Committed [short-sha] — review closed without a verdict, what do you want to change? (moor was present, so absent means it closed before writing one — surface it as the anomaly it is.)If moor isn't on PATH, the wrapper deferred to your git-configured difftool (diff.tool — e.g. vscode, kdiff3, vimdiff), which presents the diff but doesn't speak the sidecar contract, so the verdict comes back absent. Here absent means the change was shown in your difftool, not that no review happened — report Committed [short-sha] — reviewed in your difftool, what do you want to change? and act on the reply, rather than prompting as if over an invisible diff. If the wrapper's output shows the difftool never launched (no diff.tool set, or it points at a tool that isn't installed), that's a local git misconfiguration: surface it plainly so the user can fix their config or install moor — don't substitute another tool.
Either way the commit has already landed — apply any requested changes, re-stage, amend the commit (it's unpushed), and re-launch.