Add preview_configure tool for trait injection#54
Merged
Conversation
) Enable AI agents and CLI users to preview SwiftUI views under different rendering traits (dark mode, dynamic type sizes) without editing source. Traits are injected as .preferredColorScheme() and .dynamicTypeSize() modifiers in the generated bridge code and persist across hot-reload. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixes code injection vulnerability: preview_start and preview_playground were passing unvalidated trait strings into generated Swift source. Now parseTraits() validates against allowed values on all paths. Also adds dynamicTypeSize enum constraints to all MCP tool schemas and propagates loadPreview errors in preview_configure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
After reconfiguring, read currentTraits from the session (post-merge) so the response shows all active traits, not just the ones passed in this call. Also adds currentTraits getter to IOSPreviewSession. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rename for consistency with the MCP parameter name dynamicTypeSize. Both --color-scheme and --dynamic-type-size now validate against PreviewTraits.validColorSchemes/validDynamicTypeSizes at parse time, producing clear error messages instead of cryptic compilation failures. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When preview_start or handleIOSPreviewStart is called with traits, the response now mentions them (e.g., "Traits: colorScheme=dark.") so the user gets confirmation that traits were applied. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New tests: generateOverlaySource with traits, validColorSchemes contains exactly light/dark, validDynamicTypeSizes has all 12 cases, and PreviewTraits Equatable conformance. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add comment explaining the narrow race window where a concurrent structural file change and preview_configure call could cause the file watcher to snapshot stale traits when creating a new session. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Instead of creating a new PreviewSession in the file watcher slow path (which snapshots traits and creates a new session, racing with preview_configure), reuse the existing session and call compile() on it. Since compile() re-reads the source file and uses the session's stored traits (which live inside the actor), traits set via preview_configure are always preserved without a race. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The headless parameter was only wired up for iOS simulator sessions. macOS windows were always positioned off-screen (-10000, -10000) because HostApp.headless was derived from mode (.serve), ignoring the tool param. Thread the headless flag from the MCP tool call through startMacOSPreview into loadPreview, matching how iOS already handles it. When headless is false, switch activation policy to .regular so the window can come to front with a Dock icon. Also update integration test skill to test the opposite color scheme from system default so trait changes are always visually obvious. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The success path always returns a valid PreviewTraits, so the optional wrapper was unnecessary. Remove ?? PreviewTraits() fallbacks at all three call sites. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
macOS does not scale fonts in response to .dynamicTypeSize() — this is a platform limitation, not a bug. Document in the preview_configure tool description and CLAUDE.md so users know to test dynamic type on iOS simulator. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.
Summary
preview_configureMCP tool to change rendering traits (color scheme, dynamic type) on running preview sessions without editing sourcecolorSchemeanddynamicTypeSizeparams added topreview_startandpreview_playgroundfor initial configuration--color-schemeand--dynamic-typeCLI flags onrunandsnapshotcommandsHow it works
Traits are injected as
.preferredColorScheme()and.dynamicTypeSize()SwiftUI modifiers in the generated bridge code byBridgeGenerator. Changing traits triggers a full recompile (@Stateis reset). ThePreviewTraitsstruct flows throughPreviewSession→BridgeGeneratorand is preserved across file-watcher reloads.Test plan
swift buildpassesswift test— all 97 tests pass (15 new trait tests)swift-format lint --strict— cleanpreview_configurewithcolorScheme: "dark"→ snapshot shows dark backgroundpreview_configurewith invalid value → clear error message--color-scheme darkon CLIsnapshotcommandCloses #10
🤖 Generated with Claude Code