Desktop dev builds: empty sidecar stubs shadow real binaries, so agent sign-in fails as "Sign-in unavailable"
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
**Describe the bug**
On a source build, agent sign-in is impossible: the onboarding runtime card shows **"Sign-in unavailable"**. The label points at the auth provider, but the cause is local — the desktop cannot execute its own `buzz-acp` helper.
`just dev` depends on `_ensure-sidecar-stubs` (`Justfile:153`), which `touch`es five empty placeholder files so the Tauri build doesn't fail on missing sidecars:
```
buzz-acp buzz-agent buzz-dev-mcp git-credential-nostr buzz
```
The helper is then resolved in `desktop/src-tauri/src/commands/agent_auth.rs:122`:
```rust
let acp_path = std::env::current_exe()
.map(|path| path.with_file_name(format!("buzz-acp{}", std::env::consts::EXE_SUFFIX)))
.ok()
.filter(|path| path.exists()) // existence only — not executability
.or_else(|| resolve_command("buzz-acp"))
.ok_or_else(|| "buzz-acp helper not found".to_string())?;
```
The 0-byte stub lands next to `buzz-desktop` in `desktop/src-tauri/target/debug/`, so it satisfies `path.exists()` and the `or_else` fallback that would have found the real binary never runs. The real binaries build into the **workspace** target (`target/debug/`), a different directory, so the two never meet.
Executing the stub returns `permission denied` (mode `-rw-r--r--`, 0 bytes), `discover_acp_auth_methods` returns `Err`, and `SetupStep.tsx:189` renders `label="Sign-in unavailable"` — which is the *"couldn't load sign-in options"* branch, distinct from the `"Sign-in failed"` branch for an actual auth failure. The message therefore misattributes a local exec failure to the provider.
All five stubs are affected, so the same shadowing should also break the agent runtime, dev MCP tools, git credential signing, and the bundled CLI.
**Steps to reproduce**
1. Clone, then `. ./bin/activate-hermit && just setup && just dev`
2. In onboarding, find a runtime whose availability is `available` and auth status `logged_out` (reproduced with `claude-agent-acp`)
3. Click **SIGN IN**
4. The card shows **"Sign-in unavailable"**
Reproduce without the UI:
```bash
# what the app runs — 0-byte stub
./desktop/src-tauri/target/debug/buzz-acp auth-methods --json
# -> permission denied
# the real binary, same args
BUZZ_ACP_AGENT_COMMAND=$(command -v claude-agent-acp) \
./target/debug/buzz-acp auth-methods --json
# -> {"methods":[{"id":"claude-ai-login",...},{"id":"console-login",...}]}
```
**Expected behavior**
The desktop should locate a working `buzz-acp`. Either:
- gate the adjacent-path candidate on executability and non-emptiness rather than `path.exists()`, so the `resolve_command` fallback engages; and/or
- have `_ensure-sidecar-stubs` write a non-executable name that cannot be mistaken for a real sidecar, or skip stubbing when a real build exists.
Separately, "Sign-in unavailable" is worth rewording. A failure to spawn a local helper reads as a provider outage, which sent this debugging session to the wrong place first.
**Version and platform**
- Buzz version: source build at `485d03a35` (workspace `0.1.0`, desktop `0.5.0`)
- OS: macOS 15 (Darwin 25.5.0), Apple Silicon (aarch64-apple-darwin)
- Adapter: `@agentclientprotocol/claude-agent-acp` 0.63.0
**Logs / additional context**
Stub as built by `just dev`:
```
-rw-r--r-- 0 desktop/src-tauri/target/debug/buzz-acp
-rwxr-xr-x 40259608 target/debug/buzz-acp
```
Workaround — fill both the stub source and the resolved path:
```bash
TARGET=aarch64-apple-darwin
for b in buzz-acp buzz-agent buzz-dev-mcp git-credential-nostr buzz; do
cp -f "target/debug/$b" "desktop/src-tauri/binaries/${b}-${TARGET}"
cp -f "target/debug/$b" "desktop/src-tauri/target/debug/$b"
chmod +x "desktop/src-tauri/binaries/${b}-${TARGET}" "desktop/src-tauri/target/debug/$b"
done
```
`binaries/` is gitignored and `_ensure-sidecar-stubs` uses `touch` (which does not truncate), so filled binaries survive later `just dev` runs. The workaround does carry a staleness footgun: after a later `git pull` + rebuild, `target/debug/` updates while the two copies do not, and the adjacent copy still wins — so the app would silently run stale sidecars. That is an argument for fixing the resolution order rather than the stubs.
Contributor guide
Assessment
This issue has not been assessed yet.