mirror of
https://github.com/jlengrand/Maestro.git
synced 2026-03-10 08:31:19 +00:00
refactor(cli): Replace pkg with esbuild for smaller builds
Migrate from @yao-pkg/pkg (standalone binaries) to esbuild (bundled JS). This removes ~46 packages from the dependency tree and produces a 174KB bundle instead of ~50MB per-platform binaries. Users of the CLI already have Node.js installed (required for Claude Code), so standalone binaries are unnecessary overhead. Changes: - Remove @yao-pkg/pkg, add esbuild - Add scripts/build-cli.mjs for esbuild bundling - Update package.json build scripts and extraResources config - Update README with new installation instructions - Include batch-processor improvements from linter Session: 472b48d8-4774-4955-8c98-2c5b6294beb5
This commit is contained in:
22
README.md
22
README.md
@@ -346,21 +346,29 @@ You can run separate batch processes in different Maestro sessions simultaneousl
|
||||
|
||||
## Command Line Interface
|
||||
|
||||
Maestro includes a CLI tool (`maestro-playbook`) for running playbooks from the command line, cron jobs, or CI/CD pipelines. The CLI is a standalone binary that requires no additional dependencies.
|
||||
Maestro includes a CLI tool (`maestro-playbook`) for running playbooks from the command line, cron jobs, or CI/CD pipelines. The CLI requires Node.js (which you already have if you're using Claude Code).
|
||||
|
||||
### Installation
|
||||
|
||||
The CLI binary is bundled with Maestro. After installation, create a symlink to add it to your PATH:
|
||||
The CLI is bundled with Maestro as a JavaScript file. Create a shell wrapper to run it:
|
||||
|
||||
```bash
|
||||
# macOS (after installing Maestro.app)
|
||||
sudo ln -sf "/Applications/Maestro.app/Contents/Resources/maestro-playbook" /usr/local/bin/maestro-playbook
|
||||
echo '#!/bin/bash\nnode "/Applications/Maestro.app/Contents/Resources/maestro-playbook.js" "$@"' | sudo tee /usr/local/bin/maestro-playbook && sudo chmod +x /usr/local/bin/maestro-playbook
|
||||
|
||||
# Windows (run as Administrator in PowerShell)
|
||||
# The binary is located at: C:\Program Files\Maestro\resources\maestro-playbook.exe
|
||||
# Linux (deb/rpm installs to /opt)
|
||||
echo '#!/bin/bash\nnode "/opt/Maestro/resources/maestro-playbook.js" "$@"' | sudo tee /usr/local/bin/maestro-playbook && sudo chmod +x /usr/local/bin/maestro-playbook
|
||||
|
||||
# Linux (AppImage - extract first, or use deb/rpm which installs to /opt)
|
||||
sudo ln -sf "/opt/Maestro/resources/maestro-playbook" /usr/local/bin/maestro-playbook
|
||||
# Windows (PowerShell as Administrator) - create a batch file
|
||||
@"
|
||||
@echo off
|
||||
node "%ProgramFiles%\Maestro\resources\maestro-playbook.js" %*
|
||||
"@ | Out-File -FilePath "$env:ProgramFiles\Maestro\maestro-playbook.cmd" -Encoding ASCII
|
||||
```
|
||||
|
||||
Alternatively, run directly with Node.js:
|
||||
```bash
|
||||
node "/Applications/Maestro.app/Contents/Resources/maestro-playbook.js" list groups
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
1318
package-lock.json
generated
1318
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
37
package.json
37
package.json
@@ -13,17 +13,7 @@
|
||||
"url": "https://github.com/yourusername/maestro.git"
|
||||
},
|
||||
"bin": {
|
||||
"maestro-playbook": "./dist/cli/cli/index.js"
|
||||
},
|
||||
"pkg": {
|
||||
"scripts": "dist/cli/**/*.js",
|
||||
"targets": [
|
||||
"node20-macos-arm64",
|
||||
"node20-macos-x64",
|
||||
"node20-win-x64",
|
||||
"node20-linux-x64"
|
||||
],
|
||||
"outputPath": "dist/cli/bin"
|
||||
"maestro-playbook": "./dist/cli/maestro-playbook.js"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "concurrently \"npm run dev:main\" \"npm run dev:renderer\"",
|
||||
@@ -33,14 +23,13 @@
|
||||
"generate:pwa-icons": "node scripts/generate-pwa-icons.mjs",
|
||||
"build": "npm run build:main && npm run build:renderer && npm run build:web && npm run build:cli",
|
||||
"build:main": "tsc -p tsconfig.main.json",
|
||||
"build:cli": "tsc -p tsconfig.cli.json",
|
||||
"build:cli:bin": "npm run build:cli && pkg dist/cli/cli/index.js --config package.json",
|
||||
"build:cli": "node scripts/build-cli.mjs",
|
||||
"build:renderer": "vite build",
|
||||
"build:web": "vite build --config vite.config.web.mts",
|
||||
"package": "node scripts/set-version.mjs npm run build && npm run build:cli:bin && node scripts/set-version.mjs electron-builder --mac --win --linux",
|
||||
"package:mac": "node scripts/set-version.mjs npm run build && npm run build:cli:bin && node scripts/set-version.mjs electron-builder --mac",
|
||||
"package:win": "node scripts/set-version.mjs npm run build && npm run build:cli:bin && node scripts/set-version.mjs electron-builder --win",
|
||||
"package:linux": "node scripts/set-version.mjs npm run build && npm run build:cli:bin && node scripts/set-version.mjs electron-builder --linux",
|
||||
"package": "node scripts/set-version.mjs npm run build && node scripts/set-version.mjs electron-builder --mac --win --linux",
|
||||
"package:mac": "node scripts/set-version.mjs npm run build && node scripts/set-version.mjs electron-builder --mac",
|
||||
"package:win": "node scripts/set-version.mjs npm run build && node scripts/set-version.mjs electron-builder --win",
|
||||
"package:linux": "node scripts/set-version.mjs npm run build && node scripts/set-version.mjs electron-builder --linux",
|
||||
"start": "electron .",
|
||||
"clean": "rm -rf dist release node_modules/.vite",
|
||||
"postinstall": "electron-rebuild -f -w node-pty"
|
||||
@@ -78,8 +67,8 @@
|
||||
"icon": "build/icon.icns",
|
||||
"extraResources": [
|
||||
{
|
||||
"from": "dist/cli/bin/maestro-macos-${arch}",
|
||||
"to": "maestro-playbook"
|
||||
"from": "dist/cli/maestro-playbook.js",
|
||||
"to": "maestro-playbook.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -101,8 +90,8 @@
|
||||
"icon": "build/icon.ico",
|
||||
"extraResources": [
|
||||
{
|
||||
"from": "dist/cli/bin/maestro-win-x64.exe",
|
||||
"to": "maestro-playbook.exe"
|
||||
"from": "dist/cli/maestro-playbook.js",
|
||||
"to": "maestro-playbook.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -116,8 +105,8 @@
|
||||
"icon": "build/icon.png",
|
||||
"extraResources": [
|
||||
{
|
||||
"from": "dist/cli/bin/maestro-linux-x64",
|
||||
"to": "maestro-playbook"
|
||||
"from": "dist/cli/maestro-playbook.js",
|
||||
"to": "maestro-playbook.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -166,13 +155,13 @@
|
||||
"@types/react-syntax-highlighter": "^15.5.13",
|
||||
"@types/ws": "^8.5.10",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"@yao-pkg/pkg": "^6.10.1",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"canvas": "^3.2.0",
|
||||
"concurrently": "^8.2.2",
|
||||
"electron": "^28.1.0",
|
||||
"electron-builder": "^24.9.1",
|
||||
"electron-rebuild": "^3.2.9",
|
||||
"esbuild": "^0.24.2",
|
||||
"lucide-react": "^0.303.0",
|
||||
"postcss": "^8.4.33",
|
||||
"react": "^18.2.0",
|
||||
|
||||
49
scripts/build-cli.mjs
Normal file
49
scripts/build-cli.mjs
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Build script for the Maestro CLI using esbuild.
|
||||
*
|
||||
* Bundles the CLI into a single JavaScript file that can be run with Node.js.
|
||||
* Users of this CLI already have Node.js installed (required for Claude Code),
|
||||
* so we don't need standalone binaries.
|
||||
*/
|
||||
|
||||
import * as esbuild from 'esbuild';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const rootDir = path.resolve(__dirname, '..');
|
||||
|
||||
const outfile = path.join(rootDir, 'dist/cli/maestro-playbook.js');
|
||||
|
||||
async function build() {
|
||||
console.log('Building CLI with esbuild...');
|
||||
|
||||
try {
|
||||
await esbuild.build({
|
||||
entryPoints: [path.join(rootDir, 'src/cli/index.ts')],
|
||||
bundle: true,
|
||||
platform: 'node',
|
||||
target: 'node20',
|
||||
outfile,
|
||||
format: 'cjs',
|
||||
sourcemap: true,
|
||||
minify: false, // Keep readable for debugging
|
||||
// Note: shebang is already in src/cli/index.ts, no banner needed
|
||||
external: [],
|
||||
});
|
||||
|
||||
// Make the output executable
|
||||
fs.chmodSync(outfile, 0o755);
|
||||
|
||||
const stats = fs.statSync(outfile);
|
||||
const sizeKB = (stats.size / 1024).toFixed(1);
|
||||
console.log(`✓ Built ${outfile} (${sizeKB} KB)`);
|
||||
} catch (error) {
|
||||
console.error('Build failed:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
build();
|
||||
@@ -298,20 +298,23 @@ export async function* runPlaybook(
|
||||
};
|
||||
|
||||
// Substitute template variables in the prompt
|
||||
const finalPrompt = substituteTemplateVariables(playbook.prompt, templateContext);
|
||||
const basePrompt = substituteTemplateVariables(playbook.prompt, templateContext);
|
||||
|
||||
// Read document content and expand template variables in it
|
||||
const { content: docContent } = readDocAndCountTasks(folderPath, docEntry.filename);
|
||||
if (docContent) {
|
||||
const expandedDocContent = substituteTemplateVariables(docContent, templateContext);
|
||||
// Write the expanded content back to the document temporarily
|
||||
// (Claude will read this file, so it needs the expanded variables)
|
||||
if (expandedDocContent !== docContent) {
|
||||
writeDoc(folderPath, `${docEntry.filename}.md`, expandedDocContent);
|
||||
}
|
||||
const expandedDocContent = docContent
|
||||
? substituteTemplateVariables(docContent, templateContext)
|
||||
: '';
|
||||
|
||||
// Write expanded content back to document (so agent edits have correct paths)
|
||||
if (expandedDocContent && expandedDocContent !== docContent) {
|
||||
writeDoc(folderPath, `${docEntry.filename}.md`, expandedDocContent);
|
||||
}
|
||||
|
||||
// Spawn agent
|
||||
// Combine prompt with document content - agent works on what it's given
|
||||
const finalPrompt = `${basePrompt}\n\n---\n\n# ${docEntry.filename}.md\n\n${expandedDocContent}`;
|
||||
|
||||
// Spawn agent with combined prompt + document
|
||||
const result = await spawnAgent(session.cwd, finalPrompt);
|
||||
|
||||
const elapsedMs = Date.now() - taskStartTime;
|
||||
|
||||
Reference in New Issue
Block a user