Skip to content

kjj#1783

Closed
parlitoparlo wants to merge 5 commits intobmad-code-org:mainfrom
parlitoparlo:main
Closed

kjj#1783
parlitoparlo wants to merge 5 commits intobmad-code-org:mainfrom
parlitoparlo:main

Conversation

@parlitoparlo
Copy link
Copy Markdown

What

Why

How

Testing

Brian Madison and others added 5 commits September 29, 2025 17:09
* qwen cli - custom commands

* moved prompt to the inside of the command

---------

Co-authored-by: Davor Racic <davor.racic@gmail.com>
Co-authored-by: Brian <bmadcode@gmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 27, 2026

📝 Walkthrough

Walkthrough

This PR updates project versioning to 4.44.0, adjusts GitHub workflows and issue templates, adds a version announcement to README, and refactors the IDE installer setup to replace JSON-based settings with TOML-based command files organized under a new directory structure.

Changes

Cohort / File(s) Summary
GitHub Configuration
.github/ISSUE_TEMPLATE/config.yml, .github/workflows/manual-release.yaml
Disables blank issue creation and adds Discord community support link in issue template; updates checkout step to use GH_PAT token instead of GITHUB_TOKEN.
Documentation & Versioning
README.md, package.json
Inserts version announcement block highlighting v4.x stable, v6 Alpha availability, and usage instructions; bumps package version from 4.43.0 to 4.44.0.
IDE Installer Configuration
tools/installer/config/install.config.yaml
Updates Qwen Code IDE configuration paths and format from .qwen/bmad-method/ (single-file .md) to .qwen/commands/BMad/ (multi-file .toml); refreshes instructions to reflect new BMad command workflow.
IDE Installer Implementation
tools/installer/lib/ide-setup.js
Refactors qwen-code setup to generate per-agent and per-task TOML command files under .qwen/commands/BMad/ instead of manipulating legacy .qwen/settings.json and .qwen/agents/; adds directory creation, file reading/writing logic with error handling for missing resources.

Sequence Diagram(s)

sequenceDiagram
    actor Setup as IDE Setup Process
    participant Config as Install Config
    participant FS as File System
    participant Agents as Agent/Task Files

    Setup->>Config: Read qwen-code configuration
    Config-->>Setup: Return commands directory path
    
    Setup->>FS: Create .qwen/commands/BMad/agents directory
    Setup->>FS: Create .qwen/commands/BMad/tasks directory
    
    loop For each selected agent
        Setup->>Agents: Read agent file content
        Agents-->>Setup: Return agent definition
        Setup->>FS: Write TOML command file<br/>(agents directory)
        FS-->>Setup: File created
    end
    
    loop For each core/expansion task
        Setup->>Agents: Read task content
        Agents-->>Setup: Return task definition
        Setup->>FS: Write TOML command file<br/>(tasks directory)
        FS-->>Setup: File created
    end
    
    Setup->>Setup: Log success & command availability
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • bmadcode
🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description contains only a template with empty placeholders and no actual content describing the changes, objectives, or testing approach. Complete the description template with concrete details about what changed, why it was needed, how it was implemented, and how it was tested.
Title check ❓ Inconclusive The title 'kjj' is vague and does not convey meaningful information about the changeset, which includes version bump, workflow updates, CLI command changes, documentation, and repository governance updates. Provide a descriptive title that summarizes the main change, such as 'Version 4.44.0 release with Qwen CLI custom commands and documentation updates'.
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/manual-release.yaml:
- Line 29: The workflow injects a broad PAT into the checkout step by setting
token: ${{ secrets.GH_PAT }}, exposing secrets and preventing fallback; change
the checkout step to use the built-in github.token (token: ${{ github.token }})
for read-only checkout operations and reserve secrets.GH_PAT only for the later
push/tag steps (the git push and tag steps referenced around the push/tag block)
where elevated permissions are required so checkout can succeed if GH_PAT is
absent and least-privilege is enforced.

In `@package.json`:
- Line 4: The version bump in the package.json "version" field is insufficient
(patch) because the PR changes Qwen installer command format/path behavior;
update the package.json version to at least a minor bump (e.g., x.y+1.0) instead
of patch and add a clear migration note in the repository changelog/release
notes describing the Qwen installer command/path changes and any required user
migration steps; ensure the updated version and migration note are committed
alongside the code changes so release tooling and consumers see the
compatibility impact.

In `@README.md`:
- Line 22: The README's timeline sentence ("📅 Timeline: Official beta version
will be merged mid-October 2025") is outdated—locate the "📅 Timeline" line in
README.md and replace it with the current, factual status (e.g., "Official beta
released on <actual date>", "Official beta merged on <actual date>", or
"Official beta released; now stable" as applicable), or remove the dated
projection entirely and add a short, accurate status update; ensure the new text
clearly states the real outcome/date rather than a past projection.

In `@tools/installer/lib/ide-setup.js`:
- Around line 2069-2096: Wrap the per-agent work in a try/catch so a single
failing agent doesn't abort the whole setup: inside the for (const agentId of
agents) loop (where findAgentPath, getAgentTitle, path.join, relativeAgentPath,
fileManager.readFile and fileManager.writeFile are used) enclose the sequence
that reads the agent file, builds tomlContent and writes commandPath in a try
block and on catch log the error (include agentId and the caught error) and
continue to the next agent; do the same for the other loop region noted (lines
~2100-2129) to make read/write errors resilient per-agent.
- Around line 2082-2092: The embedded agent/task content is being inserted
verbatim into tomlContent, leaving `{root}` tokens unresolved; before
constructing tomlContent (after reading agentContent via
fileManager.readFile(agentPath)), replace all `{root}` placeholders with the
actual runtime root path (e.g. rootPath or whatever variable holds the installer
root) using a global replace on agentContent, then use the replaced content when
building tomlContent; apply the same replacement in the other block mentioned
(the similar code at 2116-2126) so any `{root}` tokens are correctly
substituted.
- Around line 2085-2092: The TOML generator embeds agentTitle, agentContent, and
taskContent directly into basic and multiline TOML strings (see tomlContent
construction) so backslashes, double quotes, and triple-quote sequences can
break the file; fix by adding escaping utilities (e.g., escapeTomlBasicString
for values used in basic strings and escapeTomlMultiline for blocks used in
triple-quoted multiline strings) and run those on agentTitle, agentContent, and
taskContent before interpolating into tomlContent (and any similar template);
ensure escapeTomlBasicString replaces \ and " with \\ and \" and
escapeTomlMultiline also escapes any """ sequences and backslashes so the
generated TOML is always valid.
- Line 2095: Update the CLI log messages that print command namespaces to use
the correct uppercase "BMad" instead of "bmad" to match the configured folders;
replace occurrences of the lowercase strings (e.g. `/bmad:agents:${agentId}`,
`/bmad:tasks:${taskId}`) with `/BMad:agents:${agentId}` and
`/BMad:tasks:${taskId}` respectively so logs match the `.gemini/commands/BMad/`
and `.qwen/commands/BMad/` folder structure and the documented
`/BMad:agents:<agent-name>` and `/BMad:tasks:<task-name>` format.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5ad35d6 and 3b6a507.

📒 Files selected for processing (6)
  • .github/ISSUE_TEMPLATE/config.yml
  • .github/workflows/manual-release.yaml
  • README.md
  • package.json
  • tools/installer/config/install.config.yaml
  • tools/installer/lib/ide-setup.js

with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
token: ${{ secrets.GH_PAT }}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n .github/workflows/manual-release.yaml

Repository: bmad-code-org/BMAD-METHOD

Length of output: 7058


Use least-privilege auth for checkout, not a broad PAT.

Line 29 injects secrets.GH_PAT directly into checkout, expanding secret exposure unnecessarily. If the secret is absent, checkout fails immediately rather than falling back to the default github.token. For checkout (a read operation), github.token is sufficient; reserve the PAT only for the git push and tag operations at lines 131–148 if they require elevated permissions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/manual-release.yaml at line 29, The workflow injects a
broad PAT into the checkout step by setting token: ${{ secrets.GH_PAT }},
exposing secrets and preventing fallback; change the checkout step to use the
built-in github.token (token: ${{ github.token }}) for read-only checkout
operations and reserve secrets.GH_PAT only for the later push/tag steps (the git
push and tag steps referenced around the push/tag block) where elevated
permissions are required so checkout can succeed if GH_PAT is absent and
least-privilege is enforced.

"$schema": "https://json.schemastore.org/package.json",
"name": "bmad-method",
"version": "4.43.0",
"version": "4.44.0",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Patch bump under-represents the compatibility risk in this PR.

Line 4 bumps to 4.44.0, but this PR changes Qwen installer command format/path behavior. That is likely beyond a patch-level change for existing Qwen users; bump at least minor and include a migration note.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` at line 4, The version bump in the package.json "version" field
is insufficient (patch) because the PR changes Qwen installer command
format/path behavior; update the package.json version to at least a minor bump
(e.g., x.y+1.0) instead of patch and add a clear migration note in the
repository changelog/release notes describing the Qwen installer command/path
changes and any required user migration steps; ensure the updated version and
migration note are committed alongside the code changes so release tooling and
consumers see the compatibility impact.

> - Incomplete features
> - Experimental functionality
>
> **📅 Timeline:** Official beta version will be merged mid-October 2025
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

The timeline is now factually outdated.

Line 22 says beta merge is expected in mid-October 2025, which is already in the past (today is February 27, 2026). Update this to the actual status/date to avoid misleading users.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` at line 22, The README's timeline sentence ("📅 Timeline: Official
beta version will be merged mid-October 2025") is outdated—locate the "📅
Timeline" line in README.md and replace it with the current, factual status
(e.g., "Official beta released on <actual date>", "Official beta merged on
<actual date>", or "Official beta released; now stable" as applicable), or
remove the dated projection entirely and add a short, accurate status update;
ensure the new text clearly states the real outcome/date rather than a past
projection.

Comment on lines +2069 to +2096
for (const agentId of agents) {
const agentPath = await this.findAgentPath(agentId, installDir);
if (!agentPath) {
console.log(chalk.yellow(`✗ Agent file not found for ${agentId}, skipping.`));
continue;
}
}

// Remove old agents directory
const agentsDir = path.join(qwenDir, 'agents');
if (await fileManager.pathExists(agentsDir)) {
await fileManager.removeDirectory(agentsDir);
console.log(chalk.green('✓ Removed old .qwen/agents directory'));
}
const agentTitle = await this.getAgentTitle(agentId, installDir);
const commandPath = path.join(agentCommandsDir, `${agentId}.toml`);

// Get all available agents
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
let concatenatedContent = '';
// Get relative path from installDir to agent file for @{file} reference
const relativeAgentPath = path.relative(installDir, agentPath).replaceAll('\\', '/');

for (const agentId of agents) {
// Find the source agent file
const agentPath = await this.findAgentPath(agentId, installDir);
// Read the agent content
const agentContent = await fileManager.readFile(agentPath);

if (agentPath) {
const agentContent = await fileManager.readFile(agentPath);
const tomlContent = `description = " Activates the ${agentTitle} agent from the BMad Method."
prompt = """
CRITICAL: You are now the BMad '${agentTitle}' agent. Adopt its persona, follow its instructions, and use its capabilities.

// Create properly formatted agent rule content (similar to gemini)
let agentRuleContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
agentRuleContent += `This rule is triggered when the user types \`*${agentId}\` and activates the ${await this.getAgentTitle(
agentId,
installDir,
)} agent persona.\n\n`;
agentRuleContent += '## Agent Activation\n\n';
agentRuleContent +=
'CRITICAL: Read the full YAML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n';
agentRuleContent += '```yaml\n';
// Extract just the YAML content from the agent file
const yamlContent = extractYamlFromAgent(agentContent);
if (yamlContent) {
agentRuleContent += yamlContent;
} else {
// If no YAML found, include the whole content minus the header
agentRuleContent += agentContent.replace(/^#.*$/m, '').trim();
}
agentRuleContent += '\n```\n\n';
agentRuleContent += '## File Reference\n\n';
const relativePath = path.relative(installDir, agentPath).replaceAll('\\', '/');
agentRuleContent += `The complete agent definition is available in [${relativePath}](${relativePath}).\n\n`;
agentRuleContent += '## Usage\n\n';
agentRuleContent += `When the user types \`*${agentId}\`, activate this ${await this.getAgentTitle(
agentId,
installDir,
)} persona and follow all instructions defined in the YAML configuration above.\n`;
READ THIS BEFORE ANSWERING AS THE PERSONA!

${agentContent}
"""`;

// Add to concatenated content with separator
concatenatedContent += agentRuleContent + '\n\n---\n\n';
console.log(chalk.green(`✓ Added context for *${agentId}`));
await fileManager.writeFile(commandPath, tomlContent);
console.log(chalk.green(`✓ Created agent command: /bmad:agents:${agentId}`));
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

One command generation failure can abort the whole Qwen setup.

The loops do not isolate read/write errors per agent/task. A single bad file can terminate setup and leave a partial install.

Suggested resilience fix
 for (const agentId of agents) {
-  const agentPath = await this.findAgentPath(agentId, installDir);
-  ...
-  await fileManager.writeFile(commandPath, tomlContent);
-  console.log(chalk.green(`✓ Created agent command: /bmad:agents:${agentId}`));
+  try {
+    const agentPath = await this.findAgentPath(agentId, installDir);
+    ...
+    await fileManager.writeFile(commandPath, tomlContent);
+    console.log(chalk.green(`✓ Created agent command: /BMad:agents:${agentId}`));
+  } catch (error) {
+    console.log(chalk.yellow(`⚠︎ Failed to create agent command for ${agentId}: ${error.message}`));
+    continue;
+  }
 }

Also applies to: 2100-2129

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/installer/lib/ide-setup.js` around lines 2069 - 2096, Wrap the
per-agent work in a try/catch so a single failing agent doesn't abort the whole
setup: inside the for (const agentId of agents) loop (where findAgentPath,
getAgentTitle, path.join, relativeAgentPath, fileManager.readFile and
fileManager.writeFile are used) enclose the sequence that reads the agent file,
builds tomlContent and writes commandPath in a try block and on catch log the
error (include agentId and the caught error) and continue to the next agent; do
the same for the other loop region noted (lines ~2100-2129) to make read/write
errors resilient per-agent.

Comment on lines +2082 to +2092
// Read the agent content
const agentContent = await fileManager.readFile(agentPath);

if (agentPath) {
const agentContent = await fileManager.readFile(agentPath);
const tomlContent = `description = " Activates the ${agentTitle} agent from the BMad Method."
prompt = """
CRITICAL: You are now the BMad '${agentTitle}' agent. Adopt its persona, follow its instructions, and use its capabilities.

// Create properly formatted agent rule content (similar to gemini)
let agentRuleContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
agentRuleContent += `This rule is triggered when the user types \`*${agentId}\` and activates the ${await this.getAgentTitle(
agentId,
installDir,
)} agent persona.\n\n`;
agentRuleContent += '## Agent Activation\n\n';
agentRuleContent +=
'CRITICAL: Read the full YAML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n';
agentRuleContent += '```yaml\n';
// Extract just the YAML content from the agent file
const yamlContent = extractYamlFromAgent(agentContent);
if (yamlContent) {
agentRuleContent += yamlContent;
} else {
// If no YAML found, include the whole content minus the header
agentRuleContent += agentContent.replace(/^#.*$/m, '').trim();
}
agentRuleContent += '\n```\n\n';
agentRuleContent += '## File Reference\n\n';
const relativePath = path.relative(installDir, agentPath).replaceAll('\\', '/');
agentRuleContent += `The complete agent definition is available in [${relativePath}](${relativePath}).\n\n`;
agentRuleContent += '## Usage\n\n';
agentRuleContent += `When the user types \`*${agentId}\`, activate this ${await this.getAgentTitle(
agentId,
installDir,
)} persona and follow all instructions defined in the YAML configuration above.\n`;
READ THIS BEFORE ANSWERING AS THE PERSONA!

${agentContent}
"""`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

{root} placeholders are left unresolved in embedded content.

This path writes raw agent/task markdown directly, but does not replace {root} tokens like other setup flows do. Commands that depend on those paths will carry invalid instructions at runtime.

Also applies to: 2116-2126

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/installer/lib/ide-setup.js` around lines 2082 - 2092, The embedded
agent/task content is being inserted verbatim into tomlContent, leaving `{root}`
tokens unresolved; before constructing tomlContent (after reading agentContent
via fileManager.readFile(agentPath)), replace all `{root}` placeholders with the
actual runtime root path (e.g. rootPath or whatever variable holds the installer
root) using a global replace on agentContent, then use the replaced content when
building tomlContent; apply the same replacement in the other block mentioned
(the similar code at 2116-2126) so any `{root}` tokens are correctly
substituted.

Comment on lines +2085 to +2092
const tomlContent = `description = " Activates the ${agentTitle} agent from the BMad Method."
prompt = """
CRITICAL: You are now the BMad '${agentTitle}' agent. Adopt its persona, follow its instructions, and use its capabilities.

// Create properly formatted agent rule content (similar to gemini)
let agentRuleContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
agentRuleContent += `This rule is triggered when the user types \`*${agentId}\` and activates the ${await this.getAgentTitle(
agentId,
installDir,
)} agent persona.\n\n`;
agentRuleContent += '## Agent Activation\n\n';
agentRuleContent +=
'CRITICAL: Read the full YAML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n';
agentRuleContent += '```yaml\n';
// Extract just the YAML content from the agent file
const yamlContent = extractYamlFromAgent(agentContent);
if (yamlContent) {
agentRuleContent += yamlContent;
} else {
// If no YAML found, include the whole content minus the header
agentRuleContent += agentContent.replace(/^#.*$/m, '').trim();
}
agentRuleContent += '\n```\n\n';
agentRuleContent += '## File Reference\n\n';
const relativePath = path.relative(installDir, agentPath).replaceAll('\\', '/');
agentRuleContent += `The complete agent definition is available in [${relativePath}](${relativePath}).\n\n`;
agentRuleContent += '## Usage\n\n';
agentRuleContent += `When the user types \`*${agentId}\`, activate this ${await this.getAgentTitle(
agentId,
installDir,
)} persona and follow all instructions defined in the YAML configuration above.\n`;
READ THIS BEFORE ANSWERING AS THE PERSONA!

${agentContent}
"""`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cd tools/installer/lib && wc -l ide-setup.js

Repository: bmad-code-org/BMAD-METHOD

Length of output: 86


🏁 Script executed:

cd tools/installer/lib && sed -n '2085,2092p' ide-setup.js

Repository: bmad-code-org/BMAD-METHOD

Length of output: 373


🏁 Script executed:

cd tools/installer/lib && sed -n '2119,2126p' ide-setup.js

Repository: bmad-code-org/BMAD-METHOD

Length of output: 310


🏁 Script executed:

cd tools/installer/lib && sed -n '2070,2140p' ide-setup.js

Repository: bmad-code-org/BMAD-METHOD

Length of output: 2572


🌐 Web query:

TOML escaping rules double quotes triple quotes basic string multiline string

💡 Result:

TOML basic strings ("...") — escaping rules

  • Delimiters: double quotes (").
  • Must escape: " and \, plus control characters (generally U+0000–U+001F and U+007F, except tab). (toml.io)
  • Valid escapes (TOML 1.1.0): \b \t \n \f \r \e \" \\ \xHH \uHHHH \UHHHHHHHH. Any other \... escape is an error. (toml.io)

TOML multi-line basic strings ("""...""") — escaping rules

  • Delimiters: triple double quotes ("""), newlines allowed. (toml.io)
  • First newline trimming: if a newline appears immediately after the opening """, it’s trimmed. (toml.io)
  • Escapes: all the same escapes as basic strings are valid. (toml.io)
  • Which characters must be escaped: you still must escape backslash and disallowed control characters, but LF and CR are allowed (with CR only as part of CRLF). (toml.io)
  • Line-ending backslash for folding: if the last non-whitespace char on a line is an unescaped \, TOML trims that backslash and all following whitespace/newlines up to the next non-whitespace (or the closing delimiter). (toml.io)
  • Including " inside """...""": you can include " and even "" without escaping, but a """ sequence must be avoided/escaped (e.g., ""\"). (toml.io)

Citations:


🏁 Script executed:

rg "escapeToml|escapeTom|toml.*escap" tools/installer/lib/

Repository: bmad-code-org/BMAD-METHOD

Length of output: 51


🏁 Script executed:

rg "replaceAll.*\"" tools/installer/lib/ide-setup.js | head -20

Repository: bmad-code-org/BMAD-METHOD

Length of output: 182


🏁 Script executed:

grep -n "readFile\|writeFile" tools/installer/lib/ide-setup.js | head -10

Repository: bmad-code-org/BMAD-METHOD

Length of output: 766


🏁 Script executed:

sed -n '2072,2095p' tools/installer/lib/ide-setup.js

Repository: bmad-code-org/BMAD-METHOD

Length of output: 1051


🏁 Script executed:

sed -n '2100,2135p' tools/installer/lib/ide-setup.js

Repository: bmad-code-org/BMAD-METHOD

Length of output: 1274


Escape TOML content before writing command files.

Lines 2085–2092 and 2119–2126 interpolate agentTitle, agentContent, and taskContent directly into TOML strings without escaping. TOML syntax requires that backslashes and double quotes in basic strings be escaped (\" and \\), and that """ sequences in multiline strings be escaped. If agent/task files or titles contain these characters, the generated TOML will be malformed, causing command execution to fail.

Suggested hardening
+const escapeTomlBasicString = (value) =>
+  String(value).replaceAll('\\', '\\\\').replaceAll('"', '\\"');
+
+const escapeTomlMultiline = (value) =>
+  String(value).replaceAll('"""', '\\"""').replaceAll('\\', '\\\\');

-const tomlContent = `description = " Activates the ${agentTitle} agent from the BMad Method."
+const tomlContent = `description = "Activates the ${escapeTomlBasicString(agentTitle)} agent from the BMad Method."
 prompt = """
 ...
-${agentContent}
+${escapeTomlMultiline(agentContent)}
 """`;

-const tomlContent = `description = " Executes the BMad Task: ${taskTitle}"
+const tomlContent = `description = "Executes the BMad Task: ${escapeTomlBasicString(taskTitle)}"
 prompt = """
 ...
-${taskContent}
+${escapeTomlMultiline(taskContent)}
 """`;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/installer/lib/ide-setup.js` around lines 2085 - 2092, The TOML
generator embeds agentTitle, agentContent, and taskContent directly into basic
and multiline TOML strings (see tomlContent construction) so backslashes, double
quotes, and triple-quote sequences can break the file; fix by adding escaping
utilities (e.g., escapeTomlBasicString for values used in basic strings and
escapeTomlMultiline for blocks used in triple-quoted multiline strings) and run
those on agentTitle, agentContent, and taskContent before interpolating into
tomlContent (and any similar template); ensure escapeTomlBasicString replaces \
and " with \\ and \" and escapeTomlMultiline also escapes any """ sequences and
backslashes so the generated TOML is always valid.

concatenatedContent += agentRuleContent + '\n\n---\n\n';
console.log(chalk.green(`✓ Added context for *${agentId}`));
await fileManager.writeFile(commandPath, tomlContent);
console.log(chalk.green(`✓ Created agent command: /bmad:agents:${agentId}`));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's look at the specific lines mentioned in the review
head -2140 tools/installer/lib/ide-setup.js | tail -50

Repository: bmad-code-org/BMAD-METHOD

Length of output: 1662


🏁 Script executed:

# Let's search for namespace references and configuration
rg "BMad|bmad" tools/installer/lib/ide-setup.js -n

Repository: bmad-code-org/BMAD-METHOD

Length of output: 8161


🏁 Script executed:

# Let's also check for namespace configuration files or constants
rg "namespace|BMad|bmad" tools/installer/ -t js -A 2 -B 2 | head -100

Repository: bmad-code-org/BMAD-METHOD

Length of output: 6470


🏁 Script executed:

# Search for where these commands are actually defined/registered
rg "agents:|agents" tools/installer/lib/ide-setup.js -n -A 2 -B 2

Repository: bmad-code-org/BMAD-METHOD

Length of output: 20769


🏁 Script executed:

# Search for how Qwen Code or Gemini CLI commands are actually registered/created
rg "setupQwenCode|setupGeminiCli" tools/installer/lib/ide-setup.js -A 50 | head -150

Repository: bmad-code-org/BMAD-METHOD

Length of output: 6246


🏁 Script executed:

# Look for any TOML file creation or command registration that might show actual namespace
rg "tomlContent|description.*Activates|description.*Executes" tools/installer/lib/ide-setup.js -B 5 -A 3

Repository: bmad-code-org/BMAD-METHOD

Length of output: 3082


🏁 Script executed:

# Search for documentation or comments about Qwen Code namespace
rg -i "qwen|gemini" tools/installer/ -t js -B 3 -A 3

Repository: bmad-code-org/BMAD-METHOD

Length of output: 4696


🏁 Script executed:

# Check IDE configuration files to understand how Qwen Code and Gemini CLI are configured
find tools/installer -name "*.yaml" -o -name "*.yml" -o -name "*config*" | grep -v node_modules

Repository: bmad-code-org/BMAD-METHOD

Length of output: 216


🏁 Script executed:

# Search for IDE configuration loading
rg "getIdeConfiguration|ide.*config" tools/installer/lib/ -t js -A 5 -B 2

Repository: bmad-code-org/BMAD-METHOD

Length of output: 9078


🏁 Script executed:

# Look for the actual IDE configuration for gemini and qwen-code
rg "gemini|qwen" tools/installer/ --type yaml --type yml -A 10

Repository: bmad-code-org/BMAD-METHOD

Length of output: 96


🏁 Script executed:

# Look at the IDE configuration YAML file directly
cat tools/installer/config/install.config.yaml

Repository: bmad-code-org/BMAD-METHOD

Length of output: 7341


🏁 Script executed:

# Also check for IDE agent config
cat tools/installer/config/ide-agent-config.yaml

Repository: bmad-code-org/BMAD-METHOD

Length of output: 1618


🏁 Script executed:

# Verify if the rule-dir folder name actually determines the command namespace
# by looking at any documentation or checking if there's logic that uses the folder name
rg "rule-dir|commands/BMad|commands/bmad" tools/installer/lib/ -t js -B 3 -A 3

Repository: bmad-code-org/BMAD-METHOD

Length of output: 1712


🏁 Script executed:

# Check if there's any code that constructs the command prefix dynamically from slashPrefix
rg "slashPrefix|getSlashPrefix" tools/installer/lib/ide-setup.js -B 2 -A 5

Repository: bmad-code-org/BMAD-METHOD

Length of output: 2224


🏁 Script executed:

# Check the exact configuration for gemini and qwen-code to confirm the folder names
cat tools/installer/config/install.config.yaml | grep -A 5 "gemini:\|qwen-code:"

Repository: bmad-code-org/BMAD-METHOD

Length of output: 345


🏁 Script executed:

# Verify the log messages at lines 2052 and 2137 more carefully
sed -n '2048,2055p' tools/installer/lib/ide-setup.js
sed -n '2133,2140p' tools/installer/lib/ide-setup.js

Repository: bmad-code-org/BMAD-METHOD

Length of output: 505


🏁 Script executed:

# Check the Gemini CLI log messages at line 2015 and 2044
sed -n '2010,2020p' tools/installer/lib/ide-setup.js
sed -n '2040,2050p' tools/installer/lib/ide-setup.js

Repository: bmad-code-org/BMAD-METHOD

Length of output: 642


🏁 Script executed:

# Count how many times /bmad: appears vs /BMad: in console.log statements
rg "console\.log.*bmad:|console\.log.*BMad:" tools/installer/lib/ide-setup.js -i

Repository: bmad-code-org/BMAD-METHOD

Length of output: 497


Log messages use incorrect case for command namespace in Gemini CLI and Qwen Code.

Lines 2015, 2044, 2052 (Gemini) and lines 2095, 2129, 2137 (Qwen) log /bmad:agents: and /bmad:tasks: (lowercase), but the configured folder structure uses .gemini/commands/BMad/ and .qwen/commands/BMad/ (uppercase). The instructions correctly document /BMad:agents:<agent-name> and /BMad:tasks:<task-name>. Update log messages to use the correct uppercase case to match configuration and prevent user confusion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/installer/lib/ide-setup.js` at line 2095, Update the CLI log messages
that print command namespaces to use the correct uppercase "BMad" instead of
"bmad" to match the configured folders; replace occurrences of the lowercase
strings (e.g. `/bmad:agents:${agentId}`, `/bmad:tasks:${taskId}`) with
`/BMad:agents:${agentId}` and `/BMad:tasks:${taskId}` respectively so logs match
the `.gemini/commands/BMad/` and `.qwen/commands/BMad/` folder structure and the
documented `/BMad:agents:<agent-name>` and `/BMad:tasks:<task-name>` format.

@alexeyv
Copy link
Copy Markdown
Collaborator

alexeyv commented Feb 27, 2026

Looks like some LLM hallucinated a PR. No description of intent.

@alexeyv alexeyv closed this Feb 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants