@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 +109 -73
- package/package.json +12 -3
- package/src/docs/dev/tmux/colors.conf +26 -34
- package/src/docs/dev/tmux/paste_image_wrapper.sh +11 -0
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,
|
|
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
|
-
|
|
645
|
-
console.log(chalk.
|
|
646
|
-
console.log('
|
|
647
|
-
|
|
648
|
-
console.log(
|
|
649
|
-
console.log(
|
|
650
|
-
console.log(' ' + chalk.white('
|
|
651
|
-
console.log('
|
|
652
|
-
|
|
653
|
-
console.log('
|
|
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
|
-
|
|
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
|
-
//
|
|
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(
|
|
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
|
|
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.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "BMAD Method — AI-native agile workflow system for Claude Code and compatible AI assistants",
|
|
5
|
-
"keywords": [
|
|
5
|
+
"keywords": [
|
|
6
|
+
"bmad",
|
|
7
|
+
"ai-agents",
|
|
8
|
+
"claude",
|
|
9
|
+
"agile",
|
|
10
|
+
"workflow",
|
|
11
|
+
"llm"
|
|
12
|
+
],
|
|
6
13
|
"license": "MIT",
|
|
7
|
-
"engines": {
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
#
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|