Skip to content

Add sender-side CLI / automation (URL scheme + launch args)#107

Open
kabirh wants to merge 1 commit into
swellweb:mainfrom
kabirh:feat/sender-cli-automation
Open

Add sender-side CLI / automation (URL scheme + launch args)#107
kabirh wants to merge 1 commit into
swellweb:mainfrom
kabirh:feat/sender-cli-automation

Conversation

@kabirh

@kabirh kabirh commented Jun 8, 2026

Copy link
Copy Markdown

Adds a focused, sender-side automation surface so TargetBridge can be driven without the GUI — for scripting, SSH, and connecting automatically on login or wake. (Following up on our discussion — thanks for the green light!)

Two equivalent entry points, both handled in the existing app entry point and dispatched to TBDisplaySenderService.shared — they call the same session.connect() / stop() the GUI uses, so there's no separate/parallel control
path
:

  • URL scheme: open "targetbridge://connect?receiver=auto&mode=mirror&preset=1440p" / open "targetbridge://disconnect"
  • Launch args: open -a TargetBridge --args --connect --receiver auto --preset 1440p (login item / LaunchAgent)

Options: receiver (auto | id | name | ip), mode (mirror | extended), preset, transport, session, local-ip. receiver=auto waits briefly for Bonjour and uses the first receiver; a raw IP/hostname bypasses discovery.

Also included:

  • cli/targetbridge — a thin shell wrapper over the URL scheme.
  • docs/Automation.md — CLI, URL scheme, launch-at-login, SSH (launchctl asuser … open), and wake recipes.

Scope

Kept deliberately small per your guidance — practical sender-side connect automation that builds on the current model. Natural follow-ups (out of scope here): richer queryable control (status / wait-for-stream) and a long-lived control
socket.

Notes for review

  • Registers the targetbridge scheme via a small base Info.plist merged with Xcode's generated one. The three INFOPLIST_KEY_* usage strings move into that file because Xcode drops them once INFOPLIST_FILE is set (verified the
    built plist retains the generated keys + the scheme).
  • project.pbxproj is regenerated (xcodegen) to pick up the new file + the INFOPLIST_FILE setting.
  • Built and tested on Xcode 26.5 / macOS 14; verified end-to-end that both entry points drive the existing connect() and bring up the capture display.

How to test

Build + run the app, then:
open "targetbridge://connect?receiver=auto&mode=mirror&preset=1440p" then open "targetbridge://disconnect".

🤖 Generated with Claude Code

Drive the Sender without the GUI — for scripting, SSH, and connecting
automatically on login or wake — reusing the existing sender/session model.

- targetbridge:// URL scheme and launch arguments (--connect/--disconnect),
  both handled in the existing app entry point and dispatched to
  TBDisplaySenderService.shared. They call the same session connect()/stop()
  the GUI uses — no separate/parallel control path.
- Options: receiver (auto|id|name|ip), mode (mirror|extended), preset,
  transport, session, local-ip.
- cli/targetbridge: thin shell wrapper over the URL scheme.
- docs/Automation.md: CLI, URL scheme, launch-at-login, SSH, and wake recipes.

The scheme is registered via a small base Info.plist merged with Xcode's
generated one; the three INFOPLIST_KEY_* usage strings move into that file
because Xcode drops them once INFOPLIST_FILE is set.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@swellweb

swellweb commented Jun 9, 2026

Copy link
Copy Markdown
Owner

I pushed a small maintainer-side follow-up onto this PR branch to tighten two review points before merge:\n\n- invalid \ values now fail explicitly instead of silently falling back to session 1 or disconnecting everything\n- the automation connect path now refreshes local interfaces / discovery state before resolving \ and picking the local interface, which should make login/wake/SSH-driven flows more reliable\n\nI also rebuilt the Sender after the change to make sure the branch still compiles cleanly.\n\nThanks again — the overall direction here is still very good.

@swellweb

swellweb commented Jun 9, 2026

Copy link
Copy Markdown
Owner

Small follow-up: I also pushed a maintainer-side fix on top of this PR branch to tighten two review points before merge:

  • invalid --session values now fail explicitly instead of silently falling back to session 1 or disconnecting everything
  • the automation connect path now refreshes local interfaces / discovery state before resolving receiver=auto and picking the local interface, which should make login/wake/SSH-driven flows more reliable

I rebuilt the Sender after the change as well, so the branch still compiles cleanly.

Thanks again — the overall direction here is still very good.

@swellweb

swellweb commented Jun 9, 2026

Copy link
Copy Markdown
Owner

We’re currently testing this PR on our side as well.

I’m also making a few small maintainer-side adjustments to better align it with the current TargetBridge project structure and behavior, while keeping the overall scope the same.

So if you notice a couple of follow-up commits on this branch, that’s just us tightening the integration and validating it before merge.

@kabirh

kabirh commented Jun 9, 2026

Copy link
Copy Markdown
Author

Please feel free to edit, discard or integrate it as you see fit. I'm just happy to see this functionality make it in the main project and hope it expands the audience.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants