Tutorials Search / Native Mac IDE / Magic Push: AI-written commit messages
📝 Written ● Beginner Updated 2026-05-13

Magic Push: AI-written commit messages

Stage. Click. Push. Magic Push reads the actual diff, writes a commit message that describes what changed and why, then pushes — no "wip" placeholders, no "fix stuff" entries.

Most engineers know what a good commit message looks like, and most engineers' commit logs are full of bad ones. The reason isn't that good messages are hard to write — they aren't. The reason is that by the time you're ready to commit, you've already done the work, you're tired, the diff is complicated, and writing a short imperative summary of all of it is one more cognitive task you don't want. So you type "fix" or "updates" or worst of all "wip" and move on. Three weeks later, when something is wrong and you're trying to git blame the regression, you find a commit message that tells you nothing.

This problem is asymmetric. Writing the commit message takes thirty seconds; reading a bad one costs minutes every time it gets read. Yet the cost is paid by future-you, and the time is saved by present-you, so the equilibrium drifts toward bad messages. The only sustainable fix is to remove the friction at write-time. If the message takes zero seconds to write, you'll write a good one.

Magic Push closes that gap. The agent reads the staged diff — what files changed, what lines, what shape of change — and drafts a commit message describing it. You review the draft, edit if it's wrong, and push. Total time: about the time it takes to read three lines. The activation energy for "actually write a good message" goes from "thirty seconds of thought" to "five seconds of reading."

What you'll learn

Step 1: Stage your changes

1

The git panel, like any other UI

Open the git panel in the sidebar. You'll see two sections — "Unstaged" with current edits, "Staged" with what's ready to commit. Click to move files between the two, or click hunks within a file to stage by hunk.

The granularity matters: Magic Push describes what's staged, not what's modified. If you've changed five things and only want to commit one of them, stage just that one. The generated message will be about that one, not the full diff.

Step 2: Click "Generate commit message"

2

The diff goes in, a message comes out

Above the commit message text box in the git panel, there's a button (typically a sparkle icon, sometimes labeled "Suggest"). Click it. The agent reads the staged diff and writes a draft message into the box, usually in the form of an imperative one-line summary, optionally with a body paragraph for non-trivial changes.

For example, a diff that adds rate-limit logging to one HTTP handler might produce: "Add rate-limit logging to /api/upload." A diff that refactors three files to use a shared helper might produce: "Extract shared signing logic into AuthHelper." A diff that mixes two unrelated changes might produce: "Add rate-limit logging and rename UserRepo to UserStore." That last one is a flag: when the agent struggles to write one summary, the commit is probably two commits in a trench coat.

The "two commits in a trench coat" smell: if the generated message has an "and" connecting two unrelated changes, the right answer is usually to split the staging — commit the first change with its own message, commit the second separately. Magic Push's confusion is informative.

Step 3: Edit the draft

3

The agent is right about what, sometimes wrong about why

The agent's draft is good at describing what changed because it can see the diff. It's less good at describing why, because the why isn't in the diff — it's in your head, in the ticket, in last week's discussion. When the why matters (which is for most non-trivial commits), edit the draft to add it.

Example: "Rename UserRepo to UserStore" is what the diff shows. The why might be "Match the StoreRepo / FooStore naming convention adopted in #1422." The agent doesn't know about #1422 unless you said so. Add it.

For trivial commits (lint fixes, formatting, typo corrections), the draft is usually fine as-is.

Step 4: Push

4

Commit and push in one action

With the message in place, click the push button. The git panel commits with your message, then pushes to the tracking remote. The whole flow — stage, generate, edit, push — fits in well under a minute for typical changes.

If you'd rather commit without pushing (you're not ready to share yet), there's a separate "Commit only" option. Push later when you are.

Step 5: Tune the style for your team

5

Set conventions once, get them every time

Different teams have different commit message conventions. Conventional Commits (feat: ..., fix: ..., chore: ...). Imperative without a prefix. Short summary only, no body. Reference ticket IDs at the end.

Tell the agent your team's convention once in CLAUDE.md at the project root:

## Commit messages

Use imperative voice, no conventional-commit prefix. End with the
ticket ID if applicable, e.g. "Add rate-limit logging (#1422)".

From then on, generated drafts follow the convention. The whole repo benefits — anyone using LingCode in this project gets the same style.

Step 6: When NOT to use it

6

The agent doesn't know secrets

  • Security fixes. When a commit fixes a CVE-class issue, you may want to commit with a minimal message and disclose details only after a release. The agent's full description gives the vulnerability shape away. Write these by hand.
  • Highly contextual commits. A commit that only makes sense if you know the ticket, the customer, the prior incident — the agent will produce something accurate-but-shallow. You're better off writing it yourself.
  • Squash commits with hundreds of files. The agent works best on focused diffs. A massive squash gets a thin summary. Either commit at higher granularity (the better answer), or write the squash message by hand.
Don't let the agent push to main if you have a "never push to main" policy. Magic Push respects whatever branch you're on. If your team uses PR-based workflows, push to a feature branch and open the PR. (You can also enforce this with a PreToolUse hook — "refuse any git push targeting main.")

What's next