fix(opencode): put altimate-dbt on PATH after npm install, with or without postinstall

Closed
EK
1d ago
+300-0

Issue for this PR

Closes #982

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

After npm install -g altimate-code, altimate-dbt often isn't available. The agent then falls back to plain dbt and loses the manifest-aware tools (schema-verify, lineage, execute).

There are two causes:

  1. script/publish.ts only declares altimate and altimate-code as bin entries. altimate-dbt only reaches the package's bin/ through postinstall.mjs, so it's missing whenever install scripts don't run: --ignore-scripts, pnpm/bun script allow-lists, or locked-down CI.
  2. The app only adds that folder to PATH inside the bash tool (ALTIMATE_BIN_DIR). The dbt-schema-verify validator spawns altimate-dbt with the app's own PATH, so it couldn't find it even when postinstall did run.

The fix:

  • script/publish.ts: declare "altimate-dbt": "./dbt-tools/bin/altimate-dbt" in both generated bin maps. Package managers link bin entries without running scripts, and npm creates the Windows .cmd/.ps1 shims.
  • bin/altimate and bin/altimate-code: prepend the package bin/ to the app's PATH. Also prepend ../dbt-tools/bin when postinstall didn't link altimate-dbt. Everything the app spawns inherits this, including the validators. It uses path.delimiter, finds the PATH key case-insensitively (Path on Windows), and doesn't add duplicate entries.

postinstall.mjs and tool/bash.ts are unchanged.

How did you verify your code works?

  • New tests. test/install/dbt-tools-on-path.test.ts checks the publish bin entries. It also runs an end-to-end npm pack and npm install -g --ignore-scripts, then runs altimate-dbt doctor from PATH. That test has a control without the fix, and a postinstall that exits 1 to prove scripts never ran. test/install/bin-wrapper.test.ts covers both launchers: the fallback, the postinstall-linked case, and no duplicate PATH entries. Without the fix, the publish test and 4 launcher tests fail.
  • bun test test/install/ test/tool/bash.test.ts test/altimate/validators/: 1,091 pass, 0 fail. tsgo --noEmit is clean.
  • Manual, macOS (Apple silicon), v0.12.10, clean shell with nothing extra on PATH, both installed with npm install -g --prefix <dir> --ignore-scripts:
    • stock: bin/ has only altimate and altimate-code. In Builder mode, the agent's which altimate-dbt gives altimate-dbt not found.
    • patched: bin/ also has altimate-dbt, and altimate-dbt doctor passes in a dbt + DuckDB project. In Builder mode, the agent's which altimate-dbt resolves to .../altimate-code/dbt-tools/bin/altimate-dbt through the launcher fallback.
  • Windows: not run on a Windows machine. I checked npm's generated cmd-shim output for the new bin: the .cmd and .ps1 shims both run node <path>/dbt-tools/bin/altimate-dbt. The dbt-tools/bin fallback has no .cmd, so on Windows the bin entry is the fix.

Cost side effects

None. It changes package metadata and PATH setup at launch, and adds no model calls, queries or cloud resources.

Screenshots / recordings

N/A (not a UI change).

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR
  • I checked for cost side effects (model calls, queries or cloud resources that grow with user data) and described them, or wrote "none"

Out of scope: the standalone installers (install, install.ps1) don't appear to ship altimate-dbt at all, which may be worth a separate look.

I diagnosed and patched this with help from Claude, and verified the behavior myself as described above.


Summary by cubic

Makes altimate-dbt available after npm install -g altimate-code, with or without lifecycle scripts, and on the PATH for everything the app spawns.

Previously altimate-dbt only reached the package's bin/ through postinstall.mjs, so it was missing when install scripts were skipped (--ignore-scripts, pnpm/bun allow-lists, locked-down CI), and the dbt-schema-verify validator spawned altimate-dbt with the app's own PATH, which never included it. The agent then silently fell back to plain dbt, losing schema-verify, lineage, and execute. Now the published package.json declares altimate-dbt as a bin (so package managers link it without running scripts), and both launchers put the package bin/ and the bundled dbt-tools/bin fallback at the front of the app's PATH, ahead of any existing entry, case-insensitively and without duplicates.

Bug Fixes

  • Declares altimate-dbt as a bin in both generated package.json files in script/publish.ts; npm also creates the Windows .cmd/.ps1 shims. If another package already owns a global altimate-dbt, npm stops with EEXIST; remove or rename that shim or install with --force.
  • Puts the packaged tool dirs on PATH in bin/altimate and bin/altimate-code so validators and the agent inherit them, falling back to dbt-tools/bin when postinstall didn't link altimate-dbt. The dirs are moved ahead of the existing PATH, so an older altimate-dbt can't shadow the bundled one.
  • Adds tests for the pack + global install with --ignore-scripts flow and the launcher PATH handling for both wrappers; npm calls are time-bounded so a stalled registry fails instead of hanging CI, and the launcher extends a mixed-case Path key rather than adding a second PATH.

Summary by CodeRabbit

  • New Features
    • The altimate-dbt command is now available from both package variants, including after a global installation that skips install scripts.
  • Bug Fixes
    • The app can locate the bundled altimate-dbt executable when a post-install link is unavailable. The launcher prioritizes the relevant tool directories, avoids duplicate entries, and preserves existing PATH settings.