Skip to content

Compiled binary not self-contained: reads package.json + theme/* from binary's own dir at startup #5108

@william-jin-cmu

Description

@william-jin-cmu

What happened?

The Bun-compiled pi binary opens several files relative to its executable's parent directory at startup, instead of resolving them from the embedded $bunfs or via import.meta.dir. When the binary is shipped without its surrounding tree (e.g. as a Tauri sidecar, or any single-file distribution), startup fails.

Concrete files we hit, in order:

  1. <bindir>/package.json
    • init_config does JSON.parse(readFileSync(getPackageJsonPath(), "utf-8"))
  2. <bindir>/theme/dark.json, <bindir>/theme/light.json
    • getBuiltinThemes()themesDir = getThemesDir() resolves to <bindir>/theme/
  3. Likely more we didn't reach (presumably assets/, extension scaffolding, etc.)
ENOENT: no such file or directory, open '/.../pi-install/package.json'
  at <anonymous> (/$bunfs/root/pi:961:32)

ENOENT: no such file or directory, open '/.../pi-install/theme/dark.json'
  at getBuiltinThemes (/$bunfs/root/pi:202327:40)
  at loadThemeJson  (/$bunfs/root/pi:202429:41)
  at loadTheme      (/$bunfs/root/pi:202484:34)
  at initTheme      (/$bunfs/root/pi:202558:29)
  at main           (/$bunfs/root/pi:288472:12)

Context

Integrating @earendil-works/pi-coding-agent as a Tauri sidecar for a desktop chat UI. Build:

npm view @earendil-works/pi-coding-agent dist.tarball | xargs curl -L | tar xz
cd package && bun install && bun build --compile ./dist/bun/cli.js --outfile pi

If we ship just pi next to a .app and spawn it from anywhere, it crashes on the reads above. The workaround is to also ship the entire package/ tree (theme/, dist/, node_modules/, package.json) alongside the binary and spawn pi from that directory — ~260 MB instead of ~70 MB.

Related

Expected behavior

The compiled binary should be runnable from any cwd with no sibling files on disk. Bun supports this via Bun.embeddedFiles / import.meta.dir referring to /$bunfs/root/.... Specifically:

  • getPackageJsonPath() should return an embedded asset, or version metadata should be a compile-time constant.
  • getThemesDir() should resolve to the embedded theme dir, or themes should be inlined as imported JSON modules.

If embedding is undesirable, document the required sibling layout (package.json + theme/ + assets/ at minimum) so integrators can ship a deterministic tree.

Steps to reproduce

mkdir /tmp/pi-test && cd /tmp/pi-test
TARBALL=$(npm view @earendil-works/pi-coding-agent dist.tarball)
curl -fsSL "$TARBALL" | tar xz
cd package && bun install --silent
bun build --compile ./dist/bun/cli.js --outfile /tmp/pi-test/pi
cd /tmp                                  # leave the install tree
/tmp/pi-test/pi --mode rpc               # ENOENT on package.json

Version

Latest published @earendil-works/pi-coding-agent as of 2026-05-28; Bun 1.3.8 on macOS arm64. Same behavior reproducible on Linux per the issue trail above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    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