From c9d6306981dec80d59413afce27845876ad17a71 Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Thu, 30 Apr 2026 22:30:16 -0400 Subject: [PATCH] =?UTF-8?q?fix(hermes):=20rewrite=20CLAUDE.md=20=E2=86=92?= =?UTF-8?q?=20HERMES.md=20(revert=20from=20.hermes.md=20per=20spec)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per the issue spec for #2841 and CodeRabbit feedback on PR #2920, the project-context filename rewrite should produce HERMES.md, not .hermes.md. Reverts the earlier .hermes.md change at all 5 substitution sites in bin/install.js and updates the corresponding regression test in tests/hermes-install.test.cjs to assert HERMES.md. Full suite: 6127/6127 pass. --- bin/install.js | 10 +++++----- tests/hermes-install.test.cjs | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/bin/install.js b/bin/install.js index ad88b9542..e1020afbc 100755 --- a/bin/install.js +++ b/bin/install.js @@ -5370,7 +5370,7 @@ function copyCommandsAsClaudeSkills(srcDir, skillsDir, prefix, pathPrefix, runti } // Hermes Agent reuses Claude skill format; rewrite branding + paths. if (runtime === 'hermes') { - content = content.replace(/CLAUDE\.md/g, '.hermes.md'); + content = content.replace(/CLAUDE\.md/g, 'HERMES.md'); content = content.replace(/\bClaude Code\b/g, 'Hermes Agent'); content = content.replace(/\.claude\//g, '.hermes/'); } @@ -5619,7 +5619,7 @@ function copyWithPathReplacement(srcDir, destDir, pathPrefix, runtime, isCommand content = content.replace(/\.claude\//g, '.qwen/'); fs.writeFileSync(destPath, content); } else if (isHermes) { - content = content.replace(/CLAUDE\.md/g, '.hermes.md'); + content = content.replace(/CLAUDE\.md/g, 'HERMES.md'); content = content.replace(/\bClaude Code\b/g, 'Hermes Agent'); content = content.replace(/\.claude\//g, '.hermes/'); fs.writeFileSync(destPath, content); @@ -5678,7 +5678,7 @@ function copyWithPathReplacement(srcDir, destDir, pathPrefix, runtime, isCommand let jsContent = fs.readFileSync(srcPath, 'utf8'); jsContent = jsContent.replace(/\.claude\/skills\//g, '.hermes/skills/'); jsContent = jsContent.replace(/\.claude\//g, '.hermes/'); - jsContent = jsContent.replace(/CLAUDE\.md/g, '.hermes.md'); + jsContent = jsContent.replace(/CLAUDE\.md/g, 'HERMES.md'); jsContent = jsContent.replace(/\bClaude Code\b/g, 'Hermes Agent'); fs.writeFileSync(destPath, jsContent); } else { @@ -7336,7 +7336,7 @@ function install(isGlobal, runtime = 'claude') { content = content.replace(/\bClaude Code\b/g, 'Qwen Code'); content = content.replace(/\.claude\//g, '.qwen/'); } else if (isHermes) { - content = content.replace(/CLAUDE\.md/g, '.hermes.md'); + content = content.replace(/CLAUDE\.md/g, 'HERMES.md'); content = content.replace(/\bClaude Code\b/g, 'Hermes Agent'); content = content.replace(/\.claude\//g, '.hermes/'); } @@ -7404,7 +7404,7 @@ function install(isGlobal, runtime = 'claude') { content = content.replace(/\bClaude Code\b/g, 'Qwen Code'); } if (isHermes) { - content = content.replace(/CLAUDE\.md/g, '.hermes.md'); + content = content.replace(/CLAUDE\.md/g, 'HERMES.md'); content = content.replace(/\bClaude Code\b/g, 'Hermes Agent'); } content = content.replace(/\{\{GSD_VERSION\}\}/g, pkg.version); diff --git a/tests/hermes-install.test.cjs b/tests/hermes-install.test.cjs index 3d02ee2ea..3724e4d0c 100644 --- a/tests/hermes-install.test.cjs +++ b/tests/hermes-install.test.cjs @@ -150,14 +150,14 @@ describe('Hermes Agent local install/uninstall', () => { uninstall(false, 'hermes'); }); - test('replaces CLAUDE.md references with .hermes.md (Hermes-discovered project context name)', () => { + test('replaces CLAUDE.md references with HERMES.md', () => { install(false, 'hermes'); const targetDir = path.join(tmpDir, '.hermes'); const skillsDir = path.join(targetDir, 'skills'); - // Walk all skill files and confirm no `CLAUDE.md` token leaks; if any - // skill body referenced project context, it should now point at - // `.hermes.md` (per https://hermes-agent.nousresearch.com/docs). + // Walk all skill files and confirm no `CLAUDE.md` token leaks; any + // skill body that referenced project context should now point at + // `HERMES.md` per the issue spec. let referencedHermesMd = false; const walk = (dir) => { for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { @@ -167,13 +167,13 @@ describe('Hermes Agent local install/uninstall', () => { const content = fs.readFileSync(full, 'utf8'); assert.ok(!/\bCLAUDE\.md\b/.test(content), `${path.relative(targetDir, full)} still references CLAUDE.md`); - if (/\.hermes\.md/.test(content)) referencedHermesMd = true; + if (/\bHERMES\.md\b/.test(content)) referencedHermesMd = true; } }; walk(skillsDir); // Sanity: at least one skill in the GSD set references the project // context filename, so the substitution actually exercises. - assert.ok(referencedHermesMd, 'at least one skill references .hermes.md after substitution'); + assert.ok(referencedHermesMd, 'at least one skill references HERMES.md after substitution'); uninstall(false, 'hermes'); });