Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9ad339d
feat(claude): add desktop manifest and packaging workflow
grabbou Oct 23, 2026
c0058c8
fix(claude): ask for ambiguous devices in chat
grabbou Oct 23, 2026
fb9f259
fix(claude): disable codex updater and polling
grabbou Oct 23, 2026
45535fe
feat(ui): support fullscreen in claude desktop
grabbou Oct 23, 2026
b41f98b
fix(ui): gate openai chat routing by host capability
grabbou Oct 23, 2026
a3ce405
feat(ui): support standard mcp context attachments
grabbou Oct 23, 2026
92babc3
fix(ui): use host theme tokens without openai styles
grabbou Oct 23, 2026
aa487ad
fix(ui): respect structured context capability
grabbou Oct 23, 2026
9f142b8
fix(ui): report usable inline workspace height
grabbou Oct 23, 2026
fcc0438
fix(logs): expose session handles to mcp models
grabbou Oct 23, 2026
9cfac3a
fix(ui): declare clipboard permission for mcp hosts
grabbou Oct 23, 2026
b50c45b
test(claude): verify packaged host compatibility
grabbou Oct 23, 2026
e243493
chore(claude): merge latest main and preserve host compatibility
grabbou Oct 23, 2026
5f7c3d7
docs(claude): document manual installation and local development
grabbou Oct 23, 2026
6495896
fix(claude): keep annotation context behind readable chat drafts
grabbou Oct 23, 2026
1c73cbe
feat(claude): manage annotation drafts in the attachment bar
grabbou Oct 23, 2026
3325582
fix(claude): direct annotation requests to widget context
grabbou Oct 23, 2026
ce7eef6
fix(claude): identify the widget for native context reads
grabbou Oct 23, 2026
4026b99
fix(claude): include selection locators in annotation drafts
grabbou Oct 23, 2026
322210d
fix(ui): apply standard MCP host style tokens and fonts in every host
grabbou Oct 23, 2026
e768b95
refactor(claude): replace host flag with capability checks
grabbou Oct 23, 2026
3d0714d
feat(claude): package mobile dev as a claude plugin
grabbou Oct 23, 2026
5766f33
docs(skills): drop host-specific node runtime notes
grabbou Oct 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "mobile-dev",
"displayName": "Mobile Dev",
"version": "0.1.164",
"description": "Stream iOS and Android devices into the chat while building, running, or debugging mobile apps. Read native and Metro logs, inspect and control apps, and record CPU, memory, and FPS. Apple Silicon development preview.",
"author": {
"name": "Callstack",
"email": "hello@callstack.com"
},
"homepage": "https://github.com/callstackincubator/codex-mobile-dev-plugin",
"repository": "https://github.com/callstackincubator/codex-mobile-dev-plugin",
"license": "MIT",
"keywords": ["ios", "android", "simulator", "emulator", "react-native", "expo", "logs", "performance"],
"icon": "./assets/icon.svg",
"documentationUrl": "https://github.com/callstackincubator/codex-mobile-dev-plugin#readme",
"supportUrl": "https://github.com/callstackincubator/codex-mobile-dev-plugin/blob/main/SUPPORT.md",
"privacyPolicyUrl": "https://github.com/callstackincubator/codex-mobile-dev-plugin/blob/main/PRIVACY.md",
"termsOfServiceUrl": "https://github.com/callstackincubator/codex-mobile-dev-plugin/blob/main/TERMS.md",
"mcpServers": {
"mobile-dev": {
"command": "node",
"args": ["${CLAUDE_PLUGIN_ROOT}/dist/server.mjs"]
}
}
}
48 changes: 47 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ not included in the plugin package.

## Install the local build

### Codex

From this project directory, after packaging:

```sh
Expand All @@ -104,9 +106,53 @@ Open a new chat after installing, then open Mobile Dev from the sidebar.

`npm run package` writes the local ZIP to `release/mobile-dev-<version>-darwin-arm64.zip`. Install through the local marketplace above. The New Plugin archive dialog uploads to the workspace plugin service; it is a separate install route. This package has not gone through public directory review or publication.

### Claude Desktop local development

Complete the first-time runtime and native-helper setup under [Build and package](#build-and-package),
then run from this checkout with Node.js 22.19 or later:

```sh
npm run build
npm run claude:config
```

1. Open Claude Desktop **Settings > Developer > Edit Config**. On macOS, this is
`~/Library/Application Support/Claude/claude_desktop_config.json`.
2. Merge the `mobile-dev` entry from `.local-dev/claude-desktop-config.json` into
the existing `mcpServers` object, preserving other servers and settings. The
snippet uses absolute paths to this checkout and the Node executable running
the generator.
3. Fully quit and reopen Claude, start a new conversation, and ask **“Open Mobile Dev.”**
Approve the connector when prompted; use **Expand** when available.

After UI or server edits, run `npm run build` and fully restart Claude. This
workflow uses the checkout directly and needs no repackaging. Regenerate the
config if the checkout or Node path changes. For connection failures, check
**Settings > Developer** for the server status and logs.

To create and check a bundle for manual installation instead:

```sh
npm run package:claude
npm run test:claude
```

This writes `release/mobile-dev-<version>-claude-desktop-darwin-arm64.mcpb` and
the Claude plugin folder `release/claude-plugin/mobile-dev`. The plugin folder
uses `.claude-plugin/plugin.json`, which starts `dist/server.mjs` with Node.js
22.19 or later from `PATH`, and leaves out the Codex manifest, `.mcp.json`, and
launcher. Check it with `claude plugin validate ./release/claude-plugin/mobile-dev`,
or load it with `claude --plugin-dir ./release/claude-plugin/mobile-dev`.
Follow the [manual installation steps](README.md#claude-desktop-manual-installation).
Remove the `mobile-dev` development entry before installing the bundle to avoid
duplicate servers. Rebuild, repackage, and reinstall to update a bundled copy.

Local builds retain the `development` telemetry environment. Public releases use
`npm run build:release` and `npm run package:claude -- --release`.

## Live React UI development

Run `npm run dev` after installing the plugin. It watches the UI sources and
In Codex, run `npm run dev` after installing the plugin. It watches the UI sources and
rebuilds a self-contained HTML bundle. Open panels read updates through MCP,
then reload and reconnect their streams. Edits reset UI state.

Expand Down
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Callstack

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
61 changes: 50 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
# Mobile Dev for Codex
# Mobile Dev

Keep iOS and Android devices beside your Codex desktop chat while building,
running, and debugging mobile apps. Mobile Dev works with Expo, React Native,
SwiftUI, and other native mobile projects.
Keep iOS and Android devices beside your chat while building, running, and
debugging mobile apps. Mobile Dev works with Expo, React Native, SwiftUI, and
other native mobile projects.

Mobile Dev is an MCP plugin that works with both Codex and Claude. Codex shows it
beside the chat; Claude opens it in the conversation, with an expanded view when
available. Claude support is a development preview.

- [Live devices beside your chat](#live-devices-beside-your-chat): stream simulators, emulators, and physical devices.
- [Device control, inspection and annotations](#device-control-inspection-and-annotations): tap, type, inspect elements, and leave notes for the agent.
- [Native and JavaScript logs](#native-and-javascript-logs): iOS, Android, and Metro logs in one stream.
- [Live performance monitoring and improvements](#live-performance-monitoring-and-improvements): CPU, memory, Display FPS, recordings, and comparisons.
- [App storage](#app-storage): inspect and watch what an app saves, without adding code.

## Install

### Codex

Install the prebuilt plugin from the release marketplace:

```sh
Expand All @@ -27,6 +39,24 @@ codex plugin marketplace upgrade mobile-dev

Fully quit and reopen Codex after updating.

### Claude Desktop: manual installation

On an Apple Silicon Mac, obtain a `mobile-dev-<version>-claude-desktop-darwin-arm64.mcpb`
bundle from the person sharing the preview, or [build one locally](CONTRIBUTING.md#claude-desktop-local-development).
The Claude bundle is not yet published through this repository's release workflow.

1. Open Claude Desktop **Settings > Extensions > Advanced settings**.
2. Under **Extension Developer**, click **Install Extension…**, select the `.mcpb`
file, and confirm installation. You can also open the file with Claude Desktop.
3. Fully quit and reopen Claude, then start a new conversation and ask **“Open Mobile Dev.”**
4. Approve the connector when prompted. Click **Expand** to use the larger view
when available; Mobile Dev does not add a permanent Claude sidebar entry.

The bundle includes the plugin and native helpers; Claude supplies Node, so no
`npm install` is needed. Install a newer `.mcpb` manually to update. Use either
the bundle or the [local development connection](CONTRIBUTING.md#claude-desktop-local-development)
to avoid duplicate Mobile Dev servers. See [Claude's installation guide](https://support.claude.com/en/articles/10949351-getting-started-with-local-mcp-servers-on-claude-desktop).

## Features

### Live devices beside your chat
Expand All @@ -35,7 +65,7 @@ Stream iOS simulators, Android emulators, and connected iPhones, iPads, and Andr
![](/img/screenshot_side_by_side.png)

### Device control, inspection and annotations
Select and boot simulators or emulators, interact with taps and drags, type on supported devices, and let Codex inspect accessibility elements and control your app through MCP tools. Select an element or screen region and leave instructions for Codex, with React Native component and source details when available.
Select and boot simulators or emulators, interact with taps and drags, type on supported devices, and let the agent inspect accessibility elements and control your app through MCP tools. Select an element or screen region and leave instructions for the agent, with React Native component and source details when available.

![](/img/screenshot_annotations.png)

Expand All @@ -45,7 +75,7 @@ Read iOS unified logs, Android logcat, and Metro console messages together. Foll
![](/img/screenshot_logs.png)

### Live performance monitoring and improvements
Track app CPU and memory, expand individual thread charts, and view device-wide Display FPS on supported devices. Ask Codex to record an interaction, inspect interactive charts in chat, compare runs, and analyze selected ranges. Android recordings include display frame pacing and jank statistics.
Track app CPU and memory, expand individual thread charts, and view device-wide Display FPS on supported devices. Ask the agent to record an interaction, inspect interactive charts in chat, compare runs, and analyze selected ranges. Android recordings include display frame pacing and jank statistics.

![](/img/screenshot_performance.png)

Expand All @@ -62,8 +92,9 @@ See [storage privacy and review checks](docs/storage-privacy.md).
## Requirements

The prebuilt plugin targets Codex desktop on an Apple Silicon Mac and uses
Codex's bundled Node runtime from its workspace dependency cache. Install the
tools for the platforms you use:
Codex's bundled Node runtime from its workspace dependency cache. The Claude
Desktop preview also targets Apple Silicon and uses Claude's Node runtime when
installed as a bundle. Install the tools for the platforms you use:

| Platform or feature | Requirements |
| --- | --- |
Expand All @@ -84,15 +115,18 @@ its device panel, inspection, logs, and performance tools.

## Get started

Open Mobile Dev from the Codex sidebar, or ask Codex to open the simulator beside
this chat. Pick a device from the toolbar; selecting a stopped simulator or AVD
In Codex, open Mobile Dev from the sidebar or ask to open the simulator beside
this chat. In Claude Desktop, ask **“Open Mobile Dev”** in a conversation with the
connector enabled, then use **Expand** when available.

Pick a device from the toolbar; selecting a stopped simulator or AVD
boots it. Use the iOS and Android toggles to show either platform or both.

Click an iOS simulator or Android screen to focus it, then press **Command-V** to
paste text into the device. Paste accepts up to 4,096 printable US-ASCII characters;
line breaks and other characters show a notice without sending partial text.

Ask Codex to work with your app, for example:
Ask your assistant to work with your app, for example:

- “Build and run my Expo app in the simulator beside this chat.”
- “Read the app logs and help me fix this error.”
Expand Down Expand Up @@ -132,3 +166,8 @@ for implementation details.

For help, email [hello@callstack.com](mailto:hello@callstack.com).
See [Support](SUPPORT.md) for reporting bugs, security issues, and privacy requests.

## License

Mobile Dev is available under the [MIT License](LICENSE). Bundled third-party
components keep their own licenses; see [Third-party notices](THIRD_PARTY_NOTICES.md).
21 changes: 21 additions & 0 deletions claude-desktop/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"manifest_version": "0.3",
"name": "mobile-dev",
"display_name": "Mobile Dev",
"version": "0.1.164",
"description": "Inspect local iOS and Android devices, logs and performance in Claude Desktop. Initial Apple Silicon development preview.",
"author": { "name": "Callstack" },
"server": {
"type": "node",
"entry_point": "dist/server.mjs",
"mcp_config": {
"command": "node",
"args": ["${__dirname}/dist/server.mjs"]
}
},
"compatibility": {
"platforms": ["darwin"],
"runtimes": { "node": ">=22.19.0" }
},
"tools_generated": true
}
4 changes: 3 additions & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ Annotations send text only. Each note includes the user request, element label,
## Native device requests

When a mobile task has ambiguous targets, `mobile_choose_devices` asks the user
through Codex's native inline request form. The agent discovers suitable devices
through Codex's native inline request form. The server lists this tool only for
clients that advertise the `openai/elicitation` form extension; other hosts ask in
chat. The agent discovers suitable devices
first, then supplies their IDs, platform and kind, a task-specific question, and
optional operation details. The form shows canonical device names, platform/type,
runtime, optional verified app labels, and platform phone illustrations. Use
Expand Down
5 changes: 3 additions & 2 deletions docs/releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,9 @@ Release builds check for updates when Mobile Dev becomes visible. The server
checks GitHub's latest full release and the public `release/latest` manifest;
their versions must agree before the banner offers an update. Successful checks
are cached for one hour across chats in the active Codex profile; unavailable
checks retry after fifteen minutes. Development builds do not check or install
public updates. The embedded UI needs no GitHub network permissions.
checks retry after fifteen minutes. Development builds, and installs that are
not a Codex plugin package (such as the Claude MCPB bundle), do not check or
install public updates. The embedded UI needs no GitHub network permissions.

The Update button calls an app-only MCP tool. It locates the CLI process that
launched the plugin, verifies the `mobile-dev` Git marketplace belongs to this
Expand Down
7 changes: 7 additions & 0 deletions docs/telemetry.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,13 @@ Since 0.1.93, `ui.video.paint` and the platform frame counters also cover frames

`ui.annotations.send` measures the host send round trip, including composer retries. Outcome counters distinguish success, a missing composer, timeout and other failures. Unexpected send failures use a fixed error message. No message content goes to Sentry. A timeout keeps notes for a manual retry; it never triggers an automatic resend, since delivery may have succeeded without acknowledgement.

The standard-host attachment bar reuses these annotation measurements. On standard hosts,
the measured operation includes publishing selection context before preparing the
chat draft. `ui.annotations.send_success` means the host accepted the request;
it does not confirm user submission or a model response. Notes remain until the
user clears them. Message/context construction timings, surface attribution, and
content scrubbing are preserved; no note text or selection evidence enters telemetry.

Since 0.1.99, `ui.logs.foreground_change` counts automatic app-filter changes applied while Logs is active, including selected-device and process-lifetime changes. From 0.1.103, these changes update the visible query and local process identity mapping instead of restarting a scoped collector. `ui.logs.app_identity` measures batch insertion with native PID-to-app joins and discovery updates in milliseconds, using bounded aggregate windows. Hidden or closed log views defer row processing until reopened. Shared `ui.device_apps.discovery` timing and handled discovery-error coverage remain in place, including Android's foreground PID lookup; native session operations retain MCP tracing, Node runtime coverage, and `logs.ios.parse` timings. No app IDs, PIDs, package names, device IDs, or query text are attached to these measurements. Native helper telemetry and symbols are unchanged.

Since 0.1.99, `ui.logs.query_parse` measures query compilation in milliseconds once per edit, including automatic app-clause edits from 0.1.103. Existing `ui.logs.filter`, buffered/filtered row gauges, and search counts cover keyword filtering and visible age refreshes; filtering time still covers snapshot derivation and grouping. Query text, field values, regex patterns, and validation messages remain local. Age refresh timers stop when Logs closes, unmounts, or the document becomes hidden.
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
"test:ios-cpu": "node scripts/smoke-ios-cpu.mjs",
"package": "node scripts/package.mjs",
"package:release": "node scripts/package.mjs --release",
"claude:config": "node scripts/claude-config.mjs",
"package:claude": "node scripts/package-claude.mjs",
"test:claude": "node scripts/smoke-claude-package.mjs",
"vendor:serve-emu": "node scripts/vendor-serve-emu.mjs",
"dev": "node scripts/dev-ui.mjs",
"dev:off": "node scripts/dev-ui.mjs --off",
Expand Down
18 changes: 18 additions & 0 deletions scripts/claude-config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { access, mkdir, readFile, writeFile } from "node:fs/promises";
import { resolve } from "node:path";

// Generate a snippet only; never replace the user's existing Claude configuration.
await access("dist/server.mjs");
const manifest = JSON.parse(await readFile("claude-desktop/manifest.json", "utf8"));
const config = {
mcpServers: {
"mobile-dev": {
command: process.execPath,
args: [resolve(manifest.server.entry_point)],
},
},
};
await mkdir(".local-dev", { recursive: true });
const path = resolve(".local-dev/claude-desktop-config.json");
await writeFile(path, JSON.stringify(config, null, 2) + "\n");
console.log(`Merge the mcpServers entry from ${path} into Claude Desktop Settings > Developer > Edit Config, then fully restart Claude.`);
Loading
Loading