@devo-bmad-custom/agent-orchestration 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/installer.js CHANGED
@@ -130,8 +130,10 @@ async function install(opts) {
130
130
  // ── Interactive prompts ───────────────────────────────────────────────────
131
131
  let resolvedUserName = userName;
132
132
 
133
+ let resolvedTools = tools ? tools.split(',').map(t => t.trim()).filter(t => t !== 'none') : ['claude-code'];
134
+
133
135
  if (!yes) {
134
- const { intro, text, select, outro } = require('@clack/prompts');
136
+ const { intro, text, multiselect, outro, isCancel } = require('@clack/prompts');
135
137
  intro(chalk.bold.cyan(`BMAD Method — ${isUpdate ? 'Update' : 'Install'}`));
136
138
 
137
139
  if (isUpdate && existingManifest) {
@@ -145,12 +147,31 @@ async function install(opts) {
145
147
  placeholder: 'Developer',
146
148
  defaultValue: existingManifest?.userName || 'Developer',
147
149
  });
150
+ if (isCancel(resolvedUserName)) { process.exit(0); }
151
+ }
152
+
153
+ const platformChoices = await multiselect({
154
+ message: 'Which AI tools / IDEs are you installing for?',
155
+ options: [
156
+ { value: 'claude-code', label: 'Claude Code', hint: 'agents, CLAUDE.md, settings.json, tmux setup' },
157
+ { value: 'cursor', label: 'Cursor', hint: '.cursor/rules/bmad.mdc' },
158
+ { value: 'windsurf', label: 'Windsurf', hint: '.windsurfrules' },
159
+ { value: 'cline', label: 'Cline', hint: '.clinerules' },
160
+ { value: 'github-copilot', label: 'GitHub Copilot', hint: '.github/copilot-instructions.md' },
161
+ { value: 'gemini', label: 'Gemini CLI', hint: 'GEMINI.md' },
162
+ ],
163
+ initialValues: existingManifest?.tools || ['claude-code'],
164
+ required: false,
165
+ });
166
+ if (isCancel(platformChoices)) { process.exit(0); }
167
+ if (platformChoices && platformChoices.length > 0) {
168
+ resolvedTools = platformChoices;
148
169
  }
170
+
149
171
  outro(`${isUpdate ? 'Updating' : 'Installing'} BMAD...`);
150
172
  }
151
173
 
152
174
  const selectedModules = modules.split(',').map(m => m.trim()).filter(Boolean);
153
- const resolvedTools = tools ? tools.split(',').map(t => t.trim()).filter(t => t !== 'none') : [];
154
175
 
155
176
  console.log(`\n${chalk.bold.blue('BMAD')} ${isUpdate ? 'Update' : 'Install'}`);
156
177
  console.log(` Target: ${chalk.cyan(projectRoot)}`);
@@ -636,21 +657,46 @@ async function setupTmux(projectRoot, chalk) {
636
657
  console.log(chalk.dim(' pane-title-changed hook requires set-hook -wg (3.4 feature)'));
637
658
  console.log(chalk.dim(' Upgrade: sudo apt-get install -y tmux (or build from source for latest)\n'));
638
659
  } else {
639
- console.log(chalk.green(` ✓ tmux ${match[1]}.${match[2]} — version OK`));
660
+ console.log(chalk.green(` ✓ tmux ${match[1]}.${match[2]} — version OK\n`));
640
661
  }
641
662
  }
642
663
  } catch { /* tmux not installed yet — skip check */ }
643
664
 
644
- console.log('\n' + chalk.bold('Step 1 Prerequisites'));
645
- console.log(chalk.dim(' tmux runs in WSL2 (Ubuntu). You need these before continuing:\n'));
646
- console.log(' ' + chalk.white('① WSL2 + Ubuntu') + chalk.dim(' — in PowerShell (Admin): ') + chalk.cyan('wsl --install'));
647
- console.log(' ' + chalk.white('② Update packages') + chalk.dim(' — in Ubuntu: ') + chalk.cyan('sudo apt-get update && sudo apt-get upgrade -y'));
648
- console.log(' ' + chalk.white(' Install tmux 3.4+') + chalk.dim(' ') + chalk.cyan('sudo apt-get install -y tmux'));
649
- console.log(' ' + chalk.white('④ Install clipboard + image tools') + chalk.dim(' ') + chalk.cyan('sudo apt-get install -y wl-clipboard imagemagick wslu'));
650
- console.log(' ' + chalk.white(' NVM + Node') + chalk.dim(' (for MCP servers) ') + chalk.cyan('curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash && source ~/.bashrc && nvm install --lts'));
651
- console.log(' ' + chalk.white(' Docker Desktop WSL integration') + chalk.dim(' — Docker Desktop → Settings → Resources → WSL Integration → toggle your Ubuntu distro → Apply & Restart'));
652
-
653
- console.log('\n' + chalk.dim(' These require sudo/GUI and must be done manually. Press Enter once WSL2 is ready.'));
665
+ // ── Step 1: Prerequisites ────────────────────────────────────────────────
666
+ console.log(chalk.bold('Step 1 Prerequisites'));
667
+ console.log('');
668
+
669
+ console.log(chalk.bold.red(' Must be done manually (require WSL install or sudo):'));
670
+ console.log(chalk.dim(' These cannot be automated. Complete them before continuing.\n'));
671
+ console.log(' ' + chalk.white(' Install WSL2 + Ubuntu') + chalk.dim(' run in PowerShell (Admin):'));
672
+ console.log(' ' + chalk.cyan('wsl --install'));
673
+ console.log(' ' + chalk.white('② Update packages') + chalk.dim(' — run in Ubuntu terminal:'));
674
+ console.log(' ' + chalk.cyan('sudo apt-get update && sudo apt-get upgrade -y'));
675
+ console.log(' ' + chalk.white('③ Install tmux 3.4+') + chalk.dim(' — run in Ubuntu terminal:'));
676
+ console.log(' ' + chalk.cyan('sudo apt-get install -y tmux'));
677
+ console.log(' ' + chalk.white('④ Install clipboard + image tools') + chalk.dim(' — run in Ubuntu terminal:'));
678
+ console.log(' ' + chalk.cyan('sudo apt-get install -y wl-clipboard imagemagick wslu'));
679
+ console.log(' ' + chalk.white('⑤ Docker Desktop WSL integration') + chalk.dim(' — GUI only:'));
680
+ console.log(' ' + chalk.dim('Docker Desktop → Settings → Resources → WSL Integration → toggle Ubuntu → Apply & Restart'));
681
+
682
+ console.log('');
683
+ console.log(chalk.bold.yellow(' ✦ Can be done manually OR by an AI with relaxed permissions:'));
684
+ console.log(chalk.dim(' These are safe to automate — no sudo or system-level access needed.\n'));
685
+ console.log(' ' + chalk.white('⑥ NVM + Node') + chalk.dim(' (required for Node-based MCP servers):'));
686
+ console.log(' ' + chalk.cyan('curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash'));
687
+ console.log(' ' + chalk.cyan('source ~/.bashrc && nvm install --lts'));
688
+ console.log(' ' + chalk.white('⑦ TPM (tmux Plugin Manager):'));
689
+ console.log(' ' + chalk.cyan('git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm'));
690
+ console.log(' ' + chalk.dim(' Then inside tmux: press Ctrl+B I to install plugins'));
691
+ console.log(' ' + chalk.white('⑧ fzf') + chalk.dim(' (required for Actions popup menu):'));
692
+ console.log(' ' + chalk.cyan('mkdir -p ~/.local/bin && curl -Lo /tmp/fzf.tar.gz https://github.com/junegunn/fzf/releases/download/v0.54.3/fzf-0.54.3-linux_amd64.tar.gz && tar -xzf /tmp/fzf.tar.gz -C ~/.local/bin'));
693
+ console.log(' ' + chalk.white('⑨ Nerd Fonts') + chalk.dim(' (required for Powerline status bar separators):'));
694
+ console.log(' ' + chalk.dim(' Download JetBrainsMono NFM from https://www.nerdfonts.com/'));
695
+ console.log(' ' + chalk.dim(' Install JetBrainsMonoNerdFontMono-Regular.ttf to Windows (double-click → Install for all users)'));
696
+ console.log(' ' + chalk.white(' Cursor/VS Code:') + ' ' + chalk.cyan('"terminal.integrated.fontFamily": "JetBrainsMono NFM"'));
697
+ console.log(' ' + chalk.white(' Windows Terminal:') + ' ' + chalk.cyan('"font": { "face": "JetBrainsMono NFM", "builtinGlyphs": false }'));
698
+
699
+ console.log('\n' + chalk.dim(' Complete the manual steps above, then press Enter to continue with config file installation.'));
654
700
  await ask(chalk.yellow(' Press Enter to continue → '));
655
701
 
656
702
  // ── Detect environment ──────────────────────────────────────────────────
@@ -673,9 +719,53 @@ async function setupTmux(projectRoot, chalk) {
673
719
  await fs.ensureDir(path.join(homeDir, '.local', 'bin'));
674
720
  await fs.ensureDir(path.join(homeDir, '.tmux', 'plugins'));
675
721
 
676
- console.log('\n' + chalk.bold('Step 2 Writing config files'));
722
+ // ── Step 2: Shell aliases ────────────────────────────────────────────────
723
+ console.log('\n' + chalk.bold('Step 2 — Shell aliases'));
724
+ const bashrc = path.join(homeDir, '.bashrc');
725
+ const resolvedRoot = path.resolve(projectRoot);
726
+ const tmuxAlias = `alias tmux-ai='tmux new-session -c ${resolvedRoot}'`;
727
+ const tmuxClaudeAlias = `alias tmux-claude='tmux new-session -c ${resolvedRoot} "claude --dangerously-skip-permissions"'`;
728
+ let bashrcContent = '';
729
+ if (await fs.pathExists(bashrc)) bashrcContent = await fs.readFile(bashrc, 'utf8');
730
+
731
+ const aliasBlock = `\n# BMAD tmux shortcuts\n${tmuxAlias}\n${tmuxClaudeAlias}\n`;
732
+ if (!bashrcContent.includes('tmux-claude')) {
733
+ const addAliases = await ask(chalk.yellow(` Add 'tmux-ai' and 'tmux-claude' aliases to ~/.bashrc? (Y/n): `));
734
+ if (!addAliases.toLowerCase().startsWith('n')) {
735
+ await fs.appendFile(bashrc, aliasBlock, 'utf8');
736
+ console.log(chalk.green(' ✓ Aliases added to ~/.bashrc'));
737
+ console.log(chalk.dim(' Run: source ~/.bashrc'));
738
+ }
739
+ } else {
740
+ console.log(chalk.dim(' ○ Aliases already in ~/.bashrc'));
741
+ }
742
+
743
+ // xdg-open symlink → wslview
744
+ if (!await fs.pathExists(xdgOpenPath)) {
745
+ try {
746
+ await fs.ensureSymlink('/usr/bin/wslview', xdgOpenPath);
747
+ console.log(chalk.green(` ✓ ${xdgOpenPath} → /usr/bin/wslview`));
748
+ } catch {
749
+ console.log(chalk.dim(` ○ Could not create xdg-open symlink (run manually: ln -sf /usr/bin/wslview ~/.local/bin/xdg-open)`));
750
+ }
751
+ } else {
752
+ console.log(chalk.dim(` ○ ${xdgOpenPath} already exists`));
753
+ }
754
+
755
+ // ── Step 3: TPM check ────────────────────────────────────────────────────
756
+ console.log('\n' + chalk.bold('Step 3 — TPM check'));
757
+ if (await fs.pathExists(tpmPath)) {
758
+ console.log(chalk.green(' ✓ TPM already installed at ~/.tmux/plugins/tpm'));
759
+ } else {
760
+ console.log(chalk.yellow(' ⚠ TPM not found — install it before starting tmux:'));
761
+ console.log(' ' + chalk.cyan('git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm'));
762
+ console.log(chalk.dim(' Then inside tmux press Ctrl+B I to install plugins.'));
763
+ }
764
+
765
+ // ── Step 4: Write config files (last) ───────────────────────────────────
766
+ console.log('\n' + chalk.bold('Step 4 — Writing config files'));
767
+ console.log(chalk.dim(' Installing tmux.conf, scripts, and support files...\n'));
677
768
 
678
- // Map: src filename → dest absolute path
679
769
  const FILE_MAP = [
680
770
  ['tmux.conf', tmuxConf],
681
771
  ['colors.conf', colorsConf],
@@ -708,78 +798,24 @@ async function setupTmux(projectRoot, chalk) {
708
798
  }
709
799
 
710
800
  await fs.copy(src, dest, { overwrite: true });
711
- // Make shell scripts and xclip executable
712
801
  if (dest.endsWith('.sh') || dest.endsWith('.py') || dest === xclipPath) {
713
802
  try { await fs.chmod(dest, 0o755); } catch {}
714
803
  }
715
804
  console.log(chalk.green(` ✓ ${dest}`));
716
805
  }
717
806
 
718
- // Also copy tmux-setup.md as reference doc to the project
807
+ // xdg-open symlink wslview
808
+ // Copy reference doc to the project
719
809
  const tmuxSetupSrc = path.join(tmuxSrc, 'tmux-setup.md');
720
810
  if (await fs.pathExists(tmuxSetupSrc)) {
721
- const refDocDest = path.join(projectRoot, 'docs', 'dev', 'tmux', 'README.md');
811
+ const refDocDest = path.join(resolvedRoot, 'docs', 'dev', 'tmux', 'README.md');
722
812
  await fs.ensureDir(path.dirname(refDocDest));
723
813
  await fs.copy(tmuxSetupSrc, refDocDest, { overwrite: true });
724
814
  console.log(chalk.green(` ✓ ${refDocDest} (reference doc)`));
725
815
  }
726
816
 
727
- // xdg-open symlink → wslview
728
- if (!await fs.pathExists(xdgOpenPath)) {
729
- try {
730
- await fs.ensureSymlink('/usr/bin/wslview', xdgOpenPath);
731
- console.log(chalk.green(` ✓ ${xdgOpenPath} → /usr/bin/wslview`));
732
- } catch {
733
- console.log(chalk.dim(` ○ Could not create xdg-open symlink (run manually: ln -sf /usr/bin/wslview ~/.local/bin/xdg-open)`));
734
- }
735
- } else {
736
- console.log(chalk.dim(` ○ ${xdgOpenPath} already exists`));
737
- }
738
-
739
- console.log('\n' + chalk.bold('Step 3 — TPM (tmux Plugin Manager)'));
740
- if (await fs.pathExists(tpmPath)) {
741
- console.log(chalk.dim(' ✓ TPM already installed at ~/.tmux/plugins/tpm'));
742
- } else {
743
- console.log(chalk.dim(' TPM not found. Run this to install it:'));
744
- console.log(' ' + chalk.cyan('git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm'));
745
- console.log(chalk.dim(' Then start tmux and press Ctrl+B I to install plugins.'));
746
- }
747
-
748
- console.log('\n' + chalk.bold('Step 4 — Nerd Fonts (required for status bar icons)'));
749
- console.log(chalk.dim(' Download JetBrainsMono NFM from https://www.nerdfonts.com/'));
750
- console.log(chalk.dim(' Install JetBrainsMonoNerdFontMono-Regular.ttf to Windows (double-click → Install for all users)'));
751
- console.log(chalk.dim(' Then set your terminal font:'));
752
- console.log(' ' + chalk.white('Cursor/VS Code') + ' → ' + chalk.cyan('"terminal.integrated.fontFamily": "JetBrainsMono NFM"'));
753
- console.log(' ' + chalk.white('Windows Terminal') + ' → ' + chalk.cyan('"font": { "face": "JetBrainsMono NFM", "builtinGlyphs": false }'));
754
-
755
- console.log('\n' + chalk.bold('Step 5 — fzf (Actions menu)'));
756
- console.log(chalk.dim(' Run:'));
757
- console.log(' ' + chalk.cyan('mkdir -p ~/.local/bin && curl -Lo /tmp/fzf.tar.gz https://github.com/junegunn/fzf/releases/download/v0.54.3/fzf-0.54.3-linux_amd64.tar.gz && tar -xzf /tmp/fzf.tar.gz -C ~/.local/bin'));
758
-
759
- console.log('\n' + chalk.bold('Step 6 — Shell aliases'));
760
- const bashrc = path.join(homeDir, '.bashrc');
761
- const squidAlias = `alias squid='tmux new-session -c ${projectRoot}'`;
762
- const squidClaudeAlias = `alias squid-claude='tmux new-session -c ${projectRoot} "claude --dangerously-skip-permissions"'`;
763
- let bashrcContent = '';
764
- if (await fs.pathExists(bashrc)) {
765
- bashrcContent = await fs.readFile(bashrc, 'utf8');
766
- }
767
- const aliasBlock = `\n# BMAD tmux shortcuts\n${squidAlias}\n${squidClaudeAlias}\n`;
768
- if (!bashrcContent.includes('squid-claude')) {
769
- const addAliases = await ask(chalk.yellow(` Add 'squid' and 'squid-claude' aliases to ~/.bashrc? (Y/n): `));
770
- if (!addAliases.toLowerCase().startsWith('n')) {
771
- await fs.appendFile(bashrc, aliasBlock, 'utf8');
772
- console.log(chalk.green(' ✓ Aliases added to ~/.bashrc'));
773
- console.log(chalk.dim(' Run: source ~/.bashrc'));
774
- }
775
- } else {
776
- console.log(chalk.dim(' ○ Aliases already in ~/.bashrc'));
777
- }
778
-
779
817
  console.log('\n' + chalk.bold.green('✓ tmux setup complete!'));
780
- console.log(chalk.dim(' Start a session with: ') + chalk.cyan('squid'));
781
- console.log(chalk.dim(' Or launch Claude directly: ') + chalk.cyan('squid-claude'));
782
- console.log(chalk.dim(' Full docs: ') + chalk.cyan('docs/dev/tmux/README.md\n'));
818
+ console.log(chalk.dim(' Start tmux and press Ctrl+B I to finish TPM plugin install.\n'));
783
819
 
784
820
  rl.close();
785
821
  }
package/package.json CHANGED
@@ -1,10 +1,19 @@
1
1
  {
2
2
  "name": "@devo-bmad-custom/agent-orchestration",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "BMAD Method — AI-native agile workflow system for Claude Code and compatible AI assistants",
5
- "keywords": ["bmad", "ai-agents", "claude", "agile", "workflow", "llm"],
5
+ "keywords": [
6
+ "bmad",
7
+ "ai-agents",
8
+ "claude",
9
+ "agile",
10
+ "workflow",
11
+ "llm"
12
+ ],
6
13
  "license": "MIT",
7
- "engines": { "node": ">=20.0.0" },
14
+ "engines": {
15
+ "node": ">=20.0.0"
16
+ },
8
17
  "bin": {
9
18
  "bmad": "bin/bmad.js",
10
19
  "bmad-install": "bin/bmad.js"
@@ -1,34 +1,26 @@
1
- # Catppuccin Frappe color palette — sourced by ~/.tmux.conf
2
- # These variables are available for use in tmux format strings and shell scripts.
3
- # The status bar in tmux.conf uses these values hardcoded for compatibility.
4
-
5
- # Base
6
- tm_crust='#232634'
7
- tm_mantle='#292c3c'
8
- tm_base='#303446'
9
- tm_surface0='#414559'
10
- tm_surface1='#51576d'
11
- tm_surface2='#626880'
12
-
13
- # Text
14
- tm_text='#c6d0f5'
15
- tm_subtext1='#b5bfe2'
16
- tm_subtext0='#a5adce'
17
-
18
- # Overlay
19
- tm_overlay0='#737994'
20
- tm_overlay1='#838ba7'
21
- tm_overlay2='#949cbb'
22
-
23
- # Status bar pill colors (also hardcoded in tmux.conf)
24
- tm_navy='#3d6095'
25
- tm_forest='#4a6e38'
26
- tm_teal='#316862'
27
- tm_slate='#306075'
28
- tm_crimson='#783a3c'
29
- tm_purple='#5c3c78'
30
- tm_rust='#784828'
31
- tm_gold='#685820'
32
-
33
- # Pill text
34
- tm_pill_text='#d8ddf0'
1
+ set -g @thm_rosewater "#f2d5cf"
2
+ set -g @thm_flamingo "#eebebe"
3
+ set -g @thm_pink "#f4b8e4"
4
+ set -g @thm_mauve "#ca9ee6"
5
+ set -g @thm_red "#e78284"
6
+ set -g @thm_maroon "#ea999c"
7
+ set -g @thm_peach "#ef9f76"
8
+ set -g @thm_yellow "#e5c890"
9
+ set -g @thm_green "#a6d189"
10
+ set -g @thm_teal "#81c8be"
11
+ set -g @thm_sky "#99d1db"
12
+ set -g @thm_sapphire "#85c1dc"
13
+ set -g @thm_blue "#8caaee"
14
+ set -g @thm_lavender "#babbf1"
15
+ set -g @thm_text "#c6d0f5"
16
+ set -g @thm_subtext1 "#b5bfe2"
17
+ set -g @thm_subtext0 "#a5adce"
18
+ set -g @thm_overlay2 "#949cbb"
19
+ set -g @thm_overlay1 "#838ba7"
20
+ set -g @thm_overlay0 "#737994"
21
+ set -g @thm_surface2 "#626880"
22
+ set -g @thm_surface1 "#51576d"
23
+ set -g @thm_surface0 "#414559"
24
+ set -g @thm_base "#303446"
25
+ set -g @thm_mantle "#292c3c"
26
+ set -g @thm_crust "#232634"
@@ -45,6 +45,17 @@ if [ -n "$IMAGE_TYPE" ]; then
45
45
  || mv "$RAWFILE" "$PNGFILE"
46
46
  fi
47
47
 
48
+ # WSLg Wayland bridge sometimes lists image types but writes 0 bytes.
49
+ # Fall back to PowerShell (Windows clipboard API) when wl-paste produces empty output.
50
+ if [ ! -s "$PNGFILE" ]; then
51
+ WINPATH=$(wslpath -w "$PNGFILE" 2>/dev/null)
52
+ powershell.exe -NoProfile -Command "
53
+ Add-Type -AssemblyName System.Windows.Forms
54
+ \$img = [System.Windows.Forms.Clipboard]::GetImage()
55
+ if (\$img -ne \$null) { \$img.Save('$WINPATH') }
56
+ " 2>/dev/null
57
+ fi
58
+
48
59
  [ -s "$PNGFILE" ] || exit 1
49
60
  send_path "@$PNGFILE"
50
61
  /usr/bin/wl-copy --type image/png < "$PNGFILE" 2>/dev/null || true