From 62219e8b53e24adc12eec7ed71477ec3e65e5ad4 Mon Sep 17 00:00:00 2001 From: abhigyantrumio Date: Sun, 26 Jul 2026 06:30:43 +0530 Subject: [PATCH] fix(setup): group skill-rename leftover notices into one line per rename A multi-tool setup printed the "skill X was renamed to Y" notice once per agent target (4x for Claude Code/Cursor/OpenCode/Codex). Leftover legacy dirs are now collected during install and flushed as a single grouped notice per rename - all target paths on one line - just before the summary block. Co-Authored-By: Claude Fable 5 --- gitnexus/src/cli/setup.ts | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/gitnexus/src/cli/setup.ts b/gitnexus/src/cli/setup.ts index dc0a0867e..e95ca8048 100644 --- a/gitnexus/src/cli/setup.ts +++ b/gitnexus/src/cli/setup.ts @@ -1031,6 +1031,23 @@ export const RENAMED_SKILL_DIRS: Readonly> = { */ export const LEGACY_SKILL_DIR_NAMES: readonly string[] = Object.values(RENAMED_SKILL_DIRS).flat(); +/** Legacy skill dirs found during this run, keyed `oldName|newName` — flushed + * as one grouped notice per rename by {@link flushSkillRenameNotices}. */ +const pendingSkillRenameNotices = new Map(); + +/** Print the collected rename leftovers (one line per rename, all target + * paths grouped) and reset the collector. */ +export function flushSkillRenameNotices(): void { + for (const [key, paths] of pendingSkillRenameNotices) { + const [oldName, skillName] = key.split('|'); + console.log( + ` Note: skill "${oldName}" was renamed to "${skillName}". Left in place ` + + `(delete manually if you have not customized them): ${paths.join(', ')}`, + ); + } + pendingSkillRenameNotices.clear(); +} + /** * Install GitNexus skills to a target directory. * Each skill is installed as {targetDir}/gitnexus-{skillName}/SKILL.md @@ -1102,14 +1119,16 @@ async function installSkillsTo(targetDir: string): Promise { // A directory superseded by a shipped rename is warned about, never // deleted: the installer cannot prove it owns the contents (users // customize installed skills or hand-write their own under these - // names), so an upgrade must not destroy data. + // names), so an upgrade must not destroy data. Collected instead of + // printed here so a multi-tool setup emits one grouped notice per + // rename, not one line per target directory. for (const oldName of RENAMED_SKILL_DIRS[skillName] ?? []) { const legacyDir = path.join(targetDir, oldName); if (await dirExists(legacyDir)) { - console.log( - `[gitnexus] skill "${oldName}" was renamed to "${skillName}"; ` + - `left ${legacyDir} in place — delete it manually if you have not customized it.`, - ); + const key = `${oldName}|${skillName}`; + const paths = pendingSkillRenameNotices.get(key) ?? []; + paths.push(legacyDir); + pendingSkillRenameNotices.set(key, paths); } } installed.push(skillName); @@ -1267,6 +1286,8 @@ export const setupCommand = async (options?: { codingAgent?: string[] | string } } } + flushSkillRenameNotices(); + console.log(''); console.log(' Summary:'); console.log(