Skip to content

postinstall.mjs uses unscoped package name that no longer exists #53

@byapparov

Description

@byapparov

Problem

packages/cli/script/postinstall.mjs:52 resolves the platform binary package under an unscoped name:

const packageName = `aictrl-${platform}-${arch}`
// ...
const packageJsonPath = require.resolve(`${packageName}/package.json`)

But every platform binary we publish is scoped: @aictrl/cli-linux-x64, @aictrl/cli-darwin-arm64, etc. The unscoped name aictrl-linux-x64 has never existed on npm (confirmed: npm view aictrl-linux-x64 → 404).

require.resolve('aictrl-linux-x64/package.json') always throws MODULE_NOT_FOUND, which is caught by the try/catch and propagated, and then the top-level main() catches it, logs "Failed to setup aictrl binary:", and calls process.exit(0) (line 128-131) — so it silently no-ops on every install.

Why it hasn't broken anything user-visible

The real binary resolution happens in packages/cli/bin/aictrl, which uses the correct scoped name ("@aictrl/cli-" + platform + "-" + arch) and walks the node_modules tree to find it. postinstall.mjs was apparently meant as a performance optimization (symlink/hardlink the platform binary to bin/.aictrl at install time so bin/aictrl can short-circuit) but it has been no-opping for at least as long as the scoped package names have existed.

Evidence it's dead

Options

Option 1: Fix the scoped name

-const packageName = `aictrl-${platform}-${arch}`
+const packageName = `@aictrl/cli-${platform}-${arch}`

This makes postinstall.mjs actually do something: hardlink/symlink node_modules/@aictrl/cli-linux-x64/bin/aictrl into packages/cli/bin/.aictrl so bin/aictrl finds it immediately via its cached check (line 29-32) instead of walking node_modules.

Risk: postinstall.mjs becomes load-bearing after being silent forever. If the fix-up writes to an unexpected location, or if the script has latent bugs that only surface when it actually runs, we could break npm install @aictrl/cli on a fresh machine for the first time. The linking logic also tries multiple strategies (hardlink fallback to copy) so there are multiple paths to verify.

Option 2: Delete postinstall.mjs entirely

bin/aictrl already does full platform detection (including avx2, baseline, musl variants — see lines 34-149) and walks node_modules looking for any matching platform binary. It works today without any postinstall hook. The only thing we lose is the startup-path short-circuit via the .aictrl cache file, which is probably negligible.

Both options remove the same confusion. Option 2 is the minimum-risk path — delete dead code, don't resurrect it. Option 1 is only worth it if someone has evidence the startup short-circuit measurably matters (e.g. profiling showing the node_modules walk is slow on large trees).

Recommend Option 2 unless someone has benchmark data.

Related observations

  • The workflow publishes postinstall.mjs inside the @aictrl/cli tarball (via scripts.postinstall written by script/publish.ts:31), so if we delete the file we also need to remove the "postinstall" script entry from the published package.json
  • Note: script/publish.ts itself appears to be dead code (writes a package named @aictrl/cli-ai, not invoked by any workflow). See the separate issue tracking that.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions