Best-Effort Mermaid CLI Provisioning¶
amplihack install provisions the Mermaid CLI (mmdc, the npm package
@mermaid-js/mermaid-cli)
on a best-effort basis. When mmdc is available, the
pr-guide skill renders
mermaid diagrams to images locally for Azure DevOps pull requests — where
mermaid historically does not render inside PR descriptions/comments — instead
of sending diagram source to the third-party mermaid.ink service.
This component is optional. A failed or skipped mmdc install never fails
or blocks amplihack install. It emits a warning and continues, in keeping
with the install-completeness invariant:
amplihack install fails loudly only when a required component cannot be
staged. mmdc is not required.
Why This Matters¶
The pr-guide skill converts mermaid diagrams to images for Azure DevOps
tenants that do not yet render ```mermaid fences natively in PR descriptions
and comments. It has two rendering paths (see
pr-guide §9, "Mermaid on Azure DevOps"):
| Path | Renderer | Privacy |
|---|---|---|
| Preferred | Local mmdc -i diagram.mmd -o diagram.svg, published via the PR attachments API |
Diagram source never leaves the machine |
| Fallback | Hosted https://mermaid.ink/img/<base64> |
Diagram source is sent to a third-party service |
Provisioning mmdc at install time means the preferred, privacy-preserving
local path is available without a separate manual step. Because mmdc pulls in
puppeteer and a headless Chromium download (hundreds of MB) and requires
Node.js/npm — which may be absent or restricted in CI, containers, or hardened
servers — the install is deliberately best-effort: it attempts the install when
it cheaply can, and otherwise steps aside quietly so the pr-guide skill falls
back to mermaid.ink.
Behavior¶
The provisioning step runs near the end of amplihack install, after the
version stamp and install manifest are written and after Copilot-home staging.
Running last guarantees that an mmdc failure can never leave required install
state unwritten.
Decision flow¶
amplihack install
└── (after version stamp + manifest + copilot-home staging)
└── ensure mermaid CLI (best-effort)
├── AMPLIHACK_SKIP_MMDC set (non-empty)? ── yes ─▶ SkippedByEnv (info, continue)
├── `mmdc --version` succeeds? ── yes ─▶ AlreadyPresent (info, continue)
├── `npm --version` fails / npm absent? ── yes ─▶ SkippedNoNpm (info, continue)
├── `npm install -g @mermaid-js/mermaid-cli`
│ ├── success AND re-probe finds mmdc ─────────▶ Installed (success, continue)
│ └── failure OR mmdc still off PATH ─────────▶ Failed (warn, continue)
└── (always returns Ok — never aborts install)
Outcomes¶
The step resolves to exactly one outcome, each mapped to a user-facing line:
| Outcome | Condition | Message | Stream |
|---|---|---|---|
SkippedByEnv |
AMPLIHACK_SKIP_MMDC is set to any non-empty value |
ℹ AMPLIHACK_SKIP_MMDC set; skipping mermaid CLI install |
stdout |
AlreadyPresent |
mmdc --version already succeeds on PATH |
✓ mermaid CLI (mmdc) already installed; skipping |
stdout |
SkippedNoNpm |
npm --version fails (npm not on PATH) |
ℹ npm not available; skipping mermaid CLI install (pr-guide will fall back to mermaid.ink) |
stdout |
Installed |
npm install -g … succeeded and the re-probe found mmdc |
Installing mermaid CLI for local diagram rendering... then a success line |
stdout |
Failed |
install command failed, or succeeded but mmdc is still not discoverable on PATH |
mermaid CLI not installed; pr-guide will fall back to mermaid.ink for Azure DevOps diagrams |
stderr (⚠️) + tracing::warn! |
In every case the step returns Ok(()). Install continues to its normal
completion banner regardless of the outcome.
Idempotency¶
The step is safe to re-run. On any subsequent amplihack install, an
already-installed mmdc is detected by the mmdc --version probe and the step
short-circuits to AlreadyPresent without contacting npm or re-downloading
Chromium. Self-heal re-installs (triggered by a stale version stamp) and
post-update installs therefore do not repeatedly attempt the npm install.
Non-interactive and offline environments¶
- The step never prompts. It honors
AMPLIHACK_NONINTERACTIVEautomatically because there is no interactive confirmation to suppress — the globalnpm install -gruns the same way whether or not the flag is set. - For minimal, offline, or bandwidth-constrained environments, set
AMPLIHACK_SKIP_MMDC=1to disable the attempt entirely (see below). This avoids even the fastmmdc/npmprobes. - When npm is absent, the step skips cleanly with an informational line; it
does not attempt to install Node.js or npm. (Node.js auto-install is a
separate, launch-time mechanism for
amplihack copilot; see Node.js Runtime Auto-Install.)
Configuration¶
AMPLIHACK_SKIP_MMDC¶
Type: flag Values: any non-empty value disables the attempt; absence or empty string means the step runs.
When set to any non-empty value (1, true, yes, etc.), amplihack install
skips the Mermaid CLI provisioning step entirely — no mmdc probe, no npm
probe, and no npm install. The step resolves to SkippedByEnv and prints one
informational line. Use it for:
- Offline or air-gapped installs that must not reach npm or download Chromium.
- Minimal containers/CI where the hundreds-of-MB puppeteer/Chromium
download is undesirable and the
pr-guidemermaid.inkfallback (or native ADO rendering) is acceptable. - Deterministic test harnesses that manage tool availability explicitly.
Truthiness: any non-empty value triggers the skip. An empty string
(AMPLIHACK_SKIP_MMDC="") is treated as unset and the step runs normally.
This matches the presence-flag convention used elsewhere in the installer (for
example AMPLIHACK_SKIP_AUTO_INSTALL).
Examples¶
Default install on a host with npm¶
$ amplihack install
...
✅ Amplihack installation completed successfully!
...
✅ Copilot home staged (~/.copilot/)
Installing mermaid CLI for local diagram rendering...
✓ mermaid CLI (mmdc) installed
Install on a host without npm¶
$ amplihack install
...
✅ Amplihack installation completed successfully!
...
✅ Copilot home staged (~/.copilot/)
ℹ npm not available; skipping mermaid CLI install (pr-guide will fall back to mermaid.ink)
Install still succeeds. The pr-guide skill will use the mermaid.ink
fallback (or native ADO rendering) for Azure DevOps diagrams.
Re-running install when mmdc is already present¶
$ amplihack install
...
✅ Amplihack installation completed successfully!
...
✅ Copilot home staged (~/.copilot/)
✓ mermaid CLI (mmdc) already installed; skipping
Install with the npm step failing (e.g. permission or network error)¶
$ amplihack install
...
✅ Amplihack installation completed successfully!
...
✅ Copilot home staged (~/.copilot/)
Installing mermaid CLI for local diagram rendering...
⚠️ mermaid CLI not installed; pr-guide will fall back to mermaid.ink for Azure DevOps diagrams
The warning is advisory. Exit status is success — the optional component did not gate the install.
Skipping the attempt explicitly¶
$ AMPLIHACK_SKIP_MMDC=1 amplihack install
...
✅ Amplihack installation completed successfully!
...
✅ Copilot home staged (~/.copilot/)
ℹ AMPLIHACK_SKIP_MMDC set; skipping mermaid CLI install
Installing mmdc manually later¶
If you skip the attempt or it fails, you can provision mmdc yourself at any
time and the pr-guide skill will pick it up automatically on the next run:
How It Works (Implementation Notes)¶
The step is implemented in
crates/amplihack-cli/src/commands/install/mermaid_cli.rs and invoked from
local_install() in crates/amplihack-cli/src/commands/install/mod.rs, after
the Copilot-home staging block and before the final Ok(()).
ensure_mermaid_cli() -> Result<Outcome>¶
Owns the entire probe → install → re-probe sequence and prints the user-facing
status line for the resolved outcome. It always returns Ok — a failed or
skipped install is encoded in the returned Outcome, never as an
Err. The caller pretty-prints based on the outcome and logs tracing::warn!
on Failed.
| Step | Action |
|---|---|
| 1 | If AMPLIHACK_SKIP_MMDC is non-empty → Outcome::SkippedByEnv. |
| 2 | Probe mmdc --version. Success → Outcome::AlreadyPresent. |
| 3 | Probe npm --version. Failure → Outcome::SkippedNoNpm. |
| 4 | Run npm install -g @mermaid-js/mermaid-cli. On command failure → Outcome::Failed (warn + continue). |
| 5 | Re-probe mmdc --version. Success → Outcome::Installed. Still absent (e.g. npm global prefix not on PATH) → Outcome::Failed (warn + continue). |
Outcome¶
enum Outcome {
AlreadyPresent, // mmdc was already discoverable on PATH
Installed, // npm install -g succeeded and re-probe found mmdc
SkippedByEnv, // AMPLIHACK_SKIP_MMDC was set
SkippedNoNpm, // npm not available on PATH
Failed, // install failed, or mmdc not on PATH after install
}
Process execution and safety¶
- Commands are run with
std::process::Commandusing the argument-vector form (Command::new("npm").args(["install", "-g", "@mermaid-js/mermaid-cli"])), never through a shell. This prevents command injection. - The package spec
@mermaid-js/mermaid-cliis hardcoded. It is never built from environment, config, or user input. AMPLIHACK_SKIP_MMDCis read as a presence flag only (var_os(..).map(|v| !v.is_empty())); its value never reaches any command.- No privilege escalation: the step never invokes
sudo. Permission failures resolve toFailed(warn-and-continue), not a retry with elevated privileges. - No npm integrity bypass flags (no
--unsafe-perm, no audit/integrity disabling) are used. - The
--versionprobes are fast and use the abstraction-freeCommanddirectly. Thenpm install -ghas no hard timeout kill, because the Chromium download is legitimately slow; it is bounded by npm's own network timeouts. Because the step is non-fatal, a slow or stalled download can never block required install state.
PATH resolution caveat¶
mmdc and npm are resolved via PATH, consistent with the installer's other
npm/cargo/Copilot invocations. If npm install -g succeeds but the npm
global-prefix bin directory is not on PATH, the re-probe will not find
mmdc and the step resolves to Failed with the fallback warning — even though
the binary exists off-PATH. This mirrors the ~/.cargo/bin caveat in the
recipe-runner install path. The installer does not prepend to PATH; add the
npm global bin directory to your PATH and re-run, or invoke mmdc by its
absolute path.
Testing¶
Hermetic, no-network unit tests live in
crates/amplihack-cli/src/commands/install/tests/mermaid_cli_tests.rs and are
serialized via home_env_lock(). They cover:
AMPLIHACK_SKIP_MMDCset →SkippedByEnvshort-circuit (no commands run).- npm absent (via
PATHmanipulation) →SkippedNoNpm, handled gracefully. - A stub
mmdconPATH→AlreadyPresentskip. - The function never returns
Err— failure does not propagate as an install error.
The tests never perform a real npm install or contact the network.
See Also¶
- pr-guide skill — Mermaid on Azure DevOps — how
mmdcandmermaid.inkare used at PR-creation time - amplihack install / uninstall — Command Reference — full install phase list and environment variables
- Install Completeness Verification — required vs. optional component contract
- Environment Variables — Reference —
AMPLIHACK_SKIP_MMDC - Node.js Runtime Auto-Install — separate launch-time Node.js provisioning for
amplihack copilot