Visual design exploration
Follow the android-design skill for every design decision: its section 0 answers, components, theming, layout, and the screen check's questions. This skill owns the workflow. Each run is one shot: brief in, one proposal written, checked, shown, then stop. Phone, foldable, tablet, desktop, and Wear OS app screens are in scope; Wear tiles, watch faces, and widgets are not. Where Wear differs, the Wear OS section below says how.
A proposal is a data file that the previewer app, a native macOS window, draws with real Compose Material 3 components and redraws on every save. You check it through the app's layout tree; the user judges taste in the window.
Requirements
macOS, with the previewer app installed and registered as an MCP server named android_design_preview. Call its status tool first. When its tools are unavailable, stop and tell the user the two steps, then wait:
- Build and install the app from a checkout of the android-design repository:
cd app && ./gradlew :app:installApp, which installs~/Applications/AndroidDesignPreview.app. - Register it for their harness, then restart the session (
<binary>is~/Applications/AndroidDesignPreview.app/Contents/MacOS/AndroidDesignPreview, written as an absolute path where the harness does not expand~):- Claude Code:
claude mcp add --scope user android_design_preview -- <binary> - Codex: a
[mcp_servers.android_design_preview]table in~/.codex/config.tomlwithcommand = "<binary>"anddefault_tools_approval_mode = "approve" - Antigravity:
agy mcp add android_design_preview <binary>
- Claude Code:
Brief
When there is an app, read its relevant screens, theme, assets, and any existing DESIGN.md and design/ proposals first. Answer section 0 of android-design in the reply.
- Pick one seed: the brand color, or a content color from the subject (a dish, an album, a trip), never the app's default
#6750A4. - When the screen is a hero moment (question 3 of section 0), layer three or more tactics (section 3) and name them.
- Keep app code and dependencies unchanged.
- Use representative, non-sensitive data and assets. Use image generation only for assets inside a proposal, never as a substitute for one.
Make several proposals only when the user asks. Each is its own file, a distinct composition (not a recoloring) with its own seed in its theme, and at least one is a hero.
Files
Work in the app's repository root, or the folder the user names. Never write into this skill's own repository.
DESIGN.mdat the root holds the shared design system. Create it when missing, with the chosen seed, faces, and named styles. Change it only when the direction changes what every proposal shares; a direction's own look goes in its proposal'stheme.design/<slug>.proposal.jsonholds one proposal.
Both are ordinary tracked files; committing them follows the project's own workflow. Tell the user the proposal's absolute path.
Write
- Call
get_catalog(its tool description says what it returns). It is the only component vocabulary: a component it lacks is out of reach, so build the idea fromBox,Row,Column,Text, andShape, or leave it out. - Read
references/proposal-format.md, then writeDESIGN.mdand the proposal, compactly as its "Writing it compactly" section says.
The proposal carries these design rules; proposal-format.md gives the syntax for each, and its Component rules section holds the rules for tabs, carousels, overlays, choices, toolbars, menus, app bars, and badges:
- The screen has one primary action, marked as primary, and it leads its peers as
android-designsection 2 describes. - It adapts at 600 and 840 dp: a navigation bar in compact becomes a rail from medium up, and a list's detail screen opens beside the list at expanded widths.
- Text truncates on purpose, with an ellipsis. Button, chip, and navigation labels fit on one line.
Check
For a proposal, this step replaces the rendering in android-design's screen check. Answer its questions from the check_proposal layout summaries and errors (and get_tree when they are not enough), never from a render or pixels. Screenshots stay out of this loop: never take one or ask for one.
- Call
open_proposalwith the proposal's absolute path. It loads the file, watches it, shows the window, and returns validation errors. Fix them and callstatusuntil it reports none. - Call
check_proposal. One call checks every screen at every view and returns each view's errors andlayoutsummary; its tool description gives the format. - Fix every error once, then call
check_proposalagain. Anoverflowerror names a node laid out wider than its parent or the view (a row that needs more width than its cell); narrow it, wrap it, or let it scroll. Report anything still failing instead of looping. - Confirm the adaptation from the
layoutsummaries: each larger view reveals what your section 0 adaptation answer promised, such as a second pane, a rail, or more regions. Google: "Additional space doesn't just mean making the same thing bigger." A larger view with the phone's regions only spread wider fails. - Call
get_treeonly when a summary or an error is not enough; its tool description says what it returns.
The step is done when check_proposal passes or each remaining error is on the list you report, and the adaptation is confirmed.
Show
Call show_preview. Say in one line what the proposal is, name the tactics a hero layers, list any unresolved findings, and report "visual quality judged from the layout tree only". Then stop and wait for the user's reply.
Revise
Edit the same proposal with the user's feedback; the window redraws on save. Repeat the check on the screens you changed. The revision replaces the old version; keep no copies.
Approve and port
Approval is the user saying so in chat. Report the approved proposal's path and that references/compose-mapping.md is the porting table. An explore-only request ends there: do not implement. A build request (the android-design skill sends design-focused builds of new apps, screens, and redesigns here first) continues to the port. Approval never authorizes library version changes.
The port follows the requesting project's planning, branch, verification, and review rules:
- Call
export_kotlinfor the screens to port. Its Kotlin is the first draft, not finished code. - Fit it to the app's conventions and library versions with
references/compose-mapping.md. - Render the result with the
compose-previewskill and compare it with the proposal's trees at the same views.
Report components the mapping marks unverified, and anything it lacks, instead of inventing a Compose equivalent. If the design cannot be preserved with the app's dependencies, ask.
Wear OS
A Wear proposal follows the same workflow. android-design references/wear-os.md owns the design rules, and proposal-format.md owns the file format (catalog id, views, Screen, primary, large).
- Its own file. One surface per proposal: write
design/<slug>-wear.proposal.jsonbeside the phone one. - Adaptation check: the Wear size override applies from 225dp, so the check is "fits and reads at both watch sizes, and the large one shows more value, never less".
- Shared
DESIGN.md: its seed and color roles apply to Wear; its typography is replaced by Roboto Flex. - Findings: fix
round-edge-clipped(control or text cut by the round edge on a fixed screen) with percentage-style margins or a smaller layout. - Port: the same three steps.
export_kotlinwrites Wear Compose: aWearAppThemewith the previewer's exact colors,AppScaffoldandScreenScaffold, and Navigation 3 with swipe to dismiss. Render the port at both round sizes (204 and 227dp).
Delete
When the user asks, remove design/<slug>.proposal.json. Keep DESIGN.md unless the user asks to remove it too.