HarperFast / HarperFast/harper

First-class install flags so install.command isn't the only lever

Open
#1,979 0 comments 0 reactions 0 assignees View on GitHub
area:components enhancement
Dominant language
JavaScript
Stars
89
Forks
10
Avg merge
2d 6h
Merged PRs (30d)
200

Description

## 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`):

```js
const args = ['install', '--force', '--omit=dev', '--json'];
```

…while the actual deploy path (`components/Application.ts:424`) does not:

```js
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

Contributor guide

Open the contributing guide

Research direction

Start by reading components/Application.ts around the install argument construction and utility/npmUtilities.ts for the deprecated flags. Trace the existing install block and package-manager resolution, then determine the option shape, scope, and compatibility behavior before implementation. Done means the proposal is settled and structured flags compose with existing install behavior without requiring install.command.

Written by the indexing model from the issue text.

Assessment

Tech stack
nodejs
Domain
backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.