Summary
There is no way to adjust a component install short of replacing the entire invocation. Common, routine adjustments — most obviously "don't install devDependencies" — require setting install.command, which discards --ignore-scripts, the devEngines.packageManager resolution, and applications_packageManagerPrefix along with it.
So the escape hatch is the only lever, and every small adjustment forces a large, control-bypassing one.
Evidence the flags are already wanted
The deprecated install_node_modules operation already passes --omit=dev (utility/npmUtilities.ts:45):
const args = ['install', '--force', '--omit=dev', '--json'];
…while the actual deploy path (components/Application.ts:424) does not:
const npmInstallArgs = application.install?.allowInstallScripts
? ['install', '--force']
: ['install', '--force', '--ignore-scripts'];
The flag is desired; it's just applied in a deprecated code path and not the live one. A component deployed normally gets its devDependencies installed.
Proposal
Structured options for the common flags — omit, preferOffline, noAudit, noFund — plus an extraArgs: string[] pressure valve. The important property is that these compose with --ignore-scripts, the package-manager resolution, and the prefix, rather than replacing them the way install.command does.
Boundary rule, stated up front because this is the proposal most exposed to scope creep: expose only flags that are (a) meaningful across npm/yarn/pnpm, since all three are reachable via devEngines.packageManager, and (b) about what gets installed or how it is fetched. Anything else keeps using install.command. extraArgs covers the tail without turning this into an arbitrary passthrough surface.
The creep matters in both directions: if this doesn't cover real use cases, install.command stays mandatory and hardening it stays unpalatable.
Open question
Should --omit=dev be the default for component installs? Shipping devDependencies to a deployed component is rarely intended, and it's what the deprecated operation already does. But it's a behavior change — a component that currently resolves a devDependency at runtime would start failing. Probably wants a minor version and a release note rather than a patch.
Also worth deciding: whether these are operator-level (global config) or component-author-level (per-app install block), or both. The existing install block is component-author-settable and already carries allowInstallScripts, so there's a precedent for author control — but "what gets installed on my host" has an operator flavor too.
Related: #1974 — note that any lifecycle option added here won't take effect for payload-deployed components until they're redeployed, since those never re-enter the install path.
🤖 Filed by Claude on behalf of @heskew
Summary
There is no way to adjust a component install short of replacing the entire invocation. Common, routine adjustments — most obviously "don't install devDependencies" — require setting
install.command, which discards--ignore-scripts, thedevEngines.packageManagerresolution, andapplications_packageManagerPrefixalong with it.So the escape hatch is the only lever, and every small adjustment forces a large, control-bypassing one.
Evidence the flags are already wanted
The deprecated
install_node_modulesoperation already passes--omit=dev(utility/npmUtilities.ts:45):…while the actual deploy path (
components/Application.ts:424) does not:The flag is desired; it's just applied in a deprecated code path and not the live one. A component deployed normally gets its devDependencies installed.
Proposal
Structured options for the common flags —
omit,preferOffline,noAudit,noFund— plus anextraArgs: string[]pressure valve. The important property is that these compose with--ignore-scripts, the package-manager resolution, and the prefix, rather than replacing them the wayinstall.commanddoes.Boundary rule, stated up front because this is the proposal most exposed to scope creep: expose only flags that are (a) meaningful across npm/yarn/pnpm, since all three are reachable via
devEngines.packageManager, and (b) about what gets installed or how it is fetched. Anything else keeps usinginstall.command.extraArgscovers the tail without turning this into an arbitrary passthrough surface.The creep matters in both directions: if this doesn't cover real use cases,
install.commandstays mandatory and hardening it stays unpalatable.Open question
Should
--omit=devbe the default for component installs? Shipping devDependencies to a deployed component is rarely intended, and it's what the deprecated operation already does. But it's a behavior change — a component that currently resolves a devDependency at runtime would start failing. Probably wants a minor version and a release note rather than a patch.Also worth deciding: whether these are operator-level (global config) or component-author-level (per-app
installblock), or both. The existinginstallblock is component-author-settable and already carriesallowInstallScripts, so there's a precedent for author control — but "what gets installed on my host" has an operator flavor too.Related: #1974 — note that any lifecycle option added here won't take effect for payload-deployed components until they're redeployed, since those never re-enter the install path.
🤖 Filed by Claude on behalf of @heskew