feat(probe): import the desktop probe core into crates/probe (phase 1)
Summary
Phase 1 of moving the Agent Relay desktop probe core into relay. The probe is the native Rust daemon that discovers running agent sessions (Claude Code, Codex, Devin, OpenCode, Grok, Pi, …) and injects Relay messages into them through each harness's native route. With it in relay, the CLI (relay init) can install and run it headless, without the desktop GUI. relay 15.0.0 is held until injection works through the probe.
- Clean snapshot of relay-desktop
origin/main(5601b739)probe/→crates/probe/. No relay-desktop history comes along: that history has scrubbed internal docs and an old PostHog key. - Separate Cargo workspace with its own
Cargo.lock. It does not join the root workspace yet, becauserelaycast10 vs 9,nix=0.25.1 vs 0.30 andportable-pty=0.8.1 vs 0.8 conflict with the broker. Rootcargocommands and the broker CI don't see it. - Only the core moves. The macOS, GTK (Linux and Windows) and iPad apps stay in relay-desktop. This PR changes nothing in relay-desktop;
docs/probe-move.mdlists what it must change to consume the core.
What was excluded, and the GTK split
Excluded (stays in relay-desktop):
src/linux_app/: the GTK app, about 41k lines.- The
gtkfeature. - The
agent-relay(GUI launcher) andagent-relay-fake-corebinaries. - The tests
linux_app_gtk(and its directory),linux_app_hosting,linux_app_core_e2eandlinux_package. resources/linuxandresources/windows.- The GUI-only dependencies
gtk4,ksni,tray-icon,tauri-winrt-notification,zipandtar. Removing them pruned 107 packages fromCargo.lock, and nothing was added or upgraded.
Only three places in the core used linux_app, and none of them needed GTK:
| Core file | Used | Resolution |
|---|---|---|
relay/login_item.rs | linux_app::install (packaged-app paths; Windows registry helpers) | Moved to crate::install |
relay/session_query.rs | LocalSessionQuery, LocalSessionRow, StatusView, SessionUploadState | Moved the six modules in their closure to crate::session_model |
relay/uploader/query.rs | StatusView | Same as above |
The six modules in crate::session_model are agent_kind, agent_names, local_sessions, session_project, session_query and uploads. They are unchanged apart from paths, and their unit tests came with them. The shared/session-*.json vectors are now in tests/fixtures/shared/.
No core test depended on GTK. The tests left out all test the app; linux_app_core_e2e drives a real core, but through the app's bridge client.
Other changes
-
Version stamping.
build.rsno longer reads relay-desktop'sCHANGELOG.md.AGENT_RELAY_PROBE_VERSIONis stamped exactly, as release builds already pass it.- Development builds are
<base>-dev+<rev>. The base isAGENT_RELAY_PROBE_BASE_VERSION, which relay-desktop sets to its CalVer, or else the crate version.
-
Contract.
relay-contract-codegendefaults to the checked-incrates/probe/contract/CoreContract.swift. It also takes--out FILEand--app-root DIR; the second writes relay-desktop's macOS path. The generated output is byte-identical to relay-desktop's currentCoreContract.swiftexcept the two header lines that name the regenerate script and source path. -
Docs.
crates/probe/docs/relay-core.md(the contract test checks its tables) andcrates/probe/docs/agent-relay-probe.mdwere imported.- Links to relay-desktop docs that were not imported are now plain-text references.
crates/probe/README.mdis new, and so is the design notedocs/probe-move.md(what moved, what stayed, the GTK split, phases 2–5, and the relay-desktop changes).
-
Open-source hygiene.
crates/probe/LICENSE(Apache-2.0, the same as relay); the crate already declareslicense = "Apache-2.0".crates/probe/scripts/check-open-source.shports relay-desktop's check and adds credential patterns. It also flags Relaycastrk_/at_/nt_values that are not obvious fixtures, and prints only file:line.- Neutralised fixture strings:
github.com/AgentWorkforce/relay-desktopremote URLs (relay-desktop is private) becameacme/..., and personal handles becameada-lovelace/sam-codex. - GitHub push protection read four long
rk_live_/rk_test_fixtures inworkspace_recovery_tests.rs(repeated or sequential characters, not real keys) as Stripe restricted keys. They are now built withconcat!instead of being allowlisted.
-
CI.
.github/workflows/probe-ci.ymlruns only for changes undercrates/probe/**(and its own file). It runs:- Linux x64 build and test, with an empty
HOME; - macOS arm64 build and test;
- Windows x64 build (MSVC);
- the contract-drift check;
- the public-source check.
Actions are pinned to the SHAs relay already uses. PR runs cancel superseded runs, and other runs get a per-SHA group (the #2010 pattern).
- Linux x64 build and test, with an empty
No CHANGELOG entry: this is internal and not user-visible yet.
Test plan
-
cargo build --locked(Linux x64). -
cargo test --locked(Linux x64, emptyHOME, clean env): about 3,380 passed and 19 ignored. One timing test,live::selected_remote::tests::selected_claude_worker_refreshes_shallow_catalog_and_selected_evidence(an 8 seventuallydeadline in code this PR does not touch), is flaky: it failed in 1 of 2 runs of the binary's tests and passes on its own.cloud::tests::cloud_bearer_reuses_only_a_matching_unexpired_official_cli_sessionfails only when the caller's environment has Agent Relay or Claude variables set, and passes underenv -iwith a tempHOME. Alive_capturestop-timing test failed once under a loaded first run and passed on the clean rerun. -
scripts/generate-contract.shregeneratescontract/CoreContract.swiftwith no diff. -
scripts/check-open-source.shpasses, and a staged canary key, private link and home path were all flagged. - probe-ci on macOS arm64 and Windows x64 (first runs on this PR).
Blockers and notes for phase 2
src/relay/workspace.rsresolves the Relaycast workspace only from the Cloud sign-in. Phase 2 must follow the CLI ladder: env key → projectworkspace-key.json→~/.agentworkforce/relay/workspaces.json, plus therelaycast-origins.jsonorigin bindings. The core already locates the CLI home (workspace::relay_home) but only reads it.- Not ported from relay-desktop CI yet:
rust-oleum(the config is pruned of GUI entries), the glibc floor, and the arm64 Linux, x64 macOS and arm64 Windows lanes. rustfmt --checkreports drift in about 80 upstream files. They were left verbatim to keep the snapshot faithful, so CI does not gate on fmt.
🤖 Generated with Claude Code
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Agent Relay sessions