For agents, on top of README.md, which they read first.

  • launch.sh must never build, wait, or enter nix develop. Its whole job is to answer inside the client's 30 s startup timeout on an empty buck-out. Anything slow goes in install.sh.
  • Nothing but JSON-RPC on launch.sh's stdout. Diagnostics go to stderr; the one stdout line it may write itself is the error reply to initialize. Same rule as the proxy's (../../apps/native/CLAUDE.md).
  • run/bin/native is a copy, not a symlink into buck-out, on purpose - see the comment in install.sh. Do not "simplify" it into a symlink.
  • Test a change with tools/mcp/test.sh: scripted stdio, timed, in a bare environment (env -i PATH=/usr/bin:/bin, all a profile-less NixOS process gets), with and without a binary, against a scratch copy of the layout so the real run/bin is never moved.
  • launch.sh uses bash builtins only. In that bare environment dirname, sed and jq do not exist; a dirname there made the repo root "" and the launcher looked for //run/bin/native (2026-09-21).
  • Keep both scripts shellcheck-clean: nix develop -c shellcheck tools/mcp/*.sh.