Skip to content

Instantly share code, notes, and snippets.

@trvswgnr
Created October 9, 2024 18:39
Show Gist options
  • Save trvswgnr/140f7aaf048234d22276587771d7065d to your computer and use it in GitHub Desktop.
Save trvswgnr/140f7aaf048234d22276587771d7065d to your computer and use it in GitHub Desktop.
ai generate git commit message from diffs of staged files
#!/usr/bin/env bun
import { exec } from "child_process";
/*
Generate a commit message for the staged changes.
*/
import Anthropic from "@anthropic-ai/sdk";
const anthropic = new Anthropic();
async function sendPrompt(prompt: string) {
const msg = await anthropic.messages.create({
model: "claude-3-5-sonnet-20240620",
max_tokens: 8192,
temperature: 0,
messages: [
{
role: "user",
content:
prompt +
"\n\n" +
"Generate a detailed commit message for the staged changes. Output like this:\n\n" +
"```json\n" +
'{ "commit_message": {' +
' "lines": ["<line1>", "<line2>", "<line3>"]' +
"} }\n" +
"```" +
"\n\n" +
"The commit message should be all lowercase, UNLESS referring to code or some other capitalized term. It does not need to be concise.",
},
],
stream: false,
});
return msg;
}
async function getStagedChangesDiffs() {
return new Promise<string>((resolve, reject) => {
const p = exec("git diff --cached");
let stdout = "";
let stderr = "";
p.stdout?.on("data", (data) => {
stdout += data;
});
p.stderr?.on("data", (data) => {
stderr += data;
});
p.on("close", () => {
if (stderr) {
reject(stderr);
}
resolve(stdout);
});
});
}
async function main() {
const stagedChangesDiffs = await getStagedChangesDiffs();
if (stagedChangesDiffs.trim().length === 0) {
console.error("No staged changes");
process.exit(1);
}
const response = await sendPrompt(stagedChangesDiffs);
const msg = response.content.map((c) => ("text" in c ? c.text : "")).join("");
// get the message starting with "```json" and ending with "```"
const jsonStart = msg.indexOf("```json");
const jsonEnd = msg.indexOf("```", jsonStart + 1);
try {
const json = JSON.parse(msg.slice(jsonStart + 7, jsonEnd));
const message = json.commit_message.lines;
// trim each line
const trimmedMessage = message
.map((line: string, index: number) => {
if (line.trim().length === 0) {
return null;
}
if (index === 0) {
return line.trim() + "\n";
}
return line.trim();
})
.filter((line: string | null) => line !== null)
.join("\n");
console.log(trimmedMessage);
} catch (e) {
console.error("Error parsing JSON for commit message");
console.log("original message:", msg);
}
}
await main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment