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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions