Created
October 9, 2024 18:39
-
-
Save trvswgnr/140f7aaf048234d22276587771d7065d to your computer and use it in GitHub Desktop.
ai generate git commit message from diffs of staged files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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