Skip to content

feat(mobile): agents on the phone can open apps and send intents with am - #50

Open
tebiggs wants to merge 2 commits into
mainfrom
claude/android-am
Open

tebiggs wants to merge 2 commits into
mainfrom
claude/android-am

Conversation

@tebiggs

@tebiggs tebiggs commented Nov 14, 2026

Copy link
Copy Markdown
Owner

Agents on the phone could open URLs and files but couldn't launch an app or send a broadcast, such as Tailscale's com.tailscale.ipn.CONNECT_VPN. There's no am or pm in the phone's Ubuntu.

This adds Android's own shell syntax to the bridge:

  • am start and am broadcast (also termux-am) with -a -d -t -c -n -p --es --ez --ei --el --ef and a last argument that's a URI, package/class or package. am start <package> opens the app as its launcher icon does.
  • pm list packages [-3 | -s] [filter], so agents can find a package name.
  • A new Other apps category in Settings > Agent access covers both, defaulting to Ask each time. The phone's approval dialog shows the whole intent.

Intents go out as T3 Code, with its permissions, so AppIntents.kt builds each one from am's flags instead of parsing it. That means no flags, URI grants, selector or Parcelable extras. It also refuses T3 Code's own package and file-provider URIs, sends call actions to termux-telephony-call instead (T3 Code holds CALL_PHONE), and requires broadcasts to name their app. Broadcasts with no declared receiver say so, which catches a wrong action name.

A <queries> entry for launcher activities makes apps with an icon visible. It avoids QUERY_ALL_PACKAGES, which Play restricts.

termux-open-url is unchanged: intent: URIs still aren't supported there, and am covers that case. The user doc's Agent access line also said approvals appear in the thread; it now says on the phone, as main already does.

Testing: bridge-script tests cover the argument parsing. The Kotlin module compiles. Emulator and phone checks are in comments below.

Done with Claude Opus 5.5 in Claude Code.

🤖 Generated with Claude Code

tebiggs and others added 2 commits November 14, 2026 18:04
Agents on the phone could open URLs and files but not launch an app or
send a broadcast, such as Tailscale's CONNECT_VPN.

Adds Android's am (start, broadcast; also termux-am) and pm list
packages to the bridge, behind a new "Other apps" category in Agent
access. The app builds each intent from am's flags, so it carries no
flags, URI grants, selector or Parcelable extras, can't target T3 Code
itself, and can't place calls outside the Phone category. Broadcasts
must name their app. A launcher-intent <queries> entry makes apps with
an icon visible without QUERY_ALL_PACKAGES.

Done with Claude Opus 5.5 in Claude Code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tebiggs

tebiggs commented Nov 14, 2026

Copy link
Copy Markdown
Owner Author

Emulator check (android-35 x86_64, debuggable release build of 11e2237, phone runtime installed and connected, stand-in Claude credentials). Every request below showed the phone's "Allow Other apps?" dialog with the request's JSON, then:

  • pm list packages -3 → package:com.t3tools.t3code.preview, package:com.tailscale.ipn (Tailscale from F-Droid, visible through the launcher query).
  • am start com.android.settings → Settings resumed on top.
  • am broadcast -a com.tailscale.ipn.CONNECT_VPN -n com.tailscale.ipn/.IPNReceiver → no warning; dumpsys activity broadcasts shows it DELIVERED to Tailscale's manifest receiver, caller T3 Code.
  • am broadcast -a com.tailscale.ipn.NOT_AN_ACTION -p com.tailscale.ipn → "Sent, but no app on this phone declares a receiver for it…"
  • Refused as designed: broadcast without -p/-n, -p T3 Code itself, ACTION_CALL, a content:// URI from T3 Code's file provider, a bad --ei value.
  • "Don't allow" → The user didn't allow am on the phone. Settings > Agent access > Other apps controls this.
  • Guest wrappers am, termux-am and pm are installed in /usr/local/bin.

Not covered: the off-screen notification path for am start (it reuses startOrNotify, unchanged), and a real Tailscale connect (the emulator's Tailscale isn't signed in).

This branch has not been deployed

No deployments
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.

1 participant