Originally created by: Akarsh-Hegde
The DMG install path (backend_install.rs) unconditionally staged and registered a separate com.meridiona.a11y-helper launchd agent on every packaged install/update — even though capture has been the default (and only shipped) feature since the Gap-2 Bucket 2 cutover.
That agent's whole job was poking AXManualAccessibility on Electron/Chromium apps so the old external screenpipe process could see their AX tree. Since the cutover, the in-process capture engine's screenpipe-a11y tree walker (tray/src-tauri/src/capture/screenpipe.rs) already does that same poke itself, under the tray's own Accessibility grant (confirmed in that module's own doc comment: "Running the frame grab + OCR + AX walk in this process is what yields the single 'Meridian' Screen-Recording / Accessibility TCC entries"). health.rs even already special-cases #[cfg(feature = "capture")] to skip the a11y-helper trust check for exactly this reason.
So the helper agent was pure dead weight — its only visible effect was a second, confusingly-named "meridian-a11y-helper" entry showing up in System Settings → Privacy & Security → Accessibility, alongside the real "Meridian" entry.
This is also consistent with an existing guard test (tests/tray_assets.rs::install_dev_skips_screenpipe_agents), whose comment already states "a11y capture is in-process inside the Tauri tray since v1.64.0" — install-dev.sh was already correctly skipping this; only the packaged DMG install path (backend_install.rs) had missed the memo.
tray/src-tauri/src/backend_install.rs: stop staging/registering the a11y-helper binary + launchd agent in install(). Added cleanup_legacy_a11y_helper() (mirroring the existing cleanup_legacy_screenpipe/cleanup_legacy_mlx_server pattern) that boots out any leftover agent from a prior install, removes its plist + staged binary, kills any live process, and best-effort tccutil resets its Accessibility grant so the stale entry doesn't linger grayed-out in System Settings after the binary is gone. Updated module docs and the bundled_templates_fully_substituted test accordingly.tray/src-tauri/tauri.conf.json: stop bundling meridian-a11y-helper + its plist into Meridian.app/Contents/Resources/backend/.tray/src-tauri/src/lib.rs: updated the ensure_backend_installed call-site comment.tray/src-tauri/src/backend_install.rs (review follow-up): added cleanup_legacy_a11y_helper_removes_stale_files, a regression test proving the leftover plist + staged binary get removed.Intentionally left scripts/a11y-helper/, scripts/install-a11y-helper-daemon.sh, and the npm/curl bundle path (scripts/install-from-bundle.sh) untouched — that install path still runs the external screenpipe process (see its pinned SCREENPIPE_VERSION), where the helper may still be load-bearing. This PR only retires it from the DMG/tray path ("the app"), which is the one built on capture by default and the one this was reported against.
cargo fmt --check (workspace + tray crate)cargo clippy -- -D warnings (workspace + tray crate)cargo test --lib backend_install — 4/4 pass, including the new cleanup_legacy_a11y_helper_removes_stale_files and the updated bundled_templates_fully_substitutedpre-push hook (fmt + clippy + UI build + UI tests + security audit + cargo test) — all greentauri.conf.json's bundle.resources ships only backend/meridian + backend/com.meridiona.daemon.plist — nothing exists for a fresh install to stage/register, so no "meridian-a11y-helper" entry can appearcleanup_legacy_a11y_helper_removes_stale_files proves the plist + staged binary are actually removed on an updatecom.meridiona.a11y-helper launchd agent + Accessibility grant, confirm an update boots out the agent and the entry disappears from System Settings → Privacy & Security → Accessibility (the launchctl/tccutil syscalls themselves aren't unit-testable — see PR comment)🤖 Generated with Claude Code
Originally posted by: coderabbitai[bot]
✨ Finishing Touches
🧪 Generate unit tests (beta)
- [ ] Create PR with unit tests - [ ] Commit unit tests in branch `fix/remove-a11y-helper-privacy-entry`Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
❤️ Share
- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai) - [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai) - [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai) - [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)Comment
@coderabbitai helpto get the list of available commands.Originally posted by: adityaharishch
Review
Overview: Retires the redundant
com.meridiona.a11y-helperlaunchd agent from the DMG (.app) install path, since the in-process capture engine (screenpipe-a11ytree walker) already does the sameAXManualAccessibilitypoke under the tray's own Accessibility grant. Stops staging/bundling the helper binary + plist, addscleanup_legacy_a11y_helper()to boot out any leftover install from a prior version, and updates docs/tests accordingly.Correctness
cleanup_legacy_a11y_helperfollows the exact same shape as the existingcleanup_legacy_screenpipe/cleanup_legacy_mlx_serversiblings (bootout → remove plist → remove binary → pkill), so it's consistent with established conventions.tccutil reset Accessibility com.meridiona.a11y-helpercall is correct:scripts/a11y-helper/build.shad-hoc signs the binary with--identifier com.meridiona.a11y-helper, which is exactly the identifier TCC keys grants to for un-bundled Mach-O binaries. So the reset call will actually clear the stale grant, not silently no-op.health.rs's a11y trust-check codepath is already#[cfg(not(feature = "capture"))]-gated, so no dangling reference to the retired agent survives under the default (capture-enabled) build.tauri.conf.jsonblocks) still references the helper outside the intentionally-untouched npm/bundle scripts underscripts/.scripts/a11y-helper/,install-a11y-helper-daemon.sh,install-from-bundle.shalone since that path still runs external screenpipe) is accurate and well-justified.Style / conventions
install(),AGENTS, test doc) — good adherence to the repo's "document as you go" convention..rsfile header (inherited, unchanged) and propertracing::info!on the one non-best-effort-swallowed success path.Minor observations (non-blocking)
cleanup_legacy_a11y_helperdirectly, but this matches the existing precedent — none of the sibling cleanup fns (cleanup_legacy_screenpipe,cleanup_legacy_mlx_server) have direct unit tests either (they'd need a mockedlaunchctl/filesystem), so this isn't a regression in coverage.Risk: Low. All changes are additive cleanup + removal of dead staging code; failure modes are best-effort/non-fatal by design (matches existing patterns), so a
launchctl/tccutilhiccup can't break tray startup.Looks good to merge once the manual verification steps are checked off.
Originally posted by: Akarsh-Hegde
Thanks for the review — addressed the one open item (automated test coverage was called out as a non-blocking gap).
Fix pushed (
fcf8c7c4): addedcleanup_legacy_a11y_helper_removes_stale_files, a#[tokio::test]that stages a fake leftover plist + binary under a temphomeand assertscleanup_legacy_a11y_helperremoves both.cargo fmt --check,cargo clippy -- -D warnings, andcargo test --lib backend_install(now 4/4) all pass, as does the full pre-push suite.On the two manual checklist items:
tauri.conf.json'sbundle.resourcesonly shipsbackend/meridian+backend/com.meridiona.daemon.plistnow (re-verified on this branch — nomeridian-a11y-helperbinary/plist is bundled), so there is nothing for a fresh.appinstall to stage or register in the first place.launchctl bootout/tccutil resetsyscalls actually clearing a live agent + TCC grant on a machine that has the old helper installed — is inherently a real-machine/GUI check (same category as PR [#425]'s manual items), since it needs an actual System Settings inspection to confirm visually. I don't have a way to drive that from here; recommend whoever tests this before merging do a quick smoke check (start from a machine/VM with the oldcom.meridiona.a11y-helperagent + grant present, run through an "update," confirm the entry disappears from System Settings → Privacy & Security → Accessibility).No other code changes were needed — the review didn't flag any correctness issues, and grepping the branch again confirms no other stray staging/bundling reference survives outside the intentionally-untouched npm/bundle scripts.
Related
Tickets:
#425Ticket changed by: Akarsh-Hegde