A small macOS app that creates new project folders pre-configured with the BMad method for Claude Code and opencode, and installs a custom "marketing growth" module on top.
A Windows port via Tauri lives under tauri/ — see
issue #25 for the
shipping plan. All three stages (scaffold, Rust services + Svelte UI,
bundled Node + PortableGit) have landed; the Windows build ships via
Scoop as a portable app with Node and Git bundled inside.
The UI is intentionally tiny:
- Pick a project root folder (one-time setup in Settings).
- Type a new project name, click Create new project.
- By default the marketing-growth module is pulled fresh from
github.com/lpalokan/bmad-marketing-growth
via a shallow
git clone. You can switch to a local.zipin Settings — if you switch to local-zip without one configured, the app pops a file picker, remembers your choice, and continues. - When other projects already carry a company context
(
output/company-context/, the legacy_bmad-output/company-context/, or a top-levelcompany-context/, holding the marketing-growth module's recognized files —icp.md,positioning.md,brand-voice.md,kpis.md,tech-stack.md), a Context menu appears under the create row. Pick a source project to copy its context files into the new project right after a successful install, or leave Start from scratch selected. Imported files are copied verbatim; run the module's company-context-bootstrap workflow in the new project to adapt them. - Each project row shows when it was created and has buttons to open it in Claude Code or opencode in a Terminal window, plus a trash button (moves to macOS Trash).
- A Sort menu above the list reorders projects by name (A→Z) or by creation date (newest or oldest first). The choice is persisted.
brew install --cask lpalokan/tap/bmad-manager
xattr -r -d com.apple.quarantine /Applications/bmad-manager.app
The first command installs the app. The second removes the Gatekeeper
quarantine attribute Homebrew applies to downloads — without it, the
first launch needs a right-click → Open dance. Homebrew
intentionally won't bypass quarantine from inside a cask,
so this stays as a one-time user step instead of cask magic. Rerun the
xattr command after every brew upgrade, since the upgrade reinstalls
the bundle and quarantine gets reapplied. No paid Apple Developer ID
required either way.
Manual DMG install below still works if you prefer it.
The Windows build is distributed via Scoop. Add the bucket once, then install:
scoop bucket add lpalokan https://github.com/lpalokan/scoop-bucket
scoop install bmad-manager
scoop update bmad-manager upgrades in place — your projects folder,
settings, and npm cache are preserved (they live outside the install
dir, in %APPDATA% / %LOCALAPPDATA%).
Prefer not to use Scoop? Every release also attaches a portable zip
(bmad-manager-windows-x64-portable.zip) to its
GitHub Release.
Extract it anywhere and run bmad-manager.exe — no installer, no admin.
Either way:
- Set your projects folder in Settings, then type a name and click
Create new project. The bundled Node and Git mean you don't need
to install anything else —
npx bmad-method installruns inside the app's sandbox using the pre-warmed npm cache. - If SmartScreen warns on first launch, click More info → Run anyway. This is a one-time dismissal — Windows remembers the choice.
Settings shows the bundled Node and Git versions under "Bundled tooling"
so you can answer "what version is this running?" without digging into
AppData. Configuration is persisted at %APPDATA%\bmad-manager\settings.json.
Heads-up: If your Windows machine is managed by corporate IT (Intune / AppLocker / Defender for Endpoint), the unsigned binary may be blocked outright with no override. The colleagues this tool is built for are running personal Windows machines.
You receive bmad-manager.dmg from the developer.
- Double-click the DMG.
- Drag
bmad-manager.apponto theApplicationsshortcut. - First launch only: right-click
bmad-managerin/Applications→ Open, then click Open in the Gatekeeper warning. (The app is ad-hoc signed, not notarized — this one-time step is normal for indie macOS apps.) - The first time you click "Claude Code" or "opencode" on a project, macOS will ask permission for the app to control Terminal. Click OK.
Settings (cogwheel icon) let you change:
- Projects root folder — every new project becomes a subfolder here.
- Marketing growth module source — pick one:
- GitHub repo (default): a public
https://...URL plus an optional branch/tag/SHA. Blank ref = follow the repo's default branch. Each project creation does agit clone --depth 1into a temp dir, so you always get the latest upstream. Requiresgiton PATH — Xcode Command Line Tools provides it (xcode-select --install). - Local zip: path to a
.zipon disk. GitHub "Download ZIP" archives are auto-unwrapped (the app descends into the single wrapper folder so--custom-sourcesees the module root).
- GitHub repo (default): a public
- Init command — the headless command run after the project folder is
created. The default uses the BMad headless install
flags
(
--yes --modules bmm,bmb,cis --tools claude-code,opencode,pi --custom-source ... --directory ...) to install the BMad Method core, BMad Builder, and Creative Intelligence Suite configured for Claude Code, opencode, and Pi, and to register the materialised marketing-growth bundle as a proper BMad module via--custom-source(rather than overlaying its files on the project). If you're upgrading an existing install, hit Reset to defaults so your persisted command picks up the current flags. Available placeholders:{PROJECT_PATH}— absolute path of the new project folder{MODULE_PATH}— absolute path of the materialised module (in/tmp/...){PROJECT_NAME}— bare folder name
- Claude Code / opencode commands — the binaries (or aliases) invoked by the per-row launch buttons.
Defaults are restored via Reset to defaults in Settings. Configuration is
persisted at ~/Library/Application Support/bmad-manager/settings.json.
Requirements: macOS with Xcode (or Command Line Tools), Swift 5.9+. No
.xcodeproj is used — everything builds from the terminal via SwiftPM.
./scripts/build_release.shThat produces dist/bmad-manager.dmg. Share that single file with end users.
The script:
swift build -c release --arch arm64 --arch x86_64(universal binary; falls back to host arch if the multi-arch flags aren't supported).- Wraps the binary into
build/bmad-manager.appwithResources/Info.plist. - Ad-hoc codesigns the bundle (
codesign --sign -) — no paid Apple Developer ID required. - Wraps the
.appplus anApplicationssymlink intodist/bmad-manager.dmgviahdiutil.
To iterate while developing without producing the DMG:
swift runThe Windows port lives under tauri/. The CI workflow
.github/workflows/tauri-windows.yml runs on windows-latest,
downloads portable Node and PortableGit at build time, pre-warms the
bmad-method npm cache, compiles the app with pnpm tauri build --no-bundle, and packages it into a portable zip uploaded as a
workflow artifact named bmad-manager-windows-x64-portable.zip (the
artifact Scoop installs). Tagging a commit with windows-v* (e.g.
windows-v0.1.0) additionally publishes a GitHub Release with the zip
attached.
To bump the bundled Node or PortableGit version, edit
NODE_VERSION / GIT_FOR_WINDOWS_VERSION in
.github/workflows/tauri-windows.yml and re-run the workflow.
See tauri/README.md for the local dev loop on
Windows or macOS, and for the layout of the Rust + Svelte tree.
Default behavior is fine for personal use — end users right-click → Open the first time to bypass Gatekeeper. To skip that step entirely (paid Apple Developer ID required), set two environment variables:
APPLE_DEVELOPER_ID="Developer ID Application: Your Name (TEAMID)" \
NOTARY_PROFILE="my-notary-profile" \
./scripts/build_release.shOne-time setup for NOTARY_PROFILE:
xcrun notarytool store-credentials "my-notary-profile" \
--apple-id "you@example.com" \
--team-id "TEAMID" \
--password "your-app-specific-password"If only APPLE_DEVELOPER_ID is set (no NOTARY_PROFILE), the app is signed
but not notarized — Gatekeeper will still warn. Set both for a clean
double-click experience.
swift testCovers AppSettings, ProjectService, both ModuleSource adapters
(GitRepoModuleSource, LocalZipModuleSource), ProjectCreator
orchestration via a fake source, CompanyContextService resolution and
import, the shared Subprocess runner, and the TerminalLauncher
escaping helpers. Tests are macOS-only (the package platform is .macOS(.v14))
and require full Xcode (XCTest isn't shipped in the Command Line Tools
stand-alone install).
Package.swift
Sources/BmadManager/
BmadManagerApp.swift # @main App
Models/ # AppSettings, ProjectItem, CompanyContext
Services/ # SettingsStore, ProjectService,
# CompanyContextService,
# ModuleSource (+ GitRepoModuleSource,
# LocalZipModuleSource), Subprocess,
# CommandRunner, TerminalLauncher
Views/ # ContentView, ProjectRowView,
# SettingsView, CommandOutputView
Resources/
Info.plist
icon-source.png # 1024x1024 source for the app icon
scripts/
build_release.sh
make_icon.sh # turns icon-source.png into AppIcon.icns (macOS sips + iconutil)
The .icns and .iconset are generated at build time (via scripts/make_icon.sh,
which build_release.sh calls automatically when the .icns is missing) and are
git-ignored. To regenerate after editing icon-source.png, just rerun the build
script or call ./scripts/make_icon.sh directly.
- Validate the typed name (non-empty, no
/, no leading., not already present). - If the source is Local zip and none is configured, pop a file picker, save the choice to settings, then continue. (The GitHub-repo source has a default URL and never prompts.)
mkdir <projectsRoot>/<name>.- Materialise the module into a fresh
/tmp/bmad-manager-<uuid>/:- GitHub repo:
git clone --depth 1 [--branch <ref>] <url>into the temp dir. The clone root is the module root. - Local zip: extract with
/usr/bin/unzip, then descend into the single wrapper folder if the archive has GitHub's "Download ZIP" shape.
- GitHub repo:
- Substitute placeholders in the init command, and append
--output-folder outputso BMAD core installs into the sameoutput/folder the modules and the company context use, instead of its own_bmad-output/default. Skipped when your configured command already sets--output-folderor--set core.output_folder=. This is a create-only step: Update re-runs your command as written, so an existing project keeps whichever output folder it was installed with. - Run the command in
/bin/zsh -lc '...'with the project folder as the working directory (sonpx, Homebrew, nvm, etc. resolve from your shell PATH). Output streams into the bottom panel. - Clean up the
/tmpmaterialisation directory. - If a source context was selected in the Context menu, copy its
recognized files into
<project>/output/company-context/— the canonical folder, whichever layout the source used (files the init command already created there are never overwritten). This step is skipped when the init command failed.
On failure the partial project folder is kept so you can inspect it; delete it from the list with the trash button when you're done.