Closed general

install.sh links the PATH binary into the workspace: clearing adom_modules silently stops the relay unit instead of reporting a missing CLI

John Lauer · 2mo ago ·closed by John Lauer

What happens

install.sh puts the PATH entries for adom-bridge and adom-bridge-cli on the package payload rather than installing the binary:

adom-bridge      -> /home/adom/project/adom_modules/adom/adom-bridge/dist/linux/adom-bridge
adom-bridge-cli  -> /home/adom/project/adom_modules/adom/adom-bridge/dist/linux/adom-bridge

That is a binary on PATH pointing into the user's workspace root. Every other Adom CLI installs a real file. Measured in a converged container today, ~/.local/bin holds ten of them as actual binaries:

adom-wiki 14.2 MB, adom-chipsmith 10.1 MB, adom-tts 5.5 MB, adom-parts-search 4.7 MB,
adom-chip-thumbnailer 4.0 MB, adom-footprint 3.6 MB, adom-digikey 3.4 MB, adom-usb 3.3 MB,
adom-ds2sf 3.2 MB, adom-shotlog 2.8 MB

adom-bridge is the only compiled CLI in the tree that links to its payload instead.

Why it matters more here than it would anywhere else

Hydrogen's golden image bakes a systemd unit that targets that exact path:

ConditionPathExists=/home/adom/.local/bin/adom-bridge
ExecStart=/home/adom/.local/bin/adom-bridge serve

So when adom_modules is cleared (a reinstall, a workspace re-import, a user tidying their project tree), the symlink dangles and two things happen, neither of them loud:

  1. ConditionPathExists resolves through the link, finds nothing, and the unit is skipped rather than failed. systemctl status reports it as inactive with a condition failure, not as broken.
  2. Anything that does reach ExecStart gets exit 203/EXEC on a dangling link.

The result is a container whose relay silently stops waking, so the user's laptop cannot reach it, and the CLI reports itself as a broken link rather than as a package that is simply not installed. A missing package should look missing.

This is the same class of failure as v2.0.17, where a 2.0.16 install that exposed only adom-bridge left adom-relay.service crash-looping on exit 127. That one was loud. This one is quiet, which is worse.

The fix

Install the binary into ~/.local/bin in install.sh, the way the other ten do, rather than linking to the payload. uninstall.sh removes it, so uninstall stays correct and nothing is orphaned.

Two things to preserve:

  • Both names, still. adom-bridge-cli is load-bearing, not an alias: the baked adom-relay.service execs it, and the v2.0.17 comment in install.sh already says to keep both forever. Two real files, or one real file and one symlink beside it in the same directory, either is fine since neither crosses out of ~/.local/bin.
  • The link_or_copy fallback. It exists for filesystems that refuse symlinks, and a copy-based install makes that path the normal one rather than the exception.

The cost is about 9 MB duplicated between the payload and ~/.local/bin. That is the same trade adom-wiki already makes at 14 MB, so the precedent is set and the ecosystem has accepted it.

The skill-bundle symlinks into ~/.claude/skills/ are a separate question and I am not asking for those to change: a dangling skill link degrades to a skill that does not load, not to a daemon that stops waking.

Where this was found

Auditing what the Hydrogen v25-full golden image puts on PATH, and writing down why each of the four symlinks in ~/.local/bin is shaped the way it is. The other three are correct: shotlog -> adom-shotlog is the installer's own shape, and claude pointing at a versioned directory is how its self-update swings the pointer without touching PATH.

1 Reply

John Lauer · 2mo ago

Fixed - your diagnosis was right and the fix landed in 2.0.17, prompted by a failure that matches yours exactly.

Current wiki-pkg/install.sh:

install_bin() {                       # <src> <dest>
  mkdir -p "$(dirname "$2")"
  rm -rf "$2" 2>/dev/null || true
  cp -f "$1" "$2" && chmod +x "$2"    # a REAL FILE, not a link into the payload
}
install_bin "$CLI" "$HOME/.local/bin/adom-bridge"

So adom-bridge is now a real binary in ~/.local/bin, like every other Adom CLI. Clearing adom_modules no longer dangles it.

adom-bridge-cli is kept - it is load-bearing, not an alias: Hydrogen's baked adom-relay.service execs that exact name, and a 2.0.16 install that exposed only adom-bridge left the service crash-looping exit 127 with the relay dead. That is the same class of failure you reported, from the other direction. It is now a relative symlink created beside the real file (cd ~/.local/bin && ln -sfn adom-bridge adom-bridge-cli), so it resolves within ~/.local/bin and never points into the workspace, with a full copy as fallback where symlinks are refused.

Your framing was the useful part: a binary on PATH pointing into the user's workspace root is a landmine, because the workspace is a thing users are told they may clear.

The "silently stops the relay unit instead of reporting a missing CLI" half is worth keeping in mind separately - a dangling exec still surfaces as a systemd exit 127 rather than something that names the missing file. That is the service unit's error surface rather than install.sh's, and it is no longer reachable by this path, so I am closing here. If you see a relay unit fail with an unhelpful error from some other cause, that is worth its own issue.

John Lauer closed this · 2mo ago

Log in to reply.