Repository navigation
feat: restructure as a workspace, add Claude Desktop and a Mac app - #37
Open
lauridskern wants to merge 45 commits into
Open
lauridskern wants to merge 45 commits into
lauridskern wants to merge 45 commits into
Conversation
Move host-independent code into packages/ (shared, core, ui, native, runtimes) and the Codex plugin's manifest, launcher, skills, assets and panel shell into apps/codex-plugin. Build scripts move to tooling/. The published release/latest layout is unchanged: the packaged plugin matches the previous layout file-for-file, and bundles differ only in module path comments and Sentry debug IDs. Native sources are pure renames; their recorded source hashes are refreshed because the hashes include repo-relative paths and build-script contents.
Map the shared theme tokens to standard MCP host variables with the existing light/dark fallbacks, replacing the Claude Desktop-only overrides, and apply host-provided fonts in each app. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drop MOBILE_DEV_HOST and every claudeDesktop branch so behavior follows what the client and install advertise, including in Claude Code: - Use one host-neutral set of server instructions and tool descriptions. - List mobile_choose_devices only for clients advertising openai/elicitation forms. - Enable the updater only in release builds running from a Codex plugin package. - Show the display mode control whenever the host offers the other mode. - Size the inline workspace from MCP Apps containerDimensions. Remove docs/claude-desktop.md; the MCPB bundle ships the repo README, which now introduces Codex and Claude support and links each feature. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shared views now depend on HostBridge, the subset of the MCP Apps App they use, so another host can provide it. The iOS/Android panel orchestration moves from the Codex shell into DeviceWorkspace, the server exposes configureUI and serves a mac.html page when a runtime ships one, and the page bundling moves to tooling/ui-page.mjs. UI and server telemetry gain a low-cardinality host value (codex or mac); the server's metadata allowlist accepts only those two.
A SwiftUI window with a native sidebar (tools and visible device platforms) hosts the shared UI in a web view. The app starts the bundled server over stdio as Codex does, reads its page through MCP so it gets the server's telemetry metadata, and relays JSON-RPC between server and page. The page implements HostBridge with an MCP client and offers no chat capabilities. npm run build:mac assembles release/mac/Mobile Dev.app (signed ad hoc); npm run test:mac launches it, waits for the page to connect and draw, and checks quitting stops the server.
SwiftPM recorded the deployment target as the SDK version, so AppKit gave the window the macOS 15 appearance. The build now records the SDK it compiles against and checks the binary.
While the sidebar is collapsed, the leading panel's top row is padded by the width of the traffic lights and sidebar button; views without a toolbar row move below them. Shared top rows are marked panel-toolbar.
The web view ignored every safe area, so it ran under the floating sidebar. It now ignores only the top edge. The smoke test also clears a snapshot left by an earlier run.
Main's native app storage changes land in packages/core and packages/ui; their imports use the workspace paths and the storage panel takes a HostBridge.
Brings in #34 and fits it to the workspace: - The MCP Apps panel shell moves from apps/codex-plugin/src to packages/mcp-app, since Codex and Claude Desktop load the same panel; Mike's display-mode and context-attachment controls join it. - The MCPB manifest lives in apps/claude-desktop; its config, packaging and smoke scripts move to tooling/. - Shared UI keeps HostBridge, so chat-message and the standard MCP context attachments work in every host, and PanelContext still accepts no OpenAI extensions for the Mac app. - Host telemetry no longer assumes Codex: panels label themselves codex (OpenAI extensions), claude or other once connected, the server labels itself from the MCP client name, and the allowlist accepts only those values and mac. Co-authored-by: Mike Grabowski <grabbou@gmail.com>
- Server: createPlugin takes ServerFeatures and runStdioServer runs the shared server with a host's features. Codex's self-updater moves to apps/codex-plugin/server and the Mac page resource to apps/mac/server, so the shared server and Claude Desktop's bundle no longer carry them. - Panel: startMcpApp takes a host's workspace chrome. The update banner moves to apps/codex-plugin/ui; Claude Desktop loads the shared entry. - Build: dist/ holds the host-neutral runtime and panel; host pieces build into dist/hosts/<host>. Each app's tooling/ packages from the runtime only, so Claude Desktop no longer packages through Codex. - Version: the root package.json is the source; host manifests carry no version and each package step writes it. Smoke tests now check the Codex package has the updater and banner and the Claude bundle has neither.
PanelContext and RecordingController take a HostAttachmentsSource, a vendor-neutral interface for hosts that keep the panel's context as composer attachments. The MCP Apps shell supplies it from OpenAI's extension, so packages/ui no longer depends on @openai/mcp-extensions.
The tool skills move to packages/skills, and each host's package step includes the ones its host supports; the Codex plugin still ships mobile-dev and mobile-dev-setup. The build-codex-native-plugins skill helps agents working on this repository, so it moves to .agents/skills.
Shared code copied serve-emu's startup stage and outcome names and the Baguette pin from vendored files; a test keeps the copies equal to their sources, so packages/shared imports nothing outside itself.
Each package and app has a test/ folder, tooling/test covers the build and release scripts, and fixtures shared across packages move to packages/test-support. npm test runs all of them from the repository root.
Uploads, releases and the server bundler read the ui, server and native slugs from tooling/sentry-projects.mjs, so renaming a project changes one line.
The ui, server and native projects are renamed in Sentry to host-neutral slugs; their IDs and DSNs are unchanged, so history and incoming events stay in the same projects.
The repository moves to callstackincubator/mobile-dev. Links, the release notes URL and the updater's endpoints use the new name, and the updater still accepts the old marketplace URL that existing installs keep; GitHub redirects it.
- WorkspaceTools owns the four tool panels, their selection policy, availability, host changes and disposal; the Codex workspace and the Mac page only choose the tool and draw chrome. - startCardApp runs the recording, comparison and TraceSift cards, and applyHostStyles replaces four copies of host theming. - createPlugin takes named options instead of seven positional ones. - Codex builds its own server and panel in its package step, so the shared build no longer imports an app and dist/hosts is gone. A card test covers the shared bootstrap in every card view.
The feature list adds app control, device settings and network conditions, and TraceSift profile analysis. Install covers Codex, Claude Desktop and the Mac app, and a table maps the packages and apps.
Codex's lg radius is 12.5px with its superellipse scale, a size larger than the 10px scale the panel's radii are built on. Its md radius is 10px, so the panel uses that and keeps 10px when a host sends none.
The shared panel shows Expand / Back to chat whenever a host advertises both display modes. Claude needs it to leave the expanded view, but Codex has its own fullscreen and sidebar controls, so the duplicate button misbehaved there. Codex's entry now turns it off; Claude keeps it.
The MCP SDK labels every converted tool schema draft-07. Claude Desktop validates 2020-12 only and refuses mobile_open_simulator for its draft-07 output schema. The schemas use no keyword whose meaning differs between the dialects, which a test checks, so the server declares 2020-12 when it lists its tools.
Contributor
|
Shall we first squash merge #34 into main, and then, rebase/merge this one? that way we can ship Claude a bit sooner |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Restructures the repo as an npm workspace so the server and UI can be shared across hosts. It also merges Mike's Claude Desktop support (#34) into that layout and adds a standalone Mac app.
Repository layout
packages/sharedpackages/corepackages/uipackages/mcp-apppackages/skillspackages/test-supportpackages/nativevendor/packages/runtimesapps/codex-pluginapps/claude-desktopapps/mactoolingscripts/); each app'stooling/holds its packaging and smoke testsThe published
release/latestlayout is unchanged. The packaged plugin has the same files as before; bundles differ only in path comments and Sentry debug IDs.Claude Desktop (#34)
Mike's branch is merged with his history kept. It adds a Claude manifest,
.mcpbpackaging, capability-driven host behavior (fullscreen, inline sizing, theme tokens and fonts, context attachments, clipboard), annotation drafts and log session handles. Fitting it to the workspace layout took three changes:apps/codex-plugin/srctopackages/mcp-app, because both Codex and Claude Desktop load it. Mike's display-mode and context-attachment controls moved there with it.apps/claude-desktop, andclaude:config,package:claudeandtest:clauderun fromtooling/.chat-message, standard MCP context attachments) useHostBridge, andPanelContextstill accepts no OpenAI extensions for the Mac app.The Cursor (#35) and VS Code (#36) PRs are not included. Mike closed both to restart them after #34.
Shared UI seam
HostBridge(packages/ui/src/host-bridge.ts), the sevenAppoperations they use. Codex passes its ext-appsApp.DeviceWorkspacetakes over the iOS/Android panel orchestration from the Codex shell, so both hosts share it.configureUI. It servesui://mobile-dev/mac.htmlonly when a runtime shipsmac.html, which the Codex package doesn't.tooling/ui-page.mjs.hosttag:codex,claude,macorother.codexwhen the host advertises OpenAI extensions, otherwise the mapped host name.MOBILE_DEV_HOST=mac.docs/telemetry.mddocuments it.Host separation
Adding a host now means adding an app; the shared packages know no host by name.
runStdioServertakes a host'sServerFeatures. Codex's self-updater moved toapps/codex-plugin/serverand the Mac page resource toapps/mac/server, so the shared server and the Claude bundle no longer carry them.startMcpApptakes a host's workspace chrome. The update banner moved toapps/codex-plugin/ui; Claude loads the shared entry.packages/uinames context attachments (HostAttachments) instead of depending on@openai/mcp-extensions.dist/holds the host-neutral runtime and panel, and host pieces build intodist/hosts/<host>. Each app packages from the runtime only; Claude no longer packages through Codex. The version comes from the rootpackage.json, and each package step writes it into its host's manifest.packages/skills, and Codex packages the ones it supports.build-codex-native-pluginsis a repo-maintenance skill and moved to.agents/skills.packages/sharedno longer imports vendored runtimes; a test keeps its copied constants equal to the originals.test/folder, and shared fixtures live inpackages/test-support.mobile-dev-ui,mobile-dev-serverandmobile-dev-native(done in Sentry already). IDs and DSNs are unchanged, so history and events stay put. The slugs live intooling/sentry-projects.mjs.Review cleanup
A strict code-quality pass before merge removed duplication the restructure had left:
WorkspaceTools(packages/ui) owns the four tool panels, their show/close policy, availability, host changes and disposal. The Codex workspace and the Mac page only pick the tool and draw chrome. On the Mac, switching away from Performance now keeps capture running, like Codex; closing the tools stops it.startCardAppruns the recording, comparison and TraceSift cards, andapplyHostStylesreplaces four copies of host theming. Three entry files are gone, and a new test covers every card's connect, theme, render and teardown.createPlugintakes named options instead of seven positional ones.dist/hostsis gone.Mac app
npm run build:macwritesrelease/mac/Mobile Dev.app, signed ad hoc and linked against the current macOS SDK.npm run test:maclaunches it, waits for the page to connect and draw, and checks that quitting stops the server.Before merging / after pulling
npm run rebuild:baguetteonce. Its hash lives in the untrackedvendor/baguette/release.json.callstackincubator/mobile-dev(renamed on GitHub). GitHub redirects the old URL for git, the API and raw files, so released versions keep updating. The updater accepts both the old and the new marketplace URL, and a test covers installs made before the rename. Links and the README install command use the new name.Not included
Verification
npm test: 822 pass.packages/core/test/tracesift-client.test.tsfails intermittently: about 5 in 24 runs under parallel load, with an undiciReadableStream is already closederror. It does the same onmain. CI on PRs doesn't run tests, but the release job does.tests/tracesift-client.test.tsis intermittently flaky (undici stream state) both on this branch and before the restructure.npm run typecheck:telemetryis clean. A fulltscrun reports 23 errors, fewer than the 25 main had.npm run test:package,npm run test:codex-plugin(real Codex install) andnpm run check:mcp-budgetpass.npm run package:claudeandnpm run test:claudepass (relocated bundle, development and release, with and without form elicitation).npm run build:macandnpm run test:macpass, with live iOS simulator and Android emulator streams in the app.Merging
Use Create a merge commit. #34's head commit is in this branch, so GitHub marks #34 as merged only with a merge commit; squash or rebase leaves it open. #35 and #36 were already closed by their author.