diff --git a/.vscodeignore b/.vscodeignore
index 98b4927..8fa4baf 100644
--- a/.vscodeignore
+++ b/.vscodeignore
@@ -14,3 +14,4 @@ Makefile
**/*.tsbuildinfo
node_modules/**
builds/**
+examples/**
diff --git a/README.md b/README.md
index 19ba231..afb04c6 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,7 @@
Installation •
+ Demo •
Features •
AI Tools •
Physical Devices •
@@ -34,6 +35,16 @@ Install [XBridge from the Visual Studio Marketplace](https://marketplace.visuals
---
+## See XBridge in action
+
+
+
+The tour uses the included [XBridgeDemo Xcode project](examples/XBridgeDemo). View the full-resolution captures: [project and destination controls](docs/images/overview.png), [XCTest and Swift Testing in Test Explorer](docs/images/tests.png), [build and run](docs/images/build-and-run.png), and [the iPhone app](docs/images/demo-app.png).
+
+[Explore every XBridge command and AI tool](docs/capabilities.md).
+
+---
+
## Why XBridge?
- Run the core Xcode workflow from the editor where you write Swift.
diff --git a/docs/capabilities.md b/docs/capabilities.md
new file mode 100644
index 0000000..0c3be71
--- /dev/null
+++ b/docs/capabilities.md
@@ -0,0 +1,80 @@
+# XBridge capabilities
+
+XBridge puts the everyday Xcode workflow in VS Code. These are the commands and tools available in version 1.4.2. Open the Command Palette and type `XBridge:` to find a command; the most common actions also appear in the XBridge sidebar and status bar.
+
+## Project and workflow
+
+| Command | What it does |
+|:---|:---|
+| `XBridge: Select Xcode Project or Workspace` | Choose an `.xcodeproj`, `.xcworkspace`, or Swift package when more than one is available. |
+| `XBridge: Select Scheme` | Choose the Xcode scheme. |
+| `XBridge: Select Build Configuration` | Switch between configurations such as Debug and Release. |
+| `XBridge: Select Scheme, Configuration or Destination` | Open one picker for the active build target. |
+| `XBridge: Refresh Schemes` | Reload schemes and targets from Xcode. |
+| `XBridge: Open in Xcode` | Open the active project or workspace in Xcode. |
+| `XBridge: Getting Started` | Open the guided VS Code walkthrough. |
+
+## Build, run, test, and packages
+
+| Command | What it does |
+|:---|:---|
+| `XBridge: Build` | Compile the active scheme. |
+| `XBridge: Build & Run` | Build, install, and launch the app on the selected destination. |
+| `XBridge: Stop` | Cancel the active operation or stop the running app. |
+| `XBridge: Stop Running App` | Terminate the launched app without shutting down the simulator. |
+| `XBridge: Clean Build Folder` | Remove the active project's DerivedData build products. |
+| `XBridge: Run Tests` | Run the selected test plan or target with `xcodebuild`. |
+| `XBridge: Select Test Plan` | Choose an Xcode test plan, if the scheme has one. |
+| `XBridge: Select Test Target` | Limit a run to one test target. |
+| `XBridge: Resolve Package Dependencies` | Resolve Swift Package Manager dependencies through Xcode. |
+
+The native VS Code Test Explorer discovers XCTest methods and Swift Testing `@Test` methods, shows per-test results, and lets you run individual tests. Build errors and test failures appear in Problems and at their source locations.
+
+## Results and logs
+
+| Command | What it does |
+|:---|:---|
+| `XBridge: Show Build Output` | Open the `XBridge Build` output channel. |
+| `XBridge: Show Build Issues` | Browse errors and warnings and jump to the source line. |
+| `XBridge: Show App Console` | Open the launched app's console output. |
+
+The status bar also shows the selected scheme and destination, build activity, and error and warning counts.
+
+## Simulators and devices
+
+| Command | What it does |
+|:---|:---|
+| `XBridge: Select Destination (Simulator/Device)` | Choose a simulator or connected physical device. |
+| `XBridge: Set as Destination` | Use the selected device from the Destinations tree. |
+| `XBridge: Boot Simulator` | Start a simulator. |
+| `XBridge: Shutdown Simulator` | Shut down a simulator. |
+| `XBridge: Open Simulator.app` | Bring Apple's Simulator app forward. |
+| `XBridge: Refresh Simulators` | Reload the local simulator list. |
+| `XBridge: Refresh Devices & Simulators` | Reload simulator and connected-device discovery. |
+| `XBridge: Erase Simulator Content` | Reset a simulator's content and settings. |
+| `XBridge: Copy Simulator UDID` | Copy the simulator identifier. |
+| `XBridge: Open URL or Deep Link…` | Open a URL in a simulator. |
+| `XBridge: Take Screenshot` | Save a PNG from a booted simulator. |
+| `XBridge: Start / Stop Screen Recording` | Save a simulator recording as video. |
+| `XBridge: Toggle Light / Dark Appearance` | Change the simulator appearance. |
+| `XBridge: Open App Data Container` | Open the installed app's container in Finder. |
+| `XBridge: Uninstall App from Simulator` | Remove the installed app. |
+
+Connected iPhones and iPads appear in Destinations through Apple's `devicectl`. Physical-device builds require working code signing and Developer Mode.
+
+## AI agent tools
+
+Compatible VS Code AI agents can call these eight tools directly:
+
+| Tool | Capability |
+|:---|:---|
+| `xbridge_build` | Build and return compiler diagnostics. |
+| `xbridge_test` | Run tests and return failures. |
+| `xbridge_run` | Build and launch an app. |
+| `xbridge_listSchemes` | List schemes, configurations, and targets. |
+| `xbridge_listSimulators` | List available simulators and status. |
+| `xbridge_bootSimulator` | Boot a simulator. |
+| `xbridge_readDiagnostics` | Read the last build or test diagnostics. |
+| `xbridge_clean` | Clean the Xcode build folder. |
+
+See the [main README](../README.md#settings) for the eleven configurable settings and [XBridgeDemo](../examples/XBridgeDemo) for a project you can try locally.
diff --git a/docs/images/build-and-run.png b/docs/images/build-and-run.png
new file mode 100644
index 0000000..2b6772c
Binary files /dev/null and b/docs/images/build-and-run.png differ
diff --git a/docs/images/demo-app.png b/docs/images/demo-app.png
new file mode 100644
index 0000000..af59a8a
Binary files /dev/null and b/docs/images/demo-app.png differ
diff --git a/docs/images/feature-tour.gif b/docs/images/feature-tour.gif
new file mode 100644
index 0000000..7dcf4e0
Binary files /dev/null and b/docs/images/feature-tour.gif differ
diff --git a/docs/images/overview.png b/docs/images/overview.png
new file mode 100644
index 0000000..cc1011c
Binary files /dev/null and b/docs/images/overview.png differ
diff --git a/docs/images/tests.png b/docs/images/tests.png
new file mode 100644
index 0000000..0de32bd
Binary files /dev/null and b/docs/images/tests.png differ
diff --git a/examples/XBridgeDemo/.gitignore b/examples/XBridgeDemo/.gitignore
new file mode 100644
index 0000000..445b095
--- /dev/null
+++ b/examples/XBridgeDemo/.gitignore
@@ -0,0 +1,4 @@
+.build/
+.vscode/
+*.xcuserstate
+xcuserdata/
diff --git a/examples/XBridgeDemo/README.md b/examples/XBridgeDemo/README.md
new file mode 100644
index 0000000..87dcb3e
--- /dev/null
+++ b/examples/XBridgeDemo/README.md
@@ -0,0 +1,9 @@
+# XBridge Demo
+
+A small, buildable SwiftUI app used to demonstrate XBridge in VS Code. It includes one XCTest and one Swift Testing test so both appear in Test Explorer.
+
+1. Open this folder in VS Code on a Mac with Xcode installed.
+2. Select the `XBridgeDemo` scheme and an iOS Simulator in the XBridge sidebar.
+3. Use **Build & Run** to launch the app, or open Test Explorer and run both tests.
+
+The app has no external packages or signing requirement for Simulator. Xcode build products and local VS Code settings are ignored by Git.
diff --git a/examples/XBridgeDemo/XBridgeDemo.xcodeproj/project.pbxproj b/examples/XBridgeDemo/XBridgeDemo.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..bb2437b
--- /dev/null
+++ b/examples/XBridgeDemo/XBridgeDemo.xcodeproj/project.pbxproj
@@ -0,0 +1,459 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 3339FC342000793B43D0BD6E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D21DF1F5E075569C85A5A80D /* Foundation.framework */; };
+ 42D7BFFFA5CBABA2F46D7E50 /* ModernTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ABB7018A6B79EA9E51BB8FB /* ModernTests.swift */; };
+ 7A85D9FDE9A8B9352A26476B /* XBridgeDemoApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15A1711653BCBC7EB5A424C4 /* XBridgeDemoApp.swift */; };
+ 7A99EADFB04BDDA6FD8EA929 /* XBridgeDemoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89D0980295DEE023A32B5DC9 /* XBridgeDemoTests.swift */; };
+ 9F3DFB026CACCEA2DD8BF023 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C94386DDF7FC57A34733389 /* ContentView.swift */; };
+ A056ED2D15E03B6267D834B4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D21DF1F5E075569C85A5A80D /* Foundation.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 5744DE6251B303F1CB3C9DF3 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 926908D120004E2CDF95387F /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 38C28A02E02E1A716344BAFD;
+ remoteInfo = XBridgeDemo;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 15A1711653BCBC7EB5A424C4 /* XBridgeDemoApp.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = XBridgeDemoApp.swift; sourceTree = ""; };
+ 1ABB7018A6B79EA9E51BB8FB /* ModernTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ModernTests.swift; sourceTree = ""; };
+ 2C5D9B1CEA7CDD627FE83B70 /* XBridgeDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XBridgeDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 6238FA757782EB5EADFF0828 /* XBridgeDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XBridgeDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 89D0980295DEE023A32B5DC9 /* XBridgeDemoTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = XBridgeDemoTests.swift; sourceTree = ""; };
+ 8C94386DDF7FC57A34733389 /* ContentView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; };
+ D21DF1F5E075569C85A5A80D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 5623CC290D6BB5B3555C9E37 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ A056ED2D15E03B6267D834B4 /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 797F4E7CC0A84E8ADD920E9C /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 3339FC342000793B43D0BD6E /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 4F75EA34634134EB2327C973 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 6238FA757782EB5EADFF0828 /* XBridgeDemo.app */,
+ 2C5D9B1CEA7CDD627FE83B70 /* XBridgeDemoTests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 5AABD117A77BFAA3F72F4001 = {
+ isa = PBXGroup;
+ children = (
+ 4F75EA34634134EB2327C973 /* Products */,
+ 76777653C83C84E6DFCCB739 /* Frameworks */,
+ A4B20FD811B3FAA4740D5F89 /* XBridgeDemo */,
+ 79D6CE832ACE6D6DC6AC9F05 /* XBridgeDemoTests */,
+ );
+ sourceTree = "";
+ };
+ 76777653C83C84E6DFCCB739 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ C4778F146AEF9B99291A3F90 /* iOS */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 79D6CE832ACE6D6DC6AC9F05 /* XBridgeDemoTests */ = {
+ isa = PBXGroup;
+ children = (
+ 89D0980295DEE023A32B5DC9 /* XBridgeDemoTests.swift */,
+ 1ABB7018A6B79EA9E51BB8FB /* ModernTests.swift */,
+ );
+ name = XBridgeDemoTests;
+ path = XBridgeDemoTests;
+ sourceTree = "";
+ };
+ A4B20FD811B3FAA4740D5F89 /* XBridgeDemo */ = {
+ isa = PBXGroup;
+ children = (
+ 15A1711653BCBC7EB5A424C4 /* XBridgeDemoApp.swift */,
+ 8C94386DDF7FC57A34733389 /* ContentView.swift */,
+ );
+ name = XBridgeDemo;
+ path = XBridgeDemo;
+ sourceTree = "";
+ };
+ C4778F146AEF9B99291A3F90 /* iOS */ = {
+ isa = PBXGroup;
+ children = (
+ D21DF1F5E075569C85A5A80D /* Foundation.framework */,
+ );
+ name = iOS;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 38C28A02E02E1A716344BAFD /* XBridgeDemo */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 9B8353B98D321DDF7007E5DD /* Build configuration list for PBXNativeTarget "XBridgeDemo" */;
+ buildPhases = (
+ 3ED4D77EFBB1BAF4890B3D9F /* Sources */,
+ 797F4E7CC0A84E8ADD920E9C /* Frameworks */,
+ 5A26789469FEB06DBB37C2A2 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = XBridgeDemo;
+ productName = XBridgeDemo;
+ productReference = 6238FA757782EB5EADFF0828 /* XBridgeDemo.app */;
+ productType = "com.apple.product-type.application";
+ };
+ E343816C6E356CED400EAB1F /* XBridgeDemoTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 974B1B4BE0A6E8DBF5A93B89 /* Build configuration list for PBXNativeTarget "XBridgeDemoTests" */;
+ buildPhases = (
+ 95855EDEB98C88C5E50A19C9 /* Sources */,
+ 5623CC290D6BB5B3555C9E37 /* Frameworks */,
+ 56C8A09B750384342F4A89E2 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ A3AC2A892FD3D0A005C28BE6 /* PBXTargetDependency */,
+ );
+ name = XBridgeDemoTests;
+ productName = XBridgeDemoTests;
+ productReference = 2C5D9B1CEA7CDD627FE83B70 /* XBridgeDemoTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 926908D120004E2CDF95387F /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 2660;
+ LastUpgradeCheck = 2660;
+ };
+ buildConfigurationList = 4FE1DAE27A9BF849A7EFCED6 /* Build configuration list for PBXProject "XBridgeDemo" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 5AABD117A77BFAA3F72F4001;
+ minimizedProjectReferenceProxies = 0;
+ preferredProjectObjectVersion = 77;
+ productRefGroup = 4F75EA34634134EB2327C973 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 38C28A02E02E1A716344BAFD /* XBridgeDemo */,
+ E343816C6E356CED400EAB1F /* XBridgeDemoTests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 56C8A09B750384342F4A89E2 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 5A26789469FEB06DBB37C2A2 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 3ED4D77EFBB1BAF4890B3D9F /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 7A85D9FDE9A8B9352A26476B /* XBridgeDemoApp.swift in Sources */,
+ 9F3DFB026CACCEA2DD8BF023 /* ContentView.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 95855EDEB98C88C5E50A19C9 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 7A99EADFB04BDDA6FD8EA929 /* XBridgeDemoTests.swift in Sources */,
+ 42D7BFFFA5CBABA2F46D7E50 /* ModernTests.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ A3AC2A892FD3D0A005C28BE6 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = XBridgeDemo;
+ target = 38C28A02E02E1A716344BAFD /* XBridgeDemo */;
+ targetProxy = 5744DE6251B303F1CB3C9DF3 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 03F3B0CAB58D500D2D3DCF86 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CLANG_ENABLE_OBJC_WEAK = NO;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = "";
+ GENERATE_INFOPLIST_FILE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 17.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.chaiwithcode.XBridgeDemoTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = iphoneos;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/XBridgeDemo.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/XBridgeDemo";
+ };
+ name = Debug;
+ };
+ 44B5F68238D33181F33D81DC /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Release;
+ };
+ 5915172CE0D64BA5F77731AE /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CLANG_ENABLE_OBJC_WEAK = NO;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = "";
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
+ INFOPLIST_KEY_UILaunchScreen_Generation = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 17.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = com.chaiwithcode.XBridgeDemo;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = iphoneos;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 7E6DCA70F2C65BCFF5E627F8 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CLANG_ENABLE_OBJC_WEAK = NO;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = "";
+ GENERATE_INFOPLIST_FILE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 17.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.chaiwithcode.XBridgeDemoTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = iphoneos;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/XBridgeDemo.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/XBridgeDemo";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ B3BC7A1BB930F45E88B8E6F9 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Debug;
+ };
+ C0216E6A1D67B593D084CC55 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CLANG_ENABLE_OBJC_WEAK = NO;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = "";
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
+ INFOPLIST_KEY_UILaunchScreen_Generation = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 17.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = com.chaiwithcode.XBridgeDemo;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = iphoneos;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 4FE1DAE27A9BF849A7EFCED6 /* Build configuration list for PBXProject "XBridgeDemo" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B3BC7A1BB930F45E88B8E6F9 /* Debug */,
+ 44B5F68238D33181F33D81DC /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 974B1B4BE0A6E8DBF5A93B89 /* Build configuration list for PBXNativeTarget "XBridgeDemoTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 7E6DCA70F2C65BCFF5E627F8 /* Release */,
+ 03F3B0CAB58D500D2D3DCF86 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 9B8353B98D321DDF7007E5DD /* Build configuration list for PBXNativeTarget "XBridgeDemo" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C0216E6A1D67B593D084CC55 /* Release */,
+ 5915172CE0D64BA5F77731AE /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 926908D120004E2CDF95387F /* Project object */;
+}
diff --git a/examples/XBridgeDemo/XBridgeDemo.xcodeproj/xcshareddata/xcschemes/XBridgeDemo.xcscheme b/examples/XBridgeDemo/XBridgeDemo.xcodeproj/xcshareddata/xcschemes/XBridgeDemo.xcscheme
new file mode 100644
index 0000000..be305a4
--- /dev/null
+++ b/examples/XBridgeDemo/XBridgeDemo.xcodeproj/xcshareddata/xcschemes/XBridgeDemo.xcscheme
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/XBridgeDemo/XBridgeDemo/ContentView.swift b/examples/XBridgeDemo/XBridgeDemo/ContentView.swift
new file mode 100644
index 0000000..775e19f
--- /dev/null
+++ b/examples/XBridgeDemo/XBridgeDemo/ContentView.swift
@@ -0,0 +1,71 @@
+import SwiftUI
+
+struct ContentView: View {
+ private let features = [
+ Feature(title: "Build", detail: "Compile with xcodebuild", symbol: "hammer.fill", color: .blue),
+ Feature(title: "Test", detail: "XCTest & Swift Testing", symbol: "checkmark.seal.fill", color: .green),
+ Feature(title: "Run", detail: "Simulator or device", symbol: "play.circle.fill", color: .indigo),
+ Feature(title: "Diagnose", detail: "Inline build issues", symbol: "waveform.path.ecg", color: .orange),
+ ]
+
+ var body: some View {
+ NavigationStack {
+ ScrollView {
+ VStack(alignment: .leading, spacing: 24) {
+ VStack(alignment: .leading, spacing: 8) {
+ Image(systemName: "point.3.connected.trianglepath.dotted")
+ .font(.system(size: 42, weight: .semibold))
+ .foregroundStyle(.blue.gradient)
+
+ Text("Xcode power.\nVS Code flow.")
+ .font(.system(size: 36, weight: .bold, design: .rounded))
+
+ Text("A tiny project built to demonstrate XBridge.")
+ .foregroundStyle(.secondary)
+ }
+
+ LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())], spacing: 14) {
+ ForEach(features) { feature in
+ VStack(alignment: .leading, spacing: 10) {
+ Image(systemName: feature.symbol)
+ .font(.title2)
+ .foregroundStyle(feature.color)
+ Text(feature.title)
+ .font(.headline)
+ Text(feature.detail)
+ .font(.caption)
+ .foregroundStyle(.secondary)
+ }
+ .frame(maxWidth: .infinity, minHeight: 108, alignment: .leading)
+ .padding()
+ .background(.thinMaterial, in: RoundedRectangle(cornerRadius: 18))
+ }
+ }
+
+ Label("Connected to XBridge", systemImage: "checkmark.circle.fill")
+ .font(.subheadline.weight(.semibold))
+ .foregroundStyle(.green)
+ .frame(maxWidth: .infinity)
+ .padding()
+ .background(.green.opacity(0.1), in: Capsule())
+ }
+ .padding(24)
+ }
+ .background(Color(.systemGroupedBackground))
+ .navigationTitle("XBridge Demo")
+ }
+ }
+}
+
+private struct Feature: Identifiable {
+ let title: String
+ let detail: String
+ let symbol: String
+ let color: Color
+
+ var id: String { title }
+}
+
+#Preview {
+ ContentView()
+}
diff --git a/examples/XBridgeDemo/XBridgeDemo/XBridgeDemoApp.swift b/examples/XBridgeDemo/XBridgeDemo/XBridgeDemoApp.swift
new file mode 100644
index 0000000..6595fd1
--- /dev/null
+++ b/examples/XBridgeDemo/XBridgeDemo/XBridgeDemoApp.swift
@@ -0,0 +1,10 @@
+import SwiftUI
+
+@main
+struct XBridgeDemoApp: App {
+ var body: some Scene {
+ WindowGroup {
+ ContentView()
+ }
+ }
+}
diff --git a/examples/XBridgeDemo/XBridgeDemoTests/ModernTests.swift b/examples/XBridgeDemo/XBridgeDemoTests/ModernTests.swift
new file mode 100644
index 0000000..8cd4cae
--- /dev/null
+++ b/examples/XBridgeDemo/XBridgeDemoTests/ModernTests.swift
@@ -0,0 +1,9 @@
+import Testing
+@testable import XBridgeDemo
+
+struct ModernTests {
+ @Test("XBridge discovers Swift Testing tests")
+ func xbridgeDiscoversModernTests() {
+ #expect("XBridge".hasPrefix("X"))
+ }
+}
diff --git a/examples/XBridgeDemo/XBridgeDemoTests/XBridgeDemoTests.swift b/examples/XBridgeDemo/XBridgeDemoTests/XBridgeDemoTests.swift
new file mode 100644
index 0000000..1ce42de
--- /dev/null
+++ b/examples/XBridgeDemo/XBridgeDemoTests/XBridgeDemoTests.swift
@@ -0,0 +1,8 @@
+import XCTest
+@testable import XBridgeDemo
+
+final class XBridgeDemoTests: XCTestCase {
+ func testDemoProjectLoads() {
+ XCTAssertEqual(2 + 2, 4)
+ }
+}