The headless install command in the install guide stops at an interactive prompt on 6.12.1 and exits 0 without installing anything, so a CI step that runs it as written succeeds with no _bmad/ in the project. Adding --directory makes the same command install.
This looks like the directory half of #1962. That issue reported both this prompt and a literal {output_folder} folder, and was closed as a duplicate of #1917; the closing note and the later v6.6.0 comment there are both about output_folder, so the prompt half may not have been tracked since.
Expected. The guide's "Headless CI installs" section (install-bmad.md L100-L106) gives, "For a typical fresh headless install of BMM configured for Claude Code":
npx bmad-method install --yes --modules bmm --tools claude-code
and the install command describes --directory <path> as "Installation directory (default: current directory)". So I expected an install into the current directory with no prompt, as #1962 also expected ("--yes without --directory should default to process.cwd()").
Actual. The installer shows Installation directory: and the process ends there with exit 0. No _bmad/ is created. With --directory added, the same command installs and exits 0.
Repro script and one full run
Clean HOME, Node.js from the nodejs.org tarball, temp project directories, cleanup trap. stdin is /dev/null, as in CI.
#!/usr/bin/env bash
# bmad-method 6.12.1: the documented headless install, with and without --directory.
# Clean HOME, Node.js from the nodejs.org tarball, temp project dirs, cleanup trap.
set -euo pipefail
NODE_V=v24.18.0
BMAD_V=6.12.1
ROOT="$(mktemp -d "${TMPDIR:-/tmp}/bmad-dir.XXXXXX")"
trap 'rm -rf -- "$ROOT"' EXIT
export HOME="$ROOT/home"; mkdir -p "$HOME"
export PATH="$ROOT/node/bin:/opt/homebrew/bin:/usr/bin:/bin" # /opt/homebrew/bin for uv only; it has no node
echo "== host: $(sw_vers -productName) $(sw_vers -productVersion) $(uname -m)"
cd "$ROOT"
tgz="node-$NODE_V-darwin-arm64.tar.gz"
curl -fsSLO "https://nodejs.org/dist/$NODE_V/$tgz"
curl -fsSLO "https://nodejs.org/dist/$NODE_V/SHASUMS256.txt"
grep " $tgz\$" SHASUMS256.txt | shasum -a 256 -c -
mkdir node && tar -xzf "$tgz" -C node --strip-components 1
echo "node $(node --version), uv $(uv --version | cut -d' ' -f2)"
try() { # label, then extra install args
local label="$1"; shift
local P="$ROOT/$label"; mkdir -p "$P" && cd "$P" && git init -q .
echo
echo "== $label: npx -y bmad-method@$BMAD_V install --yes --modules bmm --tools claude-code $*"
set +e
npx -y "bmad-method@$BMAD_V" install --yes --modules bmm --tools claude-code "$@" < /dev/null > "$P.log" 2>&1
local rc=$?
set -e
echo "exit $rc; _bmad present: $([[ -d _bmad ]] && echo yes || echo no)"
echo "last 3 log lines, escapes removed:"
python3 -c 'import re,sys; t=open(sys.argv[1],encoding="utf-8",errors="replace").read(); t=re.sub(r"\x1b\[[0-9;?]*[A-Za-z]","",t); print("\n".join(l.rstrip() for l in t.splitlines()[-3:]))' "$P.log"
cd "$ROOT"
}
# Positive control: the same command with --directory installs.
try with-directory --directory "$ROOT/with-directory"
# The command as documented in docs/start/install-bmad.md, "Headless CI installs".
try as-documented
== host: macOS 26.5.2 arm64
node-v24.18.0-darwin-arm64.tar.gz: OK
node v24.18.0, uv 0.12.1
== with-directory: npx -y bmad-method@6.12.1 install --yes --modules bmm --tools claude-code --directory $TMPDIR/bmad-dir.vaXmtK/with-directory
exit 0; _bmad present: yes
last 3 log lines, escapes removed:
npm notice Changelog: https://github.com/npm/cli/releases/tag/v12.2.0
npm notice To update run: npm install -g npm@12.2.0
npm notice
== as-documented: npx -y bmad-method@6.12.1 install --yes --modules bmm --tools claude-code
exit 0; _bmad present: no
last 3 log lines, escapes removed:
◆ Installation directory:
│ $TMPDIR/bmad-dir.vaXmtK/as-documented█
└
Mechanism. When options.directory is unset, promptInstall goes to getConfirmedDirectory(), which prompts for the directory and asks for confirmation, and nothing on that path (getConfirmedDirectory, promptForDirectory, confirmDirectory) checks options.yes. Later steps in the same function do check it, for example the module selection at L511. I have not traced the exit code: the log ends at the prompt with no "Operation cancelled" line, so the process seems to end when stdin closes, not through handleCancel.
Relevant paths: tools/installer/ui.js L283-L296, tools/installer/ui.js L840, tools/installer/commands/install.js L14
Could --yes without --directory use process.cwd(), as that option text says?
The headless install command in the install guide stops at an interactive prompt on 6.12.1 and exits 0 without installing anything, so a CI step that runs it as written succeeds with no
_bmad/in the project. Adding--directorymakes the same command install.This looks like the directory half of #1962. That issue reported both this prompt and a literal
{output_folder}folder, and was closed as a duplicate of #1917; the closing note and the later v6.6.0 comment there are both aboutoutput_folder, so the prompt half may not have been tracked since.Expected. The guide's "Headless CI installs" section (install-bmad.md L100-L106) gives, "For a typical fresh headless install of BMM configured for Claude Code":
and the install command describes
--directory <path>as "Installation directory (default: current directory)". So I expected an install into the current directory with no prompt, as #1962 also expected ("--yeswithout--directoryshould default toprocess.cwd()").Actual. The installer shows
Installation directory:and the process ends there with exit 0. No_bmad/is created. With--directoryadded, the same command installs and exits 0.Repro script and one full run
Clean
HOME, Node.js from the nodejs.org tarball, temp project directories, cleanup trap. stdin is/dev/null, as in CI.Mechanism. When
options.directoryis unset,promptInstallgoes togetConfirmedDirectory(), which prompts for the directory and asks for confirmation, and nothing on that path (getConfirmedDirectory,promptForDirectory,confirmDirectory) checksoptions.yes. Later steps in the same function do check it, for example the module selection at L511. I have not traced the exit code: the log ends at the prompt with no "Operation cancelled" line, so the process seems to end when stdin closes, not throughhandleCancel.Relevant paths:
tools/installer/ui.jsL283-L296,tools/installer/ui.jsL840,tools/installer/commands/install.jsL14Could
--yeswithout--directoryuseprocess.cwd(), as that option text says?