Skip to content

feat(ide): add Bob IDE installer support#1786

Open
timgraepel wants to merge 3 commits intobmad-code-org:mainfrom
timgraepel:feature/add-bob-support
Open

feat(ide): add Bob IDE installer support#1786
timgraepel wants to merge 3 commits intobmad-code-org:mainfrom
timgraepel:feature/add-bob-support

Conversation

@timgraepel
Copy link

What

Adds IBM Bob (agentic IDE) as a supported platform with a custom installer that creates .bobmodes and writes workflows to .bob/workflows/.

Why

Bob is an IBM agentic IDE that requires a custom installation path similar to Kilo. Without this, BMAD users on Bob have no supported install path.
Fixes #1768

How

  • Add tools/cli/installers/lib/ide/bob.js — custom installer using correct Bob mode schema (roleDefinition/whenToUse/customInstructions/groups)
  • Register Bob in tools/cli/installers/lib/ide/manager.js and add platform config to tools/platform-codes.yaml and tools/cli/installers/lib/ide/platform-codes.yaml
  • Add .bobmodes to .gitignore and .bob/** to eslint ignores

Testing

Manually tested the installer against a Bob workspace; .bobmodes and .bob/workflows/ are created correctly with valid mode schema.

@coderabbitai
Copy link

coderabbitai bot commented Feb 27, 2026

📝 Walkthrough

Walkthrough

This PR adds support for IBM Bob IDE integration to BMAD's installer system. It introduces a new BobSetup class to manage Bob configuration files, updates the IDE manager to load the Bob installer, registers Bob as a platform in configuration files, and adds Bob-related patterns to gitignore.

Changes

Cohort / File(s) Summary
Configuration & Platform Registration
.gitignore, tools/platform-codes.yaml, tools/cli/installers/lib/ide/platform-codes.yaml
Added Bob IDE platform entries and corresponding gitignore patterns (.bob and .bobmodes) for the new IDE integration.
IDE Installer Implementation
tools/cli/installers/lib/ide/bob.js
New BobSetup class extending BaseIdeSetup to manage Bob IDE configuration, including setup/cleanup workflows, YAML parsing, mode object creation, custom agent launcher installation, and workflow artifact generation.
IDE Manager Update
tools/cli/installers/lib/ide/manager.js
Updated customFiles list to load the new bob.js installer module alongside existing IDE setup handlers.

Sequence Diagram(s)

sequenceDiagram
    participant Manager as IdeManager
    participant BobSetup
    participant FS as File System
    participant YAML as YAML Parser

    Manager->>BobSetup: instantiate BobSetup()
    Manager->>BobSetup: setup(projectDir, bmadDir, options)
    
    BobSetup->>FS: read .bob/custom_modes.yaml
    FS-->>BobSetup: config file (or empty)
    
    BobSetup->>YAML: parse YAML
    YAML-->>BobSetup: parsed config object
    
    BobSetup->>BobSetup: ensure customModes array
    BobSetup->>BobSetup: createModeObject(artifact)
    BobSetup->>BobSetup: append mode to config
    
    BobSetup->>FS: write updated .bob/custom_modes.yaml
    BobSetup->>FS: write workflows to .bob/workflows/
    BobSetup->>BobSetup: log summary (modes, workflows, tasks, tools)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • bmadcode
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely summarizes the main change: adding Bob IDE installer support, which is the primary objective of the changeset.
Description check ✅ Passed The PR description is directly related to the changeset, providing clear context on what Bob IDE support entails, why it's needed, and how it's implemented.
Linked Issues check ✅ Passed The PR implementation fully addresses the requirements from issue #1768: Bob is registered as a supported IDE with a custom installer that handles Bob's specific mode schema and workflows.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the linked issue objectives. The modifications include Bob IDE support in the installer, platform registration, gitignore updates, and ESLint configuration - all within scope of issue #1768.
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

@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

🧹 Nitpick comments (2)
tools/cli/installers/lib/ide/bob.js (2)

276-276: Remove debug/placeholder comment.

// Made with Bob appears to be a leftover joke or debug marker. Remove it before merging.

-
-// Made with Bob
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/cli/installers/lib/ide/bob.js` at line 276, Remove the stray
debug/placeholder comment "// Made with Bob" from the bob.js module (the
top-level comment in the IDE installer module) so the file no longer contains
this leftover joke; simply delete that single-line comment and commit the
change.

162-172: Inconsistent fs-extra require — inline instead of top-level.

fs-extra is required inline in clearBmadWorkflows() and cleanup() but other methods use this.pathExists, this.readFile, this.writeFile from the base class. Either use base class methods consistently or move require('fs-extra') to the top of the file.

♻️ Option 1: Use base class methods
   async clearBmadWorkflows(workflowsDir) {
-    const fs = require('fs-extra');
-    if (!(await fs.pathExists(workflowsDir))) return;
+    if (!(await this.pathExists(workflowsDir))) return;

-    const entries = await fs.readdir(workflowsDir);
+    const fs = require('fs-extra'); // Only for readdir/remove
+    const entries = await fs.readdir(workflowsDir);
     for (const entry of entries) {
♻️ Option 2: Move require to top of file
 const path = require('node:path');
+const fs = require('fs-extra');
 const { BaseIdeSetup } = require('./_base-ide');

Then remove inline requires from clearBmadWorkflows() and cleanup().

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

In `@tools/cli/installers/lib/ide/bob.js` around lines 162 - 172, The inline
require('fs-extra') in clearBmadWorkflows (and cleanup) is inconsistent with the
rest of the class which uses base-class helpers (this.pathExists, this.readFile,
this.writeFile); fix by either (A) replacing the inline fs-extra calls in
clearBmadWorkflows and cleanup to use the base-class methods (use
this.pathExists(workflowsDir), this.readdir/readDir equivalent, this.remove or
this.unlink via base helpers) or (B) move const fs = require('fs-extra') to the
top of the file and remove inline requires from clearBmadWorkflows and cleanup
so all uses import fs the same way; update references to path.join as needed and
keep function names clearBmadWorkflows and cleanup to locate the changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.gitignore:
- Around line 57-58: Remove the unused `.bobmodes` entry from .gitignore: delete
the `.bobmodes` line and keep the existing `.bob` ignore (which already covers
the `.bob` directory), and if necessary ensure `.bob/custom_modes.yaml` (the
actual bob.js config path) remains untracked via the `.bob` rule.

In `@tools/cli/installers/lib/ide/bob.js`:
- Line 143: The customInstructions string assigned (customInstructions) is a
run-on sentence and unclear; update the template that combines activationHeader
and relativePath to add proper punctuation and clearer clauses (e.g., separate
sentences or commas) so it reads like distinct steps: instruct to read the full
YAML from ${relativePath}, then start activation, follow the startup section
instructions, and remain in the activated mode until explicitly told to exit;
keep activationHeader and ${relativePath} interpolation intact.
- Line 135: Guard against artifact.sourcePath being undefined before calling
path.relative: update the logic around the assignment to relativePath so it
first checks artifact.sourcePath (the same property read earlier) and only calls
path.relative(projectDir, artifact.sourcePath).replaceAll('\\', '/') when
present; otherwise set relativePath to a safe default (e.g., empty string or
null) and handle that downstream. Modify the code that uses relativePath
accordingly so no TypeError is thrown when artifact.sourcePath is missing.
- Around line 253-260: The custom mode added in installCustomAgentLauncher
(config.customModes.push) is inconsistent with createModeObject: include the
icon prefix in the name (use `${icon} ${title}` like createModeObject) and fix
the malformed customInstructions string by ensuring activationHeader, agentPath
and instructions are concatenated into a single well-formed sentence (no stray
"start activation" fragment) — update the object created in
installCustomAgentLauncher to match createModeObject’s shape (fields: slug, name
(with icon), roleDefinition, whenToUse, customInstructions, groups) and reuse
the same template/variable order (icon, title, agentName, activationHeader,
agentPath) so display and instructions are consistent with createModeObject.
- Line 217: The installCustomAgentLauncher function currently declares an unused
parameter metadata; either remove metadata from the function signature of
installCustomAgentLauncher and update all call sites to stop passing it, or use
metadata inside the function (e.g., read metadata.title, metadata.description,
metadata.icon) when constructing the launcher/manifest so the values are
applied; update any code that builds the launcher (same function) to consume
those fields and ensure linter/tests no longer report an unused variable.
- Around line 65-90: Wrap the sequence of file writes (the call to
this.writeFile(bobModesPath, ...),
workflowGenerator.writeDashArtifacts(workflowsDir, ...), and
taskToolGen.writeDashArtifacts(workflowsDir, ...)) in a try/catch so partial
success doesn't leave inconsistent state; on catch clean up any partial
artifacts by removing the written bobModesPath and clearing workflowsDir (you
can reuse clearBmadWorkflows(workflowsDir)), then rethrow or throw a new error
that includes context (e.g., which write failed) so callers can handle it;
ensure you reference bobModesPath, workflowsDir, writeFile, writeDashArtifacts,
and clearBmadWorkflows when implementing the recovery.

In `@tools/platform-codes.yaml`:
- Around line 52-57: Pick one canonical description for the bob entry and make
both platform-codes.yaml files consistent: update the bob key's description
field (the "description" value under the bob entry) in both the main
platform-codes.yaml and the installer's platform-codes.yaml so they match
exactly (preserve quoting/formatting), e.g., change both to either "IBM's AI
development environment" or "IBM's agentic IDE for AI-powered development".

---

Nitpick comments:
In `@tools/cli/installers/lib/ide/bob.js`:
- Line 276: Remove the stray debug/placeholder comment "// Made with Bob" from
the bob.js module (the top-level comment in the IDE installer module) so the
file no longer contains this leftover joke; simply delete that single-line
comment and commit the change.
- Around line 162-172: The inline require('fs-extra') in clearBmadWorkflows (and
cleanup) is inconsistent with the rest of the class which uses base-class
helpers (this.pathExists, this.readFile, this.writeFile); fix by either (A)
replacing the inline fs-extra calls in clearBmadWorkflows and cleanup to use the
base-class methods (use this.pathExists(workflowsDir), this.readdir/readDir
equivalent, this.remove or this.unlink via base helpers) or (B) move const fs =
require('fs-extra') to the top of the file and remove inline requires from
clearBmadWorkflows and cleanup so all uses import fs the same way; update
references to path.join as needed and keep function names clearBmadWorkflows and
cleanup to locate the changes.

ℹ️ 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 1677d54 and 5af885a.

⛔ Files ignored due to path filters (1)
  • eslint.config.mjs is excluded by !eslint.config.mjs
📒 Files selected for processing (5)
  • .gitignore
  • tools/cli/installers/lib/ide/bob.js
  • tools/cli/installers/lib/ide/manager.js
  • tools/cli/installers/lib/ide/platform-codes.yaml
  • tools/platform-codes.yaml

.gitignore Outdated
Comment on lines +57 to +58
.bobmodes
.bob
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== Searching for .bobmodes references ==="
rg -i "bobmodes" --type-add 'all:*' -t all
echo ""
echo "=== Git history of .gitignore around line 57-58 ==="
git log -p --follow -- .gitignore | grep -A 5 -B 5 "bobmodes" | head -30
echo ""
echo "=== Checking .gitignore content around lines 55-60 ==="
sed -n '55,60p' .gitignore

Repository: bmad-code-org/BMAD-METHOD

Length of output: 359


Remove .bobmodes — it has no references in the codebase and doesn't match the actual config file path.

The bob.js installer uses .bob/custom_modes.yaml, not .bobmodes. A search of the entire codebase found zero references to .bobmodes, indicating it's unused or dead code. The .bob entry on line 58 already ignores the entire directory and its contents, making .bobmodes redundant.

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

In @.gitignore around lines 57 - 58, Remove the unused `.bobmodes` entry from
.gitignore: delete the `.bobmodes` line and keep the existing `.bob` ignore
(which already covers the `.bob` directory), and if necessary ensure
`.bob/custom_modes.yaml` (the actual bob.js config path) remains untracked via
the `.bob` rule.

Comment on lines +65 to +90
// Write .bob/custom_modes.yaml file with proper YAML structure
const finalContent = yaml.stringify(config, { lineWidth: 0 });
await this.writeFile(bobModesPath, finalContent);

// Generate workflow commands
const workflowGenerator = new WorkflowCommandGenerator(this.bmadFolderName);
const { artifacts: workflowArtifacts } = await workflowGenerator.collectWorkflowArtifacts(bmadDir);

// Write to .bob/workflows/ directory
const workflowsDir = path.join(projectDir, '.bob', 'workflows');
await this.ensureDir(workflowsDir);

// Clear old BMAD workflows before writing new ones
await this.clearBmadWorkflows(workflowsDir);

// Write workflow files
const workflowCount = await workflowGenerator.writeDashArtifacts(workflowsDir, workflowArtifacts);

// Generate task and tool commands
const taskToolGen = new TaskToolCommandGenerator(this.bmadFolderName);
const { artifacts: taskToolArtifacts, counts: taskToolCounts } = await taskToolGen.collectTaskToolArtifacts(bmadDir);

// Write task/tool files to workflows directory (same location as workflows)
await taskToolGen.writeDashArtifacts(workflowsDir, taskToolArtifacts);
const taskCount = taskToolCounts.tasks || 0;
const toolCount = taskToolCounts.tools || 0;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

No error recovery for partial write failures.

If writeFile at line 67 succeeds but writeDashArtifacts at line 81 or 88 throws, the user is left with modes but no workflows. Consider wrapping write operations in try/catch with rollback, or at minimum document that failures may leave partial state.

🛡️ Minimal improvement: wrap writes with error context
     // Write .bob/custom_modes.yaml file with proper YAML structure
     const finalContent = yaml.stringify(config, { lineWidth: 0 });
-    await this.writeFile(bobModesPath, finalContent);
+    try {
+      await this.writeFile(bobModesPath, finalContent);
+    } catch (err) {
+      throw new Error(`Failed to write ${this.configFile}: ${err.message}`);
+    }

     // Generate workflow commands
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Write .bob/custom_modes.yaml file with proper YAML structure
const finalContent = yaml.stringify(config, { lineWidth: 0 });
await this.writeFile(bobModesPath, finalContent);
// Generate workflow commands
const workflowGenerator = new WorkflowCommandGenerator(this.bmadFolderName);
const { artifacts: workflowArtifacts } = await workflowGenerator.collectWorkflowArtifacts(bmadDir);
// Write to .bob/workflows/ directory
const workflowsDir = path.join(projectDir, '.bob', 'workflows');
await this.ensureDir(workflowsDir);
// Clear old BMAD workflows before writing new ones
await this.clearBmadWorkflows(workflowsDir);
// Write workflow files
const workflowCount = await workflowGenerator.writeDashArtifacts(workflowsDir, workflowArtifacts);
// Generate task and tool commands
const taskToolGen = new TaskToolCommandGenerator(this.bmadFolderName);
const { artifacts: taskToolArtifacts, counts: taskToolCounts } = await taskToolGen.collectTaskToolArtifacts(bmadDir);
// Write task/tool files to workflows directory (same location as workflows)
await taskToolGen.writeDashArtifacts(workflowsDir, taskToolArtifacts);
const taskCount = taskToolCounts.tasks || 0;
const toolCount = taskToolCounts.tools || 0;
// Write .bob/custom_modes.yaml file with proper YAML structure
const finalContent = yaml.stringify(config, { lineWidth: 0 });
try {
await this.writeFile(bobModesPath, finalContent);
} catch (err) {
throw new Error(`Failed to write ${this.configFile}: ${err.message}`);
}
// Generate workflow commands
const workflowGenerator = new WorkflowCommandGenerator(this.bmadFolderName);
const { artifacts: workflowArtifacts } = await workflowGenerator.collectWorkflowArtifacts(bmadDir);
// Write to .bob/workflows/ directory
const workflowsDir = path.join(projectDir, '.bob', 'workflows');
await this.ensureDir(workflowsDir);
// Clear old BMAD workflows before writing new ones
await this.clearBmadWorkflows(workflowsDir);
// Write workflow files
const workflowCount = await workflowGenerator.writeDashArtifacts(workflowsDir, workflowArtifacts);
// Generate task and tool commands
const taskToolGen = new TaskToolCommandGenerator(this.bmadFolderName);
const { artifacts: taskToolArtifacts, counts: taskToolCounts } = await taskToolGen.collectTaskToolArtifacts(bmadDir);
// Write task/tool files to workflows directory (same location as workflows)
await taskToolGen.writeDashArtifacts(workflowsDir, taskToolArtifacts);
const taskCount = taskToolCounts.tasks || 0;
const toolCount = taskToolCounts.tools || 0;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/cli/installers/lib/ide/bob.js` around lines 65 - 90, Wrap the sequence
of file writes (the call to this.writeFile(bobModesPath, ...),
workflowGenerator.writeDashArtifacts(workflowsDir, ...), and
taskToolGen.writeDashArtifacts(workflowsDir, ...)) in a try/catch so partial
success doesn't leave inconsistent state; on catch clean up any partial
artifacts by removing the written bobModesPath and clearing workflowsDir (you
can reuse clearBmadWorkflows(workflowsDir)), then rethrow or throw a new error
that includes context (e.g., which write failed) so callers can handle it;
ensure you reference bobModesPath, workflowsDir, writeFile, writeDashArtifacts,
and clearBmadWorkflows when implementing the recovery.

const roleDefinition = `You are a ${title} specializing in ${title.toLowerCase()} tasks.`;

// Get relative path
const relativePath = path.relative(projectDir, artifact.sourcePath).replaceAll('\\', '/');
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Potential crash if artifact.sourcePath is undefined.

Line 135 uses artifact.sourcePath unconditionally in path.relative(), but lines 119-125 only read from it conditionally. If an artifact lacks sourcePath, this will throw TypeError: Cannot read properties of undefined.

🐛 Proposed fix: guard against missing sourcePath
-    // Get relative path
-    const relativePath = path.relative(projectDir, artifact.sourcePath).replaceAll('\\', '/');
+    // Get relative path (fall back to artifact name if sourcePath unavailable)
+    const relativePath = artifact.sourcePath
+      ? path.relative(projectDir, artifact.sourcePath).replaceAll('\\', '/')
+      : `${this.bmadFolderName}/agents/${artifact.name}.md`;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/cli/installers/lib/ide/bob.js` at line 135, Guard against
artifact.sourcePath being undefined before calling path.relative: update the
logic around the assignment to relativePath so it first checks
artifact.sourcePath (the same property read earlier) and only calls
path.relative(projectDir, artifact.sourcePath).replaceAll('\\', '/') when
present; otherwise set relativePath to a safe default (e.g., empty string or
null) and handle that downstream. Modify the code that uses relativePath
accordingly so no TypeError is thrown when artifact.sourcePath is missing.

name: `${icon} ${title}`,
roleDefinition: roleDefinition,
whenToUse: whenToUse,
customInstructions: `${activationHeader} Read the full YAML from ${relativePath} start activation to alter your state of being follow startup section instructions stay in this being until told to exit this mode\n`,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Malformed customInstructions — missing punctuation and unclear phrasing.

The instruction string is a run-on sentence: "Read the full YAML from ${relativePath} start activation to alter your state of being follow startup section instructions stay in this being until told to exit this mode".

This is likely to confuse the AI model. Add periods or commas to separate clauses.

✏️ Suggested fix
-      customInstructions: `${activationHeader} Read the full YAML from ${relativePath} start activation to alter your state of being follow startup section instructions stay in this being until told to exit this mode\n`,
+      customInstructions: `${activationHeader} Read the full agent definition from ${relativePath}. Start activation to assume this persona. Follow the startup section instructions. Stay in this mode until told to exit.\n`,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
customInstructions: `${activationHeader} Read the full YAML from ${relativePath} start activation to alter your state of being follow startup section instructions stay in this being until told to exit this mode\n`,
customInstructions: `${activationHeader} Read the full agent definition from ${relativePath}. Start activation to assume this persona. Follow the startup section instructions. Stay in this mode until told to exit.\n`,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/cli/installers/lib/ide/bob.js` at line 143, The customInstructions
string assigned (customInstructions) is a run-on sentence and unclear; update
the template that combines activationHeader and relativePath to add proper
punctuation and clearer clauses (e.g., separate sentences or commas) so it reads
like distinct steps: instruct to read the full YAML from ${relativePath}, then
start activation, follow the startup section instructions, and remain in the
activated mode until explicitly told to exit; keep activationHeader and
${relativePath} interpolation intact.

* @param {Object} metadata - Agent metadata
* @returns {Object} Installation result
*/
async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Unused metadata parameter.

The metadata parameter is declared in the function signature but never referenced in the method body. Either use it (e.g., to extract title, description, or icon) or remove it from the signature.

✏️ Example usage
     // Add custom mode object
-    const title = `BMAD Custom: ${agentName}`;
+    const title = metadata?.title || `BMAD Custom: ${agentName}`;
+    const icon = metadata?.icon || '🤖';
     const activationHeader = (await this.getAgentCommandHeader()).trim();
     config.customModes.push({
       slug: slug,
-      name: title,
+      name: `${icon} ${title}`,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/cli/installers/lib/ide/bob.js` at line 217, The
installCustomAgentLauncher function currently declares an unused parameter
metadata; either remove metadata from the function signature of
installCustomAgentLauncher and update all call sites to stop passing it, or use
metadata inside the function (e.g., read metadata.title, metadata.description,
metadata.icon) when constructing the launcher/manifest so the values are
applied; update any code that builds the launcher (same function) to consume
those fields and ensure linter/tests no longer report an unused variable.

Comment on lines +253 to +260
config.customModes.push({
slug: slug,
name: title,
roleDefinition: `You are a custom BMAD agent "${agentName}". Follow the persona and instructions from the agent file.`,
whenToUse: `Use for custom BMAD agent "${agentName}" tasks`,
customInstructions: `${activationHeader} Read the full agent from ${agentPath} start activation to alter your state of being follow startup section instructions stay in this being until told to exit this mode\n`,
groups: ['read', 'edit', 'browser', 'command', 'mcp'],
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Inconsistent mode object format vs createModeObject().

createModeObject() at line 140 includes an icon in the name (${icon} ${title}), but installCustomAgentLauncher() at line 254 does not. This creates inconsistent display in the Bob UI. Also, line 258 has the same malformed customInstructions issue noted earlier.

✏️ Align with createModeObject format
     config.customModes.push({
       slug: slug,
-      name: title,
+      name: `🤖 ${title}`,
       roleDefinition: `You are a custom BMAD agent "${agentName}". Follow the persona and instructions from the agent file.`,
       whenToUse: `Use for custom BMAD agent "${agentName}" tasks`,
-      customInstructions: `${activationHeader} Read the full agent from ${agentPath} start activation to alter your state of being follow startup section instructions stay in this being until told to exit this mode\n`,
+      customInstructions: `${activationHeader} Read the full agent definition from ${agentPath}. Start activation to assume this persona. Follow the startup section instructions. Stay in this mode until told to exit.\n`,
       groups: ['read', 'edit', 'browser', 'command', 'mcp'],
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/cli/installers/lib/ide/bob.js` around lines 253 - 260, The custom mode
added in installCustomAgentLauncher (config.customModes.push) is inconsistent
with createModeObject: include the icon prefix in the name (use `${icon}
${title}` like createModeObject) and fix the malformed customInstructions string
by ensuring activationHeader, agentPath and instructions are concatenated into a
single well-formed sentence (no stray "start activation" fragment) — update the
object created in installCustomAgentLauncher to match createModeObject’s shape
(fields: slug, name (with icon), roleDefinition, whenToUse, customInstructions,
groups) and reuse the same template/variable order (icon, title, agentName,
activationHeader, agentPath) so display and instructions are consistent with
createModeObject.

Comment on lines +52 to +57
bob:
name: "IBM Bob"
preferred: false
category: ide
description: "IBM's agentic IDE for AI-powered development"

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Description mismatch with tools/cli/installers/lib/ide/platform-codes.yaml.

This file says "IBM's agentic IDE for AI-powered development" but the installer's platform-codes.yaml (line 39) says "IBM's AI development environment". Pick one and use it consistently across both files.

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

In `@tools/platform-codes.yaml` around lines 52 - 57, Pick one canonical
description for the bob entry and make both platform-codes.yaml files
consistent: update the bob key's description field (the "description" value
under the bob entry) in both the main platform-codes.yaml and the installer's
platform-codes.yaml so they match exactly (preserve quoting/formatting), e.g.,
change both to either "IBM's AI development environment" or "IBM's agentic IDE
for AI-powered development".

@timgraepel timgraepel force-pushed the feature/add-bob-support branch from ab1dd6c to 82411fe Compare February 27, 2026 22:25
@bmadcode
Copy link
Collaborator

bmadcode commented Mar 1, 2026

We will be doing a transition soon to most workflows being skills - do you know if this tool has skills support?

@timgraepel
Copy link
Author

timgraepel commented Mar 1, 2026

Yes, structure as per agentskills.io standard.
I’ll add the skills to the installer.

Add IBM Bob (agentic IDE) as a supported IDE platform with custom installer:

- Create custom Bob installer (tools/cli/installers/lib/ide/bob.js)
- Add .bobmodes to .gitignore
- Add platform config to tools/platform-codes.yaml
- Register Bob in IDE manager's custom installer list

Bob uses a custom installer (like Kilo) that creates a .bobmodes file
to register custom modes and writes workflows to .bob/workflows/

Fixes bmad-code-org#1768
- bob.js: fix installCustomAgentLauncher using wrong mode schema
  (description/prompt/always/permissions → roleDefinition/whenToUse/
  customInstructions/groups)
- bob.js: add detectionPaths for .bob directory
- manager.js: update comments to include bob.js in custom installer list
- platform-codes.yaml: move bob entry to correct alphabetical position
- eslint.config.mjs: add .bob/** to eslint ignores (like .claude, .roo, etc.)
- Remove leftover '// Made with Bob' debug comment
- Guard artifact.sourcePath before calling path.relative() to prevent TypeError
- Fix run-on customInstructions string with proper punctuation in createModeObject
- Move fs-extra require to top of file; remove inline requires from clearBmadWorkflows/cleanup
- Wrap write sequence in try/catch with rollback to prevent partial state on failure
- Use metadata.title and metadata.icon in installCustomAgentLauncher instead of ignoring param
- Align installCustomAgentLauncher mode object with createModeObject (icon in name, fixed instructions)
- Remove unused .bobmodes entry from .gitignore (.bob already covers the directory)
- Sync bob description in tools/cli/installers/lib/ide/platform-codes.yaml to match tools/platform-codes.yaml
@timgraepel timgraepel force-pushed the feature/add-bob-support branch from 82411fe to 411219e Compare March 2, 2026 00:25
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.

Support for new IDE: IBM Bob

2 participants