hermes-git 0.3.2 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +413 -50
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -37589,9 +37589,11 @@ function initCommand(program2) {
37589
37589
  await mkdir3(".hermes", { recursive: true });
37590
37590
  await writeFile4(".hermes/config.json", JSON.stringify(config, null, 2));
37591
37591
  await mkdir3(".hermes/backups", { recursive: true });
37592
- await appendToGitignore(`.hermes/backups/
37593
- .hermes/stats.json
37594
- `);
37592
+ const added = await updateGitignore();
37593
+ if (added.length > 0) {
37594
+ console.log(`
37595
+ \uD83D\uDCDD Added to .gitignore: ${added.join(", ")}`);
37596
+ }
37595
37597
  displaySuccess("Hermes initialized successfully!");
37596
37598
  console.log(`
37597
37599
  \uD83D\uDCC4 Configuration saved to .hermes/config.json`);
@@ -37734,23 +37736,38 @@ async function interactiveConfig(repoInfo) {
37734
37736
  }
37735
37737
  };
37736
37738
  }
37737
- async function appendToGitignore(content) {
37738
- try {
37739
- const { appendFile } = await import("fs/promises");
37740
- const gitignorePath = ".gitignore";
37741
- if (existsSync4(gitignorePath)) {
37742
- const { readFile: readFile5 } = await import("fs/promises");
37743
- const existing = await readFile5(gitignorePath, "utf-8");
37744
- if (!existing.includes(".hermes/backups")) {
37745
- await appendFile(gitignorePath, `
37739
+ var GITIGNORE_ENTRIES = [
37740
+ { pattern: ".env", comment: null },
37741
+ { pattern: ".env.*", comment: null },
37742
+ { pattern: "!.env.example", comment: null },
37743
+ { pattern: ".hermes/backups/", comment: null },
37744
+ { pattern: ".hermes/stats.json", comment: null }
37745
+ ];
37746
+ async function updateGitignore() {
37747
+ const { appendFile, readFile: rf } = await import("fs/promises");
37748
+ const gitignorePath = ".gitignore";
37749
+ let existing = "";
37750
+ if (existsSync4(gitignorePath)) {
37751
+ try {
37752
+ existing = await rf(gitignorePath, "utf-8");
37753
+ } catch {}
37754
+ }
37755
+ const existingLines = existing.split(`
37756
+ `).map((l) => l.trim());
37757
+ const toAdd = GITIGNORE_ENTRIES.filter((e) => !existingLines.includes(e.pattern));
37758
+ if (toAdd.length === 0)
37759
+ return [];
37760
+ const block = `
37746
37761
  # Hermes
37747
- ` + content);
37748
- }
37749
- } else {
37750
- await writeFile4(gitignorePath, `# Hermes
37751
- ` + content);
37752
- }
37753
- } catch {}
37762
+ ` + toAdd.map((e) => e.pattern).join(`
37763
+ `) + `
37764
+ `;
37765
+ if (existsSync4(gitignorePath)) {
37766
+ await appendFile(gitignorePath, block);
37767
+ } else {
37768
+ await writeFile4(gitignorePath, block.trimStart());
37769
+ }
37770
+ return toAdd.map((e) => e.pattern);
37754
37771
  }
37755
37772
 
37756
37773
  // src/commands/stats.ts
@@ -38737,32 +38754,348 @@ function buildInstallCommand(pm) {
38737
38754
  }
38738
38755
  }
38739
38756
 
38757
+ // src/commands/commit.ts
38758
+ import { exec as exec6 } from "child_process";
38759
+ import { promisify as promisify6 } from "util";
38760
+ var execAsync6 = promisify6(exec6);
38761
+ async function getStagedFiles2() {
38762
+ try {
38763
+ const { stdout } = await execAsync6("git diff --cached --name-status");
38764
+ return stdout.trim().split(`
38765
+ `).filter(Boolean).map((line) => {
38766
+ const [status, ...rest] = line.split("\t");
38767
+ return { status: status.trim(), path: rest.join("\t").trim() };
38768
+ });
38769
+ } catch {
38770
+ return [];
38771
+ }
38772
+ }
38773
+ async function getUnstagedFiles() {
38774
+ try {
38775
+ const { stdout } = await execAsync6("git status --porcelain");
38776
+ return stdout.trim().split(`
38777
+ `).filter(Boolean).map((line) => {
38778
+ const status = line.slice(0, 2).trim();
38779
+ const path5 = line.slice(3).trim();
38780
+ return { status, path: path5 };
38781
+ }).filter(({ status }) => status === "??" || status[0] === " " || status.length === 1);
38782
+ } catch {
38783
+ return [];
38784
+ }
38785
+ }
38786
+ async function getRecentBranchCommits(n = 5) {
38787
+ try {
38788
+ const { stdout } = await execAsync6(`git log --oneline -${n} --no-merges 2>/dev/null`);
38789
+ return stdout.trim();
38790
+ } catch {
38791
+ return "";
38792
+ }
38793
+ }
38794
+ function statusLabel(s) {
38795
+ const map = {
38796
+ M: source_default.yellow("modified "),
38797
+ A: source_default.green("new file "),
38798
+ D: source_default.red("deleted "),
38799
+ R: source_default.blue("renamed "),
38800
+ C: source_default.blue("copied "),
38801
+ "??": source_default.dim("untracked"),
38802
+ " M": source_default.yellow("modified "),
38803
+ " D": source_default.red("deleted ")
38804
+ };
38805
+ return map[s] ?? source_default.dim(s.padEnd(9));
38806
+ }
38807
+ function divider() {
38808
+ console.log(source_default.dim(" " + "─".repeat(54)));
38809
+ }
38810
+ async function analyzeChanges(branch, stagedDiff, stagedStat, recentCommits) {
38811
+ const prompt2 = `You are an expert Git historian. Analyze these staged changes and produce a structured commit analysis.
38812
+
38813
+ Branch: ${branch}
38814
+ Recent commits on this branch:
38815
+ ${recentCommits || "(none — first commit)"}
38816
+
38817
+ Staged diff summary:
38818
+ ${stagedStat}
38819
+
38820
+ Full staged diff (truncated to 12000 chars):
38821
+ ${stagedDiff.slice(0, 12000)}
38822
+
38823
+ Return RAW JSON ONLY — no markdown, no code fences, just the JSON object:
38824
+ {
38825
+ "summary": "2-3 sentences: what was changed and the likely intent behind it",
38826
+ "concerns": ["array of concerns — mixed unrelated changes, debug/temp code, large binary, TODO left in, test missing, etc. Empty array if none."],
38827
+ "message": "conventional commit: type(scope): subject (max 72 chars). Be specific.",
38828
+ "body": "optional multi-line body explaining WHY (not WHAT). Empty string if the subject is self-explanatory.",
38829
+ "alternatives": ["two alternative commit messages if the intent is ambiguous"]
38830
+ }
38831
+
38832
+ Rules for message:
38833
+ - type: feat | fix | refactor | docs | test | chore | style | perf | build | ci
38834
+ - scope: the primary module/component affected (omit if changes are cross-cutting)
38835
+ - subject: imperative mood, no period, lowercase after colon
38836
+ - be specific — "add OAuth login" not "add feature"`;
38837
+ const raw = await getAISuggestion(prompt2);
38838
+ const cleaned = raw.replace(/^```(?:json)?\s*/i, "").replace(/\s*```\s*$/, "").trim();
38839
+ try {
38840
+ return JSON.parse(cleaned);
38841
+ } catch {
38842
+ return {
38843
+ summary: "Could not parse analysis.",
38844
+ concerns: [],
38845
+ message: cleaned.split(`
38846
+ `)[0].slice(0, 72),
38847
+ body: "",
38848
+ alternatives: []
38849
+ };
38850
+ }
38851
+ }
38852
+ function commitCommand(program2) {
38853
+ program2.command("commit").description("Analyze staged changes with AI and craft a commit message").option("-a, --all", "Stage all tracked changes before analysis").option("--no-body", "Omit the commit body even if one is suggested").action(async (options) => {
38854
+ const start = Date.now();
38855
+ try {
38856
+ const repoState = await getRepoState();
38857
+ if (options.all) {
38858
+ displayStep("git add -u");
38859
+ await execAsync6("git add -u");
38860
+ }
38861
+ const staged = await getStagedFiles2();
38862
+ if (staged.length === 0) {
38863
+ console.log(source_default.yellow(`
38864
+ Nothing staged to commit.`));
38865
+ console.log(source_default.dim(" Use `git add <file>` or run `hermes commit --all` to stage tracked changes.\n"));
38866
+ process.exit(0);
38867
+ }
38868
+ const unstaged = await getUnstagedFiles();
38869
+ const recentCommits = await getRecentBranchCommits(5);
38870
+ console.log();
38871
+ console.log(source_default.bold(` Staged (${staged.length} file${staged.length === 1 ? "" : "s"}):`));
38872
+ for (const f of staged) {
38873
+ console.log(` ${statusLabel(f.status)} ${source_default.white(f.path)}`);
38874
+ }
38875
+ const relevantUnstaged = unstaged.filter((u) => !staged.some((s) => s.path === u.path));
38876
+ if (relevantUnstaged.length > 0) {
38877
+ console.log();
38878
+ console.log(source_default.dim(` Not staged (${relevantUnstaged.length}):`));
38879
+ for (const f of relevantUnstaged.slice(0, 8)) {
38880
+ console.log(` ${statusLabel(f.status)} ${source_default.dim(f.path)}`);
38881
+ }
38882
+ if (relevantUnstaged.length > 8) {
38883
+ console.log(source_default.dim(` ...and ${relevantUnstaged.length - 8} more`));
38884
+ }
38885
+ }
38886
+ const { name, model } = await getActiveProvider();
38887
+ console.log();
38888
+ console.log(` Analyzing... ${source_default.dim(`[${name} / ${model}]`)}`);
38889
+ const [stagedDiff, stagedStat] = await Promise.all([
38890
+ execAsync6("git diff --cached").then((r) => r.stdout),
38891
+ execAsync6("git diff --cached --stat").then((r) => r.stdout)
38892
+ ]);
38893
+ const analysis = await analyzeChanges(repoState.currentBranch, stagedDiff, stagedStat, recentCommits);
38894
+ console.log();
38895
+ divider();
38896
+ console.log();
38897
+ console.log(" " + source_default.bold("Understanding"));
38898
+ console.log();
38899
+ const words = analysis.summary.split(" ");
38900
+ let line = " ";
38901
+ for (const w of words) {
38902
+ if (line.length + w.length > 62) {
38903
+ console.log(source_default.white(line));
38904
+ line = " " + w + " ";
38905
+ } else {
38906
+ line += w + " ";
38907
+ }
38908
+ }
38909
+ if (line.trim())
38910
+ console.log(source_default.white(line));
38911
+ if (analysis.concerns.length > 0) {
38912
+ console.log();
38913
+ for (const c of analysis.concerns) {
38914
+ console.log(` ${source_default.yellow("⚠")} ${source_default.yellow(c)}`);
38915
+ }
38916
+ }
38917
+ console.log();
38918
+ divider();
38919
+ console.log();
38920
+ const hasBody = options.body !== false && analysis.body.trim().length > 0;
38921
+ console.log(" " + source_default.bold("Proposed commit"));
38922
+ console.log();
38923
+ console.log(" " + source_default.cyan.bold(analysis.message));
38924
+ if (hasBody) {
38925
+ console.log();
38926
+ analysis.body.split(`
38927
+ `).forEach((l) => {
38928
+ console.log(" " + source_default.dim(l));
38929
+ });
38930
+ }
38931
+ console.log();
38932
+ let finalMessage = analysis.message;
38933
+ let finalBody = hasBody ? analysis.body : "";
38934
+ let committed = false;
38935
+ while (!committed) {
38936
+ const choices = [
38937
+ { name: "Commit", value: "commit" },
38938
+ { name: "Edit message", value: "edit" }
38939
+ ];
38940
+ if (analysis.alternatives?.length > 0) {
38941
+ choices.push({ name: "See alternative messages", value: "alts" });
38942
+ }
38943
+ if (relevantUnstaged.length > 0) {
38944
+ choices.push({ name: "Stage more files first", value: "stage" });
38945
+ }
38946
+ choices.push({ name: "Cancel", value: "cancel" });
38947
+ const { action } = await esm_default12.prompt([
38948
+ {
38949
+ type: "list",
38950
+ name: "action",
38951
+ message: "What would you like to do?",
38952
+ choices
38953
+ }
38954
+ ]);
38955
+ if (action === "cancel") {
38956
+ console.log(source_default.dim(`
38957
+ Cancelled. Changes remain staged.
38958
+ `));
38959
+ await recordCommand("commit", [], Date.now() - start, false);
38960
+ return;
38961
+ }
38962
+ if (action === "alts") {
38963
+ console.log();
38964
+ analysis.alternatives.forEach((alt, i) => {
38965
+ console.log(` ${source_default.dim(`${i + 1}.`)} ${source_default.cyan(alt)}`);
38966
+ });
38967
+ console.log();
38968
+ const { pick } = await esm_default12.prompt([
38969
+ {
38970
+ type: "list",
38971
+ name: "pick",
38972
+ message: "Use an alternative?",
38973
+ choices: [
38974
+ ...analysis.alternatives.map((a, i) => ({ name: a, value: `${i}` })),
38975
+ { name: "Keep original", value: "keep" }
38976
+ ]
38977
+ }
38978
+ ]);
38979
+ if (pick !== "keep") {
38980
+ finalMessage = analysis.alternatives[parseInt(pick, 10)];
38981
+ finalBody = "";
38982
+ console.log();
38983
+ console.log(" " + source_default.cyan.bold(finalMessage));
38984
+ console.log();
38985
+ }
38986
+ continue;
38987
+ }
38988
+ if (action === "edit") {
38989
+ const { edited } = await esm_default12.prompt([
38990
+ {
38991
+ type: "input",
38992
+ name: "edited",
38993
+ message: "Commit message:",
38994
+ default: finalMessage
38995
+ }
38996
+ ]);
38997
+ finalMessage = edited.trim();
38998
+ finalBody = "";
38999
+ console.log();
39000
+ continue;
39001
+ }
39002
+ if (action === "stage") {
39003
+ const { files } = await esm_default12.prompt([
39004
+ {
39005
+ type: "checkbox",
39006
+ name: "files",
39007
+ message: "Select files to stage:",
39008
+ choices: relevantUnstaged.map((f) => ({
39009
+ name: `${statusLabel(f.status)} ${f.path}`,
39010
+ value: f.path
39011
+ }))
39012
+ }
39013
+ ]);
39014
+ if (files.length > 0) {
39015
+ for (const f of files) {
39016
+ const cmd = `git add ${JSON.stringify(f)}`;
39017
+ displayStep(cmd);
39018
+ await execAsync6(cmd);
39019
+ }
39020
+ console.log(source_default.dim(`
39021
+ Staged ${files.length} file(s). Re-running analysis...
39022
+ `));
39023
+ const [newDiff, newStat] = await Promise.all([
39024
+ execAsync6("git diff --cached").then((r) => r.stdout),
39025
+ execAsync6("git diff --cached --stat").then((r) => r.stdout)
39026
+ ]);
39027
+ const newAnalysis = await analyzeChanges(repoState.currentBranch, newDiff, newStat, recentCommits);
39028
+ analysis.summary = newAnalysis.summary;
39029
+ analysis.concerns = newAnalysis.concerns;
39030
+ analysis.message = newAnalysis.message;
39031
+ analysis.body = newAnalysis.body;
39032
+ analysis.alternatives = newAnalysis.alternatives;
39033
+ finalMessage = newAnalysis.message;
39034
+ finalBody = options.body !== false && newAnalysis.body.trim().length > 0 ? newAnalysis.body : "";
39035
+ console.log(" " + source_default.bold("Updated proposal"));
39036
+ console.log();
39037
+ console.log(" " + source_default.cyan.bold(finalMessage));
39038
+ if (finalBody) {
39039
+ console.log();
39040
+ finalBody.split(`
39041
+ `).forEach((l) => console.log(" " + source_default.dim(l)));
39042
+ }
39043
+ if (newAnalysis.concerns.length > 0) {
39044
+ console.log();
39045
+ newAnalysis.concerns.forEach((c) => {
39046
+ console.log(` ${source_default.yellow("⚠")} ${source_default.yellow(c)}`);
39047
+ });
39048
+ }
39049
+ console.log();
39050
+ }
39051
+ continue;
39052
+ }
39053
+ if (action === "commit") {
39054
+ const fullMessage = finalBody ? `${finalMessage}
39055
+
39056
+ ${finalBody}` : finalMessage;
39057
+ displayStep(`git commit -m "${finalMessage}"${finalBody ? " (with body)" : ""}`);
39058
+ await execAsync6(`git commit -m ${JSON.stringify(fullMessage)}`);
39059
+ displaySuccess("Committed!");
39060
+ const { stdout: hash } = await execAsync6("git rev-parse --short HEAD");
39061
+ console.log(source_default.dim(` ${hash.trim()} ${finalMessage}
39062
+ `));
39063
+ await recordCommand("commit", [], Date.now() - start, true);
39064
+ committed = true;
39065
+ }
39066
+ }
39067
+ } catch (error3) {
39068
+ console.error("❌ Error:", error3 instanceof Error ? error3.message : error3);
39069
+ await recordCommand("commit", [], Date.now() - start, false);
39070
+ process.exit(1);
39071
+ }
39072
+ });
39073
+ }
39074
+
38740
39075
  // src/lib/update-notifier.ts
38741
39076
  import { readFile as readFile6, writeFile as writeFile6, mkdir as mkdir5 } from "fs/promises";
38742
39077
  import { existsSync as existsSync6 } from "fs";
38743
39078
  import { homedir as homedir2 } from "os";
38744
39079
  import path5 from "path";
38745
39080
  var PACKAGE_NAME2 = "hermes-git";
38746
- var CHECK_INTERVAL = 24 * 60 * 60 * 1000;
39081
+ var CHECK_INTERVAL = 12 * 60 * 60 * 1000;
38747
39082
  var CACHE_DIR = path5.join(homedir2(), ".hermes", "cache");
38748
39083
  var CACHE_FILE = path5.join(CACHE_DIR, "update-check.json");
38749
- async function getLatestVersion() {
39084
+ async function fetchDistTags() {
38750
39085
  try {
38751
- const response = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME2}/latest`);
38752
- if (!response.ok)
38753
- return null;
38754
- const data = await response.json();
38755
- return data.version || null;
39086
+ const res = await fetch(`https://registry.npmjs.org/-/package/${PACKAGE_NAME2}/dist-tags`, { signal: AbortSignal.timeout(5000) });
39087
+ if (!res.ok)
39088
+ return {};
39089
+ return await res.json();
38756
39090
  } catch {
38757
- return null;
39091
+ return {};
38758
39092
  }
38759
39093
  }
38760
39094
  async function readCache() {
38761
39095
  try {
38762
39096
  if (!existsSync6(CACHE_FILE))
38763
39097
  return null;
38764
- const content = await readFile6(CACHE_FILE, "utf-8");
38765
- return JSON.parse(content);
39098
+ return JSON.parse(await readFile6(CACHE_FILE, "utf-8"));
38766
39099
  } catch {
38767
39100
  return null;
38768
39101
  }
@@ -38773,36 +39106,66 @@ async function writeCache(cache) {
38773
39106
  await writeFile6(CACHE_FILE, JSON.stringify(cache, null, 2));
38774
39107
  } catch {}
38775
39108
  }
38776
- function isNewerVersion(current, latest) {
38777
- const currentParts = current.split(".").map(Number);
38778
- const latestParts = latest.split(".").map(Number);
39109
+ function compareVersions2(a, b) {
39110
+ const pa = a.split(".").map(Number);
39111
+ const pb = b.split(".").map(Number);
38779
39112
  for (let i = 0;i < 3; i++) {
38780
- if (latestParts[i] > currentParts[i])
38781
- return true;
38782
- if (latestParts[i] < currentParts[i])
38783
- return false;
39113
+ if (pa[i] > pb[i])
39114
+ return 1;
39115
+ if (pa[i] < pb[i])
39116
+ return -1;
38784
39117
  }
38785
- return false;
39118
+ return 0;
39119
+ }
39120
+ async function enforceMinimumVersion(currentVersion) {
39121
+ try {
39122
+ const cache = await readCache();
39123
+ const now = Date.now();
39124
+ const stale = !cache || now - cache.lastChecked > CHECK_INTERVAL;
39125
+ let minimumVersion = cache?.minimumVersion ?? null;
39126
+ let latestVersion = cache?.latestVersion ?? null;
39127
+ if (stale) {
39128
+ const tags = await fetchDistTags();
39129
+ latestVersion = tags.latest ?? latestVersion;
39130
+ minimumVersion = tags.minimum ?? null;
39131
+ await writeCache({ lastChecked: now, latestVersion: latestVersion ?? undefined, minimumVersion: minimumVersion ?? undefined });
39132
+ }
39133
+ if (minimumVersion && compareVersions2(currentVersion, minimumVersion) < 0) {
39134
+ console.error("");
39135
+ console.error(source_default.red.bold(" ✖ This version of hermes is no longer supported."));
39136
+ console.error("");
39137
+ console.error(` You have ${source_default.dim(currentVersion)}, minimum required is ${source_default.red.bold(minimumVersion)}.`);
39138
+ console.error("");
39139
+ console.error(" Update now:");
39140
+ console.error(` ${source_default.cyan("npm install -g hermes-git@latest")}`);
39141
+ console.error(` ${source_default.dim("or: hermes update")}`);
39142
+ console.error("");
39143
+ process.exit(1);
39144
+ }
39145
+ } catch {}
38786
39146
  }
38787
39147
  async function checkForUpdates(currentVersion) {
38788
39148
  try {
38789
39149
  const cache = await readCache();
38790
39150
  const now = Date.now();
38791
- const shouldCheck = !cache || now - cache.lastChecked > CHECK_INTERVAL;
38792
- let latestVersion = cache?.latestVersion || null;
38793
- if (shouldCheck) {
38794
- latestVersion = await getLatestVersion();
39151
+ const stale = !cache || now - cache.lastChecked > CHECK_INTERVAL;
39152
+ let latestVersion = cache?.latestVersion ?? null;
39153
+ if (stale) {
39154
+ const tags = await fetchDistTags();
39155
+ latestVersion = tags.latest ?? null;
38795
39156
  await writeCache({
38796
39157
  lastChecked: now,
38797
- latestVersion: latestVersion || undefined
39158
+ latestVersion: latestVersion ?? undefined,
39159
+ minimumVersion: cache?.minimumVersion
38798
39160
  });
38799
39161
  }
38800
- if (latestVersion && isNewerVersion(currentVersion, latestVersion)) {
39162
+ if (latestVersion && compareVersions2(latestVersion, currentVersion) > 0) {
39163
+ const gap = " ".repeat(Math.max(0, 17 - currentVersion.length - latestVersion.length));
38801
39164
  console.log(source_default.yellow(`
38802
- ┌─────────────────────────────────────────────────────┐`));
38803
- console.log(source_default.yellow("│") + " " + source_default.bold("Update available!") + " " + source_default.dim(currentVersion) + " " + source_default.green.bold(latestVersion) + " " + source_default.yellow("│"));
38804
- console.log(source_default.yellow("│") + " Run: " + source_default.cyan("npm install -g hermes-git@latest") + " " + source_default.yellow("│"));
38805
- console.log(source_default.yellow(`└─────────────────────────────────────────────────────┘
39165
+ ┌──────────────────────────────────────────────────────┐`));
39166
+ console.log(source_default.yellow("│") + ` ${source_default.bold("Update available!")} ${source_default.dim(currentVersion)}${source_default.green.bold(latestVersion)}${gap}` + source_default.yellow("│"));
39167
+ console.log(source_default.yellow("│") + ` Run: ${source_default.cyan("hermes update")}` + " ".repeat(36) + source_default.yellow("│"));
39168
+ console.log(source_default.yellow(`└──────────────────────────────────────────────────────┘
38806
39169
  `));
38807
39170
  }
38808
39171
  } catch {}
@@ -38889,7 +39252,7 @@ function printWorkflows() {
38889
39252
 
38890
39253
  // src/index.ts
38891
39254
  var program2 = new Command;
38892
- var CURRENT_VERSION = "0.3.2";
39255
+ var CURRENT_VERSION = "0.3.5";
38893
39256
  program2.name("hermes").description("Intent-driven Git, guided by AI").version(CURRENT_VERSION).action(() => {
38894
39257
  printBanner(CURRENT_VERSION);
38895
39258
  printWorkflows();
@@ -38907,5 +39270,5 @@ workflowCommand(program2);
38907
39270
  configCommand(program2);
38908
39271
  guardCommand(program2);
38909
39272
  updateCommand(program2, CURRENT_VERSION);
38910
- checkForUpdates(CURRENT_VERSION).catch(() => {});
38911
- program2.parse();
39273
+ commitCommand(program2);
39274
+ enforceMinimumVersion(CURRENT_VERSION).then(() => program2.parseAsync()).then(() => checkForUpdates(CURRENT_VERSION)).catch(() => {});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hermes-git",
3
- "version": "0.3.2",
3
+ "version": "0.3.5",
4
4
  "description": "Intent-driven Git, guided by AI. Turn natural language into safe, explainable Git operations.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",