From e449c5afa6bf394062ab75de349255b74e26276e Mon Sep 17 00:00:00 2001 From: Lex Christopherson Date: Mon, 16 Feb 2026 14:03:40 -0600 Subject: [PATCH] fix(gemini): escape shell variables in agent bodies for Gemini CLI Gemini CLI's templateString() treats all ${word} patterns in agent system prompts as template variables, throwing "Template validation failed: Missing required input parameters: PHASE" when GSD agents contain shell variables like ${PHASE} in bash code blocks. Convert ${VAR} to $VAR in agent bodies during Gemini installation. Both forms are equivalent bash; $VAR is invisible to Gemini's /\$\{(\w+)\}/g template regex. Complex expansions like ${VAR:-default} are preserved since they don't match the word-only pattern. Closes #613 Co-Authored-By: Claude Opus 4.6 --- bin/install.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/bin/install.js b/bin/install.js index 97f163d67..b348677d9 100755 --- a/bin/install.js +++ b/bin/install.js @@ -456,7 +456,16 @@ function convertClaudeToGeminiAgent(content) { } const newFrontmatter = newLines.join('\n').trim(); - return `---\n${newFrontmatter}\n---${stripSubTags(body)}`; + + // Escape ${VAR} patterns in agent body for Gemini CLI compatibility. + // Gemini's templateString() treats all ${word} patterns as template variables + // and throws "Template validation failed: Missing required input parameters" + // when they can't be resolved. GSD agents use ${PHASE}, ${PLAN}, etc. as + // shell variables in bash code blocks — convert to $VAR (no braces) which + // is equivalent bash and invisible to Gemini's /\$\{(\w+)\}/g regex. + const escapedBody = body.replace(/\$\{(\w+)\}/g, '$$$1'); + + return `---\n${newFrontmatter}\n---${stripSubTags(escapedBody)}`; } function convertClaudeToOpencodeFrontmatter(content) {