[
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: johnno1962\npatreon: # Replace with a single Patreon username\nopen_collective: # Replace with a single Open Collective username\nko_fi: # Replace with a single Ko-fi username\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\notechie: # Replace with a single Otechie username\ncustom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']\n"
  },
  {
    "path": ".gitignore",
    "content": "# Xcode\n#\n# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore\n\n## User settings\nxcuserdata/\n\n## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)\n*.xcscmblueprint\n*.xccheckout\n\n## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)\nbuild/\nDerivedData/\n*.moved-aside\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\n\n## Obj-C/Swift specific\n*.hmap\n\n## App packaging\n*.ipa\n*.dSYM.zip\n*.dSYM\n\n## Playgrounds\ntimeline.xctimeline\nplayground.xcworkspace\n\n# Swift Package Manager\n#\n# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.\n# Packages/\n# Package.pins\nPackage.resolved\n# *.xcodeproj\n#\n# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata\n# hence it is not needed unless you have added a package configuration file to your project\n# .swiftpm\n\n.build/\n\n# CocoaPods\n#\n# We recommend against adding the Pods directory to your .gitignore. However\n# you should judge for yourself, the pros and cons are mentioned at:\n# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control\n#\n# Pods/\n#\n# Add this line if you want to avoid checking in source code from the Xcode workspace\n# *.xcworkspace\n\n# Carthage\n#\n# Add this line if you want to avoid checking in source code from Carthage dependencies.\n# Carthage/Checkouts\n\nCarthage/Build/\n\n# Accio dependency management\nDependencies/\n.accio/\n\n# fastlane\n#\n# It is recommended to not store the screenshots in the git repo.\n# Instead, use fastlane to re-generate the screenshots whenever they are needed.\n# For more information about the recommended setup visit:\n# https://docs.fastlane.tools/best-practices/source-control/#source-control\n\nfastlane/report.xml\nfastlane/Preview.html\nfastlane/screenshots/**/*.png\nfastlane/test_output\n\n# Code Injection\n#\n# After new code Injection tools there's a generated folder /iOSInjectionProject\n# https://github.com/johnno1962/injectionforxcode\n\niOSInjectionProject/\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"fishhook\"]\n\tpath = fishhook\n\turl = https://github.com/johnno1962/fishhook\n[submodule \"DLKit\"]\n\tpath = DLKit\n\turl = https://github.com/johnno1962/DLKit\n[submodule \"InjectionLite\"]\n\tpath = InjectionLite\n\turl = https://github.com/johnno1962/InjectionLite\n[submodule \"SwiftRegex5\"]\n\tpath = SwiftRegex5\n\turl = https://github.com/johnno1962/SwiftRegex5\n[submodule \"SwiftTrace\"]\n\tpath = SwiftTrace\n\turl = https://github.com/johnno1962/SwiftTrace\n"
  },
  {
    "path": ".swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "App/InjectionBundle/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>$(DEVELOPMENT_LANGUAGE)</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>Copyright © 2017 John Holdsworth. All rights reserved.</string>\n\t<key>NSPrincipalClass</key>\n\t<string></string>\n</dict>\n</plist>\n"
  },
  {
    "path": "App/InjectionBundle/InjectionBundle-Bridging-Header.h",
    "content": "//\n//  Use this file to import your target's public headers that you would like to expose to Swift.\n//\n\n#import <Foundation/Foundation.h> // Xcode 16.3??\n\n#import \"SimpleSocket.h\"\n#import \"InjectionImplC.h\"\n#import \"InjectionClient.h\"\n\n// InjectionBundle only\n#import \"fishhook.h\"\n#import \"DLKitC.h\"\n\n#import \"SwiftTrace.h\"\n"
  },
  {
    "path": "App/InjectionNext/AppDelegate.swift",
    "content": "//\n//  AppDelegate.swift\n//  InjectionNext\n//\n//  Created by John Holdsworth on 06/11/2017.\n//  Copyright © 2017 John Holdsworth. All rights reserved.\n//\n//  $Id: //depot/HotReloading/Sources/injectiond/AppDelegate.swift#76 $\n//\n//  Implementation Toolbar menu \"UI\".\n//\n\nimport Cocoa\nimport Popen\nimport SwiftRegex\n\nenum InjectionState: String {\n    case ok = \"OK\" // Orange\n    case idle = \"Idle\" // Blue\n    case busy = \"Busy\" // Green\n    case ready = \"Ready\" // Purple\n    case error = \"Error\" // Yellow\n}\n\n@objc(AppDelegate)\nclass AppDelegate: NSObject, NSApplicationDelegate {\n\n    static var ui: AppDelegate!\n\n    // Status menu\n    @IBOutlet weak var statusMenu: NSMenu!\n    @IBOutlet var statusItem: NSStatusItem!\n    // Codesigning identity\n    @IBOutlet var identityField: NSTextField!\n    // Enable injection on devices\n    @IBOutlet var deviceTesting: NSButton!\n    // Testing libraries to link with\n    @IBOutlet var librariesField: NSTextField!\n    // Place to display last error that occured\n    @IBOutlet var lastErrorField: NSTextView!\n    // Restart XCode if crashed.\n    @IBOutlet weak var launchXcodeItem: NSMenuItem!\n    @IBOutlet weak var selectXcodeItem: NSMenuItem!\n    @IBOutlet weak var restartDeviceItem: NSMenuItem!\n    @IBOutlet weak var patchCompilerItem: NSMenuItem!\n    @IBOutlet weak var enableDevicesItem: NSMenuItem!\n    @IBOutlet weak var watchDirectoryItem: NSMenuItem!\n\n    // Interface to app's persistent state.\n    @objc let defaults = Defaults.userDefaults\n\n    @IBOutlet weak var codeSignBox: NSComboBox!\n\n    /// Code signing ID as parsed from the code signing box. If the content of the box is not\n    /// parsable as SHA1 code signing ID, an empty string.\n    var codeSigningID: String { codeSignBox.stringValue.containedSHA1 ?? \"\" }\n\n    let userIDComboBoxDataSaver = UserIDComboBoxDataSaver()\n\n    @objc func applicationDidFinishLaunching(_ aNotification: Notification) {\n        // Insert code here to initialize your application\n        Self.ui = self\n\n        let appName = \"InjectionNext\"\n\n        if Bundle.main.infoDictionary?[\"LSUIElement\"] as? Bool != true {\n            NSApp.mainMenu?.item(withTitle: \"File\")?.submenu = statusMenu\n        } else {\n            let statusBar = NSStatusBar.system\n            statusItem = statusBar.statusItem(withLength: statusBar.thickness)\n            statusItem.highlightMode = true\n            statusItem.menu = statusMenu\n            statusItem.isEnabled = true\n            statusItem.title = appName\n            setMenuIcon(.idle)\n        }\n\n        signal(SIGPIPE, { which in\n            print(APP_PREFIX+\"⚠️ SIGPIPE #\\(which)\\n\" +\n                  Thread.callStackSymbols.map { var frame = $0\n                        frame[#\"(?:\\S+\\s+){3}(\\S+)\"#, 1] = {\n                            (groups: [String], stop) in\n                            return groups[1].swiftDemangle ?? groups[1] }\n                        return frame\n                    }.joined(separator: \"\\n\")) })\n\n        if let quit = statusMenu.item(at: statusMenu.items.count-1) {\n            quit.title = \"Quit \"+appName\n            if let build = Bundle.main\n                .infoDictionary?[kCFBundleVersionKey as String] {\n                quit.toolTip = \"Quit (build #\\(build))\"\n            }\n        }\n\n        librariesField.stringValue = Defaults.deviceLibraries\n        let enableDevicesSticky = false\n        if !enableDevicesSticky || Defaults.codesigningIdentity == nil {\n            enableDevicesItem.state = .on\n        }\n        deviceEnable(nil)\n        if let xcodePath = NSRunningApplication\n            .runningApplications(withBundleIdentifier: \"com.apple.dt.Xcode\")\n            .first?.bundleURL?.path {\n            if Defaults.xcodeDefault == nil {\n                Defaults.xcodeDefault = xcodePath\n            }\n            selectXcodeItem.toolTip = Defaults.xcodePath\n            if updatePatchUnpatch() == .unpatched &&\n                getenv(INJECTION_HIDE_XCODE_ALERT) == nil {\n                InjectionServer.alert(\"\"\"\n                    Please quit Xcode and\n                    use this app to launch it\n                    (unless you are using a file watcher).\n                    \"\"\")\n            }\n        }\n \n        setupCodeSigningComboBox()\n        restartDeviceItem.state = Defaults.xcodeRestart ? .on : .off\n        selectXcodeItem.toolTip = Defaults.xcodePath\n\n//        #if DEBUG\n//        if NSHomeDirectory() == \"/Users/johnholdsworth\",\n//           let path = Bundle.main.path(forResource: \"macOSInjection\", ofType: \"bundle\"),\n//           let bundle = Bundle(path: path),\n//           bundle.load() {\n//        }\n//        #endif\n\n        if let project = Defaults.projectPath {\n            _ = MonitorXcode(args: \" '\\(project)'\")\n        }\n\n        if Defaults.mcpServer {\n            LogBuffer.shared = LogBuffer()\n            ControlServer.start()\n        }\n    }\n\n    func setMenuIcon(_ state: InjectionState) {\n        DispatchQueue.main.async {\n            let tiffName = \"Injection\"+state.rawValue\n            if let path = Bundle.main.path(forResource: tiffName, ofType: \"tif\"),\n                let image = NSImage(contentsOfFile: path) {\n    //            image.template = TRUE;\n                self.statusItem.image = image\n                self.statusItem.alternateImage = image\n            }\n        }\n    }\n\n    @IBAction func runXcode(_ sender: Any) {\n        if MonitorXcode.runningXcode == nil {\n            _ = MonitorXcode()\n        }\n    }\n\n    @IBAction func selectXcode(_ sender: NSMenuItem) {\n        let open = NSOpenPanel()\n        open.prompt = \"Select Xcode\"\n        open.directoryURL = URL(fileURLWithPath: Defaults.xcodePath)\n        open.canChooseDirectories = false\n        open.canChooseFiles = true\n        if open.runModal() == .OK, let path = open.url?.path {\n            selectXcodeItem.toolTip = path\n            Defaults.xcodeDefault = path\n            updatePatchUnpatch()\n            if Defaults.xcodeRestart {\n                runXcode(sender)\n            }\n        }\n    }\n\n    lazy var startHostLocatingServerOnce: () = {\n        InjectionServer.multicastServe(HOTRELOADING_MULTICAST,\n                                       port: HOTRELOADING_PORT)\n    }()\n\n    @IBAction func deviceEnable(_ sender: NSMenuItem?) {\n        var openPort = \"\"\n        if enableDevicesItem.state.toggle() == .on {\n            if sender != nil {\n                NSApplication.shared.activate(ignoringOtherApps: true)\n                codeSignBox.window?.makeKeyAndOrderFront(sender)\n            }\n            _ = startHostLocatingServerOnce\n            openPort = \"*\"\n        }\n        if sender != nil { InjectionServer.stopLastServer() }\n        InjectionServer.startServer(openPort+INJECTION_ADDRESS)\n    }\n\n    @IBAction func testingEnable(_ sender: NSButton) {\n        if sender.state == .on, let script = Bundle.main\n            .url(forResource: \"copy_bundle\", withExtension: \"sh\") {\n            let buildPhase = \"\"\"\n                export RESOURCES=\"\\(script.deletingLastPathComponent().path)\"\n                if [ -f \"$RESOURCES/\\(script.lastPathComponent)\" ]; then\n                    \"$RESOURCES/\\(script.lastPathComponent)\"\n                fi\n                \"\"\"\n            let pasteBoard = NSPasteboard.general\n            pasteBoard.declareTypes([.string], owner:nil)\n            pasteBoard.setString(buildPhase, forType:.string)\n            InjectionServer.error(\"Run Script, Build Phase to \" +\n                  \"copy testing libraries added to clipboard.\")\n        }\n    }\n\n    @IBAction func updateLibraries(_ sender: NSTextField) {\n        Defaults.deviceLibraries = librariesField.stringValue\n    }\n\n\n    @IBAction func updateXcodeRestart(_ sender: NSMenuItem) {\n        Defaults.xcodeRestart = sender.state.toggle() == .on\n    }\n\n    @IBAction func unhideSymbols(_ sender: NSMenuItem) {\n        Unhider.startUnhide()\n    }\n\n    @IBAction func resetUnhiding(_ sender: NSMenuItem) {\n        Unhider.unhiddens.removeAll()\n    }\n\n    @IBAction func showlastError(_ sender: NSMenuItem) {\n        lastErrorField.string = NextCompiler.lastError ?? \"No error.\"\n        lastErrorField.window?.makeKeyAndOrderFront(sender)\n        NSApplication.shared.activate(ignoringOtherApps: true)\n    }\n\n    func setupCodeSigningComboBox() {\n        codeSignBox.removeAllItems()\n\n        codeSignBox.addItems(withObjectValues: userIDComboBoxDataSaver.validCodeSigningIDs)\n\n        if let savedID = userIDComboBoxDataSaver.savedID {\n            codeSignBox.stringValue = savedID\n        } else if let firstIdentity = userIDComboBoxDataSaver.validCodeSigningIDs.first {\n            codeSignBox.stringValue = firstIdentity\n        } else {\n            codeSignBox.stringValue = \"No valid code signing IDs found\"\n        }\n\n        codeSignBox.target = userIDComboBoxDataSaver\n        codeSignBox.action = #selector(UserIDComboBoxDataSaver.comboBoxValueDidChange(_:))\n    }\n}\n\nprivate extension String {\n    /// Returns the sha1 string contained in this string, or `nil` if no such string is contained.\n    var containedSHA1: String? { self[#\"([0-9A-F]{40})\"#] }\n}\n\nclass UserIDComboBoxDataSaver {\n\n    /// List of valid IDs.\n    let validCodeSigningIDs: [String] = {\n        var identities: [String] = []\n\n        let security = Topen(exec: \"/usr/bin/security\",\n                             arguments: [\"find-identity\", \"-v\", \"-p\", \"codesigning\"])\n\n        while let line = security.readLine() {\n            let components = line.split(separator: \")\", maxSplits: 1)\n            if components.count >= 2 {\n                let identity = components[1]\n                identities.append(String(identity))\n            }\n        }\n\n        return identities\n    }()\n\n    /// Last savedID, if valid. `nil` otherwise.\n    var savedID: String? {\n        guard let savedValue = Defaults.codesigningIdentity else { return nil }\n\n        return validCodeSigningIDs.first(where: { $0.containedSHA1 == savedValue.containedSHA1} )\n    }\n\n    @objc func comboBoxValueDidChange(_ sender: NSComboBox) {\n        if let newValueSHA1 = sender.stringValue.containedSHA1,\n           validCodeSigningIDs.contains(where: { $0.containedSHA1 == newValueSHA1 }) {\n            Defaults.codesigningIdentity = newValueSHA1\n        } else {\n            NSLog(\"Selected value does not contain a valid ID\")\n            return\n        }\n    }\n}\n\nprivate extension NSControl.StateValue {\n    @discardableResult\n    mutating func toggle() -> Self {\n        switch self {\n        case .on:\n            self = .off\n        case .off:\n            self = .on\n        case .mixed:\n            self = .mixed\n        default:\n            break\n        }\n        return self\n    }\n}\n"
  },
  {
    "path": "App/InjectionNext/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"mac\",\n      \"size\" : \"16x16\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"mac\",\n      \"size\" : \"16x16\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"mac\",\n      \"size\" : \"32x32\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"mac\",\n      \"size\" : \"32x32\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"mac\",\n      \"size\" : \"128x128\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"mac\",\n      \"size\" : \"128x128\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"mac\",\n      \"size\" : \"256x256\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"mac\",\n      \"size\" : \"256x256\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"mac\",\n      \"size\" : \"512x512\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"mac\",\n      \"size\" : \"512x512\",\n      \"scale\" : \"2x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "App/InjectionNext/Base.lproj/MainMenu.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"23504\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"23504\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"NSApplication\">\n            <connections>\n                <outlet property=\"delegate\" destination=\"Voe-Tx-rLC\" id=\"GzC-gU-4Uq\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customObject id=\"Voe-Tx-rLC\" customClass=\"AppDelegate\">\n            <connections>\n                <outlet property=\"codeSignBox\" destination=\"iKZ-P7-T7T\" id=\"KiT-vS-8mL\"/>\n                <outlet property=\"deviceTesting\" destination=\"SQv-Cq-gPC\" id=\"wzU-n5-tvW\"/>\n                <outlet property=\"enableDevicesItem\" destination=\"s0A-3D-ThA\" id=\"xl4-eT-1mM\"/>\n                <outlet property=\"lastErrorField\" destination=\"yfA-aU-ldx\" id=\"oxQ-Xy-ugr\"/>\n                <outlet property=\"launchXcodeItem\" destination=\"B7f-B2-5ZH\" id=\"7Pb-Cs-Q9n\"/>\n                <outlet property=\"librariesField\" destination=\"rw0-Sb-xW5\" id=\"iLm-Qn-E1h\"/>\n                <outlet property=\"patchCompilerItem\" destination=\"cw9-XM-GH8\" id=\"uKH-nc-2sg\"/>\n                <outlet property=\"restartDeviceItem\" destination=\"6cM-gd-Yoh\" id=\"vaG-Ug-i8f\"/>\n                <outlet property=\"selectXcodeItem\" destination=\"XlL-4Y-oKk\" id=\"lAe-fa-JsE\"/>\n                <outlet property=\"statusMenu\" destination=\"V8Q-mq-A2f\" id=\"Epo-HD-J21\"/>\n                <outlet property=\"watchDirectoryItem\" destination=\"fAp-yw-BqE\" id=\"hwC-GA-RNY\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"YLy-65-1bz\" customClass=\"NSFontManager\"/>\n        <menu title=\"Main Menu\" systemMenu=\"main\" id=\"AYu-sK-qS6\">\n            <items>\n                <menuItem title=\"InjectionIII\" id=\"1Xt-HY-uBw\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"InjectionIII\" systemMenu=\"apple\" id=\"uQy-DD-JDr\">\n                        <items>\n                            <menuItem title=\"About InjectionIII\" id=\"5kV-Vb-QxS\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"orderFrontStandardAboutPanel:\" target=\"-1\" id=\"Exp-CZ-Vem\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"VOq-y0-SEH\"/>\n                            <menuItem title=\"Preferences…\" keyEquivalent=\",\" id=\"BOF-NM-1cW\"/>\n                            <menuItem isSeparatorItem=\"YES\" id=\"wFC-TO-SCJ\"/>\n                            <menuItem title=\"Services\" id=\"NMo-om-nkz\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Services\" systemMenu=\"services\" id=\"hz9-B4-Xy5\"/>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"4je-JR-u6R\"/>\n                            <menuItem title=\"Hide InjectionIII\" keyEquivalent=\"h\" id=\"Olw-nP-bQN\">\n                                <connections>\n                                    <action selector=\"hide:\" target=\"-1\" id=\"PnN-Uc-m68\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Hide Others\" keyEquivalent=\"h\" id=\"Vdr-fp-XzO\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"hideOtherApplications:\" target=\"-1\" id=\"VT4-aY-XCT\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Show All\" id=\"Kd2-mp-pUS\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"unhideAllApplications:\" target=\"-1\" id=\"Dhg-Le-xox\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"kCx-OE-vgT\"/>\n                            <menuItem title=\"Quit InjectionIII\" keyEquivalent=\"q\" id=\"4sb-4s-VLi\">\n                                <connections>\n                                    <action selector=\"terminate:\" target=\"-1\" id=\"Te7-pn-YzF\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"File\" id=\"dMs-cI-mzQ\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"File\" id=\"bib-Uj-vzu\">\n                        <items>\n                            <menuItem title=\"New\" keyEquivalent=\"n\" id=\"Was-JA-tGl\">\n                                <connections>\n                                    <action selector=\"newDocument:\" target=\"-1\" id=\"4Si-XN-c54\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Open…\" keyEquivalent=\"o\" id=\"IAo-SY-fd9\">\n                                <connections>\n                                    <action selector=\"openDocument:\" target=\"-1\" id=\"bVn-NM-KNZ\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"m54-Is-iLE\"/>\n                            <menuItem title=\"Close\" keyEquivalent=\"w\" id=\"DVo-aG-piG\">\n                                <connections>\n                                    <action selector=\"performClose:\" target=\"-1\" id=\"HmO-Ls-i7Q\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Save…\" keyEquivalent=\"s\" id=\"pxx-59-PXV\">\n                                <connections>\n                                    <action selector=\"saveDocument:\" target=\"-1\" id=\"teZ-XB-qJY\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Save As…\" keyEquivalent=\"S\" id=\"Bw7-FT-i3A\">\n                                <connections>\n                                    <action selector=\"saveDocumentAs:\" target=\"-1\" id=\"mDf-zr-I0C\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Revert to Saved\" keyEquivalent=\"r\" id=\"KaW-ft-85H\">\n                                <connections>\n                                    <action selector=\"revertDocumentToSaved:\" target=\"-1\" id=\"iJ3-Pv-kwq\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"aJh-i4-bef\"/>\n                            <menuItem title=\"Page Setup…\" keyEquivalent=\"P\" id=\"qIS-W8-SiK\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" shift=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"runPageLayout:\" target=\"-1\" id=\"Din-rz-gC5\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Print…\" keyEquivalent=\"p\" id=\"aTl-1u-JFS\">\n                                <connections>\n                                    <action selector=\"print:\" target=\"-1\" id=\"qaZ-4w-aoO\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Edit\" id=\"5QF-Oa-p0T\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Edit\" id=\"W48-6f-4Dl\">\n                        <items>\n                            <menuItem title=\"Undo\" keyEquivalent=\"z\" id=\"dRJ-4n-Yzg\">\n                                <connections>\n                                    <action selector=\"undo:\" target=\"-1\" id=\"M6e-cu-g7V\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Redo\" keyEquivalent=\"Z\" id=\"6dh-zS-Vam\">\n                                <connections>\n                                    <action selector=\"redo:\" target=\"-1\" id=\"oIA-Rs-6OD\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"WRV-NI-Exz\"/>\n                            <menuItem title=\"Cut\" keyEquivalent=\"x\" id=\"uRl-iY-unG\">\n                                <connections>\n                                    <action selector=\"cut:\" target=\"-1\" id=\"YJe-68-I9s\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Copy\" keyEquivalent=\"c\" id=\"x3v-GG-iWU\">\n                                <connections>\n                                    <action selector=\"copy:\" target=\"-1\" id=\"G1f-GL-Joy\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Paste\" keyEquivalent=\"v\" id=\"gVA-U4-sdL\">\n                                <connections>\n                                    <action selector=\"paste:\" target=\"-1\" id=\"UvS-8e-Qdg\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Paste and Match Style\" keyEquivalent=\"V\" id=\"WeT-3V-zwk\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"pasteAsPlainText:\" target=\"-1\" id=\"cEh-KX-wJQ\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Delete\" id=\"pa3-QI-u2k\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"delete:\" target=\"-1\" id=\"0Mk-Ml-PaM\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Select All\" keyEquivalent=\"a\" id=\"Ruw-6m-B2m\">\n                                <connections>\n                                    <action selector=\"selectAll:\" target=\"-1\" id=\"VNm-Mi-diN\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"uyl-h8-XO2\"/>\n                            <menuItem title=\"Find\" id=\"4EN-yA-p0u\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Find\" id=\"1b7-l0-nxx\">\n                                    <items>\n                                        <menuItem title=\"Find…\" tag=\"1\" keyEquivalent=\"f\" id=\"Xz5-n4-O0W\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"cD7-Qs-BN4\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Find and Replace…\" tag=\"12\" keyEquivalent=\"f\" id=\"YEy-JH-Tfz\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"WD3-Gg-5AJ\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Find Next\" tag=\"2\" keyEquivalent=\"g\" id=\"q09-fT-Sye\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"NDo-RZ-v9R\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Find Previous\" tag=\"3\" keyEquivalent=\"G\" id=\"OwM-mh-QMV\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"HOh-sY-3ay\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Use Selection for Find\" tag=\"7\" keyEquivalent=\"e\" id=\"buJ-ug-pKt\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"U76-nv-p5D\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Jump to Selection\" keyEquivalent=\"j\" id=\"S0p-oC-mLd\">\n                                            <connections>\n                                                <action selector=\"centerSelectionInVisibleArea:\" target=\"-1\" id=\"IOG-6D-g5B\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Spelling and Grammar\" id=\"Dv1-io-Yv7\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Spelling\" id=\"3IN-sU-3Bg\">\n                                    <items>\n                                        <menuItem title=\"Show Spelling and Grammar\" keyEquivalent=\":\" id=\"HFo-cy-zxI\">\n                                            <connections>\n                                                <action selector=\"showGuessPanel:\" target=\"-1\" id=\"vFj-Ks-hy3\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Check Document Now\" keyEquivalent=\";\" id=\"hz2-CU-CR7\">\n                                            <connections>\n                                                <action selector=\"checkSpelling:\" target=\"-1\" id=\"fz7-VC-reM\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"bNw-od-mp5\"/>\n                                        <menuItem title=\"Check Spelling While Typing\" id=\"rbD-Rh-wIN\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleContinuousSpellChecking:\" target=\"-1\" id=\"7w6-Qz-0kB\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Check Grammar With Spelling\" id=\"mK6-2p-4JG\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleGrammarChecking:\" target=\"-1\" id=\"muD-Qn-j4w\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Correct Spelling Automatically\" id=\"78Y-hA-62v\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticSpellingCorrection:\" target=\"-1\" id=\"2lM-Qi-WAP\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Substitutions\" id=\"9ic-FL-obx\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Substitutions\" id=\"FeM-D8-WVr\">\n                                    <items>\n                                        <menuItem title=\"Show Substitutions\" id=\"z6F-FW-3nz\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"orderFrontSubstitutionsPanel:\" target=\"-1\" id=\"oku-mr-iSq\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"gPx-C9-uUO\"/>\n                                        <menuItem title=\"Smart Copy/Paste\" id=\"9yt-4B-nSM\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleSmartInsertDelete:\" target=\"-1\" id=\"3IJ-Se-DZD\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Smart Quotes\" id=\"hQb-2v-fYv\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticQuoteSubstitution:\" target=\"-1\" id=\"ptq-xd-QOA\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Smart Dashes\" id=\"rgM-f4-ycn\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticDashSubstitution:\" target=\"-1\" id=\"oCt-pO-9gS\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Smart Links\" id=\"cwL-P1-jid\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticLinkDetection:\" target=\"-1\" id=\"Gip-E3-Fov\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Data Detectors\" id=\"tRr-pd-1PS\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticDataDetection:\" target=\"-1\" id=\"R1I-Nq-Kbl\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Text Replacement\" id=\"HFQ-gK-NFA\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticTextReplacement:\" target=\"-1\" id=\"DvP-Fe-Py6\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Transformations\" id=\"2oI-Rn-ZJC\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Transformations\" id=\"c8a-y6-VQd\">\n                                    <items>\n                                        <menuItem title=\"Make Upper Case\" id=\"vmV-6d-7jI\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"uppercaseWord:\" target=\"-1\" id=\"sPh-Tk-edu\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Make Lower Case\" id=\"d9M-CD-aMd\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"lowercaseWord:\" target=\"-1\" id=\"iUZ-b5-hil\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Capitalize\" id=\"UEZ-Bs-lqG\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"capitalizeWord:\" target=\"-1\" id=\"26H-TL-nsh\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Speech\" id=\"xrE-MZ-jX0\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Speech\" id=\"3rS-ZA-NoH\">\n                                    <items>\n                                        <menuItem title=\"Start Speaking\" id=\"Ynk-f8-cLZ\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"startSpeaking:\" target=\"-1\" id=\"654-Ng-kyl\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Stop Speaking\" id=\"Oyz-dy-DGm\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"stopSpeaking:\" target=\"-1\" id=\"dX8-6p-jy9\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Format\" id=\"jxT-CU-nIS\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Format\" id=\"GEO-Iw-cKr\">\n                        <items>\n                            <menuItem title=\"Font\" id=\"Gi5-1S-RQB\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Font\" systemMenu=\"font\" id=\"aXa-aM-Jaq\">\n                                    <items>\n                                        <menuItem title=\"Show Fonts\" keyEquivalent=\"t\" id=\"Q5e-8K-NDq\">\n                                            <connections>\n                                                <action selector=\"orderFrontFontPanel:\" target=\"YLy-65-1bz\" id=\"WHr-nq-2xA\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Bold\" tag=\"2\" keyEquivalent=\"b\" id=\"GB9-OM-e27\">\n                                            <connections>\n                                                <action selector=\"addFontTrait:\" target=\"YLy-65-1bz\" id=\"hqk-hr-sYV\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Italic\" tag=\"1\" keyEquivalent=\"i\" id=\"Vjx-xi-njq\">\n                                            <connections>\n                                                <action selector=\"addFontTrait:\" target=\"YLy-65-1bz\" id=\"IHV-OB-c03\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Underline\" keyEquivalent=\"u\" id=\"WRG-CD-K1S\">\n                                            <connections>\n                                                <action selector=\"underline:\" target=\"-1\" id=\"FYS-2b-JAY\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"5gT-KC-WSO\"/>\n                                        <menuItem title=\"Bigger\" tag=\"3\" keyEquivalent=\"+\" id=\"Ptp-SP-VEL\">\n                                            <connections>\n                                                <action selector=\"modifyFont:\" target=\"YLy-65-1bz\" id=\"Uc7-di-UnL\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Smaller\" tag=\"4\" keyEquivalent=\"-\" id=\"i1d-Er-qST\">\n                                            <connections>\n                                                <action selector=\"modifyFont:\" target=\"YLy-65-1bz\" id=\"HcX-Lf-eNd\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"kx3-Dk-x3B\"/>\n                                        <menuItem title=\"Kern\" id=\"jBQ-r6-VK2\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <menu key=\"submenu\" title=\"Kern\" id=\"tlD-Oa-oAM\">\n                                                <items>\n                                                    <menuItem title=\"Use Default\" id=\"GUa-eO-cwY\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"useStandardKerning:\" target=\"-1\" id=\"6dk-9l-Ckg\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Use None\" id=\"cDB-IK-hbR\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"turnOffKerning:\" target=\"-1\" id=\"U8a-gz-Maa\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Tighten\" id=\"46P-cB-AYj\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"tightenKerning:\" target=\"-1\" id=\"hr7-Nz-8ro\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Loosen\" id=\"ogc-rX-tC1\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"loosenKerning:\" target=\"-1\" id=\"8i4-f9-FKE\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                </items>\n                                            </menu>\n                                        </menuItem>\n                                        <menuItem title=\"Ligatures\" id=\"o6e-r0-MWq\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <menu key=\"submenu\" title=\"Ligatures\" id=\"w0m-vy-SC9\">\n                                                <items>\n                                                    <menuItem title=\"Use Default\" id=\"agt-UL-0e3\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"useStandardLigatures:\" target=\"-1\" id=\"7uR-wd-Dx6\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Use None\" id=\"J7y-lM-qPV\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"turnOffLigatures:\" target=\"-1\" id=\"iX2-gA-Ilz\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Use All\" id=\"xQD-1f-W4t\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"useAllLigatures:\" target=\"-1\" id=\"KcB-kA-TuK\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                </items>\n                                            </menu>\n                                        </menuItem>\n                                        <menuItem title=\"Baseline\" id=\"OaQ-X3-Vso\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <menu key=\"submenu\" title=\"Baseline\" id=\"ijk-EB-dga\">\n                                                <items>\n                                                    <menuItem title=\"Use Default\" id=\"3Om-Ey-2VK\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"unscript:\" target=\"-1\" id=\"0vZ-95-Ywn\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Superscript\" id=\"Rqc-34-cIF\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"superscript:\" target=\"-1\" id=\"3qV-fo-wpU\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Subscript\" id=\"I0S-gh-46l\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"subscript:\" target=\"-1\" id=\"Q6W-4W-IGz\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Raise\" id=\"2h7-ER-AoG\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"raiseBaseline:\" target=\"-1\" id=\"4sk-31-7Q9\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Lower\" id=\"1tx-W0-xDw\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"lowerBaseline:\" target=\"-1\" id=\"OF1-bc-KW4\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                </items>\n                                            </menu>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"Ndw-q3-faq\"/>\n                                        <menuItem title=\"Show Colors\" keyEquivalent=\"C\" id=\"bgn-CT-cEk\">\n                                            <connections>\n                                                <action selector=\"orderFrontColorPanel:\" target=\"-1\" id=\"mSX-Xz-DV3\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"iMs-zA-UFJ\"/>\n                                        <menuItem title=\"Copy Style\" keyEquivalent=\"c\" id=\"5Vv-lz-BsD\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                            <connections>\n                                                <action selector=\"copyFont:\" target=\"-1\" id=\"GJO-xA-L4q\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Paste Style\" keyEquivalent=\"v\" id=\"vKC-jM-MkH\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                            <connections>\n                                                <action selector=\"pasteFont:\" target=\"-1\" id=\"JfD-CL-leO\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Text\" id=\"Fal-I4-PZk\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Text\" id=\"d9c-me-L2H\">\n                                    <items>\n                                        <menuItem title=\"Align Left\" keyEquivalent=\"{\" id=\"ZM1-6Q-yy1\">\n                                            <connections>\n                                                <action selector=\"alignLeft:\" target=\"-1\" id=\"zUv-R1-uAa\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Center\" keyEquivalent=\"|\" id=\"VIY-Ag-zcb\">\n                                            <connections>\n                                                <action selector=\"alignCenter:\" target=\"-1\" id=\"spX-mk-kcS\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Justify\" id=\"J5U-5w-g23\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"alignJustified:\" target=\"-1\" id=\"ljL-7U-jND\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Align Right\" keyEquivalent=\"}\" id=\"wb2-vD-lq4\">\n                                            <connections>\n                                                <action selector=\"alignRight:\" target=\"-1\" id=\"r48-bG-YeY\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"4s2-GY-VfK\"/>\n                                        <menuItem title=\"Writing Direction\" id=\"H1b-Si-o9J\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <menu key=\"submenu\" title=\"Writing Direction\" id=\"8mr-sm-Yjd\">\n                                                <items>\n                                                    <menuItem title=\"Paragraph\" enabled=\"NO\" id=\"ZvO-Gk-QUH\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem id=\"YGs-j5-SAR\">\n                                                        <string key=\"title\">\tDefault</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeBaseWritingDirectionNatural:\" target=\"-1\" id=\"qtV-5e-UBP\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem id=\"Lbh-J2-qVU\">\n                                                        <string key=\"title\">\tLeft to Right</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeBaseWritingDirectionLeftToRight:\" target=\"-1\" id=\"S0X-9S-QSf\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem id=\"jFq-tB-4Kx\">\n                                                        <string key=\"title\">\tRight to Left</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeBaseWritingDirectionRightToLeft:\" target=\"-1\" id=\"5fk-qB-AqJ\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem isSeparatorItem=\"YES\" id=\"swp-gr-a21\"/>\n                                                    <menuItem title=\"Selection\" enabled=\"NO\" id=\"cqv-fj-IhA\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem id=\"Nop-cj-93Q\">\n                                                        <string key=\"title\">\tDefault</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeTextWritingDirectionNatural:\" target=\"-1\" id=\"lPI-Se-ZHp\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem id=\"BgM-ve-c93\">\n                                                        <string key=\"title\">\tLeft to Right</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeTextWritingDirectionLeftToRight:\" target=\"-1\" id=\"caW-Bv-w94\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem id=\"RB4-Sm-HuC\">\n                                                        <string key=\"title\">\tRight to Left</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeTextWritingDirectionRightToLeft:\" target=\"-1\" id=\"EXD-6r-ZUu\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                </items>\n                                            </menu>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"fKy-g9-1gm\"/>\n                                        <menuItem title=\"Show Ruler\" id=\"vLm-3I-IUL\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleRuler:\" target=\"-1\" id=\"FOx-HJ-KwY\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Copy Ruler\" keyEquivalent=\"c\" id=\"MkV-Pr-PK5\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\" control=\"YES\" command=\"YES\"/>\n                                            <connections>\n                                                <action selector=\"copyRuler:\" target=\"-1\" id=\"71i-fW-3W2\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Paste Ruler\" keyEquivalent=\"v\" id=\"LVM-kO-fVI\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\" control=\"YES\" command=\"YES\"/>\n                                            <connections>\n                                                <action selector=\"pasteRuler:\" target=\"-1\" id=\"cSh-wd-qM2\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"View\" id=\"H8h-7b-M4v\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"View\" id=\"HyV-fh-RgO\">\n                        <items>\n                            <menuItem title=\"Show Toolbar\" keyEquivalent=\"t\" id=\"snW-S8-Cw5\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"toggleToolbarShown:\" target=\"-1\" id=\"BXY-wc-z0C\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Customize Toolbar…\" id=\"1UK-8n-QPP\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"runToolbarCustomizationPalette:\" target=\"-1\" id=\"pQI-g3-MTW\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"hB3-LF-h0Y\"/>\n                            <menuItem title=\"Show Sidebar\" keyEquivalent=\"s\" id=\"kIP-vf-haE\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" control=\"YES\" option=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"toggleSourceList:\" target=\"-1\" id=\"iwa-gc-5KM\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Enter Full Screen\" keyEquivalent=\"↩\" id=\"4J7-dP-txa\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" control=\"YES\" option=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"toggleFullScreen:\" target=\"-1\" id=\"dU3-MA-1Rq\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Help\" id=\"wpr-3q-Mcd\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Help\" systemMenu=\"help\" id=\"F2S-fz-NVQ\">\n                        <items>\n                            <menuItem title=\"InjectionIII Help\" keyEquivalent=\"?\" id=\"FKE-Sm-Kum\">\n                                <connections>\n                                    <action selector=\"showHelp:\" target=\"-1\" id=\"y7X-2Q-9no\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n            </items>\n            <point key=\"canvasLocation\" x=\"141\" y=\"154\"/>\n        </menu>\n        <menu autoenablesItems=\"NO\" id=\"V8Q-mq-A2f\">\n            <items>\n                <menuItem title=\"Launch Xcode\" toolTip=\"Luach supervised Xcode\" id=\"B7f-B2-5ZH\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <accessibility description=\"Launch Xcode\"/>\n                    <connections>\n                        <action selector=\"runXcode:\" target=\"Voe-Tx-rLC\" id=\"HLd-Lq-tj9\"/>\n                    </connections>\n                </menuItem>\n                <menuItem title=\"Select Xcode\" toolTip=\"Select Path to desired Xcode\" id=\"XlL-4Y-oKk\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <accessibility description=\"Select Xcode\"/>\n                    <connections>\n                        <action selector=\"selectXcode:\" target=\"Voe-Tx-rLC\" id=\"rCK-bY-XeP\"/>\n                    </connections>\n                </menuItem>\n                <menuItem title=\"Auto Restart Xcode\" toolTip=\"Restart Xcode on crash\" id=\"6cM-gd-Yoh\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <connections>\n                        <action selector=\"updateXcodeRestart:\" target=\"Voe-Tx-rLC\" id=\"KgB-zd-aHd\"/>\n                    </connections>\n                </menuItem>\n                <menuItem title=\"...or Watch Project\" toolTip=\"Start file watcher for project.\" id=\"fAp-yw-BqE\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <connections>\n                        <action selector=\"watchProject:\" target=\"Voe-Tx-rLC\" id=\"8cH-nD-fji\"/>\n                    </connections>\n                </menuItem>\n                <menuItem title=\"Intercept Compiler\" toolTip=\"Enable(Disable) interception of swift-frontend commands by replacing it with a script.\" id=\"cw9-XM-GH8\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <connections>\n                        <action selector=\"patchCompiler:\" target=\"Voe-Tx-rLC\" id=\"tSN-cc-ZSG\"/>\n                    </connections>\n                </menuItem>\n                <menuItem isSeparatorItem=\"YES\" id=\"UYl-f8-xeq\"/>\n                <menuItem title=\"Enable Devices\" toolTip=\"Enable injecting on a device\" id=\"s0A-3D-ThA\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <accessibility description=\"Evable Devices\"/>\n                    <connections>\n                        <action selector=\"deviceEnable:\" target=\"Voe-Tx-rLC\" id=\"OAF-ab-cCp\"/>\n                    </connections>\n                </menuItem>\n                <menuItem title=\"Prepare SwiftUI\" id=\"M7c-Z3-Oni\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Prepare SwiftUI\" id=\"G29-S5-KaB\">\n                        <items>\n                            <menuItem title=\"Single Source\" toolTip=\"Prepare a SwiftUI source for injection.\" id=\"92r-y9-TU2\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <accessibility description=\"Prepare Source\"/>\n                                <connections>\n                                    <action selector=\"prepareSource:\" target=\"Voe-Tx-rLC\" id=\"FhK-O3-A0w\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Entire Project\" toolTip=\"Prepare a SwiftUI sources in a target for injection.\" id=\"E0g-Zl-9YZ\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <accessibility description=\"Prepare Project\"/>\n                                <connections>\n                                    <action selector=\"prepareProject:\" target=\"Voe-Tx-rLC\" id=\"ork-tg-HB8\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Unhide Symbols\" toolTip=\"Make a pass over object files &quot;unhiding&quot; defualt argument generators\" id=\"FEE-8j-48e\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <accessibility description=\"Unhide symbols\"/>\n                    <connections>\n                        <action selector=\"unhideSymbols:\" target=\"Voe-Tx-rLC\" id=\"6qL-3s-BHb\"/>\n                    </connections>\n                </menuItem>\n                <menuItem title=\"Show Last Error\" toolTip=\"Show the last reported error.\" id=\"KKx-re-pmY\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <accessibility description=\"Show Last Error\"/>\n                    <connections>\n                        <action selector=\"showlastError:\" target=\"Voe-Tx-rLC\" id=\"B1J-ZX-nPf\"/>\n                    </connections>\n                </menuItem>\n                <menuItem title=\"Reset Unhiding\" hidden=\"YES\" toolTip=\"Reset internal storage\" id=\"ysc-5y-buR\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <accessibility description=\"Rest Unhiding\"/>\n                    <connections>\n                        <action selector=\"resetUnhiding:\" target=\"Voe-Tx-rLC\" id=\"wee-I2-883\"/>\n                    </connections>\n                </menuItem>\n                <menuItem title=\"Quit InjectionNext\" toolTip=\"Quit InjectionNext\" id=\"LUw-n8-2Gj\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <accessibility description=\"Quit\"/>\n                    <connections>\n                        <action selector=\"terminate:\" target=\"-3\" id=\"rW8-Je-8vQ\"/>\n                    </connections>\n                </menuItem>\n            </items>\n            <point key=\"canvasLocation\" x=\"3\" y=\"613\"/>\n        </menu>\n        <userDefaultsController representsSharedInstance=\"YES\" id=\"mc2-qN-cFK\"/>\n        <window title=\"Codesigning Identity\" allowsToolTipsWhenApplicationIsInactive=\"NO\" autorecalculatesKeyViewLoop=\"NO\" releasedWhenClosed=\"NO\" visibleAtLaunch=\"NO\" frameAutosaveName=\"\" animationBehavior=\"default\" id=\"p7X-fx-AEQ\" customClass=\"NSPanel\">\n            <windowStyleMask key=\"styleMask\" titled=\"YES\" closable=\"YES\" resizable=\"YES\"/>\n            <windowPositionMask key=\"initialPositionMask\" leftStrut=\"YES\" rightStrut=\"YES\" topStrut=\"YES\" bottomStrut=\"YES\"/>\n            <rect key=\"contentRect\" x=\"1355\" y=\"786\" width=\"737\" height=\"204\"/>\n            <rect key=\"screenRect\" x=\"0.0\" y=\"0.0\" width=\"2048\" height=\"1127\"/>\n            <view key=\"contentView\" id=\"Qow-ez-PwQ\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"737\" height=\"204\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n                <subviews>\n                    <textField focusRingType=\"none\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"rw0-Sb-xW5\">\n                        <rect key=\"frame\" x=\"20\" y=\"20\" width=\"697\" height=\"80\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" title=\"-framework XCTest -lXCTestSwiftSupport\" drawsBackground=\"YES\" id=\"XCE-C6-jqh\">\n                            <font key=\"font\" metaFont=\"system\"/>\n                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </textFieldCell>\n                        <connections>\n                            <action selector=\"updateLibraries:\" target=\"Voe-Tx-rLC\" id=\"Rcu-9B-dga\"/>\n                        </connections>\n                    </textField>\n                    <comboBox focusRingType=\"none\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"iKZ-P7-T7T\">\n                        <rect key=\"frame\" x=\"19\" y=\"138\" width=\"701\" height=\"23\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" flexibleMinY=\"YES\"/>\n                        <comboBoxCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" drawsBackground=\"YES\" completes=\"NO\" numberOfVisibleItems=\"5\" id=\"A2I-vj-Z1G\">\n                            <font key=\"font\" metaFont=\"system\"/>\n                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            <objectValues>\n                                <string>Item 1</string>\n                                <string>Item 2</string>\n                                <string>Item 3</string>\n                            </objectValues>\n                        </comboBoxCell>\n                    </comboBox>\n                    <textField focusRingType=\"none\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"haQ-Mn-2en\">\n                        <rect key=\"frame\" x=\"18\" y=\"168\" width=\"169\" height=\"16\"/>\n                        <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                        <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Select codesigning identity\" id=\"9V5-ch-7QQ\">\n                            <font key=\"font\" metaFont=\"system\"/>\n                            <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                            <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </textFieldCell>\n                    </textField>\n                    <button verticalHuggingPriority=\"750\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"SQv-Cq-gPC\">\n                        <rect key=\"frame\" x=\"18\" y=\"107\" width=\"321\" height=\"18\"/>\n                        <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n                        <buttonCell key=\"cell\" type=\"check\" title=\"Enable testing on device (paste into build phase)\" bezelStyle=\"regularSquare\" imagePosition=\"left\" inset=\"2\" id=\"WAY-D9-HRe\">\n                            <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                            <font key=\"font\" metaFont=\"system\"/>\n                        </buttonCell>\n                        <connections>\n                            <action selector=\"testingEnable:\" target=\"Voe-Tx-rLC\" id=\"SgW-E7-bxy\"/>\n                        </connections>\n                    </button>\n                </subviews>\n            </view>\n            <point key=\"canvasLocation\" x=\"-1244.5\" y=\"757\"/>\n        </window>\n        <window title=\"Last Compilation Error\" allowsToolTipsWhenApplicationIsInactive=\"NO\" autorecalculatesKeyViewLoop=\"NO\" releasedWhenClosed=\"NO\" visibleAtLaunch=\"NO\" frameAutosaveName=\"\" animationBehavior=\"default\" id=\"HvJ-jZ-ITN\" customClass=\"NSPanel\">\n            <windowStyleMask key=\"styleMask\" titled=\"YES\" closable=\"YES\" resizable=\"YES\"/>\n            <windowPositionMask key=\"initialPositionMask\" leftStrut=\"YES\" rightStrut=\"YES\" topStrut=\"YES\" bottomStrut=\"YES\"/>\n            <rect key=\"contentRect\" x=\"1355\" y=\"786\" width=\"688\" height=\"268\"/>\n            <rect key=\"screenRect\" x=\"0.0\" y=\"0.0\" width=\"2048\" height=\"1127\"/>\n            <view key=\"contentView\" id=\"kR1-2l-DFV\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"688\" height=\"268\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n                <subviews>\n                    <scrollView fixedFrame=\"YES\" borderType=\"none\" horizontalLineScroll=\"10\" horizontalPageScroll=\"10\" verticalLineScroll=\"10\" verticalPageScroll=\"10\" hasHorizontalScroller=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"959-C8-bvK\">\n                        <rect key=\"frame\" x=\"8\" y=\"10\" width=\"670\" height=\"251\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <clipView key=\"contentView\" drawsBackground=\"NO\" id=\"Jya-oY-Tsg\">\n                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"670\" height=\"251\"/>\n                            <autoresizingMask key=\"autoresizingMask\"/>\n                            <subviews>\n                                <textView wantsLayer=\"YES\" editable=\"NO\" importsGraphics=\"NO\" richText=\"NO\" verticallyResizable=\"YES\" spellingCorrection=\"YES\" smartInsertDelete=\"YES\" id=\"yfA-aU-ldx\">\n                                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"670\" height=\"251\"/>\n                                    <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                    <color key=\"textColor\" name=\"textColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <size key=\"minSize\" width=\"670\" height=\"251\"/>\n                                    <size key=\"maxSize\" width=\"675\" height=\"10000000\"/>\n                                </textView>\n                            </subviews>\n                        </clipView>\n                        <scroller key=\"horizontalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"YES\" id=\"xKv-Ny-an6\">\n                            <rect key=\"frame\" x=\"-100\" y=\"-100\" width=\"225\" height=\"15\"/>\n                            <autoresizingMask key=\"autoresizingMask\"/>\n                        </scroller>\n                        <scroller key=\"verticalScroller\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"NO\" id=\"cCD-KO-rn7\">\n                            <rect key=\"frame\" x=\"655\" y=\"0.0\" width=\"15\" height=\"251\"/>\n                            <autoresizingMask key=\"autoresizingMask\"/>\n                        </scroller>\n                    </scrollView>\n                </subviews>\n            </view>\n            <point key=\"canvasLocation\" x=\"69\" y=\"1096\"/>\n        </window>\n    </objects>\n</document>\n"
  },
  {
    "path": "App/InjectionNext/ControlServer.swift",
    "content": "//\n//  ControlServer.swift\n//  InjectionNext\n//\n//  Local TCP control server for MCP integration.\n//  Listens on localhost:8919 for JSON commands and\n//  maps them to existing AppDelegate actions.\n//\n\nimport Cocoa\n\n// MARK: - Log Buffer\n\nclass LogBuffer {\n\n    static var shared: LogBuffer?\n\n    struct Entry {\n        let timestamp: TimeInterval\n        let message: String\n        let level: String\n    }\n\n    private let lock = NSLock()\n    private var entries = [Entry]()\n    private let maxEntries = 2000\n\n    func append(_ message: String, level: String = \"info\") {\n        lock.lock()\n        defer { lock.unlock() }\n        entries.append(Entry(\n            timestamp: Date().timeIntervalSince1970,\n            message: message,\n            level: level\n        ))\n        if entries.count > maxEntries {\n            entries.removeFirst(entries.count - maxEntries)\n        }\n    }\n\n    func get(since: TimeInterval = 0, limit: Int = 200) -> [[String: Any]] {\n        lock.lock()\n        defer { lock.unlock() }\n        let filtered = entries.filter { $0.timestamp > since }\n        let sliced = filtered.suffix(limit)\n        return sliced.map {\n            [\"timestamp\": $0.timestamp, \"message\": $0.message, \"level\": $0.level]\n        }\n    }\n\n    func clear() {\n        lock.lock()\n        defer { lock.unlock() }\n        entries.removeAll()\n    }\n\n    var count: Int {\n        lock.lock()\n        defer { lock.unlock() }\n        return entries.count\n    }\n}\n\n// MARK: - Control Server\n\nclass ControlServer {\n\n    static let port: UInt16 = 8919\n    static var shared: ControlServer?\n\n    private var serverSocket: Int32 = -1\n    private let queue = DispatchQueue(label: \"ControlServer\", attributes: .concurrent)\n\n    static func start() {\n        guard shared == nil else { return }\n        shared = ControlServer()\n        shared?.listen()\n    }\n\n    private func listen() {\n        queue.async { [weak self] in\n            guard let self = self else { return }\n\n            self.serverSocket = socket(AF_INET, SOCK_STREAM, 0)\n            guard self.serverSocket >= 0 else {\n                NSLog(\"\\(APP_PREFIX)ControlServer: socket() failed\")\n                return\n            }\n\n            var reuse: Int32 = 1\n            setsockopt(self.serverSocket, SOL_SOCKET, SO_REUSEADDR, &reuse, socklen_t(MemoryLayout<Int32>.size))\n\n            var addr = sockaddr_in()\n            addr.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)\n            addr.sin_family = sa_family_t(AF_INET)\n            addr.sin_port = Self.port.bigEndian\n            addr.sin_addr.s_addr = inet_addr(\"127.0.0.1\")\n\n            let bindResult = withUnsafePointer(to: &addr) {\n                $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {\n                    bind(self.serverSocket, $0, socklen_t(MemoryLayout<sockaddr_in>.size))\n                }\n            }\n\n            guard bindResult == 0 else {\n                NSLog(\"\\(APP_PREFIX)ControlServer: bind() failed on port \\(Self.port): \\(String(cString: strerror(errno)))\")\n                close(self.serverSocket)\n                return\n            }\n\n            guard Darwin.listen(self.serverSocket, 5) == 0 else {\n                NSLog(\"\\(APP_PREFIX)ControlServer: listen() failed\")\n                close(self.serverSocket)\n                return\n            }\n\n            NSLog(\"\\(APP_PREFIX)ControlServer: listening on localhost:\\(Self.port)\")\n\n            while true {\n                var clientAddr = sockaddr_in()\n                var clientLen = socklen_t(MemoryLayout<sockaddr_in>.size)\n                let clientSocket = withUnsafeMutablePointer(to: &clientAddr) {\n                    $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {\n                        accept(self.serverSocket, $0, &clientLen)\n                    }\n                }\n                guard clientSocket >= 0 else { continue }\n                self.queue.async {\n                    self.handleClient(clientSocket)\n                }\n            }\n        }\n    }\n\n    private func handleClient(_ sock: Int32) {\n        defer { close(sock) }\n\n        let maxRequestSize = 64 * 1024\n        var data = Data()\n        var buf = [UInt8](repeating: 0, count: 4096)\n        while true {\n            let n = recv(sock, &buf, buf.count, 0)\n            guard n > 0 else { break }\n            data.append(contentsOf: buf[0..<n])\n            if data.contains(UInt8(ascii: \"\\n\")) { break }\n            if data.count > maxRequestSize {\n                sendResponse(sock, success: false, error: \"Request too large\")\n                return\n            }\n        }\n\n        guard !data.isEmpty,\n              let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],\n              let action = json[\"action\"] as? String else {\n            sendResponse(sock, success: false, error: \"Invalid JSON or missing 'action'\")\n            return\n        }\n\n        let result = executeAction(action, params: json)\n        sendResponse(sock, success: result.success, data: result.data, error: result.error)\n    }\n\n    private func sendResponse(_ sock: Int32, success: Bool, data: [String: Any]? = nil, error: String? = nil) {\n        var response: [String: Any] = [\"success\": success]\n        if let error = error { response[\"error\"] = error }\n        if let data = data { response[\"data\"] = data }\n        guard let jsonData = try? JSONSerialization.data(withJSONObject: response),\n              let jsonStr = String(data: jsonData, encoding: .utf8) else { return }\n        let line = jsonStr + \"\\n\"\n        _ = line.withCString { ptr in\n            send(sock, ptr, strlen(ptr), 0)\n        }\n    }\n\n    struct ActionResult {\n        let success: Bool\n        let data: [String: Any]?\n        let error: String?\n\n        static func ok(_ data: [String: Any]? = nil) -> ActionResult {\n            ActionResult(success: true, data: data, error: nil)\n        }\n        static func fail(_ error: String) -> ActionResult {\n            ActionResult(success: false, data: nil, error: error)\n        }\n    }\n\n    private func executeAction(_ action: String, params: [String: Any]) -> ActionResult {\n        switch action {\n\n        case \"status\":\n            return getStatus()\n\n        case \"watch_project\":\n            guard let path = params[\"path\"] as? String else {\n                return .fail(\"Missing 'path' parameter\")\n            }\n            return watchProject(path: path)\n\n        case \"stop_watching\":\n            return stopWatching()\n\n        case \"launch_xcode\":\n            return launchXcode()\n\n        case \"intercept_compiler\":\n            return interceptCompiler()\n\n        case \"enable_devices\":\n            let enable = params[\"enable\"] as? Bool ?? true\n            return enableDevices(enable: enable)\n\n        case \"unhide_symbols\":\n            return unhideSymbols()\n\n        case \"get_last_error\":\n            return getLastError()\n\n        case \"prepare_swiftui_source\":\n            return prepareSwiftUISource()\n\n        case \"prepare_swiftui_project\":\n            return prepareSwiftUIProject()\n\n        case \"set_xcode_path\":\n            guard let path = params[\"path\"] as? String else {\n                return .fail(\"Missing 'path' parameter\")\n            }\n            return setXcodePath(path: path)\n\n        case \"get_logs\":\n            let since = params[\"since\"] as? TimeInterval ?? 0\n            let limit = max(0, min(params[\"limit\"] as? Int ?? 200, 500))\n            return getLogs(since: since, limit: limit)\n\n        case \"clear_logs\":\n            return clearLogs()\n\n        default:\n            return .fail(\"Unknown action: \\(action)\")\n        }\n    }\n\n    // MARK: - Actions\n\n    private func getStatus() -> ActionResult {\n        var result = [String: Any]()\n        DispatchQueue.main.sync {\n            let delegate = AppDelegate.ui!\n            result[\"xcode_running\"] = MonitorXcode.runningXcode != nil\n            result[\"xcode_path\"] = Defaults.xcodePath\n            result[\"compiler_intercepted\"] = delegate.updatePatchUnpatch() == .patched\n            result[\"devices_enabled\"] = delegate.enableDevicesItem.state == .on\n            result[\"watching_directories\"] = Array(AppDelegate.watchers.keys)\n            result[\"has_connected_client\"] = InjectionServer.currentClient != nil\n            result[\"auto_restart_xcode\"] = Defaults.xcodeRestart\n            result[\"last_error\"] = NextCompiler.lastError\n        }\n        return .ok(result)\n    }\n\n    private func watchProject(path: String) -> ActionResult {\n        guard FileManager.default.fileExists(atPath: path) else {\n            return .fail(\"Path does not exist: \\(path)\")\n        }\n        DispatchQueue.main.sync {\n            Reloader.xcodeDev = Defaults.xcodePath + \"/Contents/Developer\"\n            AppDelegate.ui.watch(path: path)\n        }\n        return .ok([\"watching\": path])\n    }\n\n    private func stopWatching() -> ActionResult {\n        DispatchQueue.main.sync {\n            AppDelegate.watchers.removeAll()\n            AppDelegate.lastWatched = nil\n            AppDelegate.ui.watchDirectoryItem.state = .off\n        }\n        return .ok()\n    }\n\n    private func launchXcode() -> ActionResult {\n        DispatchQueue.main.sync {\n            if MonitorXcode.runningXcode == nil {\n                _ = MonitorXcode()\n            }\n        }\n        return .ok([\"xcode_path\": Defaults.xcodePath])\n    }\n\n    private func interceptCompiler() -> ActionResult {\n        var state = \"\"\n        DispatchQueue.main.sync {\n            let delegate = AppDelegate.ui!\n            let currentState = delegate.updatePatchUnpatch()\n            state = currentState == .patched ? \"patched\" : \"unpatched\"\n        }\n        return .ok([\"compiler_state\": state,\n                     \"note\": \"Use Xcode UI to toggle interception (requires user confirmation alert)\"])\n    }\n\n    private func enableDevices(enable: Bool) -> ActionResult {\n        DispatchQueue.main.sync {\n            let delegate = AppDelegate.ui!\n            let currentlyEnabled = delegate.enableDevicesItem.state == .on\n            if enable != currentlyEnabled {\n                delegate.deviceEnable(delegate.enableDevicesItem)\n            }\n        }\n        return .ok([\"devices_enabled\": enable])\n    }\n\n    private func unhideSymbols() -> ActionResult {\n        Unhider.startUnhide()\n        return .ok()\n    }\n\n    private func getLastError() -> ActionResult {\n        let error = NextCompiler.lastError ?? \"No error.\"\n        return .ok([\"error\": error])\n    }\n\n    private func prepareSwiftUISource() -> ActionResult {\n        guard let lastSource = NextCompiler.lastSource else {\n            return .fail(\"No source file currently being edited\")\n        }\n        DispatchQueue.main.sync {\n            AppDelegate.ui.prepareSwiftUI(source: lastSource)\n        }\n        return .ok([\"source\": lastSource])\n    }\n\n    private func prepareSwiftUIProject() -> ActionResult {\n        DispatchQueue.main.sync {\n            AppDelegate.ui.prepareProject(AppDelegate.ui.patchCompilerItem)\n        }\n        return .ok()\n    }\n\n    private func setXcodePath(path: String) -> ActionResult {\n        guard FileManager.default.fileExists(atPath: path) else {\n            return .fail(\"Xcode not found at: \\(path)\")\n        }\n        DispatchQueue.main.sync {\n            Defaults.xcodeDefault = path\n            AppDelegate.ui.selectXcodeItem.toolTip = path\n            AppDelegate.ui.updatePatchUnpatch()\n        }\n        return .ok([\"xcode_path\": path])\n    }\n\n    private func getLogs(since: TimeInterval, limit: Int) -> ActionResult {\n        let logs = LogBuffer.shared?.get(since: since, limit: limit)\n        return .ok([\"logs\": logs ?? [], \"count\": LogBuffer.shared?.count ?? 0])\n    }\n\n    private func clearLogs() -> ActionResult {\n        LogBuffer.shared?.clear()\n        return .ok()\n    }\n}\n"
  },
  {
    "path": "App/InjectionNext/Defaults.swift",
    "content": "//\n//  Defaults.swift\n//  InjectionNext\n//\n//  Created by John Holdsworth on 24/07/2024.\n//  Copyright © 2024 John Holdsworth. All rights reserved.\n//\n\nimport Foundation\n\nstruct Defaults {\n    /// App deauflts for persistent state\n    static let userDefaults = UserDefaults.standard\n    static let xcodePathDefault = \"XcodePath\"\n    static let librariesDefault = \"libraries\"\n    static let codesigningDefault = \"codesigningIdentity\"\n    private static let xcodeRestartDefault = \"xcodeRestartDefault\"\n    static var xcodePath: String {\n        xcodeDefault ?? \"/Applications/Xcode.app\" }\n    static var xcodeDefault: String? {\n        get {\n            userDefaults.string(forKey: xcodePathDefault)\n        }\n        set {\n            userDefaults.setValue(newValue,\n                                  forKey: xcodePathDefault)\n        }\n    }\n    static var deviceLibraries: String {\n        get {\n            userDefaults.string(forKey: librariesDefault) ??\n                \"-framework XCTest -lXCTestSwiftSupport\"\n        }\n        set {\n            userDefaults.setValue(newValue,\n                                  forKey: librariesDefault)\n        }\n    }\n    static var codesigningIdentity: String? {\n        get {\n            userDefaults.string(forKey: codesigningDefault)\n        }\n        set {\n            userDefaults.setValue(newValue,\n                                  forKey: codesigningDefault)\n        }\n    }   \n\n    static var xcodeRestart: Bool {\n        get {\n            if userDefaults.value(forKey: xcodeRestartDefault) == nil { return true }\n            return userDefaults.bool(forKey: xcodeRestartDefault)\n        }\n        set {\n            userDefaults.setValue(newValue,\n                                  forKey: xcodeRestartDefault)\n        }\n    }\n    static let projectPathDefault = \"projectPath\"\n    static var projectPath: String? {\n        get {\n            userDefaults.string(forKey: projectPathDefault)\n        }\n    }\n    static var mcpServer = userDefaults.bool(forKey: \"mcpServer\")\n}\n"
  },
  {
    "path": "App/InjectionNext/Experimental.swift",
    "content": "//\n//  Experimental.swift\n//  InjectionIII\n//\n//  Created by User on 20/10/2020.\n//  Copyright © 2020 John Holdsworth. All rights reserved.\n//\n//  $Id: //depot/HotReloading/Sources/injectiond/Experimental.swift#35 $\n//\n//  Some regular expressions to automatically prepare SwiftUI sources.\n//\nimport Cocoa\nimport SwiftRegex\n\nextension AppDelegate {\n\n    /// Prepare the SwiftUI source file currently being edited for injection.\n    @IBAction func prepareSource(_ sender: NSMenuItem) {\n        if let lastSource = NextCompiler.lastSource {\n            prepareSwiftUI(source: lastSource)\n        }\n    }\n\n    /// Prepare all sources in the current target for injection.\n    @IBAction func prepareProject(_ sender: NSMenuItem) {\n        var changes = 0, edited = 0\n        for source in ((MonitorXcode.runningXcode != nil ?\n                        MonitorXcode.recompiler.lastCompilation : nil) ??\n                       FrontendServer.frontendRecompiler().lastCompilation)?\n            .swiftFiles.components(separatedBy: \"\\n\").dropLast() ??\n                       Array(Recompiler.workspaceCache.keys) {\n            InjectionHybrid.lastInjected[source] = Date.timeIntervalSinceReferenceDate\n            prepareSwiftUI(source: source, changes: &changes)\n            edited += 1\n        }\n        let s = changes == 1 ? \"\" : \"s\"\n        InjectionServer.error(\"\\(changes) automatic edit\\(s) made to \\(edited) files\")\n    }\n}\n"
  },
  {
    "path": "App/InjectionNext/FrontendServer.swift",
    "content": "//\n//  FrontendServer.swift\n//  InjectionNext\n//\n//  Created by John Holdsworth on 23/02/2025.\n//  Copyright © 2025 John Holdsworth. All rights reserved.\n//\n//  Code related to \"Intercepting\" version where the binary\n//  swift-frontend is replaced by a script which feeds all\n//  compilation commands to the app where they can be reused\n//  when a file is injected to recompile individual Swift files.\n//\nimport Cocoa\nimport Popen\nimport Fortify\n\n#if INJECTION_III_APP\nstruct Unhider { static var packageFrameworks: String? }\n#endif\n\nextension NextCompiler {\n    func writeCache() {\n        FrontendServer.writeCache(for: self.name, recompiler: self)\n    }\n}\n\nclass FrontendServer: SimpleSocket {\n\n    enum State: String {\n        case unpatched = \"Intercept Compiler\"\n        case patched = \"Unpatch Compiler\"\n    }\n\n    /// Paths to unpatched/patched swift-frontend binary/script in toolchain.\n    static let frontendQueue = DispatchQueue(label: \"InjectionCapture\")\n    static var binURL: URL { URL(fileURLWithPath: Defaults.xcodePath +\n        \"/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin\") }\n    static var unpatchedURL: URL { binURL.appendingPathComponent(\"swift-frontend\") }\n    static var patched: String { unpatchedURL.path + \".save\" }\n    static var patchedURL: URL { URL(fileURLWithPath: patched) }\n    /// Path to swift-frontend  last logged.\n    static var loggedFrontend: String?\n    /// Start server for command logging.\n    static var startOnce: Void = {\n        FrontendServer.startServer(COMMANDS_PORT)\n    }()\n\n    static var clientPlatform: String {\n        InjectionServer.currentClient?.platform ?? \"iPhoneSimulator\" }\n    static func cacheURL(platform: String) -> URL {\n        return URL(fileURLWithPath: Reloader.tmpbase+\"_\\(platform)_builds.json\")\n    }\n    static private var recompilersLock = os_unfair_lock()\n    static private var recompilers = [String: NextCompiler]()\n    static func frontendRecompiler(for platform: String = clientPlatform) -> NextCompiler {\n        os_unfair_lock_lock(&recompilersLock)\n        defer { os_unfair_lock_unlock(&recompilersLock) }\n        if let recompiler = recompilers[platform] {\n            return recompiler\n        }\n        let recompiler = NextCompiler(name: platform)\n        do {\n            let compressed = cacheURL(platform: platform).path+\".gz\"\n            if Fstat(path: compressed)?.st_size ?? 0 != 0,\n               let stream = Popen(cmd: \"gunzip <\"+compressed),\n               let cached = stream.readAll().data(using: .utf8) {\n                let stored = try JSONDecoder().decode(\n                    [String: NextCompiler.Compilation].self, from: cached)\n                for source in stored.keys.sorted() {\n                    guard let compile = stored[source] else { continue }\n                    recompiler.store(compilation: compile, for: source)\n                }\n                recompiler.modified = false\n                print(\"Loaded \\(recompiler.compilations.count) \\(platform) commands.\")\n            }\n        } catch {\n            InjectionServer.error(\"Unable to read commands cache: \\(error).\")\n        }\n        recompilers[platform] = recompiler\n        return recompiler\n    }\n    static func writeCache(for platform: String, recompiler: NextCompiler? = nil) {\n        let recompiler = recompiler ?? frontendRecompiler(for: platform)\n        do {\n            let encoder = JSONEncoder()\n            encoder.outputFormatting = .prettyPrinted\n            let cache = cacheURL(platform: platform)\n            let commands = recompiler.compilations\n            try encoder.encode(commands).write(to: cache, options: .atomic)\n            if let error = Popen.system(\"gzip -f \"+cache.path, errors: true) {\n                InjectionServer.error(\"Unable to zip commands cache: \\(error)\")\n            } else {\n                print(\"Cached \\(commands.count) \\(platform) commands\")\n            }\n            recompiler.modified = false\n        } catch {\n            InjectionServer.error(\"Unable to write commands cache: \\(error)\")\n        }\n    }\n\n    func validateConnection() -> Bool {\n        return readInt() == COMMANDS_VERSION && readString() == NSHomeDirectory()\n    }\n\n    override func run() {\n        Self.frontendQueue.async {\n            do {\n                try Fortify.protect { () -> () in\n                    guard self.validateConnection(),\n                          let vers = self.readString(), vers == \"1.0\" || vers == \"2.0\" else {\n                        return Self.frontendRecompiler()\n                            .error(\"Unpatch then repatch compiler to update script version\")\n                    }\n                    try Self.processFrontendCommandFrom(feed: self)\n                }\n            } catch {\n                Self.error(\"Feed error: \\(error)\")\n            }\n        }\n    }\n\n    class func processFrontendCommandFrom(feed: SimpleSocket) throws {\n        guard var projectRoot = feed.readString(),\n              let frontendPath = feed.readString(),\n              frontendPath.hasSuffix(\".save\"),\n              feed.readString() == \"-frontend\" &&\n                feed.readString() == \"-c\" else { return }\n        \n        // swift-frontend.sh 2.0+ capture environment\n        var env: String?\n        if let pwd: String = projectRoot[\"PWD=(.*)\\n\"] ??\n                             projectRoot[\"HOME=(.*)\\n\"] {\n            env = projectRoot\n            projectRoot = pwd\n        }\n\n        var parser = CompilationArgParser()\n        while let arg = feed.readString() {\n            if arg.hasPrefix(\"llvmcas://\") { return }\n            parser.process(arg: arg, next: feed.readString)\n        }\n\n        let update = NextCompiler.Compilation(arguments: parser.args,\n            swiftFiles: parser.swiftFiles, workingDir: projectRoot, env: env)\n\n        DispatchQueue.main.async {\n            if !projectRoot.hasSuffix(\".xcodeproj\") && projectRoot != \"/\" &&\n//                MonitorXcode.runningXcode == nil &&\n                AppDelegate.alreadyWatching(projectRoot) == nil {\n                let open = NSOpenPanel()\n//                open.titleVisibility = .visible\n//                open.title = \"InjectionNext: add directory\"\n                open.prompt = \"InjectionNext - Watch Directory?\"\n                open.directoryURL = URL(fileURLWithPath: projectRoot)\n                open.canChooseDirectories = true\n                open.canChooseFiles = false\n                if open.runModal() == .OK, let url = open.url {\n                    AppDelegate.ui.watch(path: url.path)\n                }\n            }\n        }\n\n        NextCompiler.compileQueue.async {\n            let recompiler = Self.frontendRecompiler(for: parser.platform)\n            loggedFrontend = frontendPath\n\n            for source in parser.primaries {\n                #if !INJECTION_III_APP\n                // Don't update compilations while connected\n                if InjectionServer.currentClient != nil &&\n                    recompiler.canCompile(source: source, for: parser.platform) {\n                    continue\n                }\n                #endif\n\n                print(\"Updating \\(parser.args.count) args for \\(parser.platform)/\" +\n                      URL(fileURLWithPath: source).lastPathComponent)\n                recompiler.store(compilation: update, for: source)\n            }\n        }\n    }\n\n    /// Argument parser shared by FrontendServer and MonitorXcode to accumulate\n    /// compiler arguments into a NextCompiler.Compilation.\n    struct CompilationArgParser {\n        var swiftFiles = \"\"\n        var args = [String]()\n        var primaries = [String]()\n        var platform = \"iPhoneSimulator\"\n        var workingDir = \"/tmp\"\n        var swiftFileCount = 0\n        lazy var productDirSuffix = \"-\"+clientPlatform.lowercased()\n\n        /// Process one argument, calling `next()` to consume the following\n        /// token whenever the argument takes a value.\n        mutating func process(arg: String, next: () -> String?) {\n            switch arg {\n            case \"-filelist\":\n                if let filelist = next(), let files =\n                    try? String(contentsOfFile: filelist, encoding: .utf8) {\n                    swiftFiles += files\n                }\n            case \"-primary-file\":\n                if let source = next(), !source.isEmpty {\n                    primaries.append(source)\n                    if strstr(swiftFiles, source) == nil {\n                        swiftFiles += source+\"\\n\"\n                    }\n                }\n            case \"-o\":\n                if let object = next(), !object.isEmpty &&\n                    Unhider.packageFrameworks == nil {\n                    var url = URL(fileURLWithPath: object)\n                    for _ in 1...4 { url.deleteLastPathComponent() }\n                    Unhider.packageFrameworks = url.path\n                }\n            default:\n                if let sdkPlatform: String = arg[#\"/([A-Za-z]+)[\\d\\.]+\\.sdk$\"#] {\n                    platform = sdkPlatform\n                } else if args.last == \"-F\" {\n                    if arg.hasSuffix(\"/PackageFrameworks\") {\n                        Unhider.packageFrameworks = arg\n                    } else if Unhider.packageFrameworks == nil,\n                              arg.hasSuffix(productDirSuffix) {\n                        Unhider.packageFrameworks = arg+\"/PackageFrameworks\"\n                    }\n                }\n                let pathArgFlags: Set<String> = [\"-F\", \"-I\", \"-iquote\", \"-isystem\"]\n                let isPathArgValue = pathArgFlags.contains(args.last ?? \"\")\n                    || arg.hasPrefix(\"-I\") || arg.hasPrefix(\"-F\")\n                if arg.hasSuffix(\".swift\") && !isPathArgValue {\n                    swiftFiles += arg+\"\\n\"\n                    swiftFileCount += 1\n                } else if arg[Reloader.optionsToRemove] {\n                    _ = next()\n                } else if !arg[\n                    \"-validate-clang-modules-once|-frontend-parseable-output\"] {\n                    args.append(arg)\n                }\n            }\n        }\n    }\n}\n\nextension AppDelegate {\n\n    @IBAction func patchCompiler(_ sender: NSMenuItem) {\n        let fm = FileManager.default\n        do {\n            let linksToMove = [\"swift\", \"swiftc\", \"swift-symbolgraph-extract\",\n                               \"swift-api-digester\", \"swift-cache-tool\"]\n            if updatePatchUnpatch() == .unpatched {\n                if !fm.fileExists(atPath: FrontendServer.patched),\n                   let feeder = Bundle.main\n                    .url(forResource: \"swift-frontend\", withExtension: \"sh\") {\n                    let alert: NSAlert = NSAlert()\n                    alert.alertStyle = .warning\n                    alert.messageText = APP_NAME\n                    alert.informativeText = \"\"\"\n                        The Swift compiler of your current toolchain \\\n                        \\(FrontendServer.unpatchedURL.path) will be \\\n                        replaced by a script that calls the compiler \\\n                        and captures all compilation commands. Use menu \\\n                        item \"Unpatch Compiler\" to revert this change.\n                        \"\"\"\n                    alert.addButton(withTitle: \"OK\")\n                    alert.addButton(withTitle: \"Cancel\")\n                    if alert.runModal() != .alertFirstButtonReturn {\n                        return\n                    }\n                    try fm.moveItem(at: FrontendServer.unpatchedURL,\n                                    to: FrontendServer.patchedURL)\n                    try fm.copyItem(at: feeder,\n                                    to: FrontendServer.unpatchedURL)\n                    for binary in linksToMove {\n                        let link = FrontendServer.binURL\n                            .appendingPathComponent(binary)\n                        try fm.removeItem(at: link)\n                        symlink(\"swift-frontend.save\", link.path)\n                    }\n                }\n            } else if fm.fileExists(atPath: FrontendServer.patched) {\n                try? fm.removeItem(at: FrontendServer.unpatchedURL)\n                try fm.moveItem(at: FrontendServer.patchedURL,\n                                to: FrontendServer.unpatchedURL)\n                for binary in linksToMove {\n                    let link = FrontendServer.binURL\n                        .appendingPathComponent(binary)\n                    try fm.removeItem(at: link)\n                    symlink(\"swift-frontend\", link.path)\n                }\n                FrontendServer.loggedFrontend = nil\n            }\n        } catch {\n            let chmod = FrontendServer.unpatchedURL.deletingLastPathComponent()\n            InjectionServer.error(\"Patching error: \\(error). \" +\n                                  \"Is the directory \\(chmod.path) writable?\")\n        }\n        updatePatchUnpatch()\n    }\n\n    @discardableResult\n    func updatePatchUnpatch() -> FrontendServer.State {\n        let state = FileManager.default\n            .fileExists(atPath: FrontendServer.patched) ?\n            FrontendServer.State.patched : .unpatched\n        DispatchQueue.main.async {\n            self.patchCompilerItem?.title = state.rawValue\n            if state == .patched {\n                _ = FrontendServer.startOnce\n            }\n        }\n        return state\n    }\n\n    /// Shared regular expresssions to patch .enableInjection() and @ObserveInject into a source\n    func prepareSwiftUI(source: String, changes: UnsafeMutablePointer<Int>? = nil) {\n        let fileURL = URL(fileURLWithPath: source)\n        guard let original = try? String(contentsOf: fileURL) else {\n            return\n        }\n\n        var patched = original, before = changes?.pointee\n        patched[#\"\"\"\n            ^((\\s+)(public )?(var body:|func body\\([^)]*\\) -\\>) some View \\{\\n\\#\n            (\\2(?!    (if|switch|ForEach) )\\s+(?!\\.enableInjection)\\S.*\\n|(\\s*|#.+)\\n)+)(?<!#endif\\n)\\2\\}\\n\n            \"\"\"#.anchorsMatchLines, count: changes] = \"\"\"\n            $2#if DEBUG\n            $2@ObserveInjection var forceRedraw\n            $2#endif\n\n            $1$2    .enableInjection()\n            $2}\n\n            \"\"\"\n        if changes?.pointee != before {\n            print(\"Patched\", source)\n        }\n\n        if (patched.contains(\"class AppDelegate\") ||\n            patched.contains(\"@main\\n\")) &&\n            !patched.contains(\"InjectionObserver\") {\n            if !patched.contains(\"import SwiftUI\") {\n                patched += \"\\nimport SwiftUI\\n\"\n            }\n\n            patched += \"\"\"\n\n                #if canImport(HotSwiftUI)\n                @_exported import HotSwiftUI\n                #elseif canImport(Inject)\n                @_exported import Inject\n                #else\n                // This code can be found in the Swift package:\n                // https://github.com/johnno1962/HotSwiftUI or\n                // https://github.com/krzysztofzablocki/Inject\n\n                #if DEBUG\n                import Combine\n\n                public class InjectionObserver: ObservableObject {\n                    public static let shared = InjectionObserver()\n                    @Published var injectionNumber = 0\n                    var cancellable: AnyCancellable? = nil\n                    let publisher = PassthroughSubject<Void, Never>()\n                    init() {\n                        cancellable = NotificationCenter.default.publisher(for:\n                            Notification.Name(\"INJECTION_BUNDLE_NOTIFICATION\"))\n                            .sink { [weak self] change in\n                            self?.injectionNumber += 1\n                            self?.publisher.send()\n                        }\n                    }\n                }\n\n                extension SwiftUI.View {\n                    public func eraseToAnyView() -> some SwiftUI.View {\n                        return AnyView(self)\n                    }\n                    public func enableInjection() -> some SwiftUI.View {\n                        return eraseToAnyView()\n                    }\n                    public func onInjection(bumpState: @escaping () -> ()) -> some SwiftUI.View {\n                        return self\n                            .onReceive(InjectionObserver.shared.publisher, perform: bumpState)\n                            .eraseToAnyView()\n                    }\n                }\n\n                @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)\n                @propertyWrapper\n                public struct ObserveInjection: DynamicProperty {\n                    @ObservedObject private var iO = InjectionObserver.shared\n                    public init() {}\n                    public private(set) var wrappedValue: Int {\n                        get {0} set {}\n                    }\n                }\n                #else\n                extension SwiftUI.View {\n                    @inline(__always)\n                    public func eraseToAnyView() -> some SwiftUI.View { return self }\n                    @inline(__always)\n                    public func enableInjection() -> some SwiftUI.View { return self }\n                    @inline(__always)\n                    public func onInjection(bumpState: @escaping () -> ()) -> some SwiftUI.View {\n                        return self\n                    }\n                }\n\n                @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)\n                @propertyWrapper\n                public struct ObserveInjection {\n                    public init() {}\n                    public private(set) var wrappedValue: Int {\n                        get {0} set {}\n                    }\n                }\n                #endif\n                #endif\n\n                \"\"\"\n        }\n\n        if patched != original {\n            do {\n                try patched.write(to: fileURL,\n                                  atomically: true, encoding: .utf8)\n            } catch {\n                InjectionServer.error(\"Could not save \\(source): \\(error)\")\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "App/InjectionNext/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>$(DEVELOPMENT_LANGUAGE)</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIconFile</key>\n\t<string>App.icns</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(MARKETING_VERSION)</string>\n\t<key>CFBundleVersion</key>\n\t<string>14094</string>\n\t<key>LSApplicationCategoryType</key>\n\t<string>public.app-category.developer-tools</string>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>$(MACOSX_DEPLOYMENT_TARGET)</string>\n\t<key>LSUIElement</key>\n\t<true/>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>Copyright © 2017-20 John Holdsworth. All rights reserved.</string>\n\t<key>NSMainNibFile</key>\n\t<string>MainMenu</string>\n\t<key>NSPrincipalClass</key>\n\t<string>NSApplication</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "App/InjectionNext/InjectionHybrid.swift",
    "content": "//\n//  InjectionHybrid.swift\n//  InjectionNext\n//\n//  Created by John Holdsworth on 09/11/2024.\n//  Copyright © 2024 John Holdsworth. All rights reserved.\n//\n//  Provide file watcher/log parser fallback\n//  for use outside Xcode (e.g. Cursor/VSCode)\n//  Also uses FileWatcher for operation when\n//  swift-frontend has been replaced by a\n//  script to capture compiler invocations.\n//\nimport Cocoa\n\nextension AppDelegate {\n    static var watchers = [String: InjectionHybrid]()\n    static var lastWatched: String?\n\n    @IBAction func watchProject(_ sender: NSMenuItem) {\n        let open = NSOpenPanel()\n        open.prompt = \"Select Project Directory\"\n        open.canChooseDirectories = true\n        open.canChooseFiles = false\n        // open.showsHiddenFiles = TRUE;\n        if open.runModal() == .OK, let url = open.url {\n            Reloader.xcodeDev = Defaults.xcodePath+\"/Contents/Developer\"\n            watch(path: url.path)\n        } else {\n            Self.watchers.removeAll()\n            Self.lastWatched = nil\n        }\n    }\n\n    func watch(path: String) {\n        guard Self.alreadyWatching(path) == nil else { return }\n        GitIgnoreParser.monitor(directory: path)\n        Self.watchers[path] = InjectionHybrid(watching: path)\n        Self.lastWatched = path\n        watchDirectoryItem.state = Self.watchers.isEmpty ? .off : .on\n    }\n    static func alreadyWatching(_ projectRoot: String) -> String? {\n        return Self.watchers[projectRoot] != nil ? projectRoot :\n            watchers.keys.first { projectRoot.hasPrefix($0+\"/\") }\n    }\n    static func restartLastWatcher() {\n        DispatchQueue.main.async {\n            lastWatched.flatMap { watchers[$0]?.watcher?.restart() }\n        }\n    }\n}\n\nclass InjectionHybrid: InjectionBase {\n    /// Last Injected for deduplication\n    static var lastInjected = [String: TimeInterval]()\n    /// Last queue of file changes\n    static var pendingFilesChanged = [String]()\n    /// Repository locked state - stops processing until app reconnects\n    static var isRepositoryLocked = false\n    /// Path to detected git lock file - used to check if git operation still active\n    static var gitLockPath: String?\n    /// InjectionNext compiler that uses InjectionLite log parser\n    var logParsingCompiler: NextCompiler = HybridCompiler(name: \"BuildLogs\")\n    /// Minimum seconds between injections\n    let minInterval = 1.0\n\n    init(watching path: String) { // FileWatcher compatibility\n        let watchPaths = (getenv(INJECTION_DIRECTORIES) == nil ?\n            NSHomeDirectory()+\"/Library/Developer,\" : \"\") + path\n        setenv(INJECTION_DIRECTORIES, watchPaths, 1)\n        Reloader.injectionQueue = .main\n        super.init()\n        // Extend FileWatcher pattern to detect git lock files\n        FileWatcher.INJECTABLE_PATTERN = try! NSRegularExpression(\n            pattern: #\"[^~]\\.(mm?|cpp|cc|swift|lock|o)$\"#)\n    }\n\n    /// Called from file watcher when file is edited.\n    override func inject(source: String) {\n        guard MonitorXcode.runningXcode == nil else { return }\n        // Detect git lock files - record path for later checking\n        if source.hasSuffix(\".lock\") &&\n           source.contains(\"/.git/\") {\n            Self.gitLockPath = source\n            return\n        }\n\n        // Skip processing if repository is already locked\n        if Self.isRepositoryLocked {\n            log(\"\"\"\n                File processing stopped due to git lock. \\\n                Please relaunch your app to resume injection.\n                \"\"\")\n            return\n        }\n\n        // Check if source file is changing while git lock still exists\n        if let lockPath = Self.gitLockPath {\n            if FileManager.default.fileExists(atPath: lockPath) {\n                // Source files changing while git lock exists = branch switch/merge/rebase\n                Self.isRepositoryLocked = true\n                Self.pendingFilesChanged.removeAll()\n                Self.gitLockPath = nil\n                log(\"\"\"\n                    Git operation in progress (branch switch/merge/rebase detected). \\\n                    File processing stopped. Please relaunch your app to resume injection.\n                    \"\"\")\n                return\n            } else {\n                // Lock file is gone - was probably just a commit\n                Self.gitLockPath = nil\n            }\n        }\n\n        let now = Date.timeIntervalSinceReferenceDate\n        guard !AppDelegate.watchers.isEmpty, now - (\n                Self.lastInjected[source] ?? 0.0) > minInterval else {\n            return\n        }\n        Self.lastInjected[source] = now\n\n        Self.pendingFilesChanged.append(source)\n        NextCompiler.compileQueue.async {\n            self.injectNext()\n        }\n    }\n\n    func injectNext() {\n        guard let source = (DispatchQueue.main.sync { () -> String? in\n            guard let source = Self.pendingFilesChanged.first else { return nil }\n            Self.pendingFilesChanged.removeAll(where: { $0 == source })\n            if !Self.pendingFilesChanged.isEmpty {\n                NextCompiler.compileQueue.async { self.injectNext() }\n            }\n            return source\n        }) else { return }\n\n        autoreleasepool {\n        var recompiler = MonitorXcode.recompiler\n        let platform = FrontendServer.clientPlatform\n        if recompiler.canCompile(source: source, for: platform),\n           recompiler.inject(source: source) { return }\n\n        recompiler = logParsingCompiler\n        if source.hasSuffix(\".swift\") &&\n            AppDelegate.ui.updatePatchUnpatch() == .patched {\n            let proxyCompiler = FrontendServer.frontendRecompiler(for: platform)\n            if proxyCompiler.canCompile(source: source) {\n                recompiler = proxyCompiler\n            }\n        }\n\n        if let why = GitIgnoreParser.shouldExclude(file: source) {\n            log(\"Excluded \\(source) as \\(why)\")\n        } else if !recompiler.inject(source: source) {\n            recompiler.pendingSource = source\n        }\n        }\n    }\n}\n\nclass HybridCompiler: NextCompiler {\n    /// Legacy log parsing version of recomilation\n    static var liteRecompiler = Recompiler()\n\n    override func recompile(source: String, platform: String) ->  String? {\n        let oldCache = Reloader.cacheFile\n        Reloader.sdk = platform // Select commands cache file.\n        if oldCache != Reloader.cacheFile { Self.liteRecompiler = Recompiler() }\n        return Self.liteRecompiler.recompile(source: source, platformFilter:\n                                            \"SDKs/\"+platform, dylink: false)\n    }\n\n    override func link(object: String, dylib: String, arch: String) -> (String, Double)? {\n        return super.link(object: object, dylib: dylib, arch: arch) ??\n                                   Self.liteRecompiler.linkingFailed()\n    }\n}\n"
  },
  {
    "path": "App/InjectionNext/InjectionNext-Bridging-Header.h",
    "content": "//\n//  Use this file to import your target's public headers that you would like to expose to Swift.\n//\n\n#import \"SimpleSocket.h\"\n#import \"InjectionImplC.h\"\n#import \"InjectionClient.h\"\n#import \"/tmp/InjectionNextSalt.h\"\n"
  },
  {
    "path": "App/InjectionNext/InjectionNext.entitlements",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>com.apple.security.app-sandbox</key>\n\t<false/>\n\t<key>com.apple.security.files.user-selected.read-only</key>\n\t<true/>\n\t<key>com.apple.security.network.server</key>\n\t<true/>\n\t<key>com.apple.security.print</key>\n\t<false/>\n\t<key>com.apple.security.files.bookmarks.app-scope</key>\n\t<false/>\n</dict>\n</plist>\n"
  },
  {
    "path": "App/InjectionNext/InjectionServer.swift",
    "content": "//\n//  InjectionServer.swift\n//  InjectionNext\n//\n//  Created by John H on 30/05/2024.\n//  Copyright © 2024 John Holdsworth. All rights reserved.\n//\n//  Subclass of SimpleSocket to receive connection from\n//  user apps using the InjectionNext Swift Package. An\n//  incoming connection will enter runInBackground() on\n//  a background thread. Validiates the connection and\n//  forwards \"commands\" to the client app to load dynamic\n//  libraries and inject them etc. Also receives feeds\n//  of compilation commands from swift-frontend.sh.\n//\nimport Cocoa\nimport Fortify\nimport Popen\n\nclass InjectionServer: SimpleSocket {\n\n    /// So commands from differnt threads don't get mixed up\n    static let clientQueue = DispatchQueue(label: \"InjectionCommand\")\n    static private var connected = [InjectionServer]()\n    /// All access to `connected` serialised through clientQueue.\n    static var currentClients: [InjectionServer?] {\n        return clientQueue.sync { connected.isEmpty ? [nil] : connected }\n    }\n    /// Current connection to client app. There can be only one.\n    static var currentClient: InjectionServer? { currentClients.last ?? nil }\n    static var lastAlert: NSAlert?\n\n    /// Sorted last symbols exported by source.\n    var exports = [String: [String]]()\n    /// Keeps dynamic library file names unique.\n    var injectionNumber = 0\n    /// Some defaults\n    var platform = \"iPhoneSimulator\"\n    var arch = \"arm64\"\n    var tmpPath = \"/unset\"\n\n    class func alert(_ msg: String) {\n        NSLog(\"\\(APP_PREFIX)\\(APP_NAME) \\(msg)\")\n        LogBuffer.shared?.append(\"\\(APP_NAME) \\(msg)\", level: \"alert\")\n        lastAlert = NSAlert()\n        lastAlert?.messageText = \"\\(self)\"\n        lastAlert?.informativeText = msg\n        lastAlert?.alertStyle = .warning\n        lastAlert?.addButton(withTitle: \"OK\")\n        _ = lastAlert?.runModal()\n    }\n\n    /// Pops up an alert panel for networking\n    @discardableResult\n    override public class func error(_ message: String) -> Int32 {\n        let msg = String(format:message, strerror(errno))\n        LogBuffer.shared?.append(msg, level: \"error\")\n        DispatchQueue.main.async { alert(msg) }\n        return -1\n    }\n\n    // Send command to client app\n    func sendCommand(_ command: InjectionCommand, with string: String?) {\n        Self.clientQueue.async {\n            _ = self.writeCommand(command.rawValue, with: string)\n        }\n    }\n\n    // Write message into Xcode console of client app.\n    open func log(_ msg: String) {\n        NSLog(\"\\(APP_PREFIX)\\(APP_NAME) \\(msg)\")\n        LogBuffer.shared?.append(msg, level: \"info\")\n        sendCommand(.log, with: APP_PREFIX+msg)\n    }\n    open func error(_ msg: String) {\n        log(\"⚠️ \"+msg)\n    }\n\n    lazy var copyPlugIns: () = {\n        let pattern = \"/tmp/InjectionNext.PlugIns/*.xctest\"\n        if platform == \"iPhoneOS\" && isLocalClient {\n            if let errors = Popen.system(\"\"\"\n                rm -rf \"\\(tmpPath)\"/*.xctest; \\\n                rsync -a \\(pattern) \"\\(tmpPath)\"\n                \"\"\", errors: true) {\n                error(\"Copy *.xctest failed: \"+errors)\n            }\n            return\n        }\n        guard let plugins = Glob(pattern: pattern) else { return }\n        for plugin in plugins {\n            writeCommand(InjectionCommand.log.rawValue, with: APP_PREFIX+\"Sending \"+plugin)\n            let url = URL(fileURLWithPath: plugin)\n            let dest = tmpPath+\"/\"+url.lastPathComponent\n            writeCommand(InjectionCommand.sendFile.rawValue, with: dest+\"/\")\n            writeCommand(InjectionCommand.sendFile.rawValue, with: dest+\"/_CodeSignature/\")\n            for file in [url.deletingPathExtension().lastPathComponent,\n                         \"Info.plist\", \"/_CodeSignature/CodeResources\"] {\n                writeCommand(InjectionCommand.sendFile.rawValue, with: dest+\"/\"+file)\n                sendFile(url.appendingPathComponent(file).path)\n            }\n        }\n    }()\n\n    // Simple validation to weed out invalid connections\n    func validateConnection() -> Bool {\n        guard readInt() == INJECTION_VERSION,\n              let injectionKey = readString() else { return false }\n        guard injectionKey.hasPrefix(NSHomeDirectory()) else {\n            error(\"Invalid INJECTION_KEY: \"+injectionKey)\n            return false\n        }\n        return true\n    }\n\n    // On a new connection starts executing here\n    override func runInBackground() {\n        do {\n            try Fortify.protect {\n                guard validateConnection() else {\n                    sendCommand(.invalid, with: nil)\n                    error(\"Connection did not validate.\")\n                    return\n                }\n                DispatchQueue.main.async {\n                    InjectionHybrid.pendingFilesChanged.removeAll()\n                    // Reset repository locked state on app reconnect (relaunch)\n                    if InjectionHybrid.isRepositoryLocked {\n                        InjectionHybrid.isRepositoryLocked = false\n                        InjectionHybrid.gitLockPath = nil\n                        self.log(\"Repository lock cleared - injection resumed\")\n                    }\n                }\n                AppDelegate.ui.setMenuIcon(.ok)\n                processResponses()\n                AppDelegate.ui.setMenuIcon(MonitorXcode\n                    .runningXcode != nil ? .ready : .idle)\n            }\n        } catch {\n            self.error(\"\\(self) error \\(error)\")\n        }\n        Self.clientQueue.sync {\n            Self.connected.removeAll { $0 === self }\n        } // flush messages and de-register\n    }\n\n    func processResponses() {\n        sendCommand(.xcodePath, with: Defaults.xcodePath)\n        AppDelegate.restartLastWatcher()\n\n        while true {\n            let responseInt = readInt()\n            guard let response = InjectionResponse(rawValue: responseInt) else {\n                error(\"Invalid responseInt: \\(responseInt)\")\n                break\n            }\n            switch response {\n            case .platform:\n                if let platform = readString(), let arch = readString() {\n                    log(\"Platform connected: \"+platform)\n                    self.platform = platform\n                    Reloader.arch = arch\n                    self.arch = arch\n                } else {\n                    error(\"**** Bad platform ****\")\n                    return\n                }\n            case .tmpPath:\n                if let tmpPath = readString() {\n                    print(\"Tmp path: \"+tmpPath)\n                    if tmpPath.contains(\"/Xcode/UserData/Previews/\") {\n                        return\n                    }\n                    self.tmpPath = tmpPath\n                    self.tmpPath[#\"/$\"#] = \"\" // strip trailing slash\n                    Self.clientQueue.async {\n                        Self.connected.append(self)\n                    }\n                } else {\n                    error(\"**** Bad tmp ****\")\n                }\n                if MonitorXcode.runningXcode == nil &&\n                    AppDelegate.watchers.isEmpty &&\n                    AppDelegate.ui.updatePatchUnpatch() == .unpatched {\n                    error(\"\"\"\n                        Xcode not launched via app. Injection will not be possible \\ \n                        unless you file-watch a project and Xcode logs are available. \\\n                        You can add an env var INJECTION_PROJECT_ROOT to your scheme \\\n                        with value $(SRCROOT) to auto file-watch this project.\n                        \"\"\")\n                }\n                if !AppDelegate.watchers.isEmpty {\n                    log(\"Watching directory: \" +\n                        AppDelegate.watchers.keys.joined(separator: \", \"))\n                }\n            case .projectRoot:\n                if let projectRoot = readString() {\n                    log(\"Auto-watching project: \\(projectRoot)\")\n                    DispatchQueue.main.sync {\n                        AppDelegate.ui.watch(path: projectRoot)\n                        Self.lastAlert?.buttons.last?.performClick(self)\n                        Self.lastAlert = nil\n                    }\n                } else {\n                    error(\"**** Bad root ****\")\n                }\n            case .executable:\n                if let executable = readString() {\n                    Reloader.appName = URL(fileURLWithPath:\n                                            executable).lastPathComponent\n                }\n            case .detail:\n                if let detail = readString() {\n                    setenv(INJECTION_DETAIL, detail, 1)\n                }\n            case .bazelTarget:\n                if let target = readString() {\n                    log(\"Received Bazel target: \\(target)\")\n                    BazelActionQueryHandler.cachedAppTarget = target\n                    // Set environment variable so Bazel parsers can use this target\n                    setenv(INJECTION_BAZEL_TARGET, target, 1)\n                } else {\n                    error(\"**** Bad Bazel target ****\")\n                }\n            case .injected:\n                AppDelegate.ui.setMenuIcon(.ok)\n            case .failed:\n                AppDelegate.ui.setMenuIcon(.error)\n            case .unhide:\n                log(\"Injection could not load. If this was due to a default \" +\n                    \"argument. Select the app's menu item \\\"Unhide Symbols\\\".\")\n            case .exit:\n                log(\"**** client disconnected ****\")\n                return\n            @unknown default:\n                Self.error(\"**** @unknown response case \\(responseInt) ****\")\n                return\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "App/InjectionNext/MonitorXcode.swift",
    "content": "//\n//  RunXcode.swift\n//  InjectionNext\n//\n//  Created by John H on 30/05/2024.\n//  Copyright © 2024 John Holdsworth. All rights reserved.\n//\n//  Launches Xcode and monitors console output for SourceKit\n//  logging messages which reveal the compiler arguments to\n//  use for the file currently being edited (Used for real\n//  time syntax and error checking by the SourceKit daemon).\n//  Captures this information and passes it onto a Recompiler\n//  instance to process and inject when edited file is saved.\n//\nimport Foundation\nimport SwiftRegex\nimport Fortify\nimport Popen\n\nclass MonitorXcode {\n\n    // Currently running Xcode process\n    static weak var runningXcode: MonitorXcode?\n    // The service to recompile and inject a source file.\n    static var recompiler = FrontendServer.frontendRecompiler(for: \"Xcode\")\n\n    func debug(_ what: Any..., separator: String = \" \") {\n        #if DEBUG\n        print(what, separator: separator)\n        #endif\n    }\n\n    init(args: String = \"\") {\n        var args = args\n        #if DEBUG\n        args += \" | tee \\(Reloader.tmpbase).log\"\n        #endif\n        if !FileManager.default.fileExists(atPath: Defaults.xcodePath) {\n            InjectionServer.error(\"\"\"\n                No valid Xcode at path:\n                \\(Defaults.xcodePath)\n                Use menu item \"Select Xcode\"\n                to select a valid path.\n                \"\"\")\n        }\n        else if let xcodeStdout = Popen(cmd: \"\"\"\n            export SOURCEKIT_LOGGING=1\n            export RUNNING_VIA_INJECTION_NEXT=1\n            '\\(Defaults.xcodePath)/Contents/MacOS/Xcode' 2>&1 \\(args)\n            \"\"\") {\n            Self.runningXcode = self\n            AppDelegate.ui.launchXcodeItem.state = .on\n            DispatchQueue.global().async {\n                while true {\n                    do {\n                        try Fortify.protect {\n                            AppDelegate.ui.setMenuIcon(.ready)\n                            self.processSourceKitOutput(from: xcodeStdout)\n                            AppDelegate.ui.setMenuIcon(.idle)\n                        }\n                        Self.runningXcode = nil\n                        AppDelegate.ui.launchXcodeItem.state = .off\n                        if !xcodeStdout.terminatedOK() && Defaults.xcodeRestart == true {\n                            AppDelegate.ui.runXcode(self)\n                        }\n                        Self.recompiler.writeCache()\n                        break // break on clean exit and EOF.\n                    } catch {\n                        // Continue processing on error\n                        Self.recompiler.error(error)\n                    }\n                }\n            }\n        }\n    }\n\n    func processSourceKitOutput(from xcodeStdout: Popen) {\n        var buffer = [CChar](repeating: 0, count: Popen.initialLineBufferSize)\n        func readQuotedString() -> String? {\n            var offset = 0\n            let doubleQuote = Int32(UInt8(ascii: \"\\\"\")), escaped = #\"\\\"\"#\n            while let line = fgets(&buffer[offset], CInt(buffer.count-offset),\n                                   xcodeStdout.fileStream) {\n                offset += strlen(line)\n                if offset > 0 && buffer[offset-1] == UInt8(ascii: \"\\n\") {\n                    if let start = strchr(buffer, doubleQuote),\n                       let end = strrchr(start+1, doubleQuote) {\n                        end[0] = 0\n                        var out = String(cString: start+1)\n                        // Xcode used NSLog to log internal UTF8 strings\n                        // using %s which uses the macOS system encoding.\n                        // https://en.wikipedia.org/wiki/Mac_OS_Roman\n                        // For now we need to do the following dance\n                        // to revert scrambled non-ASCII file paths.\n                        if out.hasPrefix(\"/\") &&\n                            !FileManager.default.fileExists(atPath: out),\n                           let data = out.data(using: .macOSRoman),\n                           let recovered = String(data: data, encoding: .utf8),\n                           FileManager.default.fileExists(atPath: recovered) {\n                            out = recovered\n                        }\n                        if strstr(start+1, escaped) != nil {\n                            out = out.replacingOccurrences(of: escaped, with: \"\\\"\")\n                        }\n                        return out\n                    }\n\n                    return nil\n                }\n\n                var grown = [CChar](repeating: 0, count: buffer.count*2)\n                strcpy(&grown, buffer)\n                buffer = grown\n            }\n\n            return nil\n        }\n\n        let indexBuild = \"/Index.noindex/Build/\"\n        while let line = xcodeStdout.readLine() {\n//            debug(\">>\"+line+\"<<\")\n            autoreleasepool {\n            if line.hasPrefix(\"  key.request: source.request.\") &&\n                (line == \"  key.request: source.request.editor.open,\" ||\n                 line == \"  key.request: source.request.diagnostics,\" ||\n                 line == \"  key.request: source.request.activeregions,\" ||\n                 line == \"  key.request: source.request.relatedidents,\") &&\n                xcodeStdout.readLine() == \"  key.compilerargs: [\" ||\n                line == \"  key.compilerargs: [\" {\n                var parser = FrontendServer.CompilationArgParser()\n\n                while var arg = readQuotedString() {\n                    /// Used if injecting the Swift compiler.\n                    let llvmIncs = \"/llvm-macosx-arm64/lib\"\n                    if arg.hasPrefix(\"-I\"), arg.contains(llvmIncs) {\n                        arg = arg.replacingOccurrences(of: llvmIncs,\n                            with: \"/../buildbot_osx\"+llvmIncs)\n                    }\n\n                    /// Arguments received from SourceKit while syntax highlighting the editor\n                    /// have their own \"Intermediates\" directory. Map it back to the main one.\n                    let alt = arg[indexBuild, \"/Build/\"]\n                    if !arg.hasSuffix(\".yaml\"), alt != arg,\n                       !arg.contains(\"/Intermediates.noindex/\"),\n                       let path: String = alt[#\"[^/]*([^#]+)\"#],\n                       FileManager.default.fileExists(atPath: path) {\n                        arg = alt\n                    }\n\n                    // SourceKit-specific args handled before the shared parser.\n                    if arg == \"-fsyntax-only\" || arg == \"-o\" {\n                        _ = xcodeStdout.readLine()\n                    } else if var work: String = arg[#\"-working-directory(?:=(.*))?\"#] {\n                        if work == RegexOptioned.unmatchedGroup,\n                           let swork = readQuotedString() {\n                            work = swork\n                        }\n                        parser.workingDir = work\n                    } else if parser.args.last == \"-vfsoverlay\",\n                              arg.contains(indexBuild) {\n                        // injecting tests without having run tests\n                        parser.args.removeLast()\n                    } else if arg == \"-Xfrontend\" || arg.hasPrefix(\"-driver-\") {\n                        // drop silently\n                    } else {\n                        parser.process(arg: arg, next: readQuotedString)\n                    }\n                }\n\n                guard !parser.args.isEmpty, let source =\n                        readQuotedString() ?? readQuotedString(),\n                      !source.contains(\"\\\\n\") else {\n                    return\n                }\n\n                print(\"Updating \\(parser.args.count) args with \\(parser.swiftFileCount) swift files \"+source+\" \"+line)\n                let update = NextCompiler.Compilation(arguments: parser.args,\n                    swiftFiles: parser.swiftFiles, workingDir: parser.workingDir)\n\n                NextCompiler.compileQueue.async {\n                    Self.recompiler.store(compilation: update, for: source)\n                }\n            } else if line ==\n                \"  key.request: source.request.indexer.editor-did-save-file,\",\n                let _ = xcodeStdout.readLine(), let source = readQuotedString() {\n                print(\"Injecting saved file \"+source)\n                NextCompiler.compileQueue.async {\n                    _ = Self.recompiler.inject(source: source)\n                }\n            }\n        }\n        }\n    }\n}\n"
  },
  {
    "path": "App/InjectionNext/NextCompiler.swift",
    "content": "//\n//  Recompiler.swift\n//  InjectionNext\n//\n//  Created by John Holdsworth on 21/06/2024.\n//  Copyright © 2024 John Holdsworth. All rights reserved.\n//\n//  Server side implementation of injection.\n//  Recompile, link, codesign, send to client.\n//\nimport Foundation\nimport Fortify\nimport Popen\nimport DLKit\n\n/// bring in injectingXCTest()\nstruct Reloader {}\n\n@discardableResult\npublic func log(_ what: Any..., prefix: String = APP_PREFIX, separator: String = \" \") -> Bool {\n    var msg = what.map {\"\\($0)\"}.joined(separator: separator)\n    #if INJECTION_III_APP\n    msg = \"⏳ \"+msg\n    #else\n    msg = prefix+msg\n    LogBuffer.shared?.append(msg, level: \"info\")\n    #endif\n    print(msg)\n    for client in InjectionServer.currentClients {\n        client?.sendCommand(.log, with: msg)\n    }\n    return true\n}\n\nclass NextCompiler {\n\n    /// Information required to call the compiler for a file.\n    struct Compilation: Codable, Hashable {\n        /// Sundry arguments to the compiler\n        let arguments: [String]\n        /// Swift files in the target ready to be written as a -filelist\n        let swiftFiles: String\n        /// Directory to run compiler in (not important for Swift)\n        let workingDir: String\n        /// captured environment\n        var env: String?\n    }\n\n    /// Queue for one compilation at a time.\n    static let compileQueue = DispatchQueue(label: \"InjectionCompile\")\n    /// Last build error.\n    static var lastError: String?, lastSource: String?\n\n    let name: String\n    /// Base for temporary files\n    let tmpbase = \"/tmp/injectionNext\"\n    /// Injection pending if information was not available\n    var pendingSource: String?\n    /// Information for compiling a file per source file.\n    var compilations = [String: Compilation]()\n    /// Trying to avoid fragmenting memory\n    var lastCompilation: Compilation?\n    /// Previous dynamic libraries prepared by source file\n    var prepared = [String: String]()\n    /// Invalidate on three failures\n    var strikes = [String: Int]()\n    /// Default counter for Compilertron\n    var compileNumber = 0\n    \n    init(name: String) {\n        self.name = name\n    }\n\n    func error(_ msg: String) {\n        let msg = \"⚠️ \"+msg\n        NSLog(msg)\n        log(msg)\n    }\n    func error(_ err: Error) {\n        error(\"Internal app error: \\(err)\")\n    }\n    \n    var modified = false\n\n    func store(compilation: Compilation, for source: String) {\n        Self.lastSource = source\n        if lastCompilation != compilation {\n            lastCompilation = compilation\n        } //else { print(\"reusing\") }\n        if compilations[source] != lastCompilation {\n            compilations[source] = lastCompilation\n            modified = true\n        }\n        if source == pendingSource {\n            print(\"Delayed injection of \"+source)\n            if inject(source: source) {\n                pendingSource = nil\n            }\n        }\n    }\n    \n    func canCompile(source: String, for platform: String? = nil) -> Bool {\n        if let compilation = compilations[source],\n           platform == nil || (\"SDKs/\"+platform!).withCString({ sdk in\n               compilation.arguments.first { strstr($0, sdk) != nil }}) != nil {\n            return true\n        } else { return false }\n    }\n\n    /// Main entry point called by MonitorXcode\n    func inject(source: String) -> Bool {\n        // Start tracking metrics\n        currentMetrics = InjectionMetricsTracker(sourcePath: source)\n\n        do {\n            let result = try Fortify.protect { () -> Bool in\n                for client in InjectionServer.currentClients.reversed() {\n                guard let (dylib, dylibName, platform, useFilesystem)\n                        = try prepare(source: source, connected: client),\n                   let data = codesign(dylib: dylib, platform: platform) else {\n                    error(\"Injection failed. Was your app connected?\")\n                    AppDelegate.ui.setMenuIcon(.error)\n                    return false\n                }\n\n                InjectionServer.clientQueue.sync {\n                    guard let client = client else {\n                        AppDelegate.ui.setMenuIcon(.ready)\n                        return\n                    }\n//                    if Reloader.injectingXCTest(in: dylib) {\n//                        _ = client.copyPlugIns\n//                    }\n                    if useFilesystem {\n                        client.writeCommand(InjectionCommand\n                            .load.rawValue, with: dylib)\n                    } else {\n                        client.writeCommand(InjectionCommand\n                            .inject.rawValue, with: dylibName)\n                        client.write(data)\n                    }\n                    unsupported(source: source, dylib: dylib, client: client)\n                }\n                }\n                Self.lastSource = source\n                if modified {\n                    writeCache()\n                }\n                return true\n            }\n\n            // Calculate total time and send metrics\n            if let metrics = currentMetrics {\n                metrics.success = result\n                sendMetrics(metrics)\n            }\n\n            return result\n        } catch {\n            // Send failure metrics\n            if let metrics = currentMetrics {\n                metrics.success = false\n                sendMetrics(metrics)\n            }\n            self.error(error)\n            return false\n        }\n    }\n\n    /// Seek to highlight potentially unsupported injections.\n    func unsupported(source: String, dylib: String, client: InjectionServer) {\n        #if !INJECTION_III_APP\n        if let symbols = FileSymbols(path: dylib)?.trieSymbols()?\n            .filter({ entry in\n                lazy var symbol: String = String(cString: entry.name)\n                return strncmp(entry.name, \"_$s\", 3) == 0 &&\n                strstr(entry.name, \"fU\") == nil && // closures\n                !symbol.hasSuffix(\"MD\") && !symbol.hasSuffix(\"Oh\") &&\n                !symbol.hasSuffix(\"Wl\") && !symbol.hasSuffix(\"WL\") })\n            .map({ String(cString: $0.name) }).sorted() {\n//            print(symbols)\n            if let previous = client.exports[source],\n               previous.count != symbols.count {\n                log(\"ℹ️ Symbols altered, this may not be supported.\" +\n                      \" \\(symbols.count) c.f. \\(previous.count)\")\n                if #available(macOS 15.0, *) {\n                    print(symbols.difference(from: previous))\n                }\n            }\n            client.exports[source] = symbols\n        }\n        #endif\n    }\n\n    func prepare(source: String, connected: InjectionServer?) throws\n        -> (dylib: String, dylibName: String, platform: String, Bool)? {\n        AppDelegate.ui.setMenuIcon(.busy)\n        connected?.injectionNumber += 1\n        compileNumber += 1\n        Self.lastError = nil\n\n        // Support for https://github.com/johnno1962/Compilertron\n        let isCompilertron = connected == nil && source.hasSuffix(\".cpp\")\n        let compilerTmp = \"/tmp/compilertron_patches\"\n        let compilerPlatform = \"MacOSX\"\n        let compilerArch = \"arm64\"\n\n        let tmpPath = connected?.tmpPath ?? compilerTmp\n        let platform = connected?.platform ?? compilerPlatform\n        let sourceName = URL(fileURLWithPath: source)\n            .deletingPathExtension().lastPathComponent\n        if isCompilertron, let previous = prepared[sourceName] {\n            unlink(previous)\n        }\n\n        let dylibName = DYLIB_PREFIX + sourceName +\n            \"_\\(connected?.injectionNumber ?? compileNumber).dylib\"\n        let useFilesystem = connected?.isLocalClient != false\n        #if INJECTION_III_APP\n        let dylibPath = (true ? tmpPath : \"/tmp\") + dylibName\n        #else\n        let dylibPath = (useFilesystem ? tmpPath : \"/tmp\") + dylibName\n        #endif\n        guard let object = try recompile(source: source, platform: platform), {\n                // Track compilation time\n                if let startTime = currentMetrics?.startTime {\n                    currentMetrics?.compilationTimeMs =\n                    (Date.timeIntervalSinceReferenceDate - startTime) * 1000\n                }\n                return true\n            }(),\n           tmpPath != compilerTmp || mkdir(compilerTmp, 0o777) != -999,\n           let (dylib, linkingTimeMs) = link(object: object, dylib: dylibPath,\n                    arch: connected?.arch ?? compilerArch) else {\n                        let strike = (strikes[source] ?? 0)+1\n                        strikes[source] = strike\n                        if strike >= 3 {\n                            compilations.removeValue(forKey: source)\n                            writeCache()\n                        }\n                        return nil\n                    }\n\n        currentMetrics?.linkingTimeMs = linkingTimeMs\n\n        strikes[source] = 0\n        prepared[sourceName] = dylib\n        print(\"Prepared dylib: \"+dylib)\n        return (dylib, dylibName, platform, useFilesystem)\n    }\n\n    /// Compile a source file using inforation provided by MonitorXcode\n    /// task and return the full path to the resulting object file.\n    func recompile(source: String, platform: String) throws ->  String? {\n        guard let stored = compilations[source] else {\n            error(\"Postponing: \\(source) Have you viewed it in Xcode?\")\n            pendingSource = source\n            return nil\n        }\n\n        let uniqueObject = InjectionServer.currentClient?.injectionNumber ?? 0\n        let object = tmpbase+\"_\\(uniqueObject).o\"\n        let isSwift = source.hasSuffix(\".swift\")\n        let filesfile = tmpbase+\".filelist\"\n\n        unlink(object)\n        unlink(filesfile)\n        try stored.swiftFiles.write(toFile: filesfile,\n                                    atomically: false, encoding: .utf8)\n\n        log(\"Recompiling: \"+source)\n        let toolchain = Defaults.xcodePath +\n            \"/Contents/Developer/Toolchains/XcodeDefault.xctoolchain\"\n        let compiler = (isSwift ? FrontendServer.loggedFrontend : nil) ??\n            toolchain + \"/usr/bin/\" + (isSwift ? \"swift-frontend\" : \"clang\")\n        let platformUsr = Defaults.xcodePath + \"/Contents/Developer/Platforms/\" +\n            platform.replacingOccurrences(of: \"Simulator\", with: \"OS\") +\n            \".platform/Developer/usr/\"\n        let baseOptionsToAdd = [\"-o\", object, \"-DDEBUG\", \"-DINJECTING\"]\n        let languageSpecific = (isSwift ?\n            [\"-c\", \"-filelist\", filesfile, \"-primary-file\", source,\n             Reloader.typeCheckLimit,\n             \"-external-plugin-path\",\n             platformUsr+\"lib/swift/host/plugins#\" +\n             platformUsr+\"bin/swift-plugin-server\",\n             \"-external-plugin-path\",\n             platformUsr+\"local/lib/swift/host/plugins#\" +\n             platformUsr+\"bin/swift-plugin-server\",\n             \"-plugin-path\", toolchain+\"/usr/lib/swift/host/plugins\",\n             \"-plugin-path\", toolchain+\"/usr/local/lib/swift/host/plugins\"] :\n            [\"-c\", source, \"-Xclang\", \"-fno-validate-pch\"]) + baseOptionsToAdd\n        let wmoFlags: Set<String> = [\n            \"-whole-module-optimization\",\n            \"-internalize-at-link\",\n            \"-no-serialize-debugging-options\"\n        ]\n        var arguments = [String]()\n        var skipNext = false\n        for arg in stored.arguments where !wmoFlags.contains(arg) {\n            if skipNext { skipNext = false; continue }\n            if arg == \"-o\" { skipNext = true; continue }\n            arguments.append(arg)\n        }\n        if let target = InjectionServer.currentClient?.arch, target != \"arm64\" {\n            // Simulator running in Rosetta.\n            for i in 0..<arguments.count {\n                arguments[i][#\"^(\\w+)-apple-ios\"#] = target\n            }\n        }\n        // Call compiler process with timing\n        let compilationStartTime = Date.timeIntervalSinceReferenceDate\n        var env: [String: String]?\n        if let environment = stored.env {\n            env = [String: String]()\n            for (key, value): (String, String) in environment[\n                #\"^(\\w+)=(.*)\"#.anchorsMatchLines] {\n                env?[key] = value\n            }\n        }\n        let compile = Topen(exec: compiler,\n                            arguments: arguments + languageSpecific,\n                            cd: stored.workingDir, env: env)\n\n        var errors = \"\"\n        while let line = compile.readLine() {\n            if let slow: String = line[Reloader.typeCheckRegex] {\n                log(slow)\n            }\n            errors += line+\"\\n\"\n        }\n        if errors.contains(\" error: \") {\n            error(\"Failed compilation: \"+([compiler] + arguments +\n                        languageSpecific).joined(separator: \" \"))\n            error(\"Recompile failed for: \\(source)\\n\"+errors)\n            Self.lastError = errors\n            return nil\n        }\n\n        // Log successful compilation with timing\n        let now = Date.timeIntervalSinceReferenceDate\n        let compilationTimeMs = (now - compilationStartTime) * 1000\n        detail(String(format: \"⚡ Compiled for \\(name) in %.0fms\",\n                      compilationTimeMs))\n\n        let compilationCommand = (arguments + languageSpecific)\n            .map { $0[#\"([ $()])\"#, \"\\\\\\\\$1\"] }.joined(separator:  \" \")\n        Reloader.extractLinkCommand(from: compilationCommand)\n        return object\n    }\n\n    /// Link and object file to create a dynamic library\n    func link(object: String, dylib: String, arch: String) -> (String, Double)? {\n        let linkingStartTime = Date.timeIntervalSinceReferenceDate\n        var linkCommand = Reloader.linkCommand + \" \\(object) -o \\\"\\(dylib)\\\" \"\n        if DispatchQueue.main.sync(execute: {\n            AppDelegate.ui.deviceTesting?.state == .on }) {\n            let otherOptions = DispatchQueue.main.sync { () -> String in\n                AppDelegate.ui.librariesField.stringValue = Defaults.deviceLibraries\n                return Defaults.deviceLibraries }\n            let platformDev = \"\\(Reloader.xcodeDev)/Platforms/\\(Reloader.platform).platform/Developer\"\n            linkCommand += \"\"\"\n                -F /tmp/InjectionNext.Products \\\n                -F \"\\(platformDev)/Library/Frameworks\" \\\n                -L \"\\(platformDev)/usr/lib\" \\(otherOptions)\n                \"\"\".replacingOccurrences(of: \"__PLATFORM__\", with: Reloader.sysroot)\n        }\n\n        if let errors = Popen.system(linkCommand, errors: true) {\n            error(\"Linking failed:\\n\\(linkCommand)\\nerrors:\\n\"+errors)\n            Self.lastError = errors\n            return nil\n        }\n\n        let linkingTimeMs = (Date.timeIntervalSinceReferenceDate - linkingStartTime) * 1000\n        return (dylib, linkingTimeMs)\n    }\n\n    /// Codesign a dynamic library\n    func codesign(dylib: String, platform: String) -> Data? {\n        if platform != \"iPhoneSimulator\" {\n        var identity = \"-\"\n        if !platform.hasSuffix(\"Simulator\") && platform != \"MacOSX\" {\n            identity = DispatchQueue.main.sync { AppDelegate.ui.codeSigningID }\n            log(\"Codesigning dylib with identity \"+identity)\n        }\n        let codesign = \"\"\"\n            (export CODESIGN_ALLOCATE=\"\\(Defaults.xcodePath+\"/Contents/Developer\"\n             )/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate\"; \\\n            if /usr/bin/file \\\"\\(dylib)\\\" | /usr/bin/grep ' shared library ' >/dev/null; \\\n            then /usr/bin/codesign --force -s \"\\(identity)\" \\\"\\(dylib)\\\";\\\n            else exit 1; fi)\n            \"\"\"\n        if let errors = Popen.system(codesign, errors: true) {\n            error(\"Codesign failed \\(codesign) errors:\\n\"+errors)\n            Self.lastError = errors\n        }\n        }\n        return try? Data(contentsOf: URL(fileURLWithPath: dylib))\n    }\n\n    /// Tracks timing metrics for injection process\n    final class InjectionMetricsTracker: Codable {\n        var compilationTimeMs: Double = 0\n        var linkingTimeMs: Double = 0\n        var totalTimeMs: Double = 0\n        var sourcePath: String\n        var bazelTarget: String?\n        var success: Bool = false\n        var notificationName: String = INJECTION_METRICS_NOTIFICATION\n        let startTime: Double\n\n        init(sourcePath: String) {\n            self.sourcePath = sourcePath\n            self.startTime = Date.timeIntervalSinceReferenceDate\n        }\n    }\n\n    /// Current metrics being tracked\n    var currentMetrics: InjectionMetricsTracker?\n\n    /// Enrich metrics with Bazel target and normalize source path\n    #if !INJECTION_III_APP\n    func enrichMetrics(_ metrics: inout InjectionMetricsTracker) {\n        let sourcePath = metrics.sourcePath\n\n        // Find workspace root to normalize the path\n        if let workspaceRoot = BazelInterface.findWorkspaceRoot(containing: sourcePath) {\n            let workspaceRootPath = (workspaceRoot as NSString).standardizingPath\n            let fullPath = (sourcePath as NSString).standardizingPath\n\n            // Normalize sourcePath to workspace-relative (in place)\n            if fullPath.hasPrefix(workspaceRootPath + \"/\") {\n                metrics.sourcePath = String(fullPath.dropFirst(workspaceRootPath.count + 1))\n            } else {\n                metrics.sourcePath = URL(fileURLWithPath: sourcePath).lastPathComponent\n            }\n\n            // Try to discover the Bazel app target\n            do {\n                let queryHandler = try BazelAQueryParser(workspaceRoot: workspaceRoot)\n                queryHandler.autoDiscoverAppTarget(for: sourcePath)\n                metrics.bazelTarget = queryHandler.getAppTarget()\n            } catch {\n                // Bazel discovery failed, metrics will have nil bazelTarget\n                print(\"⚠️ Could not discover Bazel target for \\(sourcePath): \\(error)\")\n            }\n        }\n    }\n    #endif\n\n    /// Send metrics to all connected clients\n    func sendMetrics(_ metrics: InjectionMetricsTracker) {\n        #if !INJECTION_III_APP\n        if AppDelegate.watchers.isEmpty &&\n            BazelActionQueryHandler.cachedAppTarget == nil { return }\n        metrics.totalTimeMs = (Date.timeIntervalSinceReferenceDate\n                               - metrics.startTime) * 1000\n        var enrichedMetrics = metrics\n        enrichMetrics(&enrichedMetrics)\n\n        let encoder = JSONEncoder()\n        encoder.keyEncodingStrategy = .convertToSnakeCase\n        guard let jsonData = try? encoder.encode(enrichedMetrics),\n              let jsonString = String(data: jsonData, encoding: .utf8) else {\n            return\n        }\n        for client in InjectionServer.currentClients {\n            client?.sendCommand(.metrics, with: jsonString)\n        }\n        #endif\n    }\n}\n"
  },
  {
    "path": "App/InjectionNext/build_bundle.sh",
    "content": "#!/bin/sh -x\n\n#  build_bundle.sh\n#  InjectionNext\n#\n#  Created by John Holdsworth on 22/07/2024.\n#  Copyright © 2024 John Holdsworth. All rights reserved.\n\nFAMILY=$1\nPLATFORM=$2\nSDK=\"$(echo $PLATFORM | tr \"[A-Z]\" \"[a-z]\")\"\nsleep $3\n\nFIXED_XCODE_DEVELOPER_PATH=/Applications/Xcode.app/Contents/Developer\nexport SWIFT_ACTIVE_COMPILATION_CONDITIONS=\"\"\n\n    SWIFT_DYLIBS_PATH=\"$FIXED_XCODE_DEVELOPER_PATH/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/$SDK\"\n    CONCURRENCY_DYLIBS=\"$FIXED_XCODE_DEVELOPER_PATH/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/$SDK\"\n    XCODE_PLATFORM_PATH=\"$FIXED_XCODE_DEVELOPER_PATH/Platforms/$PLATFORM.platform\"\n    XCTEST_FRAMEWORK_PATH=\"$XCODE_PLATFORM_PATH/Developer/Library/Frameworks\"\n    XCTEST_SUPPORT_PATH=\"$XCODE_PLATFORM_PATH/Developer/usr/lib\"\n    BUNDLE_CONFIG=Debug\n\n    if [ ! -d \"$SWIFT_DYLIBS_PATH\" -o ! -d \"${XCTEST_FRAMEWORK_PATH}/XCTest.framework\" ]; then\n        echo \"Missing RPATH $SWIFT_DYLIBS_PATH $XCTEST_FRAMEWORK_PATH\"\n        exit 1\n    fi\n    \n    ADD_INSTALL_NAME=\"\"\n    if [[ ${FAMILY} =~ Dev ]]; then\n        # real devices require a copy_bundle.sh build phase\n        ADD_INSTALL_NAME=\"LD_DYLIB_INSTALL_NAME=@rpath/lib${SDK}Injection.dylib\"\n    fi\n    for i in 1 2 3; do if\n    \"$DEVELOPER_BIN_DIR\"/xcodebuild SYMROOT=$SYMROOT ARCHS=\"$ARCHS\" $APP_SANDBOXED PRODUCT_NAME=\"${FAMILY}Injection\" LD_RUNPATH_SEARCH_PATHS=\"@loader_path/Frameworks @loader_path/${FAMILY}Injection.bundle/Frameworks $SWIFT_DYLIBS_PATH $CONCURRENCY_DYLIBS $XCTEST_FRAMEWORK_PATH $XCTEST_SUPPORT_PATH\" $ADD_INSTALL_NAME PLATFORM_DIR=\"$DEVELOPER_DIR/Platforms/$PLATFORM.platform\" -sdk $SDK -config $BUNDLE_CONFIG  -target InjectionBundle; then\n#-archivePath \"/tmp/Archive.$SDK\" -derivedDataPath \"/tmp/Derived.$SDK\"\n            break\n        elif [ \"$i\" = \"3\" ]; then\n            exit 1\n        fi\n        echo \"Retrying...\";\n    done &&\n    \n    rsync -au $SYMROOT/$BUNDLE_CONFIG-$SDK/*.bundle \"$CODESIGNING_FOLDER_PATH/Contents/Resources\" &&\n    ln -sf \"${FAMILY}Injection.bundle/${FAMILY}Injection\" \"$CODESIGNING_FOLDER_PATH/Contents/Resources/lib${SDK}Injection.dylib\"\n"
  },
  {
    "path": "App/InjectionNext/build_bundles.sh",
    "content": "#!/bin/sh\n\n#  build_bundles.sh\n#  InjectionNext\n#\n#  Created by John Holdsworth on 22/07/2024.\n#  Copyright © 2024 John Holdsworth. All rights reserved.\n\nFIXED_XCODE_DEVELOPER_PATH=/Applications/Xcode.app/Contents/Developer\nexport SWIFT_ACTIVE_COMPILATION_CONDITIONS=\"\"\nBUILD=`/usr/libexec/PlistBuddy -c \"Print :CFBundleVersion\" $CODESIGNING_FOLDER_PATH/Contents/Info.plist`\n\nfunction build_bundle () {\n    FAMILY=$1\n    PLATFORM=$2\n    SDK=$3\n    SWIFT_DYLIBS_PATH=\"$FIXED_XCODE_DEVELOPER_PATH/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/$SDK\"\n    CONCURRENCY_DYLIBS=\"$FIXED_XCODE_DEVELOPER_PATH/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/$SDK\"\n    XCODE_PLATFORM_PATH=\"$FIXED_XCODE_DEVELOPER_PATH/Platforms/$PLATFORM.platform\"\n    XCCORE_FRAMEWORK_PATH=\"$XCODE_PLATFORM_PATH/Developer/Library/PrivateFrameworks\"\n    XCTEST_FRAMEWORK_PATH=\"$XCODE_PLATFORM_PATH/Developer/Library/Frameworks\"\n    XCTEST_SUPPORT_PATH=\"$XCODE_PLATFORM_PATH/Developer/usr/lib\"\n    BUNDLE_CONFIG=Debug\n\n    if [ ! -d \"$SWIFT_DYLIBS_PATH\" -o ! -d \"${XCTEST_FRAMEWORK_PATH}/XCTest.framework\" ]; then\n        echo \"Missing RPATH $SWIFT_DYLIBS_PATH $XCTEST_FRAMEWORK_PATH\"\n        exit 1\n    fi\n\n    ADD_INSTALL_NAME=\"\"\n    if [[ ${FAMILY} =~ Dev ]]; then\n        # real devices require a copy_bundle.sh build phase\n        ADD_INSTALL_NAME=\"LD_DYLIB_INSTALL_NAME=@rpath/lib${SDK}Injection.dylib\"\n    fi\n    \"$DEVELOPER_BIN_DIR\"/xcodebuild SYMROOT=$SYMROOT ARCHS=\"$ARCHS\" $APP_SANDBOXED PRODUCT_NAME=\"${FAMILY}Injection\" LD_RUNPATH_SEARCH_PATHS=\"@executable_path/Frameworks @loader_path/Frameworks @loader_path/${FAMILY}Injection.bundle/Frameworks $SWIFT_DYLIBS_PATH $CONCURRENCY_DYLIBS $XCTEST_FRAMEWORK_PATH $XCTEST_SUPPORT_PATH $XCCORE_FRAMEWORK_PATH\" $ADD_INSTALL_NAME PLATFORM_DIR=\"$DEVELOPER_DIR/Platforms/$PLATFORM.platform\" -sdk $SDK -config $BUNDLE_CONFIG -target InjectionBundle &&\n\n    rsync -au $SYMROOT/$BUNDLE_CONFIG-$SDK/*.bundle \"$CODESIGNING_FOLDER_PATH/Contents/Resources\" &&\n    PLIST=\"$CODESIGNING_FOLDER_PATH/Contents/Resources/${FAMILY}Injection.bundle/Info.plist\" &&\n    (/usr/libexec/PlistBuddy -c \"Delete :CFBundleVersion\" \"$PLIST\" || echo -n) &&\n    /usr/libexec/PlistBuddy -c \"Add :CFBundleVersion string $BUILD\" \"$PLIST\" &&\n    ln -sf \"${FAMILY}Injection.bundle/${FAMILY}Injection\" \"$CODESIGNING_FOLDER_PATH/Contents/Resources/lib${SDK}Injection.dylib\"\n}\n\nln -sf \"macOSInjection.bundle/Contents/MacOS/macOSInjection\" \"$CODESIGNING_FOLDER_PATH/Contents/Resources/libmacosxInjection.dylib\" &&\n\nbuild_bundle iOS iPhoneSimulator iphonesimulator &&\nif [[ \"$ACTION\" = \"install\" ]]; then\n    build_bundle tvOS AppleTVSimulator appletvsimulator &&\n    build_bundle xrOS XRSimulator xrsimulator &&\n    build_bundle iOSDev iPhoneOS iphoneos &&\n    build_bundle tvOSDev AppleTVOS appletvos &&\n    build_bundle xrOSDev XROS xros\nfi &&\nexit 0\n"
  },
  {
    "path": "App/InjectionNext/copy_bundle.sh",
    "content": "#!/bin/bash -x\n#\n#  copy_bundle.sh\n#  InjectionIII\n#\n#  Copies injection bundle for on-device injection.\n#  Thanks @oryonatan\n#\n#  $Id: //depot/HotReloading/copy_bundle.sh#14 $\n#\n\nif [[ \"$CONFIGURATION\" =~ Debug ]]; then\n    if [ ! -w \"$CODESIGNING_FOLDER_PATH\" ]; then\n        echo '*** copy_bundle.sh unable to write to file system. ***' \\\n            'Change build setting \"User Script Sandboxing\" to NO'\n        exit 1;\n    fi\n\n    # determine which prebuilt bundle to copy\n    RESOURCES=${RESOURCES:-\"$(dirname \"$0\")\"}\n    # If there are frameworks used only by tests\n    TESTING_FRAMEWORKS=\"$2\"\n    COPY=\"$CODESIGNING_FOLDER_PATH/iOSInjection.bundle\"\n    PLIST=\"$COPY/Info.plist\"\n    if [ \"$PLATFORM_NAME\" == \"macosx\" ]; then\n     BUNDLE=${1:-macOSInjection}\n     COPY=\"$CODESIGNING_FOLDER_PATH/Contents/Resources/macOSInjection.bundle\"\n     PLIST=\"$COPY/Contents/Info.plist\"\n    elif [ \"$PLATFORM_NAME\" == \"appletvsimulator\" ]; then\n     BUNDLE=${1:-tvOSInjection}\n    elif [ \"$PLATFORM_NAME\" == \"appletvos\" ]; then\n     BUNDLE=${1:-tvOSDevInjection}\n    elif [ \"$PLATFORM_NAME\" == \"xrsimulator\" ]; then\n     BUNDLE=${1:-xrOSInjection}\n    elif [ \"$PLATFORM_NAME\" == \"xros\" ]; then\n     BUNDLE=${1:-xrOSDevInjection}\n    elif [ \"$PLATFORM_NAME\" == \"iphoneos\" ]; then\n     BUNDLE=${1:-iOSDevInjection}\n    else\n     BUNDLE=${1:-iOSInjection}\n    fi\n\n    mkdir -p \"$CODESIGNING_FOLDER_PATH/Frameworks\" &&\n\n    # copy frameworks used for testing into app's bundle/Frameworks\n    ln -sf \"../iOSInjection.bundle/$BUNDLE\" \"$CODESIGNING_FOLDER_PATH/Frameworks/lib${PLATFORM_NAME}Injection.dylib\" &&\n    if [[ \"$BUNDLE\" =~ Dev ]]; then\n    rsync -a \"$PLATFORM_DEVELOPER_LIBRARY_DIR\"/*Frameworks/{XC,StoreKit}* \"$PLATFORM_DEVELOPER_USR_DIR/lib\"/*.dylib \"$CODESIGNING_FOLDER_PATH/Frameworks/\" &&\n    codesign -f --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" --timestamp\\=none --preserve-metadata\\=identifier,entitlements,flags --generate-entitlement-der \"$CODESIGNING_FOLDER_PATH/Frameworks\"/{XC*,StoreKit*,*.dylib} ||\n    echo \"*** You should be able to ignore the above errors ***\"\n    else\n    rsync -a \"$PLATFORM_DEVELOPER_LIBRARY_DIR\"/*Frameworks/XC* \"$PLATFORM_DEVELOPER_USR_DIR/lib\"/*.dylib \"$CODESIGNING_FOLDER_PATH/Frameworks/\" &&\n    codesign -f --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" --timestamp\\=none --preserve-metadata\\=identifier,entitlements,flags --generate-entitlement-der \"$CODESIGNING_FOLDER_PATH/Frameworks\"/{XC*,*.dylib}\n    fi &&\n\n    # Copy frameworks only used in test target\n    PRODUCTS_DIR=\"$(dirname \"$CODESIGNING_FOLDER_PATH\")\"\n    rm -f /tmp/InjectionNext.Products\n    ln -s \"$PRODUCTS_DIR\" /tmp/InjectionNext.Products\n    (cd \"$PRODUCTS_DIR\" && for fwork in $TESTING_FRAMEWORKS; do\n        if [ -f \"$fwork/Info.plist\" -a \\\n            ! -d \"$CODESIGNING_FOLDER_PATH/Frameworks/$fwork\" ]; then\n            rsync -a \"$fwork\" \"$CODESIGNING_FOLDER_PATH/Frameworks\" &&\n            codesign -f --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" --timestamp\\=none --preserve-metadata\\=identifier,entitlements,flags --generate-entitlement-der \"$CODESIGNING_FOLDER_PATH/Frameworks/$fwork\"\n        fi\n    done)\n\n    # Xcode 16's new SwiftTesting framework\n    TESTING=\"$PLATFORM_DEVELOPER_LIBRARY_DIR/Frameworks/Testing.Framework\"\n    if [ -d \"$TESTING\" ]; then\n      rsync -a \"$TESTING\"/* \"$CODESIGNING_FOLDER_PATH/Frameworks/Testing.framework/\"\n      codesign -f --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" --timestamp\\=none --preserve-metadata\\=identifier,entitlements,flags --generate-entitlement-der \"$CODESIGNING_FOLDER_PATH/Frameworks/Testing.framework\";\n    fi\n\n    # Make copy of \"PlugIns\" directory when testing\n    export PLUGINS=\"/tmp/PlugIns.$PRODUCT_NAME.$PLATFORM_NAME\"\n    export LAST_PLUGINS=\"/tmp/InjectionNext.PlugIns\"\n    rm -f $LAST_PLUGINS\n    if [ -d \"$CODESIGNING_FOLDER_PATH/PlugIns\" ]; then\n     (sleep 5; while\n      rsync -va \"$CODESIGNING_FOLDER_PATH/PlugIns\"/* \"$PLUGINS/\" |\n      grep -v /sec | grep /; do sleep 15; done) 1>/dev/null 2>&1 &\n    else bash -x <<'CAN_FAIL' 2>/dev/null\n      # Xcode 16 deletes PlugIns directory. copy or create link\n      rsync -a \"$PLUGINS\"/* \"$CODESIGNING_FOLDER_PATH/PlugIns/\" &&\n      codesign -f --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" --timestamp\\=none --preserve-metadata\\=identifier,entitlements,flags --generate-entitlement-der \"$CODESIGNING_FOLDER_PATH/PlugIns/*.xctest\" ||\n      ln -s $PLUGINS $LAST_PLUGINS\nCAN_FAIL\n    fi\n\n    # copy prebuilt bundle into app package and codesign\n    rsync -a \"$RESOURCES/$BUNDLE.bundle\"/* \"$COPY/\" &&\n    # See +[SimpleSocket initialize] for pre-built bundles/dylibs\n    /usr/libexec/PlistBuddy -c \"Add :UserHome string $HOME\" \"$PLIST\" &&\n    (/usr/libexec/PlistBuddy -c \"Delete :InjectionUserHome\" \"$CODESIGNING_FOLDER_PATH/Info.plist\" || echo -n) &&\n    /usr/libexec/PlistBuddy -c \"Add :InjectionUserHome string $HOME\" \"$CODESIGNING_FOLDER_PATH/Info.plist\" &&\n    codesign -f --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" --timestamp\\=none --preserve-metadata\\=identifier,entitlements,flags --generate-entitlement-der \"$COPY\" &&\n    defaults write com.johnholdsworth.InjectionNext codesigningIdentity \"$EXPANDED_CODE_SIGN_IDENTITY\"\nfi\n"
  },
  {
    "path": "App/InjectionNext/main.m",
    "content": "//\n//  main.m\n//  InjectionIII\n//\n//  Created by John Holdsworth on 06/11/2017.\n//  Copyright © 2017 John Holdsworth. All rights reserved.\n//\n\n#import <Cocoa/Cocoa.h>\n\nint main(int argc, const char * argv[]) {\n    return NSApplicationMain(argc, argv);\n}\n"
  },
  {
    "path": "App/InjectionNext/swift-frontend.sh",
    "content": "#!/bin/bash\n\n#  swift-frontend.sh\n#  InjectionNext\n#\n#  Created by John Holdsworth on 23/02/2025.\n#  Copyright © 2025 John Holdsworth. All rights reserved.\n\nFRONTEND=\"$0\"\n\"$FRONTEND.save\" \"$@\" &&\nif [ \"$2\" = \"-c\" ]; then \"/Applications/InjectionNext.app/Contents/Resources/feedcommands\" \\\n    \"2.0\" \"$(/usr/bin/env)\" \"$FRONTEND.save\" \"$@\" >>/tmp/feedcommands.log 2>&1 & fi\n"
  },
  {
    "path": "App/InjectionNext.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 70;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t2217BE812C0A65C20032A832 /* Fortify in Frameworks */ = {isa = PBXBuildFile; productRef = 2217BE802C0A65C20032A832 /* Fortify */; };\n\t\t222BC9452C157C3200780A41 /* InjectionReady.tif in Resources */ = {isa = PBXBuildFile; fileRef = 222BC9442C157C3200780A41 /* InjectionReady.tif */; };\n\t\t224E57FB2C08978F00B71C79 /* SwiftRegex in Frameworks */ = {isa = PBXBuildFile; productRef = 224E57FA2C08978F00B71C79 /* SwiftRegex */; };\n\t\t224E57FE2C08BBE300B71C79 /* InjectionServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 224E57FD2C08BBE300B71C79 /* InjectionServer.swift */; };\n\t\t224E58002C08BC0E00B71C79 /* MonitorXcode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 224E57FF2C08BC0E00B71C79 /* MonitorXcode.swift */; };\n\t\t229127F12C1EEF69005D7625 /* Experimental.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEC17029253ED117002E823F /* Experimental.swift */; };\n\t\t22B645A02C18DD9D00F99B61 /* Unhider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22B6459F2C18DD9D00F99B61 /* Unhider.swift */; };\n\t\t22E3D98B2C19009900BB234E /* DLKit in Frameworks */ = {isa = PBXBuildFile; productRef = 22E3D98A2C19009900BB234E /* DLKit */; };\n\t\t22E3D98D2C19009900BB234E /* DLKitC in Frameworks */ = {isa = PBXBuildFile; productRef = 22E3D98C2C19009900BB234E /* DLKitC */; };\n\t\tBB0CECB02C73C1610000A4E6 /* Quick in Frameworks */ = {isa = PBXBuildFile; productRef = BB0CECAF2C73C1610000A4E6 /* Quick */; };\n\t\tBB0CECB32C73C1890000A4E6 /* Nimble in Frameworks */ = {isa = PBXBuildFile; productRef = BB0CECB22C73C1890000A4E6 /* Nimble */; };\n\t\tBB16653A25E9A5F2001407AE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = BB16653925E9A5F0001407AE /* main.m */; };\n\t\tBB2A66362E3E753B001EDD38 /* BAZEL.md in Resources */ = {isa = PBXBuildFile; fileRef = BB2A66352E3E753B001EDD38 /* BAZEL.md */; };\n\t\tBB2D41AC2DAD14EA0073C203 /* Popen in Frameworks */ = {isa = PBXBuildFile; productRef = BB2D41AB2DAD14EA0073C203 /* Popen */; };\n\t\tBB42F8E12EB626F100FDBBCC /* SwiftAspects.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F8D62EB626F100FDBBCC /* SwiftAspects.swift */; };\n\t\tBB42F8E22EB626F100FDBBCC /* SwiftInterpose.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F8D72EB626F100FDBBCC /* SwiftInterpose.swift */; };\n\t\tBB42F8E32EB626F100FDBBCC /* SwiftTrace.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F8DF2EB626F100FDBBCC /* SwiftTrace.swift */; };\n\t\tBB42F8E42EB626F100FDBBCC /* SwiftSwizzle.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F8DD2EB626F100FDBBCC /* SwiftSwizzle.swift */; };\n\t\tBB42F8E52EB626F100FDBBCC /* SwiftArgs.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F8D52EB626F100FDBBCC /* SwiftArgs.swift */; };\n\t\tBB42F8E62EB626F100FDBBCC /* SwiftInvoke.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F8D82EB626F100FDBBCC /* SwiftInvoke.swift */; };\n\t\tBB42F8E72EB626F100FDBBCC /* EasyPointer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F8D22EB626F100FDBBCC /* EasyPointer.swift */; };\n\t\tBB42F8E82EB626F100FDBBCC /* SwiftStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F8DB2EB626F100FDBBCC /* SwiftStack.swift */; };\n\t\tBB42F8E92EB626F100FDBBCC /* SwiftStats.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F8DC2EB626F100FDBBCC /* SwiftStats.swift */; };\n\t\tBB42F8EA2EB626F100FDBBCC /* StringIndex.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F8D42EB626F100FDBBCC /* StringIndex.swift */; };\n\t\tBB42F8EB2EB626F100FDBBCC /* SwiftLifetime.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F8D92EB626F100FDBBCC /* SwiftLifetime.swift */; };\n\t\tBB42F8EC2EB626F100FDBBCC /* SwiftMeta.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F8DA2EB626F100FDBBCC /* SwiftMeta.swift */; };\n\t\tBB42F9212EB639D100FDBBCC /* DLKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F91B2EB639D100FDBBCC /* DLKit.swift */; };\n\t\tBB42F9222EB639D100FDBBCC /* Iterators.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F91F2EB639D100FDBBCC /* Iterators.swift */; };\n\t\tBB42F9232EB639D100FDBBCC /* Interposing.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F91E2EB639D100FDBBCC /* Interposing.swift */; };\n\t\tBB42F9242EB639D100FDBBCC /* ImageSymbols.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F91D2EB639D100FDBBCC /* ImageSymbols.swift */; };\n\t\tBB42F9252EB639D100FDBBCC /* Demangling.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F91A2EB639D100FDBBCC /* Demangling.swift */; };\n\t\tBB42F9262EB639D100FDBBCC /* FileSymbols.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F91C2EB639D100FDBBCC /* FileSymbols.swift */; };\n\t\tBB42F92D2EB639E500FDBBCC /* DLKitC.c in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9292EB639E500FDBBCC /* DLKitC.c */; };\n\t\tBB42F92E2EB639E500FDBBCC /* trie_dladdr.mm in Sources */ = {isa = PBXBuildFile; fileRef = BB42F92A2EB639E500FDBBCC /* trie_dladdr.mm */; };\n\t\tBB42F92F2EB639E500FDBBCC /* trie_dlops.mm in Sources */ = {isa = PBXBuildFile; fileRef = BB42F92B2EB639E500FDBBCC /* trie_dlops.mm */; };\n\t\tBB42F9382EB63C2900FDBBCC /* KeyPaths.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9332EB63C2900FDBBCC /* KeyPaths.swift */; };\n\t\tBB42F9392EB63C2900FDBBCC /* Reloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9352EB63C2900FDBBCC /* Reloader.swift */; };\n\t\tBB42F93A2EB63C2900FDBBCC /* Generics.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9322EB63C2900FDBBCC /* Generics.swift */; };\n\t\tBB42F93B2EB63C2900FDBBCC /* Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9342EB63C2900FDBBCC /* Metadata.swift */; };\n\t\tBB42F93C2EB63C2900FDBBCC /* Common.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9312EB63C2900FDBBCC /* Common.swift */; };\n\t\tBB42F93D2EB63C2900FDBBCC /* Sweeper.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9362EB63C2900FDBBCC /* Sweeper.swift */; };\n\t\tBB42F93F2EB63CD800FDBBCC /* Common.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9312EB63C2900FDBBCC /* Common.swift */; };\n\t\tBB42F9462EB63E3400FDBBCC /* InjectionBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9412EB63E3400FDBBCC /* InjectionBase.swift */; };\n\t\tBB42F9472EB63E3400FDBBCC /* Recompiler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9442EB63E3400FDBBCC /* Recompiler.swift */; };\n\t\tBB42F9482EB63E3400FDBBCC /* InjectionLite.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9422EB63E3400FDBBCC /* InjectionLite.swift */; };\n\t\tBB42F9492EB63E3400FDBBCC /* LogParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9432EB63E3400FDBBCC /* LogParser.swift */; };\n\t\tBB42F94A2EB63E3400FDBBCC /* FileWatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9402EB63E3400FDBBCC /* FileWatcher.swift */; };\n\t\tBB42F94B2EB63E3F00FDBBCC /* FileWatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9402EB63E3400FDBBCC /* FileWatcher.swift */; };\n\t\tBB42F94C2EB63E4F00FDBBCC /* LogParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9432EB63E3400FDBBCC /* LogParser.swift */; };\n\t\tBB42F94D2EB63E5600FDBBCC /* Recompiler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9442EB63E3400FDBBCC /* Recompiler.swift */; };\n\t\tBB42F94E2EB63E7700FDBBCC /* InjectionBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9412EB63E3400FDBBCC /* InjectionBase.swift */; };\n\t\tBB42F9552EB63EFF00FDBBCC /* BazelInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9512EB63EFF00FDBBCC /* BazelInterface.swift */; };\n\t\tBB42F9562EB63EFF00FDBBCC /* GitIgnoreParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9532EB63EFF00FDBBCC /* GitIgnoreParser.swift */; };\n\t\tBB42F9572EB63EFF00FDBBCC /* BazelActionQueryHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F94F2EB63EFF00FDBBCC /* BazelActionQueryHandler.swift */; };\n\t\tBB42F9582EB63EFF00FDBBCC /* BazelAQueryParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9502EB63EFF00FDBBCC /* BazelAQueryParser.swift */; };\n\t\tBB42F9592EB63EFF00FDBBCC /* FilenameMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9522EB63EFF00FDBBCC /* FilenameMatcher.swift */; };\n\t\tBB42F95A2EB63EFF00FDBBCC /* BazelInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9512EB63EFF00FDBBCC /* BazelInterface.swift */; };\n\t\tBB42F95B2EB63EFF00FDBBCC /* GitIgnoreParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9532EB63EFF00FDBBCC /* GitIgnoreParser.swift */; };\n\t\tBB42F95C2EB63EFF00FDBBCC /* BazelActionQueryHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F94F2EB63EFF00FDBBCC /* BazelActionQueryHandler.swift */; };\n\t\tBB42F95D2EB63EFF00FDBBCC /* BazelAQueryParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9502EB63EFF00FDBBCC /* BazelAQueryParser.swift */; };\n\t\tBB42F95E2EB63EFF00FDBBCC /* FilenameMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F9522EB63EFF00FDBBCC /* FilenameMatcher.swift */; };\n\t\tBB4654812C257F110080EC40 /* NextCompiler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB4654802C257F110080EC40 /* NextCompiler.swift */; };\n\t\tBB4788802EB6B6E700464AB4 /* InjectionBoot.mm in Sources */ = {isa = PBXBuildFile; fileRef = BB47887E2EB6B6E700464AB4 /* InjectionBoot.mm */; };\n\t\tBB4788812EB6B71600464AB4 /* InjectionImplC.h in Resources */ = {isa = PBXBuildFile; fileRef = BB42F9302EB63AAF00FDBBCC /* InjectionImplC.h */; };\n\t\tBB4788902EB6B81A00464AB4 /* fast_dladdr.mm in Sources */ = {isa = PBXBuildFile; fileRef = BB4788852EB6B81A00464AB4 /* fast_dladdr.mm */; };\n\t\tBB4788912EB6B81A00464AB4 /* xt_forwarding_trampoline_arm64.s in Sources */ = {isa = PBXBuildFile; fileRef = BB47888C2EB6B81A00464AB4 /* xt_forwarding_trampoline_arm64.s */; };\n\t\tBB4788922EB6B81A00464AB4 /* xt_forwarding_trampoline_x64.s in Sources */ = {isa = PBXBuildFile; fileRef = BB47888D2EB6B81A00464AB4 /* xt_forwarding_trampoline_x64.s */; };\n\t\tBB4788932EB6B81A00464AB4 /* ObjCBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = BB4788872EB6B81A00464AB4 /* ObjCBridge.mm */; };\n\t\tBB4788942EB6B81A00464AB4 /* Trampolines.mm in Sources */ = {isa = PBXBuildFile; fileRef = BB47888A2EB6B81A00464AB4 /* Trampolines.mm */; };\n\t\tBB4788952EB6B81A00464AB4 /* xt_forwarding_trampoline_arm7.s in Sources */ = {isa = PBXBuildFile; fileRef = BB47888B2EB6B81A00464AB4 /* xt_forwarding_trampoline_arm7.s */; };\n\t\tBB4788962EB6B81A00464AB4 /* SwiftTrace.mm in Sources */ = {isa = PBXBuildFile; fileRef = BB4788882EB6B81A00464AB4 /* SwiftTrace.mm */; };\n\t\tBB4788972EB6B81A00464AB4 /* xt_forwarding_trampoline_x86.s in Sources */ = {isa = PBXBuildFile; fileRef = BB47888E2EB6B81A00464AB4 /* xt_forwarding_trampoline_x86.s */; };\n\t\tBB4788982EB6B81A00464AB4 /* fishhook.c in Sources */ = {isa = PBXBuildFile; fileRef = BB4788862EB6B81A00464AB4 /* fishhook.c */; };\n\t\tBB5155DA2CDED44F00704C7A /* InjectionHybrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB5155D92CDED44400704C7A /* InjectionHybrid.swift */; };\n\t\tAA0000012F08000000000001 /* ControlServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA0000002F08000000000001 /* ControlServer.swift */; };\n\t\tBB52AD552F1501F500297CD9 /* Unhider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22B6459F2C18DD9D00F99B61 /* Unhider.swift */; };\n\t\tBB6A56F02C50E73600C92112 /* Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6A56EF2C50E73600C92112 /* Defaults.swift */; };\n\t\tBB6A56F12C50E79800C92112 /* copy_bundle.sh in Resources */ = {isa = PBXBuildFile; fileRef = BBDD84582C4FF0B9000F3124 /* copy_bundle.sh */; };\n\t\tBB85A42B2D6B9C7B00FA29D0 /* feedcommands in Resources */ = {isa = PBXBuildFile; fileRef = BB85A4242D6B9C5300FA29D0 /* feedcommands */; };\n\t\tBB85A42E2D6BA13B00FA29D0 /* SimpleSocket.mm in Sources */ = {isa = PBXBuildFile; fileRef = BB67DBB31FB0CDA8000EAC8A /* SimpleSocket.mm */; };\n\t\tBBA082362D6BC33500FFFB2F /* FrontendServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA082352D6BC32D00FFFB2F /* FrontendServer.swift */; };\n\t\tBBA082382D6BD6CB00FFFB2F /* swift-frontend.sh in Resources */ = {isa = PBXBuildFile; fileRef = BBA082372D6BD6CB00FFFB2F /* swift-frontend.sh */; };\n\t\tBBB040641FB17A6C007DDD0A /* ScriptingBridge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBB040631FB1798A007DDD0A /* ScriptingBridge.framework */; };\n\t\tBBB64DC51FD450AF0020BE47 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = BB037DF31FAD808B004B267C /* README.md */; };\n\t\tBBB64DC61FD450B40020BE47 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = BB037DF41FAD80D0004B267C /* LICENSE */; };\n\t\tBBB64DE51FD571310020BE47 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BBB64DE41FD571300020BE47 /* libz.tbd */; };\n\t\tBBB64FEC1FD585D50020BE47 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBB64FEB1FD585D50020BE47 /* WebKit.framework */; };\n\t\tBBCA02021FB0F10300E45F0F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCA02011FB0F10300E45F0F /* AppDelegate.swift */; };\n\t\tBBCA02041FB0F10300E45F0F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BBCA02031FB0F10300E45F0F /* Assets.xcassets */; };\n\t\tBBCA02071FB0F10300E45F0F /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = BBCA02051FB0F10300E45F0F /* MainMenu.xib */; };\n\t\tBBCA022A1FB0F64800E45F0F /* SimpleSocket.mm in Sources */ = {isa = PBXBuildFile; fileRef = BB67DBB31FB0CDA8000EAC8A /* SimpleSocket.mm */; };\n\t\tBBCA02591FB112F500E45F0F /* App.icns in Resources */ = {isa = PBXBuildFile; fileRef = BBCA02581FB112F500E45F0F /* App.icns */; };\n\t\tBBCA02601FB122C300E45F0F /* InjectionIdle.tif in Resources */ = {isa = PBXBuildFile; fileRef = BBCA025E1FB122C300E45F0F /* InjectionIdle.tif */; };\n\t\tBBCA02611FB122C300E45F0F /* InjectionOK.tif in Resources */ = {isa = PBXBuildFile; fileRef = BBCA025F1FB122C300E45F0F /* InjectionOK.tif */; };\n\t\tBBCCC3B72C73B6FD00E71F81 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBBEC42D1FC56522004188B3 /* XCTest.framework */; };\n\t\tBBDD843F2C4FE8D5000F3124 /* macOSInjection.bundle in Resources */ = {isa = PBXBuildFile; fileRef = BBDD84132C4FE749000F3124 /* macOSInjection.bundle */; };\n\t\tBBDD84422C4FEA4E000F3124 /* InjectionNext.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBDD84182C4FE7E6000F3124 /* InjectionNext.swift */; };\n\t\tBBDD84542C4FEB16000F3124 /* TupleRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBDD84532C4FEB16000F3124 /* TupleRegex.swift */; };\n\t\tBBDD84552C4FEC98000F3124 /* SimpleSocket.mm in Sources */ = {isa = PBXBuildFile; fileRef = BB67DBB31FB0CDA8000EAC8A /* SimpleSocket.mm */; };\n\t\tBBDD845A2C4FF646000F3124 /* ClientBoot.mm in Sources */ = {isa = PBXBuildFile; fileRef = BBDD84592C4FF645000F3124 /* ClientBoot.mm */; };\n\t\tBBE490DB1FB2C643003D41BB /* InjectionBusy.tif in Resources */ = {isa = PBXBuildFile; fileRef = BBE490D91FB2C643003D41BB /* InjectionBusy.tif */; };\n\t\tBBE490DC1FB2C643003D41BB /* InjectionError.tif in Resources */ = {isa = PBXBuildFile; fileRef = BBE490DA1FB2C643003D41BB /* InjectionError.tif */; };\n\t\tBBEB87122C74FD930044578A /* Quick in Frameworks */ = {isa = PBXBuildFile; productRef = BBEB87112C74FD930044578A /* Quick */; };\n\t\tBBF6572E2DAFF00200638170 /* NIMBLE.md in Resources */ = {isa = PBXBuildFile; fileRef = BBF6572C2DAFF00200638170 /* NIMBLE.md */; };\n\t\tBBF6572F2DAFF00200638170 /* QUICK.md in Resources */ = {isa = PBXBuildFile; fileRef = BBF6572D2DAFF00200638170 /* QUICK.md */; };\n\t\tBBFE1B422ED7C116004E14EE /* SwiftRefs.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBFE1B412ED7C116004E14EE /* SwiftRefs.swift */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\tBB85A42C2D6B9CA200FA29D0 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = BB439B5D1FABA64300B4F50B /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = BB85A4232D6B9C5300FA29D0;\n\t\t\tremoteInfo = feedcommands;\n\t\t};\n\t\tBBDD843D2C4FE8C5000F3124 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = BB439B5D1FABA64300B4F50B /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = BBDD84122C4FE749000F3124;\n\t\t\tremoteInfo = InjectionBundle;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\tBB6224721FC5BA6F00AD7A3A /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = Contents/Library/LaunchServices;\n\t\t\tdstSubfolderSpec = 1;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBB6C87DB2520D0D3005AFCFC /* Embed Frameworks */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"\";\n\t\t\tdstSubfolderSpec = 10;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tname = \"Embed Frameworks\";\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBB85A4222D6B9C5300FA29D0 /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = /usr/share/man/man1/;\n\t\t\tdstSubfolderSpec = 0;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 1;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t222BC9442C157C3200780A41 /* InjectionReady.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = InjectionReady.tif; sourceTree = \"<group>\"; };\n\t\t224E57FC2C08BAE200B71C79 /* InjectionClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InjectionClient.h; path = ../../Sources/InjectionNextC/include/InjectionClient.h; sourceTree = \"<group>\"; };\n\t\t224E57FD2C08BBE300B71C79 /* InjectionServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InjectionServer.swift; sourceTree = \"<group>\"; };\n\t\t224E57FF2C08BC0E00B71C79 /* MonitorXcode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MonitorXcode.swift; sourceTree = \"<group>\"; };\n\t\t22B6459F2C18DD9D00F99B61 /* Unhider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Unhider.swift; path = ../../InjectionLite/Sources/InjectionImpl/Unhider.swift; sourceTree = \"<group>\"; };\n\t\tBB037DF31FAD808B004B267C /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = \"<group>\"; };\n\t\tBB037DF41FAD80D0004B267C /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = \"<group>\"; };\n\t\tBB16653925E9A5F0001407AE /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\tBB2A66352E3E753B001EDD38 /* BAZEL.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = BAZEL.md; path = ../BAZEL.md; sourceTree = SOURCE_ROOT; };\n\t\tBB42F8D22EB626F100FDBBCC /* EasyPointer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EasyPointer.swift; sourceTree = \"<group>\"; };\n\t\tBB42F8D32EB626F100FDBBCC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tBB42F8D42EB626F100FDBBCC /* StringIndex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringIndex.swift; sourceTree = \"<group>\"; };\n\t\tBB42F8D52EB626F100FDBBCC /* SwiftArgs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftArgs.swift; sourceTree = \"<group>\"; };\n\t\tBB42F8D62EB626F100FDBBCC /* SwiftAspects.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftAspects.swift; sourceTree = \"<group>\"; };\n\t\tBB42F8D72EB626F100FDBBCC /* SwiftInterpose.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftInterpose.swift; sourceTree = \"<group>\"; };\n\t\tBB42F8D82EB626F100FDBBCC /* SwiftInvoke.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftInvoke.swift; sourceTree = \"<group>\"; };\n\t\tBB42F8D92EB626F100FDBBCC /* SwiftLifetime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftLifetime.swift; sourceTree = \"<group>\"; };\n\t\tBB42F8DA2EB626F100FDBBCC /* SwiftMeta.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftMeta.swift; sourceTree = \"<group>\"; };\n\t\tBB42F8DB2EB626F100FDBBCC /* SwiftStack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftStack.swift; sourceTree = \"<group>\"; };\n\t\tBB42F8DC2EB626F100FDBBCC /* SwiftStats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftStats.swift; sourceTree = \"<group>\"; };\n\t\tBB42F8DD2EB626F100FDBBCC /* SwiftSwizzle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftSwizzle.swift; sourceTree = \"<group>\"; };\n\t\tBB42F8DE2EB626F100FDBBCC /* SwiftTrace.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftTrace.h; sourceTree = \"<group>\"; };\n\t\tBB42F8DF2EB626F100FDBBCC /* SwiftTrace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftTrace.swift; sourceTree = \"<group>\"; };\n\t\tBB42F91A2EB639D100FDBBCC /* Demangling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Demangling.swift; sourceTree = \"<group>\"; };\n\t\tBB42F91B2EB639D100FDBBCC /* DLKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DLKit.swift; sourceTree = \"<group>\"; };\n\t\tBB42F91C2EB639D100FDBBCC /* FileSymbols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileSymbols.swift; sourceTree = \"<group>\"; };\n\t\tBB42F91D2EB639D100FDBBCC /* ImageSymbols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageSymbols.swift; sourceTree = \"<group>\"; };\n\t\tBB42F91E2EB639D100FDBBCC /* Interposing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Interposing.swift; sourceTree = \"<group>\"; };\n\t\tBB42F91F2EB639D100FDBBCC /* Iterators.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Iterators.swift; sourceTree = \"<group>\"; };\n\t\tBB42F9272EB639E500FDBBCC /* DLKitC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DLKitC.h; sourceTree = \"<group>\"; };\n\t\tBB42F9292EB639E500FDBBCC /* DLKitC.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = DLKitC.c; sourceTree = \"<group>\"; };\n\t\tBB42F92A2EB639E500FDBBCC /* trie_dladdr.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = trie_dladdr.mm; sourceTree = \"<group>\"; };\n\t\tBB42F92B2EB639E500FDBBCC /* trie_dlops.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = trie_dlops.mm; sourceTree = \"<group>\"; };\n\t\tBB42F9302EB63AAF00FDBBCC /* InjectionImplC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InjectionImplC.h; path = ../InjectionLite/Sources/InjectionImplC/include/InjectionImplC.h; sourceTree = SOURCE_ROOT; };\n\t\tBB42F9312EB63C2900FDBBCC /* Common.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Common.swift; sourceTree = \"<group>\"; };\n\t\tBB42F9322EB63C2900FDBBCC /* Generics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Generics.swift; sourceTree = \"<group>\"; };\n\t\tBB42F9332EB63C2900FDBBCC /* KeyPaths.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyPaths.swift; sourceTree = \"<group>\"; };\n\t\tBB42F9342EB63C2900FDBBCC /* Metadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Metadata.swift; sourceTree = \"<group>\"; };\n\t\tBB42F9352EB63C2900FDBBCC /* Reloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Reloader.swift; sourceTree = \"<group>\"; };\n\t\tBB42F9362EB63C2900FDBBCC /* Sweeper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sweeper.swift; sourceTree = \"<group>\"; };\n\t\tBB42F9402EB63E3400FDBBCC /* FileWatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileWatcher.swift; sourceTree = \"<group>\"; };\n\t\tBB42F9412EB63E3400FDBBCC /* InjectionBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InjectionBase.swift; sourceTree = \"<group>\"; };\n\t\tBB42F9422EB63E3400FDBBCC /* InjectionLite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InjectionLite.swift; sourceTree = \"<group>\"; };\n\t\tBB42F9432EB63E3400FDBBCC /* LogParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogParser.swift; sourceTree = \"<group>\"; };\n\t\tBB42F9442EB63E3400FDBBCC /* Recompiler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Recompiler.swift; sourceTree = \"<group>\"; };\n\t\tBB42F94F2EB63EFF00FDBBCC /* BazelActionQueryHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BazelActionQueryHandler.swift; sourceTree = \"<group>\"; };\n\t\tBB42F9502EB63EFF00FDBBCC /* BazelAQueryParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BazelAQueryParser.swift; sourceTree = \"<group>\"; };\n\t\tBB42F9512EB63EFF00FDBBCC /* BazelInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BazelInterface.swift; sourceTree = \"<group>\"; };\n\t\tBB42F9522EB63EFF00FDBBCC /* FilenameMatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilenameMatcher.swift; sourceTree = \"<group>\"; };\n\t\tBB42F9532EB63EFF00FDBBCC /* GitIgnoreParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GitIgnoreParser.swift; sourceTree = \"<group>\"; };\n\t\tBB4654802C257F110080EC40 /* NextCompiler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextCompiler.swift; sourceTree = \"<group>\"; };\n\t\tBB47887C2EB6B6E700464AB4 /* InjectionImplC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InjectionImplC.h; sourceTree = \"<group>\"; };\n\t\tBB47887E2EB6B6E700464AB4 /* InjectionBoot.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = InjectionBoot.mm; sourceTree = \"<group>\"; };\n\t\tBB4788822EB6B81A00464AB4 /* fishhook.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fishhook.h; sourceTree = \"<group>\"; };\n\t\tBB4788832EB6B81A00464AB4 /* SwiftTrace.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftTrace.h; sourceTree = \"<group>\"; };\n\t\tBB4788852EB6B81A00464AB4 /* fast_dladdr.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = fast_dladdr.mm; sourceTree = \"<group>\"; };\n\t\tBB4788862EB6B81A00464AB4 /* fishhook.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = fishhook.c; sourceTree = \"<group>\"; };\n\t\tBB4788872EB6B81A00464AB4 /* ObjCBridge.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ObjCBridge.mm; sourceTree = \"<group>\"; };\n\t\tBB4788882EB6B81A00464AB4 /* SwiftTrace.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SwiftTrace.mm; sourceTree = \"<group>\"; };\n\t\tBB4788892EB6B81A00464AB4 /* SwiftTrace-Swift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = \"SwiftTrace-Swift.h\"; sourceTree = \"<group>\"; };\n\t\tBB47888A2EB6B81A00464AB4 /* Trampolines.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Trampolines.mm; sourceTree = \"<group>\"; };\n\t\tBB47888B2EB6B81A00464AB4 /* xt_forwarding_trampoline_arm7.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = xt_forwarding_trampoline_arm7.s; sourceTree = \"<group>\"; };\n\t\tBB47888C2EB6B81A00464AB4 /* xt_forwarding_trampoline_arm64.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = xt_forwarding_trampoline_arm64.s; sourceTree = \"<group>\"; };\n\t\tBB47888D2EB6B81A00464AB4 /* xt_forwarding_trampoline_x64.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = xt_forwarding_trampoline_x64.s; sourceTree = \"<group>\"; };\n\t\tBB47888E2EB6B81A00464AB4 /* xt_forwarding_trampoline_x86.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = xt_forwarding_trampoline_x86.s; sourceTree = \"<group>\"; };\n\t\tBB5155D92CDED44400704C7A /* InjectionHybrid.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InjectionHybrid.swift; sourceTree = \"<group>\"; };\n\t\tAA0000002F08000000000001 /* ControlServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlServer.swift; sourceTree = \"<group>\"; };\n\t\tBB67DBB21FB0CDA8000EAC8A /* SimpleSocket.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SimpleSocket.h; path = ../../Sources/InjectionNextC/include/SimpleSocket.h; sourceTree = \"<group>\"; };\n\t\tBB67DBB31FB0CDA8000EAC8A /* SimpleSocket.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = SimpleSocket.mm; path = ../../Sources/InjectionNextC/SimpleSocket.mm; sourceTree = \"<group>\"; };\n\t\tBB6A56EF2C50E73600C92112 /* Defaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Defaults.swift; sourceTree = \"<group>\"; };\n\t\tBB6A56F22C51154F00C92112 /* InjectionBundle-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"InjectionBundle-Bridging-Header.h\"; sourceTree = \"<group>\"; };\n\t\tBB85A4242D6B9C5300FA29D0 /* feedcommands */ = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.executable\"; includeInIndex = 0; path = feedcommands; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tBBA082352D6BC32D00FFFB2F /* FrontendServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrontendServer.swift; sourceTree = \"<group>\"; };\n\t\tBBA082372D6BD6CB00FFFB2F /* swift-frontend.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = \"swift-frontend.sh\"; sourceTree = \"<group>\"; };\n\t\tBBB040631FB1798A007DDD0A /* ScriptingBridge.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ScriptingBridge.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks/ScriptingBridge.framework; sourceTree = DEVELOPER_DIR; };\n\t\tBBB64DE41FD571300020BE47 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = \"sourcecode.text-based-dylib-definition\"; name = libz.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/lib/libz.tbd; sourceTree = DEVELOPER_DIR; };\n\t\tBBB64FEB1FD585D50020BE47 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks/WebKit.framework; sourceTree = DEVELOPER_DIR; };\n\t\tBBBEC42D1FC56522004188B3 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/MacOSX.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };\n\t\tBBCA01FE1FB0F10300E45F0F /* InjectionNext.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = InjectionNext.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tBBCA02011FB0F10300E45F0F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = \"<group>\"; };\n\t\tBBCA02031FB0F10300E45F0F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\tBBCA02061FB0F10300E45F0F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = \"<group>\"; };\n\t\tBBCA02081FB0F10400E45F0F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tBBCA020B1FB0F10400E45F0F /* InjectionNext.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = InjectionNext.entitlements; sourceTree = \"<group>\"; };\n\t\tBBCA02581FB112F500E45F0F /* App.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = App.icns; sourceTree = \"<group>\"; };\n\t\tBBCA025E1FB122C300E45F0F /* InjectionIdle.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = InjectionIdle.tif; sourceTree = \"<group>\"; };\n\t\tBBCA025F1FB122C300E45F0F /* InjectionOK.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = InjectionOK.tif; sourceTree = \"<group>\"; };\n\t\tBBCCC3B02C73A6AD00E71F81 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/WatchOS.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };\n\t\tBBDD84132C4FE749000F3124 /* macOSInjection.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = macOSInjection.bundle; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tBBDD84182C4FE7E6000F3124 /* InjectionNext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = InjectionNext.swift; path = ../../Sources/InjectionNext/InjectionNext.swift; sourceTree = \"<group>\"; };\n\t\tBBDD843A2C4FE892000F3124 /* InjectionBoot.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = InjectionBoot.mm; path = ../../InjectionLite/Sources/InjectionImplC/InjectionBoot.mm; sourceTree = \"<group>\"; };\n\t\tBBDD84532C4FEB16000F3124 /* TupleRegex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TupleRegex.swift; path = ../../SwiftRegex5/SwiftRegex5.playground/Sources/TupleRegex.swift; sourceTree = \"<group>\"; };\n\t\tBBDD84562C4FED60000F3124 /* build_bundles.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = build_bundles.sh; sourceTree = \"<group>\"; };\n\t\tBBDD84582C4FF0B9000F3124 /* copy_bundle.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = copy_bundle.sh; sourceTree = \"<group>\"; };\n\t\tBBDD84592C4FF645000F3124 /* ClientBoot.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ClientBoot.mm; path = ../../Sources/InjectionNextC/ClientBoot.mm; sourceTree = \"<group>\"; };\n\t\tBBDF943C2349277A00334E08 /* InjectionNext-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"InjectionNext-Bridging-Header.h\"; sourceTree = \"<group>\"; };\n\t\tBBE490D91FB2C643003D41BB /* InjectionBusy.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = InjectionBusy.tif; sourceTree = \"<group>\"; };\n\t\tBBE490DA1FB2C643003D41BB /* InjectionError.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = InjectionError.tif; sourceTree = \"<group>\"; };\n\t\tBBF6572C2DAFF00200638170 /* NIMBLE.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = NIMBLE.md; sourceTree = \"<group>\"; };\n\t\tBBF6572D2DAFF00200638170 /* QUICK.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = QUICK.md; sourceTree = \"<group>\"; };\n\t\tBBFE1B412ED7C116004E14EE /* SwiftRefs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftRefs.swift; sourceTree = \"<group>\"; };\n\t\tCEC17029253ED117002E823F /* Experimental.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Experimental.swift; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFileSystemSynchronizedRootGroup section */\n\t\tBB85A4252D6B9C5300FA29D0 /* feedcommands */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = feedcommands; sourceTree = \"<group>\"; };\n/* End PBXFileSystemSynchronizedRootGroup section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\tBB85A4212D6B9C5300FA29D0 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBCA01FB1FB0F10300E45F0F /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t2217BE812C0A65C20032A832 /* Fortify in Frameworks */,\n\t\t\t\t22E3D98D2C19009900BB234E /* DLKitC in Frameworks */,\n\t\t\t\tBBB64FEC1FD585D50020BE47 /* WebKit.framework in Frameworks */,\n\t\t\t\t22E3D98B2C19009900BB234E /* DLKit in Frameworks */,\n\t\t\t\tBBB040641FB17A6C007DDD0A /* ScriptingBridge.framework in Frameworks */,\n\t\t\t\t224E57FB2C08978F00B71C79 /* SwiftRegex in Frameworks */,\n\t\t\t\tBBB64DE51FD571310020BE47 /* libz.tbd in Frameworks */,\n\t\t\t\tBB2D41AC2DAD14EA0073C203 /* Popen in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBDD84102C4FE749000F3124 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBB0CECB02C73C1610000A4E6 /* Quick in Frameworks */,\n\t\t\t\tBBEB87122C74FD930044578A /* Quick in Frameworks */,\n\t\t\t\tBB0CECB32C73C1890000A4E6 /* Nimble in Frameworks */,\n\t\t\t\tBBCCC3B72C73B6FD00E71F81 /* XCTest.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\tBB42F8E02EB626F100FDBBCC /* SwiftTrace */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB47888F2EB6B81A00464AB4 /* SwiftTraceGuts */,\n\t\t\t\tBB42F8D22EB626F100FDBBCC /* EasyPointer.swift */,\n\t\t\t\tBB42F8D32EB626F100FDBBCC /* Info.plist */,\n\t\t\t\tBB42F8D42EB626F100FDBBCC /* StringIndex.swift */,\n\t\t\t\tBB42F8D52EB626F100FDBBCC /* SwiftArgs.swift */,\n\t\t\t\tBB42F8D62EB626F100FDBBCC /* SwiftAspects.swift */,\n\t\t\t\tBB42F8D72EB626F100FDBBCC /* SwiftInterpose.swift */,\n\t\t\t\tBB42F8D82EB626F100FDBBCC /* SwiftInvoke.swift */,\n\t\t\t\tBB42F8D92EB626F100FDBBCC /* SwiftLifetime.swift */,\n\t\t\t\tBB42F8DA2EB626F100FDBBCC /* SwiftMeta.swift */,\n\t\t\t\tBBFE1B412ED7C116004E14EE /* SwiftRefs.swift */,\n\t\t\t\tBB42F8DB2EB626F100FDBBCC /* SwiftStack.swift */,\n\t\t\t\tBB42F8DC2EB626F100FDBBCC /* SwiftStats.swift */,\n\t\t\t\tBB42F8DD2EB626F100FDBBCC /* SwiftSwizzle.swift */,\n\t\t\t\tBB42F8DE2EB626F100FDBBCC /* SwiftTrace.h */,\n\t\t\t\tBB42F8DF2EB626F100FDBBCC /* SwiftTrace.swift */,\n\t\t\t);\n\t\t\tname = SwiftTrace;\n\t\t\tpath = ../SwiftTrace/SwiftTrace;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\tBB42F9202EB639D100FDBBCC /* DLKit */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB42F92C2EB639E500FDBBCC /* DLKitC */,\n\t\t\t\tBB42F91A2EB639D100FDBBCC /* Demangling.swift */,\n\t\t\t\tBB42F91B2EB639D100FDBBCC /* DLKit.swift */,\n\t\t\t\tBB42F91C2EB639D100FDBBCC /* FileSymbols.swift */,\n\t\t\t\tBB42F91D2EB639D100FDBBCC /* ImageSymbols.swift */,\n\t\t\t\tBB42F91E2EB639D100FDBBCC /* Interposing.swift */,\n\t\t\t\tBB42F91F2EB639D100FDBBCC /* Iterators.swift */,\n\t\t\t);\n\t\t\tname = DLKit;\n\t\t\tpath = ../DLKit/Sources/DLKit;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\tBB42F9282EB639E500FDBBCC /* include */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB42F9272EB639E500FDBBCC /* DLKitC.h */,\n\t\t\t);\n\t\t\tpath = include;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBB42F92C2EB639E500FDBBCC /* DLKitC */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB42F9282EB639E500FDBBCC /* include */,\n\t\t\t\tBB42F9292EB639E500FDBBCC /* DLKitC.c */,\n\t\t\t\tBB42F92A2EB639E500FDBBCC /* trie_dladdr.mm */,\n\t\t\t\tBB42F92B2EB639E500FDBBCC /* trie_dlops.mm */,\n\t\t\t);\n\t\t\tname = DLKitC;\n\t\t\tpath = ../DLKit/Sources/DLKitC;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\tBB42F9372EB63C2900FDBBCC /* InjectionImpl */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB47887F2EB6B6E700464AB4 /* InjectionImplC */,\n\t\t\t\tBB42F9312EB63C2900FDBBCC /* Common.swift */,\n\t\t\t\tBB42F9322EB63C2900FDBBCC /* Generics.swift */,\n\t\t\t\tBB42F9332EB63C2900FDBBCC /* KeyPaths.swift */,\n\t\t\t\tBB42F9342EB63C2900FDBBCC /* Metadata.swift */,\n\t\t\t\tBB42F9352EB63C2900FDBBCC /* Reloader.swift */,\n\t\t\t\tBB42F9362EB63C2900FDBBCC /* Sweeper.swift */,\n\t\t\t);\n\t\t\tname = InjectionImpl;\n\t\t\tpath = ../InjectionLite/Sources/InjectionImpl;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\tBB42F9452EB63E3400FDBBCC /* InjectionLite */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB42F9402EB63E3400FDBBCC /* FileWatcher.swift */,\n\t\t\t\tBB42F9412EB63E3400FDBBCC /* InjectionBase.swift */,\n\t\t\t\tBB42F9422EB63E3400FDBBCC /* InjectionLite.swift */,\n\t\t\t\tBB42F9432EB63E3400FDBBCC /* LogParser.swift */,\n\t\t\t\tBB42F9442EB63E3400FDBBCC /* Recompiler.swift */,\n\t\t\t);\n\t\t\tname = InjectionLite;\n\t\t\tpath = ../InjectionLite/Sources/InjectionLite;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\tBB42F9542EB63EFF00FDBBCC /* InjectionBazel */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB42F94F2EB63EFF00FDBBCC /* BazelActionQueryHandler.swift */,\n\t\t\t\tBB42F9502EB63EFF00FDBBCC /* BazelAQueryParser.swift */,\n\t\t\t\tBB42F9512EB63EFF00FDBBCC /* BazelInterface.swift */,\n\t\t\t\tBB42F9522EB63EFF00FDBBCC /* FilenameMatcher.swift */,\n\t\t\t\tBB42F9532EB63EFF00FDBBCC /* GitIgnoreParser.swift */,\n\t\t\t);\n\t\t\tname = InjectionBazel;\n\t\t\tpath = ../InjectionLite/Sources/InjectionBazel;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\tBB439B5C1FABA64300B4F50B = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB037DF41FAD80D0004B267C /* LICENSE */,\n\t\t\t\tBB2A66352E3E753B001EDD38 /* BAZEL.md */,\n\t\t\t\tBBF6572D2DAFF00200638170 /* QUICK.md */,\n\t\t\t\tBBF6572C2DAFF00200638170 /* NIMBLE.md */,\n\t\t\t\tBB037DF31FAD808B004B267C /* README.md */,\n\t\t\t\tBBCA01FF1FB0F10300E45F0F /* InjectionNext */,\n\t\t\t\tBBDD84172C4FE79E000F3124 /* InjectionBundle */,\n\t\t\t\tBB85A4252D6B9C5300FA29D0 /* feedcommands */,\n\t\t\t\tBB439B661FABA64300B4F50B /* Products */,\n\t\t\t\tBBB040621FB1798A007DDD0A /* Frameworks */,\n\t\t\t);\n\t\t\tindentWidth = 4;\n\t\t\tsourceTree = \"<group>\";\n\t\t\ttabWidth = 4;\n\t\t};\n\t\tBB439B661FABA64300B4F50B /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBBCA01FE1FB0F10300E45F0F /* InjectionNext.app */,\n\t\t\t\tBBDD84132C4FE749000F3124 /* macOSInjection.bundle */,\n\t\t\t\tBB85A4242D6B9C5300FA29D0 /* feedcommands */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBB47887D2EB6B6E700464AB4 /* include */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB47887C2EB6B6E700464AB4 /* InjectionImplC.h */,\n\t\t\t);\n\t\t\tpath = include;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBB47887F2EB6B6E700464AB4 /* InjectionImplC */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB47887D2EB6B6E700464AB4 /* include */,\n\t\t\t\tBB47887E2EB6B6E700464AB4 /* InjectionBoot.mm */,\n\t\t\t);\n\t\t\tname = InjectionImplC;\n\t\t\tpath = ../InjectionLite/Sources/InjectionImplC;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\tBB4788842EB6B81A00464AB4 /* include */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB4788822EB6B81A00464AB4 /* fishhook.h */,\n\t\t\t\tBB4788832EB6B81A00464AB4 /* SwiftTrace.h */,\n\t\t\t);\n\t\t\tpath = include;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBB47888F2EB6B81A00464AB4 /* SwiftTraceGuts */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB4788842EB6B81A00464AB4 /* include */,\n\t\t\t\tBB4788852EB6B81A00464AB4 /* fast_dladdr.mm */,\n\t\t\t\tBB4788862EB6B81A00464AB4 /* fishhook.c */,\n\t\t\t\tBB4788872EB6B81A00464AB4 /* ObjCBridge.mm */,\n\t\t\t\tBB4788882EB6B81A00464AB4 /* SwiftTrace.mm */,\n\t\t\t\tBB4788892EB6B81A00464AB4 /* SwiftTrace-Swift.h */,\n\t\t\t\tBB47888A2EB6B81A00464AB4 /* Trampolines.mm */,\n\t\t\t\tBB47888B2EB6B81A00464AB4 /* xt_forwarding_trampoline_arm7.s */,\n\t\t\t\tBB47888C2EB6B81A00464AB4 /* xt_forwarding_trampoline_arm64.s */,\n\t\t\t\tBB47888D2EB6B81A00464AB4 /* xt_forwarding_trampoline_x64.s */,\n\t\t\t\tBB47888E2EB6B81A00464AB4 /* xt_forwarding_trampoline_x86.s */,\n\t\t\t);\n\t\t\tname = SwiftTraceGuts;\n\t\t\tpath = ../SwiftTrace/SwiftTraceGuts;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\tBBB040621FB1798A007DDD0A /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBBCCC3B02C73A6AD00E71F81 /* XCTest.framework */,\n\t\t\t\tBBB64FEB1FD585D50020BE47 /* WebKit.framework */,\n\t\t\t\tBBB64DE41FD571300020BE47 /* libz.tbd */,\n\t\t\t\tBBBEC42D1FC56522004188B3 /* XCTest.framework */,\n\t\t\t\tBBB040631FB1798A007DDD0A /* ScriptingBridge.framework */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBCA01FF1FB0F10300E45F0F /* InjectionNext */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB16653925E9A5F0001407AE /* main.m */,\n\t\t\t\tBBCA02011FB0F10300E45F0F /* AppDelegate.swift */,\n\t\t\t\tBB4654802C257F110080EC40 /* NextCompiler.swift */,\n\t\t\t\t224E57FF2C08BC0E00B71C79 /* MonitorXcode.swift */,\n\t\t\t\t224E57FD2C08BBE300B71C79 /* InjectionServer.swift */,\n\t\t\t\tBB5155D92CDED44400704C7A /* InjectionHybrid.swift */,\n\t\t\t\tBBA082352D6BC32D00FFFB2F /* FrontendServer.swift */,\n\t\t\t\tCEC17029253ED117002E823F /* Experimental.swift */,\n\t\t\t\tBB6A56EF2C50E73600C92112 /* Defaults.swift */,\n\t\t\t\t22B6459F2C18DD9D00F99B61 /* Unhider.swift */,\n\t\t\t\tAA0000002F08000000000001 /* ControlServer.swift */,\n\t\t\t\t224E57FC2C08BAE200B71C79 /* InjectionClient.h */,\n\t\t\t\tBB67DBB21FB0CDA8000EAC8A /* SimpleSocket.h */,\n\t\t\t\tBB67DBB31FB0CDA8000EAC8A /* SimpleSocket.mm */,\n\t\t\t\tBBCA02031FB0F10300E45F0F /* Assets.xcassets */,\n\t\t\t\tBBCA025E1FB122C300E45F0F /* InjectionIdle.tif */,\n\t\t\t\t222BC9442C157C3200780A41 /* InjectionReady.tif */,\n\t\t\t\tBBCA025F1FB122C300E45F0F /* InjectionOK.tif */,\n\t\t\t\tBBE490D91FB2C643003D41BB /* InjectionBusy.tif */,\n\t\t\t\tBBE490DA1FB2C643003D41BB /* InjectionError.tif */,\n\t\t\t\tBBCA02051FB0F10300E45F0F /* MainMenu.xib */,\n\t\t\t\tBBCA02081FB0F10400E45F0F /* Info.plist */,\n\t\t\t\tBBCA02581FB112F500E45F0F /* App.icns */,\n\t\t\t\tBBCA020B1FB0F10400E45F0F /* InjectionNext.entitlements */,\n\t\t\t\tBBDF943C2349277A00334E08 /* InjectionNext-Bridging-Header.h */,\n\t\t\t\tBB42F9542EB63EFF00FDBBCC /* InjectionBazel */,\n\t\t\t\tBBDD84562C4FED60000F3124 /* build_bundles.sh */,\n\t\t\t\tBBDD84582C4FF0B9000F3124 /* copy_bundle.sh */,\n\t\t\t\tBBA082372D6BD6CB00FFFB2F /* swift-frontend.sh */,\n\t\t\t);\n\t\t\tpath = InjectionNext;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBDD84172C4FE79E000F3124 /* InjectionBundle */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB42F9302EB63AAF00FDBBCC /* InjectionImplC.h */,\n\t\t\t\tBBDD84592C4FF645000F3124 /* ClientBoot.mm */,\n\t\t\t\tBBDD843A2C4FE892000F3124 /* InjectionBoot.mm */,\n\t\t\t\tBBDD84182C4FE7E6000F3124 /* InjectionNext.swift */,\n\t\t\t\tBBDD84532C4FEB16000F3124 /* TupleRegex.swift */,\n\t\t\t\tBB42F9452EB63E3400FDBBCC /* InjectionLite */,\n\t\t\t\tBB42F9372EB63C2900FDBBCC /* InjectionImpl */,\n\t\t\t\tBB42F9202EB639D100FDBBCC /* DLKit */,\n\t\t\t\tBB42F8E02EB626F100FDBBCC /* SwiftTrace */,\n\t\t\t\tBB6A56F22C51154F00C92112 /* InjectionBundle-Bridging-Header.h */,\n\t\t\t);\n\t\t\tpath = InjectionBundle;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\tBB85A4232D6B9C5300FA29D0 /* feedcommands */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = BB85A42A2D6B9C5300FA29D0 /* Build configuration list for PBXNativeTarget \"feedcommands\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tBBDD999A2F4AF61000E88DFB /* ShellScript */,\n\t\t\t\tBB85A4202D6B9C5300FA29D0 /* Sources */,\n\t\t\t\tBB85A4212D6B9C5300FA29D0 /* Frameworks */,\n\t\t\t\tBB85A4222D6B9C5300FA29D0 /* CopyFiles */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tfileSystemSynchronizedGroups = (\n\t\t\t\tBB85A4252D6B9C5300FA29D0 /* feedcommands */,\n\t\t\t);\n\t\t\tname = feedcommands;\n\t\t\tpackageProductDependencies = (\n\t\t\t);\n\t\t\tproductName = feedcommands;\n\t\t\tproductReference = BB85A4242D6B9C5300FA29D0 /* feedcommands */;\n\t\t\tproductType = \"com.apple.product-type.tool\";\n\t\t};\n\t\tBBCA01FD1FB0F10300E45F0F /* InjectionNext */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = BBCA020C1FB0F10400E45F0F /* Build configuration list for PBXNativeTarget \"InjectionNext\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t22240ECB2C0C7178004DCBAD /* Run Script */,\n\t\t\t\tBBCA01FA1FB0F10300E45F0F /* Sources */,\n\t\t\t\tBBCA01FB1FB0F10300E45F0F /* Frameworks */,\n\t\t\t\tBBCA01FC1FB0F10300E45F0F /* Resources */,\n\t\t\t\tBB6224721FC5BA6F00AD7A3A /* CopyFiles */,\n\t\t\t\tBB6C87DB2520D0D3005AFCFC /* Embed Frameworks */,\n\t\t\t\tBBDD84572C4FED87000F3124 /* ShellScript */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tBB85A42D2D6B9CA200FA29D0 /* PBXTargetDependency */,\n\t\t\t\tBBDD843E2C4FE8C5000F3124 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = InjectionNext;\n\t\t\tpackageProductDependencies = (\n\t\t\t\t224E57FA2C08978F00B71C79 /* SwiftRegex */,\n\t\t\t\t2217BE802C0A65C20032A832 /* Fortify */,\n\t\t\t\t22E3D98A2C19009900BB234E /* DLKit */,\n\t\t\t\t22E3D98C2C19009900BB234E /* DLKitC */,\n\t\t\t\tBB2D41AB2DAD14EA0073C203 /* Popen */,\n\t\t\t);\n\t\t\tproductName = InjectionIII;\n\t\t\tproductReference = BBCA01FE1FB0F10300E45F0F /* InjectionNext.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\tBBDD84122C4FE749000F3124 /* InjectionBundle */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = BBDD84162C4FE749000F3124 /* Build configuration list for PBXNativeTarget \"InjectionBundle\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tBBDD840F2C4FE749000F3124 /* Sources */,\n\t\t\t\tBBDD84102C4FE749000F3124 /* Frameworks */,\n\t\t\t\tBBDD84112C4FE749000F3124 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tBB2D41AE2DAD15220073C203 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = InjectionBundle;\n\t\t\tproductName = InjectionBundle;\n\t\t\tproductReference = BBDD84132C4FE749000F3124 /* macOSInjection.bundle */;\n\t\t\tproductType = \"com.apple.product-type.bundle\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\tBB439B5D1FABA64300B4F50B /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tBuildIndependentTargetsInParallel = YES;\n\t\t\t\tLastSwiftUpdateCheck = 1150;\n\t\t\t\tLastUpgradeCheck = 1640;\n\t\t\t\tORGANIZATIONNAME = \"John Holdsworth\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\tBB85A4232D6B9C5300FA29D0 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 16.3;\n\t\t\t\t\t};\n\t\t\t\t\tBBCA01FD1FB0F10300E45F0F = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 9.0.1;\n\t\t\t\t\t\tLastSwiftMigration = 1110;\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t\tSystemCapabilities = {\n\t\t\t\t\t\t\tcom.apple.Sandbox = {\n\t\t\t\t\t\t\t\tenabled = 1;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t\tBBDD84122C4FE749000F3124 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 15.2;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = BB439B601FABA64300B4F50B /* Build configuration list for PBXProject \"InjectionNext\" */;\n\t\t\tcompatibilityVersion = \"Xcode 8.0\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = BB439B5C1FABA64300B4F50B;\n\t\t\tpackageReferences = (\n\t\t\t\t224E57F92C08978F00B71C79 /* XCRemoteSwiftPackageReference \"SwiftRegex5\" */,\n\t\t\t\t2217BE7F2C0A65C20032A832 /* XCRemoteSwiftPackageReference \"Fortify\" */,\n\t\t\t\t22E3D9892C19009900BB234E /* XCRemoteSwiftPackageReference \"DLKit\" */,\n\t\t\t\tBB0CECB12C73C1890000A4E6 /* XCRemoteSwiftPackageReference \"Nimble\" */,\n\t\t\t\tBBEB87102C74FD930044578A /* XCRemoteSwiftPackageReference \"Quick\" */,\n\t\t\t\tBB2D41A42DAD10110073C203 /* XCRemoteSwiftPackageReference \"Popen\" */,\n\t\t\t);\n\t\t\tproductRefGroup = BB439B661FABA64300B4F50B /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\tBBCA01FD1FB0F10300E45F0F /* InjectionNext */,\n\t\t\t\tBBDD84122C4FE749000F3124 /* InjectionBundle */,\n\t\t\t\tBB85A4232D6B9C5300FA29D0 /* feedcommands */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\tBBCA01FC1FB0F10300E45F0F /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBB4788812EB6B71600464AB4 /* InjectionImplC.h in Resources */,\n\t\t\t\tBB85A42B2D6B9C7B00FA29D0 /* feedcommands in Resources */,\n\t\t\t\tBBDD843F2C4FE8D5000F3124 /* macOSInjection.bundle in Resources */,\n\t\t\t\tBBA082382D6BD6CB00FFFB2F /* swift-frontend.sh in Resources */,\n\t\t\t\tBB6A56F12C50E79800C92112 /* copy_bundle.sh in Resources */,\n\t\t\t\tBBB64DC61FD450B40020BE47 /* LICENSE in Resources */,\n\t\t\t\tBB2A66362E3E753B001EDD38 /* BAZEL.md in Resources */,\n\t\t\t\tBBB64DC51FD450AF0020BE47 /* README.md in Resources */,\n\t\t\t\tBBE490DC1FB2C643003D41BB /* InjectionError.tif in Resources */,\n\t\t\t\tBBCA02591FB112F500E45F0F /* App.icns in Resources */,\n\t\t\t\tBBCA02601FB122C300E45F0F /* InjectionIdle.tif in Resources */,\n\t\t\t\tBBF6572E2DAFF00200638170 /* NIMBLE.md in Resources */,\n\t\t\t\tBBF6572F2DAFF00200638170 /* QUICK.md in Resources */,\n\t\t\t\tBBCA02611FB122C300E45F0F /* InjectionOK.tif in Resources */,\n\t\t\t\tBBCA02041FB0F10300E45F0F /* Assets.xcassets in Resources */,\n\t\t\t\t222BC9452C157C3200780A41 /* InjectionReady.tif in Resources */,\n\t\t\t\tBBCA02071FB0F10300E45F0F /* MainMenu.xib in Resources */,\n\t\t\t\tBBE490DB1FB2C643003D41BB /* InjectionBusy.tif in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBDD84112C4FE749000F3124 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t22240ECB2C0C7178004DCBAD /* Run Script */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\talwaysOutOfDate = 1;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Run Script\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"# Type a script or drag a script file from your workspace to insert its path.\\nif [ \\\"$ACTION\\\" == \\\"install\\\" ]; then exit 0; fi\\nbuildNumber=$(/usr/libexec/PlistBuddy -c \\\"Print CFBundleVersion\\\" \\\"${PROJECT_DIR}/${INFOPLIST_FILE}\\\")\\nbuildNumber=$(($buildNumber + 1))\\nchmod +w \\\"${PROJECT_DIR}/${INFOPLIST_FILE}\\\"\\n/usr/libexec/PlistBuddy -c \\\"Set :CFBundleVersion $buildNumber\\\" \\\"${PROJECT_DIR}/${INFOPLIST_FILE}\\\"\\n\";\n\t\t};\n\t\tBBDD84572C4FED87000F3124 /* ShellScript */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 12;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"# Type a script or drag a script file from your workspace to insert its path.\\nInjectionNext/build_bundles.sh\\n\";\n\t\t};\n\t\tBBDD999A2F4AF61000E88DFB /* ShellScript */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"perl -e 'print \\\"#define COMMANDS_VERSION @{[1_000_000 + int(rand() * ((1 << 31)) - 1_000_000)]}\\\\n\\\"' >/tmp/InjectionNextSalt.h\\n\";\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\tBB85A4202D6B9C5300FA29D0 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBB85A42E2D6BA13B00FA29D0 /* SimpleSocket.mm in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBCA01FA1FB0F10300E45F0F /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBB6A56F02C50E73600C92112 /* Defaults.swift in Sources */,\n\t\t\t\tBB42F93F2EB63CD800FDBBCC /* Common.swift in Sources */,\n\t\t\t\tBB42F94C2EB63E4F00FDBBCC /* LogParser.swift in Sources */,\n\t\t\t\t224E58002C08BC0E00B71C79 /* MonitorXcode.swift in Sources */,\n\t\t\t\tBB42F94D2EB63E5600FDBBCC /* Recompiler.swift in Sources */,\n\t\t\t\t229127F12C1EEF69005D7625 /* Experimental.swift in Sources */,\n\t\t\t\tBBA082362D6BC33500FFFB2F /* FrontendServer.swift in Sources */,\n\t\t\t\tBBCA022A1FB0F64800E45F0F /* SimpleSocket.mm in Sources */,\n\t\t\t\tBB42F94E2EB63E7700FDBBCC /* InjectionBase.swift in Sources */,\n\t\t\t\tBB16653A25E9A5F2001407AE /* main.m in Sources */,\n\t\t\t\tBBCA02021FB0F10300E45F0F /* AppDelegate.swift in Sources */,\n\t\t\t\tBB5155DA2CDED44F00704C7A /* InjectionHybrid.swift in Sources */,\n\t\t\t\tBB42F94B2EB63E3F00FDBBCC /* FileWatcher.swift in Sources */,\n\t\t\t\tBB4654812C257F110080EC40 /* NextCompiler.swift in Sources */,\n\t\t\t\tBB42F95A2EB63EFF00FDBBCC /* BazelInterface.swift in Sources */,\n\t\t\t\tBB42F95B2EB63EFF00FDBBCC /* GitIgnoreParser.swift in Sources */,\n\t\t\t\tBB42F95C2EB63EFF00FDBBCC /* BazelActionQueryHandler.swift in Sources */,\n\t\t\t\tBB42F95D2EB63EFF00FDBBCC /* BazelAQueryParser.swift in Sources */,\n\t\t\t\tBB42F95E2EB63EFF00FDBBCC /* FilenameMatcher.swift in Sources */,\n\t\t\t\t224E57FE2C08BBE300B71C79 /* InjectionServer.swift in Sources */,\n\t\t\t\t22B645A02C18DD9D00F99B61 /* Unhider.swift in Sources */,\n\t\t\t\tAA0000012F08000000000001 /* ControlServer.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBDD840F2C4FE749000F3124 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBBDD84422C4FEA4E000F3124 /* InjectionNext.swift in Sources */,\n\t\t\t\tBB42F8E12EB626F100FDBBCC /* SwiftAspects.swift in Sources */,\n\t\t\t\tBB42F8E22EB626F100FDBBCC /* SwiftInterpose.swift in Sources */,\n\t\t\t\tBB42F8E32EB626F100FDBBCC /* SwiftTrace.swift in Sources */,\n\t\t\t\tBB42F8E42EB626F100FDBBCC /* SwiftSwizzle.swift in Sources */,\n\t\t\t\tBB42F8E52EB626F100FDBBCC /* SwiftArgs.swift in Sources */,\n\t\t\t\tBB42F8E62EB626F100FDBBCC /* SwiftInvoke.swift in Sources */,\n\t\t\t\tBB42F8E72EB626F100FDBBCC /* EasyPointer.swift in Sources */,\n\t\t\t\tBB42F8E82EB626F100FDBBCC /* SwiftStack.swift in Sources */,\n\t\t\t\tBB42F9552EB63EFF00FDBBCC /* BazelInterface.swift in Sources */,\n\t\t\t\tBB4788902EB6B81A00464AB4 /* fast_dladdr.mm in Sources */,\n\t\t\t\tBB4788912EB6B81A00464AB4 /* xt_forwarding_trampoline_arm64.s in Sources */,\n\t\t\t\tBB4788922EB6B81A00464AB4 /* xt_forwarding_trampoline_x64.s in Sources */,\n\t\t\t\tBB4788932EB6B81A00464AB4 /* ObjCBridge.mm in Sources */,\n\t\t\t\tBB4788942EB6B81A00464AB4 /* Trampolines.mm in Sources */,\n\t\t\t\tBB4788952EB6B81A00464AB4 /* xt_forwarding_trampoline_arm7.s in Sources */,\n\t\t\t\tBB4788962EB6B81A00464AB4 /* SwiftTrace.mm in Sources */,\n\t\t\t\tBB4788972EB6B81A00464AB4 /* xt_forwarding_trampoline_x86.s in Sources */,\n\t\t\t\tBB4788982EB6B81A00464AB4 /* fishhook.c in Sources */,\n\t\t\t\tBB42F9562EB63EFF00FDBBCC /* GitIgnoreParser.swift in Sources */,\n\t\t\t\tBB42F9572EB63EFF00FDBBCC /* BazelActionQueryHandler.swift in Sources */,\n\t\t\t\tBB42F9582EB63EFF00FDBBCC /* BazelAQueryParser.swift in Sources */,\n\t\t\t\tBB42F9592EB63EFF00FDBBCC /* FilenameMatcher.swift in Sources */,\n\t\t\t\tBB42F8E92EB626F100FDBBCC /* SwiftStats.swift in Sources */,\n\t\t\t\tBB42F9212EB639D100FDBBCC /* DLKit.swift in Sources */,\n\t\t\t\tBB42F9222EB639D100FDBBCC /* Iterators.swift in Sources */,\n\t\t\t\tBB42F9232EB639D100FDBBCC /* Interposing.swift in Sources */,\n\t\t\t\tBBFE1B422ED7C116004E14EE /* SwiftRefs.swift in Sources */,\n\t\t\t\tBB42F9242EB639D100FDBBCC /* ImageSymbols.swift in Sources */,\n\t\t\t\tBB42F9252EB639D100FDBBCC /* Demangling.swift in Sources */,\n\t\t\t\tBB42F9262EB639D100FDBBCC /* FileSymbols.swift in Sources */,\n\t\t\t\tBB42F8EA2EB626F100FDBBCC /* StringIndex.swift in Sources */,\n\t\t\t\tBB42F8EB2EB626F100FDBBCC /* SwiftLifetime.swift in Sources */,\n\t\t\t\tBB42F9462EB63E3400FDBBCC /* InjectionBase.swift in Sources */,\n\t\t\t\tBB42F9472EB63E3400FDBBCC /* Recompiler.swift in Sources */,\n\t\t\t\tBB42F9482EB63E3400FDBBCC /* InjectionLite.swift in Sources */,\n\t\t\t\tBB42F9492EB63E3400FDBBCC /* LogParser.swift in Sources */,\n\t\t\t\tBB42F94A2EB63E3400FDBBCC /* FileWatcher.swift in Sources */,\n\t\t\t\tBB42F8EC2EB626F100FDBBCC /* SwiftMeta.swift in Sources */,\n\t\t\t\tBB4788802EB6B6E700464AB4 /* InjectionBoot.mm in Sources */,\n\t\t\t\tBBDD845A2C4FF646000F3124 /* ClientBoot.mm in Sources */,\n\t\t\t\tBB42F92D2EB639E500FDBBCC /* DLKitC.c in Sources */,\n\t\t\t\tBB42F92E2EB639E500FDBBCC /* trie_dladdr.mm in Sources */,\n\t\t\t\tBB42F92F2EB639E500FDBBCC /* trie_dlops.mm in Sources */,\n\t\t\t\tBBDD84542C4FEB16000F3124 /* TupleRegex.swift in Sources */,\n\t\t\t\tBBDD84552C4FEC98000F3124 /* SimpleSocket.mm in Sources */,\n\t\t\t\tBB42F9382EB63C2900FDBBCC /* KeyPaths.swift in Sources */,\n\t\t\t\tBB42F9392EB63C2900FDBBCC /* Reloader.swift in Sources */,\n\t\t\t\tBB52AD552F1501F500297CD9 /* Unhider.swift in Sources */,\n\t\t\t\tBB42F93A2EB63C2900FDBBCC /* Generics.swift in Sources */,\n\t\t\t\tBB42F93B2EB63C2900FDBBCC /* Metadata.swift in Sources */,\n\t\t\t\tBB42F93C2EB63C2900FDBBCC /* Common.swift in Sources */,\n\t\t\t\tBB42F93D2EB63C2900FDBBCC /* Sweeper.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\tBB2D41AE2DAD15220073C203 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\tproductRef = BB2D41AD2DAD15220073C203 /* Popen */;\n\t\t};\n\t\tBB85A42D2D6B9CA200FA29D0 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = BB85A4232D6B9C5300FA29D0 /* feedcommands */;\n\t\t\ttargetProxy = BB85A42C2D6B9CA200FA29D0 /* PBXContainerItemProxy */;\n\t\t};\n\t\tBBDD843E2C4FE8C5000F3124 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = BBDD84122C4FE749000F3124 /* InjectionBundle */;\n\t\t\ttargetProxy = BBDD843D2C4FE8C5000F3124 /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\tBBCA02051FB0F10300E45F0F /* MainMenu.xib */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\tBBCA02061FB0F10300E45F0F /* Base */,\n\t\t\t);\n\t\t\tname = MainMenu.xib;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\tBB439B821FABA64300B4F50B /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++14\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tDEVELOPMENT_TEAM = 9V5A8WE85E;\n\t\t\t\tEMIT_FRONTEND_COMMAND_LINES = YES;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = $PLATFORM_DIR/Developer/Library/Frameworks;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tHEADER_SEARCH_PATHS = $SRCROOT/HotReloading/Sources/HotReloadingGuts/include;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 13.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(SWIFT_PLATFORM_TARGET_PREFIX)\",\n\t\t\t\t\t$PLATFORM_DIR/Developer/Library/Frameworks,\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tOTHER_SWIFT_FLAGS = \"-Xfrontend -warn-long-expression-type-checking=150\";\n\t\t\t\tPRODUCT_NAME = macOSInjection;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tBB439B831FABA64300B4F50B /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++14\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tDEVELOPMENT_TEAM = 9V5A8WE85E;\n\t\t\t\tEMIT_FRONTEND_COMMAND_LINES = YES;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = $PLATFORM_DIR/Developer/Library/Frameworks;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tHEADER_SEARCH_PATHS = $SRCROOT/HotReloading/Sources/HotReloadingGuts/include;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 13.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(SWIFT_PLATFORM_TARGET_PREFIX)\",\n\t\t\t\t\t$PLATFORM_DIR/Developer/Library/Frameworks,\n\t\t\t\t);\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tPRODUCT_NAME = macOSInjection;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_COMPILATION_MODE = wholemodule;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-O\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tBB85A4282D6B9C5300FA29D0 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++20\";\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tDEAD_CODE_STRIPPING = YES;\n\t\t\t\tENABLE_HARDENED_RUNTIME = YES;\n\t\t\t\tENABLE_USER_SCRIPT_SANDBOXING = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu17;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tLOCALIZATION_PREFERS_STRING_CATALOGS = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 15.1;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tBB85A4292D6B9C5300FA29D0 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++20\";\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tDEAD_CODE_STRIPPING = YES;\n\t\t\t\tENABLE_HARDENED_RUNTIME = YES;\n\t\t\t\tENABLE_USER_SCRIPT_SANDBOXING = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu17;\n\t\t\t\tLOCALIZATION_PREFERS_STRING_CATALOGS = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 15.1;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tBBCA020D1FB0F10400E45F0F /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = InjectionNext/InjectionNext.entitlements;\n\t\t\t\tCODE_SIGN_IDENTITY = \"-\";\n\t\t\t\tCODE_SIGN_STYLE = Manual;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tENABLE_DEBUG_DYLIB = NO;\n\t\t\t\tENABLE_HARDENED_RUNTIME = YES;\n\t\t\t\tINFOPLIST_FILE = InjectionNext/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"@executable_path/../Frameworks\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.13;\n\t\t\t\tMARKETING_VERSION = 1.6.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.johnholdsworth.InjectionNext;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSWIFT_ACTIVE_COMPILATION_CONDITIONS = \"$(inherited) INJECTION_NEXT_APP\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"InjectionNext/InjectionNext-Bridging-Header.h\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tBBCA020E1FB0F10400E45F0F /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = InjectionNext/InjectionNext.entitlements;\n\t\t\t\tCODE_SIGN_IDENTITY = \"Developer ID Application\";\n\t\t\t\tCODE_SIGN_STYLE = Manual;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tENABLE_DEBUG_DYLIB = NO;\n\t\t\t\tENABLE_HARDENED_RUNTIME = YES;\n\t\t\t\tINFOPLIST_FILE = InjectionNext/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"@executable_path/../Frameworks\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.13;\n\t\t\t\tMARKETING_VERSION = 1.6.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.johnholdsworth.InjectionNext;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSWIFT_ACTIVE_COMPILATION_CONDITIONS = \"$(inherited) INJECTION_NEXT_APP\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"InjectionNext/InjectionNext-Bridging-Header.h\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tBBDD84142C4FE749000F3124 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++17\";\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tENABLE_USER_SCRIPT_SANDBOXING = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = c17;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tINFOPLIST_KEY_NSHumanReadableCopyright = \"Copyright © 2024 John Holdsworth. All rights reserved.\";\n\t\t\t\tINFOPLIST_KEY_NSPrincipalClass = \"\";\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Bundles\";\n\t\t\t\tLD_DYLIB_INSTALL_NAME = \"/Applications/InjectionNext.app/Contents/Resources/lib$(PLATFORM_NAME)Injection.dylib\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib,\n\t\t\t\t\t/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks,\n\t\t\t\t\t/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/PrivateFrameworks,\n\t\t\t\t);\n\t\t\t\tLIBRARY_SEARCH_PATHS = \"$(PLATFORM_DIR)/Developer/usr/lib\";\n\t\t\t\tLOCALIZATION_PREFERS_STRING_CATALOGS = YES;\n\t\t\t\tMACH_O_TYPE = mh_dylib;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"-lXCTestSwiftSupport\",\n\t\t\t\t\t\"$(BUILT_PRODUCTS_DIR)/Popen.o\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.johnholdsworth.InjectionBundle;\n\t\t\t\tPRODUCT_MODULE_NAME = InjectionBundle;\n\t\t\t\tPRODUCT_NAME = macOSInjection;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"InjectionBundle/InjectionBundle-Bridging-Header.h\";\n\t\t\t\tWRAPPER_EXTENSION = bundle;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tBBDD84152C4FE749000F3124 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++17\";\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tENABLE_USER_SCRIPT_SANDBOXING = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = c17;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tINFOPLIST_KEY_NSHumanReadableCopyright = \"Copyright © 2024 John Holdsworth. All rights reserved.\";\n\t\t\t\tINFOPLIST_KEY_NSPrincipalClass = \"\";\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Bundles\";\n\t\t\t\tLD_DYLIB_INSTALL_NAME = \"/Applications/InjectionNext.app/Contents/Resources/lib$(PLATFORM_NAME)Injection.dylib\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib,\n\t\t\t\t\t/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks,\n\t\t\t\t\t/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/PrivateFrameworks,\n\t\t\t\t);\n\t\t\t\tLIBRARY_SEARCH_PATHS = \"$(PLATFORM_DIR)/Developer/usr/lib\";\n\t\t\t\tLOCALIZATION_PREFERS_STRING_CATALOGS = YES;\n\t\t\t\tMACH_O_TYPE = mh_dylib;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.15;\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"-lXCTestSwiftSupport\",\n\t\t\t\t\t\"$(BUILT_PRODUCTS_DIR)/Popen.o\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.johnholdsworth.InjectionBundle;\n\t\t\t\tPRODUCT_MODULE_NAME = InjectionBundle;\n\t\t\t\tPRODUCT_NAME = macOSInjection;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"InjectionBundle/InjectionBundle-Bridging-Header.h\";\n\t\t\t\tWRAPPER_EXTENSION = bundle;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\tBB439B601FABA64300B4F50B /* Build configuration list for PBXProject \"InjectionNext\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tBB439B821FABA64300B4F50B /* Debug */,\n\t\t\t\tBB439B831FABA64300B4F50B /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tBB85A42A2D6B9C5300FA29D0 /* Build configuration list for PBXNativeTarget \"feedcommands\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tBB85A4282D6B9C5300FA29D0 /* Debug */,\n\t\t\t\tBB85A4292D6B9C5300FA29D0 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tBBCA020C1FB0F10400E45F0F /* Build configuration list for PBXNativeTarget \"InjectionNext\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tBBCA020D1FB0F10400E45F0F /* Debug */,\n\t\t\t\tBBCA020E1FB0F10400E45F0F /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tBBDD84162C4FE749000F3124 /* Build configuration list for PBXNativeTarget \"InjectionBundle\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tBBDD84142C4FE749000F3124 /* Debug */,\n\t\t\t\tBBDD84152C4FE749000F3124 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\n/* Begin XCRemoteSwiftPackageReference section */\n\t\t2217BE7F2C0A65C20032A832 /* XCRemoteSwiftPackageReference \"Fortify\" */ = {\n\t\t\tisa = XCRemoteSwiftPackageReference;\n\t\t\trepositoryURL = \"https://github.com/johnno1962/Fortify\";\n\t\t\trequirement = {\n\t\t\t\tkind = upToNextMajorVersion;\n\t\t\t\tminimumVersion = 2.1.12;\n\t\t\t};\n\t\t};\n\t\t224E57F92C08978F00B71C79 /* XCRemoteSwiftPackageReference \"SwiftRegex5\" */ = {\n\t\t\tisa = XCRemoteSwiftPackageReference;\n\t\t\trepositoryURL = \"https://github.com/johnno1962/SwiftRegex5\";\n\t\t\trequirement = {\n\t\t\t\tkind = upToNextMajorVersion;\n\t\t\t\tminimumVersion = 6.3.0;\n\t\t\t};\n\t\t};\n\t\t22E3D9892C19009900BB234E /* XCRemoteSwiftPackageReference \"DLKit\" */ = {\n\t\t\tisa = XCRemoteSwiftPackageReference;\n\t\t\trepositoryURL = \"https://github.com/johnno1962/DLKit\";\n\t\t\trequirement = {\n\t\t\t\tkind = upToNextMajorVersion;\n\t\t\t\tminimumVersion = 3.5.7;\n\t\t\t};\n\t\t};\n\t\tBB0CECAE2C73C1610000A4E6 /* XCRemoteSwiftPackageReference \"Quick\" */ = {\n\t\t\tisa = XCRemoteSwiftPackageReference;\n\t\t\trepositoryURL = \"https://github.com/Quick/Quick\";\n\t\t\trequirement = {\n\t\t\t\tbranch = main;\n\t\t\t\tkind = branch;\n\t\t\t};\n\t\t};\n\t\tBB0CECB12C73C1890000A4E6 /* XCRemoteSwiftPackageReference \"Nimble\" */ = {\n\t\t\tisa = XCRemoteSwiftPackageReference;\n\t\t\trepositoryURL = \"https://github.com/Quick/Nimble.git\";\n\t\t\trequirement = {\n\t\t\t\tkind = upToNextMinorVersion;\n\t\t\t\tminimumVersion = 13.2.0;\n\t\t\t};\n\t\t};\n\t\tBB2D41A42DAD10110073C203 /* XCRemoteSwiftPackageReference \"Popen\" */ = {\n\t\t\tisa = XCRemoteSwiftPackageReference;\n\t\t\trepositoryURL = \"https://github.com/johnno1962/Popen\";\n\t\t\trequirement = {\n\t\t\t\tkind = upToNextMajorVersion;\n\t\t\t\tminimumVersion = 2.2.1;\n\t\t\t};\n\t\t};\n\t\tBBEB87102C74FD930044578A /* XCRemoteSwiftPackageReference \"Quick\" */ = {\n\t\t\tisa = XCRemoteSwiftPackageReference;\n\t\t\trepositoryURL = \"https://github.com/johnno1962/Quick\";\n\t\t\trequirement = {\n\t\t\t\tbranch = uncached;\n\t\t\t\tkind = branch;\n\t\t\t};\n\t\t};\n/* End XCRemoteSwiftPackageReference section */\n\n/* Begin XCSwiftPackageProductDependency section */\n\t\t2217BE802C0A65C20032A832 /* Fortify */ = {\n\t\t\tisa = XCSwiftPackageProductDependency;\n\t\t\tpackage = 2217BE7F2C0A65C20032A832 /* XCRemoteSwiftPackageReference \"Fortify\" */;\n\t\t\tproductName = Fortify;\n\t\t};\n\t\t224E57FA2C08978F00B71C79 /* SwiftRegex */ = {\n\t\t\tisa = XCSwiftPackageProductDependency;\n\t\t\tpackage = 224E57F92C08978F00B71C79 /* XCRemoteSwiftPackageReference \"SwiftRegex5\" */;\n\t\t\tproductName = SwiftRegex;\n\t\t};\n\t\t22E3D98A2C19009900BB234E /* DLKit */ = {\n\t\t\tisa = XCSwiftPackageProductDependency;\n\t\t\tpackage = 22E3D9892C19009900BB234E /* XCRemoteSwiftPackageReference \"DLKit\" */;\n\t\t\tproductName = DLKit;\n\t\t};\n\t\t22E3D98C2C19009900BB234E /* DLKitC */ = {\n\t\t\tisa = XCSwiftPackageProductDependency;\n\t\t\tpackage = 22E3D9892C19009900BB234E /* XCRemoteSwiftPackageReference \"DLKit\" */;\n\t\t\tproductName = DLKitC;\n\t\t};\n\t\tBB0CECAF2C73C1610000A4E6 /* Quick */ = {\n\t\t\tisa = XCSwiftPackageProductDependency;\n\t\t\tpackage = BB0CECAE2C73C1610000A4E6 /* XCRemoteSwiftPackageReference \"Quick\" */;\n\t\t\tproductName = Quick;\n\t\t};\n\t\tBB0CECB22C73C1890000A4E6 /* Nimble */ = {\n\t\t\tisa = XCSwiftPackageProductDependency;\n\t\t\tpackage = BB0CECB12C73C1890000A4E6 /* XCRemoteSwiftPackageReference \"Nimble\" */;\n\t\t\tproductName = Nimble;\n\t\t};\n\t\tBB2D41AB2DAD14EA0073C203 /* Popen */ = {\n\t\t\tisa = XCSwiftPackageProductDependency;\n\t\t\tpackage = BB2D41A42DAD10110073C203 /* XCRemoteSwiftPackageReference \"Popen\" */;\n\t\t\tproductName = Popen;\n\t\t};\n\t\tBB2D41AD2DAD15220073C203 /* Popen */ = {\n\t\t\tisa = XCSwiftPackageProductDependency;\n\t\t\tpackage = BB2D41A42DAD10110073C203 /* XCRemoteSwiftPackageReference \"Popen\" */;\n\t\t\tproductName = Popen;\n\t\t};\n\t\tBBEB87112C74FD930044578A /* Quick */ = {\n\t\t\tisa = XCSwiftPackageProductDependency;\n\t\t\tpackage = BBEB87102C74FD930044578A /* XCRemoteSwiftPackageReference \"Quick\" */;\n\t\t\tproductName = Quick;\n\t\t};\n/* End XCSwiftPackageProductDependency section */\n\t};\n\trootObject = BB439B5D1FABA64300B4F50B /* Project object */;\n}\n"
  },
  {
    "path": "App/InjectionNext.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "App/InjectionNext.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>IDEDidComputeMac32BitWarning</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "App/InjectionNext.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict/>\n</plist>\n"
  },
  {
    "path": "App/InjectionNext.xcodeproj/xcshareddata/xcschemes/InjectionNext.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1520\"\n   version = \"1.7\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"BBCA01FD1FB0F10300E45F0F\"\n               BuildableName = \"InjectionNext.app\"\n               BlueprintName = \"InjectionNext\"\n               ReferencedContainer = \"container:InjectionNext.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      shouldAutocreateTestPlan = \"YES\">\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"BBCA01FD1FB0F10300E45F0F\"\n            BuildableName = \"InjectionNext.app\"\n            BlueprintName = \"InjectionNext\"\n            ReferencedContainer = \"container:InjectionNext.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <EnvironmentVariables>\n         <EnvironmentVariable\n            key = \"NO_BUILTIN\"\n            value = \"\"\n            isEnabled = \"NO\">\n         </EnvironmentVariable>\n         <EnvironmentVariable\n            key = \"NO_CACHING\"\n            value = \"\"\n            isEnabled = \"YES\">\n         </EnvironmentVariable>\n      </EnvironmentVariables>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"BBCA01FD1FB0F10300E45F0F\"\n            BuildableName = \"InjectionNext.app\"\n            BlueprintName = \"InjectionNext\"\n            ReferencedContainer = \"container:InjectionNext.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "App/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2024 John Holdsworth \n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "App/NIMBLE.md",
    "content": "Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2016 Quick Team\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "App/QUICK.md",
    "content": "Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2014, Quick Team\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "App/feedcommands/main.mm",
    "content": "//\n//  main.mm\n//  feedcommands\n//\n//  Created by John Holdsworth on 23/02/2025.\n//  Copyright © 2025 John Holdsworth. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"/tmp/InjectionNextSalt.h\"\n#import \"../../../InjectionNext/Sources/InjectionNextC/include/SimpleSocket.h\"\n#import \"../../../InjectionNext/Sources/InjectionNextC/include/InjectionClient.h\"\n\n@interface FeedSocket: SimpleSocket\n@end\n@implementation FeedSocket {\n    FILE *out;\n}\n+ (int)error:(NSString *)message {\n    if (isatty(STDIN_FILENO))\n        printf([NSString stringWithFormat:@\"%@/%@\\n\",\n                self, message].UTF8String, strerror(errno));\n    return 1;\n}\n- (BOOL)writeBytes:(const void *)buffer length:(size_t)length cmd:(SEL)cmd {\n    if (!out)\n        out = fdopen(clientSocket, \"w\");\n    return fwrite(buffer, 1, length, out) == length;\n}\n- (void)dealloc {\n    if (out)\n        fclose(out);\n}\n@end\n\nint main(int argc, const char * argv[]) {\n    @autoreleasepool {\n        // insert code here...\n        if (SimpleSocket *app = [FeedSocket connectTo:@COMMANDS_PORT]) {\n            [app writeInt:COMMANDS_VERSION];\n            [app writeString:NSHomeDirectory()];\n            for (int i=1; i<argc; i++)\n                [app writeCStr:argv[i]];\n        }\n        else\n            exit(EXIT_FAILURE);\n    }\n    return 0;\n}\n"
  },
  {
    "path": "BAZEL.md",
    "content": "## Bazel Support\n\nThis version includes enhanced Bazel build system support with automatic target discovery and optimized compilation queries. When InjectionLite detects a Bazel workspace (via `MODULE.bazel` or `WORKSPACE` files), it automatically:\n\n1. **Auto-discovers iOS application targets** from your Bazel build graph, prioritizing targets closer to the workspace root\n2. **Generates optimized aquery commands** that only query dependencies of your app targets, reducing overhead\n3. **Handles Bazel-specific placeholders** like `__BAZEL_XCODE_SDKROOT__` and `__BAZEL_XCODE_DEVELOPER_DIR__`\n4. **Processes output-file-map configurations** for better compatibility with Bazel's compilation strategy\n5. **Automatically overrides whole-module-optimization** settings that interfere with hot reloading\n\nThe system uses a two-tier approach: first attempting optimized queries using discovered app targets, then falling back to legacy broad queries if needed. This ensures compatibility while providing performance benefits for typical iOS development workflows.\n\nBazel integration requires either `bazel` or `/opt/homebrew/bin/bazelisk` to be available in your system PATH.\n\n### rules_xcodeproj Support\n\nWhen a project uses `rules_xcodeproj`, Xcode builds artifacts in a separate output base at `<outputBase>/rules_xcodeproj.noindex/build_output_base/` rather than the main Bazel output base. InjectionNext automatically detects this and:\n\n- Resolves `bazel-out/` paths to the rules_xcodeproj output base\n- Maps aquery configuration hashes (e.g. `ios_sim_arm64-fastbuild-*`) to the corresponding rules_xcodeproj configs (e.g. `ios_sim_arm64-dbg-*`)\n- Uses the rules_xcodeproj exec root as the working directory for recompilation\n\nThis is transparent — hot reloading works the same whether you build via `bazel run` or from Xcode with a rules_xcodeproj-generated project.\n"
  },
  {
    "path": "INTRO.md",
    "content": "\n## A lightning introduction to Injection\n\nAs it says in the README.md, using a feature of Apple's linker Code Injection\nallows you to update the implementation (i.e. body) of functions in your\napp without having to relauch it. There are three parts to implementing\nthis functionality. Recompiling your source file and preparing a dynamic\nlibrary, loading the dynamic library and stitching the new implementations\ninto your running program and arranging for the new implementations to be\ncalled to you can see on the screen that your code changes have taken effect.\nThe first part is implemented by the InjectionNext.app that runs on the menu \nbar, the second and third by code in the InjectionNext Swift package which\nyou add to the project you want to be able to inject. On startup the Swift \npackage creates a socket connection to the InjectionNext.app so it can\nbe controlled by it and instructed to load dynamic libaries either shared\nwith it on the filesystem or received through the socket connection for\nreal devices.\n\n### Preparing the dynamic library\n\nInjectionNext comes with a new solution to this problem. It integrates with\nXcode which if you launch it using the app (with SourceKit logging enabled)\nprovides all the information you need to recompile a file with the user's \nchanges which is the first step. The object file created by the recompilation\nis then linked in a reasonably generic way to create a dyanmic library which\ncan be loaded into your program at run time using dlopen().\n\n### Loading and binding the dynamic library\n\nWhen a new dynamic library is available, the InjectionNext.app messages the\ncode in the InjectionNext swift package to load it and \"bind\" it. Binding is\nthe means by which a call site in your program is dispatched to the implementing\nfunction and when you use the \"Other Linker Flags\", \"-Xlinker -interposable\"\nthis disptach is indirect through a writable section of memory. Change the\nfunction pointer in this memory and your new version of code is called instead\nof the old. This is done by a small piece of code from facebook named \"fishhook\"\nand all that remains is to know the new functions just loaded in the dynamic\nlibrary. To do this you scan the \"symbol table\" data structures included in\nthe dynamic library to find the \"mangled\" function names. The mangled names\nof Swift functions all start with \"$s\" and generally end in \"F\" or something\nvery similar and most of injection is simply extracting these names and the \nimplementation they point to and calling fishhook to rebind them. Classes\nare a ittle more complicated in that they have \"vtables\" in the meta-data \ndescribing the class but we don't need to explain that here. For Objective-C\nmethods there way always a public runtime API to rebind them.\n\n### Forcing redisplay\n\nThis is the more difficult part of injection to realise. You can have the\nnew fuction implementtions loaded and rebound but you won't see any change in\nthe appearance on the screen until that new code is called. With SwiftUI the\nesiest way to do this is to have an observed instance variable on your View \nstruct that changes when an injection has occured. There is code to do this in\nthe HotSwiftUI and Inject packages if you add an @ObserveInjection property\nwrapper to the View struct. It's a little more complicated for legacy\nUIViewController subclasses and what needs to happen generally is \nviewDidLoad() needs to be called again each time you inject but how to arrange \nthis for all currently displayed view controllers? The solution is \nInjectionNext performs a sweep all known instances of classes in the app \nand if they have been injected in the last loaded dynamic library and have an \n\"@objc func injected()\" method, call it. This method can call viewDidLoad()\nor \"configureView()\" or perform any other work required to update the display.\nAnother approach you can use is is to \"host\" the view controller using the\nInject package which reinstantiates the view controller on injection.\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2024 John Holdsworth\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Package.swift",
    "content": "// swift-tools-version: 5.4\n// The swift-tools-version declares the minimum version of Swift required to build this package.\n\nimport PackageDescription\n\nlet package = Package(\n    name: \"InjectionNext\",\n    products: [\n        // Products define the executables and libraries a package produces, making them visible to other packages.\n        .library(\n            name: \"InjectionNext\",\n            targets: [\"InjectionBundle\"]),\n        // To avoid duplicate symbols if other\n        // packages use e.g. DLKit or fishhook\n//        .library(\n//            name: \"InjectionNextDynamic\",\n//            type: .dynamic,\n//            targets: [\"InjectionNext\"]),\n    ],\n    targets: [\n        // Targets are the basic building blocks of a package, defining a module or a test suite.\n        // Targets can depend on other targets in this package and products from dependencies.\n        .target(\n            name: \"InjectionBundle\", dependencies: [\"InjectionNextC\"],\n            path: \"Sources/InjectionNext\", swiftSettings: [.define(\"DEBUG_ONLY\")]),\n        .target(\n            name: \"InjectionNextC\",\n            cSettings: [.define(\"DEBUG_ONLY\"), .define(\"FISHHOOK_EXPORT\")]),\n        .testTarget(\n            name: \"InjectionNextTests\",\n            dependencies: [\"InjectionBundle\"]),\n    ]\n)\n"
  },
  {
    "path": "README.md",
    "content": "# InjectionNext\n\n### The fourth evolution of Code Injection for Xcode\n\nUsing a feature of Apple's linker this implementation of Code Injection\nallows you to update the implementation (i.e. body) of functions in your\napp without having to relaunch it. This can save a developer a significant\namount of time tweaking code or iterating over a design. This repo is a \nrefresh of the [InjectionIII](https://github.com/johnno1962/InjectionIII)\napp that uses different techniques to determine how to rebuild source files\nthat should be faster and more reliable for very large projects.\n\nThe basic M.O. is to download one of the binary releases in this repo (or build \nthe app in the `App` directory), move it to /Applications, quit Xcode and run the\n`InjectionNext.app` and use that to re-launch Xcode using the menu item \n`Launch Xcode` from the status bar. You then add this repo as a Swift package \ndependency of your project and that should be all that is required for injection \nin the simulator, injection on devices and injection of a MacOS app. No more \ncode changes required to load binary code bundles etc and you can leave \nthe InjectionNext package configured into your project permanently as\nits code is only included for a DEBUG build. Your code changes take effect\nwhen you save a source for an app that has this package as a dependency\nand has connected to the InjectIonNext app which has launched Xcode.\n\nAs ever, it is important to add the options `-Xlinker` and `-interposable` \n(without double quotes and on separate lines) to the \"Other Linker Flags\" of \nthe targets of your project (for the `Debug` configuration only) to enable \nfunction \"interposing\". Otherwise, you will only be able to inject non-final\nclass methods.\n\n![Icon](App/interposable.png)\n\nIf your app contains local Swift packages, add the following to their targets\nin Package.swift to be able to inject functions inside the package.\n\n    linkerSettings: [\n        .unsafeFlags([\"-Xlinker\", \"-interposable\"],\n                     .when(configuration: .debug))\n    ]\n    \n**Please note:** Due to an Xcode bug (as of version 16.2), `.when(configuration: .debug)` \nis ignored for local package linker settings. Until it's fixed, you might find this \nworkaround helpful:\n\n```swift\nvar linkerSettings: [LinkerSetting] {\n    let isInjectionRunning = ProcessInfo.processInfo.environment[\"RUNNING_VIA_INJECTION_NEXT\"] != nil\n    return isInjectionRunning ? [.unsafeFlags([\"-Xlinker\", \"-interposable\"])] : []\n}\n```\n\n**Please note:** you can only inject changes to code inside a function body\nand you cannot add/remove or rename properties with storage or add or \nreorder methods in a non final class or change function signatures.\n\nTo inject SwiftUI sucessfully a couple of minor code changes to each View are \nrequired. Consult the README of repo https://github.com/johnno1962/HotSwiftUI\nor you can make the required changes automatically using the menu item\n\"Prepare SwiftUI/...\". For SwiftUI you would generally also integrate\neither the [Inject](https://github.com/krzysztofzablocki/Inject) or\n[HotSwiftUI](https://github.com/johnno1962/HotSwiftUI) package into your project. \n\nIf you'd rather not be adding a SPM dependency to your project, the app's\nresources contains pre-built bundles which you can copy into your app during\nthe build by using a \"Run Script/Build Phase\" (while disabling the \"user \nscript sandboxing\" build setting) such as the following:\n\n```\nexport RESOURCES=\"/Applications/InjectionNext.app/Contents/Resources\"\nif [ -f \"$RESOURCES/copy_bundle.sh\" ]; then\n    \"$RESOURCES/copy_bundle.sh\"\nfi\n```\nThese bundles should load automatically if you've integrated the\n[Inject](https://github.com/krzysztofzablocki/Inject) or\n[HotSwiftUI](https://github.com/johnno1962/HotSwiftUI) packages into your project. \nOtherwise, you can add the following code to run at startup of your app:\n\n```\n    #if DEBUG\n    if let path = Bundle.main.path(forResource:\n            \"iOSInjection\", ofType: \"bundle\") ??\n        Bundle.main.path(forResource:\n            \"macOSInjection\", ofType: \"bundle\") {\n        Bundle(path: path)!.load()\n    }\n    #endif\n```\nThe binary bundles also integrate [Nimble](https://github.com/Quick/Nimble)\nand a slightly modified version of the [Quick](https://github.com/Quick/Quick) \ntesting framework to inhibit spec caching under their respective Apache licences.\n\nAn alternative to loading a bundle is to add the following additional \"Other Linker Flag\":\n\n`/Applications/InjectionNext.app/Contents/Resources/lib$(PLATFORM_NAME)Injection.dylib`\n\nWhen your app runs it should connect to the `InjectionNext.app` and it's icon\nchange to orange. After that, by parsing the messages from the \"supervised\"\nlaunch of Xcode it is possible to know when files are saved and exactly how\nto recompile them for injection. Injection on a device uses the same \nconfiguration but is opt-in through the menu item \"Enable Devices\"\n(as it needs to open a network port). You also need to select the \nproject's \"expanded codesigning identity\" from the codesigning\nphase of your build logs in the window that pops up. Sometimes a \ndevice will not connect to the app first time after unlocking it.\nIf at first it doesn't succeed, try again.\n\nThe colours of the menu bar icon bar correspond to:\n\n* Blue when you first run the InjectionNext app.\n* Purple when you have launched Xcode using the app.\n* Orange when your client app has connected to it.\n* Green while it is recompiling a saved source.\n* Yellow if the source has failed to compile.\n\nTo inject tests on a device: when enabling the \"Enable Devices\"\nmenu item, if you select \"Enable testing on device\", the arguments\nshown will be added to the link of each dynamic library. As you \ndo this, the command mentioned above will be inserted into the clipboard \nwhich you should paste into your project as a \"Run Script\" \"Build Phase\" \nof the main target to copy the required libraries into the app bundle.\n\n### Cursor/VSCode/File-watcher mode.\n\nIf you would like to use InjectionNext with the Cursor code editor,\nyou can have it fall back to InjectionIII-style log parsing using\nthe \"...or Watch Project\" menu item to select the project root\nyou will be working under (or use the new \"Proxy\" mode below\nfor Swift projects.) In this case, you shouldn't launch \nXcode from inside the InjectionNext.app but you'll need to have \nbuilt your app in Xcode at some point in the past for the logs\nto be available. You should build using the same version as that \nselected by `xcode-select`. With Xcode 16.3+, for this log parsing\nmode to continue working you'll need to add a custom build setting\nEMIT_FRONTEND_COMMAND_LINES. If you'd like the InjectionNext.app to\nautomatically file watch your project, add the following environment\nvariable to your scheme: `INJECTION_PROJECT_ROOT=$(SRCROOT)`. Also,\nInjection doesn't work with setting COMPILATION_CACHE_ENABLE_CACHING.\n\n### Scheme environment variable INJECTION_TRACE\n\nIf you add an environment variable INJECTION_TRACE to your scheme,\nlogging aspects will be added to all functions in a file when you inject \nit so you can see they are being called and as an aid to debugging. This \nmeans you can turn on detailed logging for a file just by injecting it.\nFor a full list of all environment variable that can be specified consult\n[this source file](https://github.com/johnno1962/InjectionLite/blob/main/Sources/InjectionImplC/include/InjectionImplC.h#L45).\nYMMV with global tracing but on a device it will likely be more reliable\nif you use the precompiled bundles with a copy_bundle.sh build phase.\nIf you still see crashes, this can occur when an argument's type has\nbeen miscategorised. Add a INJECTION_TRACE_REPAIR schema variable and\nfailing methods will be added to a list excluding them from logging\nwhen you re-run your app.\n\n### Fallback compiler \"proxy\" mode (Not normally used).\n\nIt is also possible to intercept swift compilation commands as a new proof of\nconcept for when at some point in the future these are no longer captured in \nthe Xcode logs (as was the case with Xcode 16.3 beta1). In this case, select \n\"Intercept compiler\" to patch the current toolchain slightly to capture all\ncompilations using a script and send them to the InjectionNext.app. Once this \npatch has been applied you don't need to launch Xcode from the app and you can \ninject by starting a file watcher using the \"...or Watch Project\" menu item\n(though this should happen automatically when you recompile Swift sources).\nFor proxy mode to work the app must be installed in /Applications.\n\nSo, InjectionNext now has three ways which it can operate. The original mode \nof operation launching Xcode inside the app takes precedence and, if you have\nselected a file watcher and are intercepting the compiler commands this \"proxy\nmode\" is the next preference followed by the log parsing fallback using\nthe [InjectionLite](https://github.com/johnno1962/InjectionLite) package\nwhich essentially works as InjectionIII did when the logs are available.\n\nFor more information consult the [original InjectionIII README](https://github.com/johnno1962/InjectionIII)\nor for the bigger picture see [this swift evolution post](https://forums.swift.org/t/weve-been-doing-it-wrong-all-this-time/72015).\n\nYou can run InjectionNext from the command line and have it open\nyour project in Xcode automatically using the -projectPath option.\n\n    open -a InjectionNext --args -projectPath /path/to/project\n\nSet a user default with the same name if you want to always open \nthis project inside the selected Xcode on launching the app.\n\nAfter 100 injections you'll be reminded you can sponsor this project on GitHub.\n\nThe fabulous app icon is thanks to Katya of [pixel-mixer.com](http://pixel-mixer.com/).\n"
  },
  {
    "path": "Sources/InjectionNext/InjectionNext.swift",
    "content": "//\n//  InjectionNext.swift\n//  InjectionNext Package\n//\n//  Created by John Holdsworth on 30/05/2024.\n//\n//  Client app side of injection using implementation of InjectionLite.\n//\n#if DEBUG || !SWIFT_PACKAGE\nimport Foundation\n#if canImport(InjectionImpl)\nimport InjectionImpl\n#endif\n#if canImport(InjectionNextC)\n@_exported import InjectionNextC\n#endif\n\n@objc(InjectionNext)\nopen class InjectionNext: SimpleSocket {\n    \n    override class open func error(_ message: String) -> Int32 {\n        let msg = String(format: message, strerror(errno))\n        print(APP_PREFIX+APP_NAME+\": \"+msg)\n        if errno == EHOSTUNREACH { // No route to host\n            print(\"ℹ️ \"+APP_NAME+\": Accept permission prompt on device.\")\n        }\n        return errno\n    }\n\n    func log(_ msg: String) {\n        print(APP_PREFIX+APP_NAME+\": \"+msg)\n    }\n    func error(_ msg: String) {\n        log(\"⚠️ \"+msg)\n    }\n\n    /// Connection from client app opened in ClientBoot.mm arrives here\n    open override func runInBackground() {\n        super.write(INJECTION_VERSION)\n        #if targetEnvironment(simulator) || os(macOS)\n        super.write(NSHomeDirectory())\n        #else\n        if let bazelWorkspace = getenv(BUILD_WORKSPACE_DIRECTORY) {\n            super.write(String(cString: bazelWorkspace))\n        } else {\n            super.write(INJECTION_KEY)\n        }\n        #endif\n\n        // Find client platform\n        #if os(macOS) || targetEnvironment(macCatalyst)\n        var platform = \"Mac\"\n        #elseif os(tvOS)\n        var platform = \"AppleTV\"\n        #elseif os(visionOS)\n        var platform = \"XR\"\n        #elseif os(watchOS)\n        var platform = \"Watch\"\n        #else\n        var platform = \"iPhone\"\n        #endif\n\n        #if targetEnvironment(simulator)\n        platform += \"Simulator\"\n        #else\n        platform += \"OS\"\n        #endif\n        #if os(macOS)\n        platform += \"X\"\n        #endif\n\n        Reloader.platform = platform\n\n        #if arch(x86_64)\n        let arch = \"x86_64\"\n        #else\n        let arch = \"arm64\"\n        #endif\n\n        // Let server side know the platform and architecture\n        writeCommand(InjectionResponse.platform.rawValue, with: platform)\n        super.write(arch)\n        if let projectRoot = getenv(INJECTION_PROJECT_ROOT) ??\n                           getenv(BUILD_WORKSPACE_DIRECTORY) {\n            writeCommand(InjectionResponse.projectRoot.rawValue,\n                         with: String(cString: projectRoot))\n        }\n        writeCommand(InjectionResponse.tmpPath.rawValue, with: NSTemporaryDirectory())\n        if let detail = getenv(INJECTION_DETAIL) {\n            writeCommand(InjectionResponse.detail.rawValue,\n                         with: String(cString: detail))\n        }\n        if let bazelTarget = getenv(INJECTION_BAZEL_TARGET) {\n            writeCommand(InjectionResponse.bazelTarget.rawValue,\n                         with: String(cString: bazelTarget))\n        }\n        if let executable = Bundle.main.executablePath {\n            writeCommand(InjectionResponse.executable.rawValue,\n                         with: executable)\n        }\n\n        Reloader.injectionQueue.sync {\n            tracingOptions()\n        }\n\n        log(\"\\(arch) \\(platform) connected to app, waiting for commands.\")\n        #if !SWIFT_PACKAGE\n        if let build = Bundle(for: Self.self)\n            .infoDictionary?[\"CFBundleVersion\"] as? String {\n            detail(\"Bundle build #\"+build)\n        }\n        #endif\n        processCommandsFromApp()\n        log(\"Connection lost, disconnecting.\")\n    }\n    \n    func tracingOptions() {\n        SwiftTrace.injectableSymbol = Reloader.injectableSymbol\n        SwiftTrace.defaultMethodExclusions += // CoreFoundation\n            #\"|\\[NS(Method|Tagged|Array|\\w*Dict|Date|Data|Timer)|allocWithZone:|__unurl|_trueSelf\"#\n          + #\"|InjectionBundle.|fast_dl\"#\n        for name in [INJECTION_TRACE_LOOKUP, INJECTION_TRACE_FILTER, INJECTION_TRACE_ALL,\n                     INJECTION_TRACE_FRAMEWORKS, INJECTION_TRACE_UIKIT, INJECTION_TRACE] {\n            if let value = getenv(name) {\n                setVariable(name: name, to: String(cString: value), first: true)\n            }\n        }\n    }\n \n    func setVariable(name: String, to value: String, first: Bool) {\n        let wasSet = getenv(name) != nil\n        if name == INJECTION_DLOPEN_MODE, let mode = Int32(value) {\n            DLKit.dlOpenMode = mode\n        } else if name == INJECTION_TRACE_FILTER {\n            if value == UNSETENV_VALUE {\n                if wasSet {\n                    SwiftTrace.traceFilterInclude = \".\"\n                }\n            } else {\n                SwiftTrace.traceFilterInclude = value\n            }\n        }\n        if value == UNSETENV_VALUE {\n            unsetenv(name)\n            return\n        }\n        \n        setenv(name, value, 1)\n        if !first && wasSet {\n            return\n        }\n\n        switch name {\n        /// Custom type lookup on tracing.\n        case INJECTION_TRACE_LOOKUP:\n            if value.hasPrefix(\"|\") {\n                SwiftTrace.defaultLookupExclusions += value\n            }\n            SwiftTrace.typeLookup = true\n        /// Entire App bundle tracing.\n        case INJECTION_TRACE_ALL:\n            if value.hasPrefix(\"|\") {\n                SwiftTrace.defaultMethodExclusions += value\n            }\n            SwiftTrace.interposeEclusions = SwiftTrace.exclusionRegexp\n            appBundleImages { imageName, _, _ in\n                if SwiftTrace.interposeMethods(inBundlePath: imageName) == 0,\n                   strstr(imageName, \"XCT\") == nil {\n                    self.error(\"\"\"\n                            Unable to interpose to trace image \\\n                            \\(String(cString: imageName)), have you added \\\n                            \"Other Linker Flags\" -Xlinker -interposable\n                            \"\"\")\n                }\n                SwiftTrace.trace(bundlePath: imageName)\n            }\n        /// Trace calls to framework e.g. SwiftUI,SwiftUICore\n        case INJECTION_TRACE_FRAMEWORKS:\n            var frmwks = value\n            if frmwks == \"\" || frmwks == \"1\" { frmwks = \"SwiftUI,SwiftUICore\" }\n            for frmwk in frmwks.components(separatedBy: \",\") {\n                if let dylib = DLKit.imageMap[frmwk] {\n                    Self.target = dylib\n                    appBundleImages { path, header, slide in\n                        rebind_symbols_trace(autoBitCast(header), slide, Self.tracer)\n                    }\n                } else {\n                    error(\"Invalid trace framework \\(frmwk)\")\n                }\n            }\n        /// Trace UIKit internals using swizzling\n        case INJECTION_TRACE_UIKIT:\n            var frmwks = value\n            if frmwks == \"\" || frmwks == \"1\" { frmwks = \"UIKitCore\" }\n            for frmwk in frmwks.components(separatedBy: \",\") {\n                if let bundle = DLKit.imageMap[frmwk]?.imageName {\n                    SwiftTrace.trace(bundlePath: bundle)\n                } else {\n                    error(\"Invalid swizzle framework \\(frmwk)\")\n                }\n            }\n        /// Function and class method tracing on injection.\n        case INJECTION_TRACE:\n            Reloader.traceHook = { (injected, name) in\n                let name = SwiftMeta.demangle(symbol: name) ?? String(cString: name)\n                detail(\"SwiftTracing \\(name)\")\n                return autoBitCast(SwiftTrace.trace(name: name, original: injected)) ?? injected\n            }\n        default:\n            break\n        }\n    }\n\n    static var target: ImageSymbols?\n    static var tracer: STTracer = { existing, symname in\n        var traced = existing\n        if SwiftTrace.injectableSymbol(symname),\n           let info = trie_iterator(existing),\n           target?.imageHeader == info.pointee.header,\n           let name = SwiftMeta.demangle(symbol: symname) {\n            detail(\"Tracing \\(name) \\(existing)\")\n            traced = autoBitCast(SwiftTrace\n                .trace(name: \"   \"+name, original: existing)) ?? existing\n        }\n        return traced\n    }\n\n    func processCommandsFromApp() {\n        var loader = Reloader() // InjectionLite injection implementation\n        func injectAndSweep(_ dylib: String) {\n            Reloader.injectionNumber += 1\n            var succeeded = false\n            if let (image, classes) = Reloader.injectionQueue\n                .sync(execute: { loader.loadAndPatch(in: dylib) }) {\n                loader.sweeper.sweepAndRunTests(image: image, classes: classes)\n                succeeded = true\n\n                let countKey = \"__injectionsPerformed\", howOften = 100\n                let count = UserDefaults.standard.integer(forKey: countKey)+1\n                UserDefaults.standard.set(count, forKey: countKey)\n                if count % howOften == 0 && getenv(\"INJECTION_SPONSOR\") == nil {\n                    log(\"\"\"\n                        ℹ️ Seems like you're using injection quite a bit. \\\n                        Have you considered sponsoring the project at \\\n                        https://github.com/johnno1962/\\(APP_NAME) or \\\n                        asking your boss if they should? (This message \\\n                        prints every \\(howOften) injections.)\n                        \"\"\")\n                }\n            } else {\n                writeCommand(InjectionResponse.unhide.rawValue, with: nil)\n            }\n            writeCommand(succeeded ? InjectionResponse.injected.rawValue :\n                            InjectionResponse.failed.rawValue, with: nil)\n        }\n\n        while true {\n            let commandInt = readInt()\n            guard let command = InjectionCommand(rawValue: commandInt) else {\n                error(\"Invalid command rawValue: \\(commandInt)\")\n                break\n            }\n            switch command {\n            case .invalid:\n                return error(\"Connection did not validate. Have you upgraded?\")\n            case .log:\n                if let msg = readString() {\n                    print(msg)\n                }\n            case .xcodePath:\n                if let xcodePath = readString() {\n                    log(\"Xcode path: \"+xcodePath)\n                    Reloader.xcodeDev = xcodePath+\"/Contents/Developer\"\n                }\n            case .sendFile:\n                guard let path = readString() else {\n                    return error(\"Unable to read path\")\n                }\n                if path.hasSuffix(\"/\") {\n                    mkdir(path, 0o755)\n                    continue\n                }\n                recvFile(path)\n            case .load:\n                guard let dylib = readString() else {\n                    return error(\"Unable to read path\")\n                }\n                injectAndSweep(dylib)\n            case .inject:\n                guard let dylibName = readString(), let data = readData() else {\n                    return error(\"Unable to read dylib\")\n                }\n                let dylib = NSTemporaryDirectory() + dylibName\n                try! data.write(to: URL(fileURLWithPath: dylib))\n                injectAndSweep(dylib)\n            case .metrics:\n                guard let metricsJSON = readString() else {\n                    return error(\"Unable to read metrics JSON\")\n                }\n                if let data = metricsJSON.data(using: .utf8),\n                   let metricsDict = try? JSONSerialization.jsonObject(with: data) as? [String: Any],\n                   let notificationName = metricsDict[\"notification_name\"] as? String {\n                    NotificationCenter.default.post(\n                        name: NSNotification.Name(notificationName),\n                        object: nil,\n                        userInfo: metricsDict\n                    )\n                }\n            case .setenv:\n                while let name = readString(), let value = readString() {\n                    setVariable(name: name, to: value, first: false)\n                    if readInt() != commandInt {\n                        break\n                    }\n                }\n            case .EOF:\n                return\n            default:\n                return error(\"**** @unknown case \\(commandInt) **** \" +\n                             \"Do you need to update the InjectionNext package?\")\n            }\n        }\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/InjectionNextC/ClientBoot.mm",
    "content": "//\n//  ClientBoot.m\n//  \n//\n//  Created by John H on 31/05/2024.\n//\n\n#if DEBUG || !SWIFT_PACKAGE\n#import <Foundation/Foundation.h>\n#import <objc/runtime.h>\n\n#import \"InjectionImplC.h\"\n#import \"InjectionClient.h\"\n#import \"SimpleSocket.h\"\n\n@interface InjectionNext : SimpleSocket\n@end\n\n@implementation NSObject(InjectionNext)\n\nstatic SimpleSocket *injectionClient;\nstatic dispatch_once_t onlyOneClient;\n\n/// Called on load of image containing this code\n+ (void)load {\n    if ([InjectionNext InjectionBoot_inPreview]) return;\n    #if !TARGET_OS_MAC\n    [self performSelectorOnMainThread:@selector(connectInBackground)\n                           withObject:nil waitUntilDone:NO];\n}\n\n+ (void)connectInBackground {\n    #endif\n    [self performSelectorInBackground:@selector(connectToInjection:)\n                           withObject:[InjectionNext self]];\n}\n\n/// Attempt to connect to InjectionNext.app\n+ (void)connectToInjection:(Class)clientClass {\n    const char *hostip = getenv(INJECTION_HOST) ?: \"127.0.0.1\";\n\n    // Do we need to use broadcasts to find devlepers Mac on the network\n    #if !TARGET_IPHONE_SIMULATOR && !TARGET_OS_OSX\n    if (@available(iOS 14.0, *)) if (![NSProcessInfo processInfo].isiOSAppOnMac) {\n        printf(APP_PREFIX APP_NAME\": Locating developer's Mac. Have you selected \\\"Enable Devices\\\"?\\n\");\n        hostip = [SimpleSocket getMulticastService:HOTRELOADING_MULTICAST port:HOTRELOADING_PORT\n                                           message:APP_PREFIX\"Connecting to %s (%s)...\\n\"].UTF8String;\n    }\n    #endif\n\n    // Have the address to connect to, connect and start local thread.\n    NSString *socketAddr = [NSString stringWithFormat:@\"%s%s\", hostip, INJECTION_ADDRESS];\n    for (int retry=0, retrys=1; retry<retrys; retry++) {\n        if (retry)\n            [NSThread sleepForTimeInterval:1.0];\n        if (SimpleSocket *client = [clientClass connectTo:socketAddr]) {\n            dispatch_once(&onlyOneClient, ^{\n                // Calls to InjectionNext.runInBackground()\n                [injectionClient = client run];\n            });\n            return;\n        }\n    }\n\n    #if TARGET_IPHONE_SIMULATOR || TARGET_OS_MAC\n    // If InjectionLite class present, start it up.\n    if (getenv(INJECTION_NOSTANDALONE)) return;\n    if (Class InjectionLite = objc_getClass(\"InjectionLite\")) {\n        printf(APP_PREFIX\"Unable to connect to app, running standalone... \"\n               \"Set env var \" INJECTION_NOSTANDALONE \" to avoid this.\\n\");\n        static NSObject *singleton;\n        singleton = [[InjectionLite alloc] init];\n    }\n    #endif\n}\n\n@end\n#endif\n"
  },
  {
    "path": "Sources/InjectionNextC/SimpleSocket.mm",
    "content": "//\n//  SimpleSocket.mm\n//  InjectionIII\n//\n//  Created by John Holdsworth on 06/11/2017.\n//  Copyright © 2017 John Holdsworth. All rights reserved.\n//\n//  $Id: //depot/HotReloading/Sources/HotReloadingGuts/SimpleSocket.mm#63 $\n//\n//  Server and client primitives for networking through sockets\n//  more esailly written in Objective-C than Swift. Subclass to\n//  implement service or client that runs on a background thread\n//  implemented by overriding the \"runInBackground\" method.\n//\n\n#if DEBUG || !SWIFT_PACKAGE\n#import \"SimpleSocket.h\"\n\n#include <sys/socket.h>\n#include <netinet/tcp.h>\n#include <net/if.h>\n#include <ifaddrs.h>\n#include <netdb.h>\n#include <sys/stat.h>\n\n#if 0\n#define SLog NSLog\n#else\n#define SLog while(0) NSLog\n#endif\n\n#define MAX_PACKET 16384\n#define EOS ~0\n\nNSString *INJECTION_KEY = @__FILE__;\n\ntypedef union {\n    struct {\n        __uint8_t       sa_len;         /* total length */\n        sa_family_t     sa_family;      /* [XSI] address family */\n    };\n    struct sockaddr_storage any;\n    struct sockaddr_in ip4;\n    struct sockaddr addr;\n} sockaddr_union;\n\n@implementation SimpleSocket\n\n#if !SWIFT_PACKAGE\n+ (void)initialize { // Pre-built bundles (+InjectionNext.app)\n    INJECTION_KEY = [NSBundle bundleForClass:self]\n        .infoDictionary[@\"UserHome\"] ?: [NSBundle mainBundle]\n        .infoDictionary[@\"InjectionUserHome\"] ?: NSHomeDirectory();\n}\n#endif\n\n+ (int)error:(NSString *)message {\n    NSLog([@\"%@/\" stringByAppendingString:message],\n          self, strerror(errno));\n    return -1;\n}\n\n+ (void)startServer:(NSString *)address {\n    [self performSelectorInBackground:@selector(runServer:) withObject:address];\n}\n\n+ (void)forEachInterface:(void (^)(ifaddrs *ifa, in_addr_t addr, in_addr_t mask))handler {\n    ifaddrs *addrs;\n    if (getifaddrs(&addrs) < 0) {\n        [self error:@\"Could not getifaddrs: %s\"];\n        return;\n    }\n    for (ifaddrs *ifa = addrs; ifa; ifa = ifa->ifa_next)\n        if (ifa->ifa_addr->sa_family == AF_INET)\n            handler(ifa, ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr,\n                    ((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr.s_addr);\n    freeifaddrs(addrs);\n}\n\nstatic int lastServerSocket;\n\n+ (void)runServer:(NSString *)address {\n    sockaddr_union serverAddr;\n    [self parseV4Address:address into:&serverAddr.any];\n\n    int serverSocket = [self newSocket:serverAddr.sa_family];\n    if (serverSocket < 0)\n        return;\n\n    lastServerSocket = serverSocket;\n    if (bind(serverSocket, &serverAddr.addr, serverAddr.sa_len) < 0)\n        [self error:@\"Could not bind service socket: %s\"];\n    else if (listen(serverSocket, 50) < 0)\n        [self error:@\"Service socket would not listen: %s\"];\n    else\n        while (serverSocket) {\n            sockaddr_union clientAddr;\n            socklen_t addrLen = sizeof clientAddr;\n\n            int clientSocket = accept(serverSocket, &clientAddr.addr, &addrLen);\n            if (clientSocket > 0) {\n                int yes = 1;\n                if (setsockopt(clientSocket, SOL_SOCKET, SO_NOSIGPIPE, &yes, sizeof yes) < 0)\n                    [self error:@\"Could not set SO_NOSIGPIPE: %s\"];\n                @autoreleasepool {\n                    struct sockaddr_in *v4Addr = &clientAddr.ip4;\n                    printf(\"%s: Connection from %s:%d\\n\", object_getClassName(self),\n                           inet_ntoa(v4Addr->sin_addr), ntohs(v4Addr->sin_port));\n                    SimpleSocket *client = [[self alloc] initSocket:clientSocket];\n                    client.isLocalClient =\n                        v4Addr->sin_addr.s_addr == htonl(INADDR_LOOPBACK);\n                    [self forEachInterface:^(ifaddrs *ifa, in_addr_t addr, in_addr_t mask) {\n                        if (v4Addr->sin_addr.s_addr == addr)\n                            client.isLocalClient = TRUE;\n                    }];\n                    [client run];\n                }\n            }\n            else if (lastServerSocket)\n                [NSThread sleepForTimeInterval:.5];\n            else\n                break;\n        }\n\n    close(serverSocket);\n}\n\n+ (void)stopLastServer {\n    if (lastServerSocket)\n        close(lastServerSocket);\n    lastServerSocket = 0;\n    [NSThread sleepForTimeInterval:.5];\n}\n\n+ (instancetype)connectTo:(NSString *)address {\n    sockaddr_union serverAddr;\n    [self parseV4Address:address into:&serverAddr.any];\n\n    int clientSocket = [self newSocket:serverAddr.sa_family];\n    if (clientSocket < 0)\n        return nil;\n\n    if (connect(clientSocket, &serverAddr.addr, serverAddr.sa_len) < 0) {\n        [self error:@\"Could not connect: %s\"];\n        return nil;\n    }\n\n    return [[self alloc] initSocket:clientSocket];\n}\n\n+ (int)newSocket:(sa_family_t)addressFamily {\n    int newSocket, yes = 1;\n    if ((newSocket = socket(addressFamily, SOCK_STREAM, 0)) < 0)\n        [self error:@\"Could not open service socket: %s\"];\n    else if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) < 0)\n        [self error:@\"Could not set SO_REUSEADDR: %s\"];\n    else if (setsockopt(newSocket, SOL_SOCKET, SO_NOSIGPIPE, &yes, sizeof yes) < 0)\n        [self error:@\"Could not set SO_NOSIGPIPE: %s\"];\n    else if (setsockopt(newSocket, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof yes) < 0)\n        [self error:@\"Could not set TCP_NODELAY: %s\"];\n    else if (fcntl(newSocket, F_SETFD, FD_CLOEXEC) < 0)\n        [self error:@\"Could not set FD_CLOEXEC: %s\"];\n    else\n        return newSocket;\n    return -1;\n}\n\n/**\n * Available formats\n * @\"<host>[:<port>]\"\n * where <host> can be NNN.NNN.NNN.NNN or hostname, empty for localhost or * for all interfaces\n * The default port is 80 or a specific number to bind or an empty string to allocate any port\n */\n+ (BOOL)parseV4Address:(NSString *)address into:(struct sockaddr_storage *)serverAddr {\n    NSArray<NSString *> *parts = [address componentsSeparatedByString:@\":\"];\n\n    struct sockaddr_in *v4Addr = (struct sockaddr_in *)serverAddr;\n    bzero(v4Addr, sizeof *v4Addr);\n\n    v4Addr->sin_family = AF_INET;\n    v4Addr->sin_len = sizeof *v4Addr;\n    v4Addr->sin_port = htons(parts.count > 1 ? parts[1].intValue : 80);\n\n    const char *host = parts[0].UTF8String;\n\n    if (!host[0])\n        v4Addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);\n    else if (host[0] == '*')\n        v4Addr->sin_addr.s_addr = htonl(INADDR_ANY);\n    else if (isdigit(host[0]))\n        v4Addr->sin_addr.s_addr = inet_addr(host);\n    else if (struct hostent *hp = gethostbyname2(host, v4Addr->sin_family))\n        memcpy(&v4Addr->sin_addr, hp->h_addr, hp->h_length);\n    else {\n        [self error:[NSString stringWithFormat:@\"Unable to look up host for %@\", address]];\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\n- (instancetype)initSocket:(int)socket {\n    if ((self = [super init])) {\n        clientSocket = socket;\n    }\n    return self;\n}\n\n- (void)run {\n    [self performSelectorInBackground:@selector(runInBackground) withObject:nil];\n}\n\n- (void)runInBackground {\n    [[self class] error:@\"-[SimpleSocket runInBackground] not implemented in subclass\"];\n}\n\ntypedef ssize_t (*io_func)(int, void *, size_t);\n\n- (BOOL)perform:(io_func)io ofBytes:(const void *)buffer\n         length:(size_t)length cmd:(SEL)cmd {\n    size_t bytes, ptr = 0;\n    SLog(@\"#%d %s %lu [%p] %s\", clientSocket, io == read ?\n         \"<-\" : \"->\", length, buffer, sel_getName(cmd));\n    while (ptr < length && (bytes = io(clientSocket,\n        (char *)buffer+ptr, MIN(length-ptr, MAX_PACKET))) > 0)\n        ptr += bytes;\n    if (ptr < length) {\n        if (errno)\n            NSLog(@\"[%@ %s:%p length:%lu] error: %lu %s\",\n                  self, sel_getName(cmd), buffer, length, ptr, strerror(errno));\n        return FALSE;\n    }\n    return TRUE;\n}\n\n- (BOOL)readBytes:(void *)buffer length:(size_t)length cmd:(SEL)cmd {\n    return [self perform:read ofBytes:buffer length:length cmd:cmd];\n}\n\n- (int)readInt {\n    int32_t anint = EOS;\n    if (![self readBytes:&anint length:sizeof anint cmd:_cmd])\n        return EOS;\n    SLog(@\"#%d <- %d\", clientSocket, anint);\n    return anint;\n}\n\n- (void *)readPointer {\n    void *aptr = (void *)EOS;\n    if (![self readBytes:&aptr length:sizeof aptr cmd:_cmd])\n        return aptr;\n    SLog(@\"#%d <- %p\", clientSocket, aptr);\n    return aptr;\n}\n\n- (NSData *)readData {\n    size_t length = [self readInt];\n    if (length == EOS) return nil;\n    void *bytes = malloc(length);\n    if (!bytes || ![self readBytes:bytes length:length cmd:_cmd])\n        return nil;\n    return [NSData dataWithBytesNoCopy:bytes length:length freeWhenDone:YES];\n}\n\n- (NSString *)readString {\n    size_t length = [self readInt];\n    if (length == EOS) return nil;\n    void *bytes = malloc(length+1);\n    if (!bytes || ![self readBytes:bytes length:length cmd:_cmd])\n        return nil;\n    ((char *)bytes)[length] = 0;\n    NSString *str = [[NSString alloc] initWithBytesNoCopy:bytes length:length\n                             encoding:NSUTF8StringEncoding freeWhenDone:YES];\n    SLog(@\"#%d <- %d '%@'\", clientSocket, (int)str.length, str);\n    return str;\n}\n\n- (BOOL)writeBytes:(const void *)buffer length:(size_t)length cmd:(SEL)cmd {\n    return [self perform:(io_func)write ofBytes:buffer length:length cmd:cmd];\n}\n\n- (BOOL)writeInt:(int)length {\n    SLog(@\"#%d %d ->\", clientSocket, length);\n    return [self writeBytes:&length length:sizeof length cmd:_cmd];\n}\n\n- (BOOL)writeCStr:(const char *)string {\n    uint32_t len = (uint32_t)strlen(string);\n    SLog(@\"#%d %d '%s' ->\", clientSocket, (int)len, string);\n    return [self writeInt:len] && [self writeBytes:string length:len cmd:_cmd];\n}\n\n- (BOOL)writePointer:(void *)ptr {\n    SLog(@\"#%d %p ->\", clientSocket, ptr);\n    return [self writeBytes:&ptr length:sizeof ptr cmd:_cmd];\n}\n\n- (BOOL)writeData:(NSData *)data {\n    uint32_t length = (uint32_t)data.length;\n    SLog(@\"#%d [%d] ->\", clientSocket, length);\n    return [self writeInt:length] &&\n        [self writeBytes:data.bytes length:length cmd:_cmd];\n}\n\n- (BOOL)writeString:(NSString *)string {\n    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];\n    SLog(@\"#%d %d '%@' ->\", clientSocket, (int)data.length, string);\n    return [self writeData:data];\n}\n\n- (BOOL)writeCommand:(int)command withString:(NSString *)string {\n    return [self writeInt:command] &&\n        (!string || [self writeString:string]);\n}\n\n- (BOOL)failed:(SEL)sel file:(id)file {\n    NSLog(@\"-[%@ %s \\\"%@\\\"]: Could not fopen(), %s\",\n          self, sel_getName(sel), file, strerror(errno));\n    return FALSE;\n}\n\n- (BOOL)sendFile:(NSString *)path {\n    struct stat st;\n    FILE *input = fopen(path.UTF8String, \"r\");\n    if (!input || fstat(fileno(input), &st))\n        return [self writeInt:INT_MAX] &&\n            [self writeString:[NSString stringWithFormat:\n             @\"-[%@ %s \\\"%@\\\"]: Could not open to send, %s\",\n             self, sel_getName(_cmd), path, strerror(errno)]] &&\n            [self failed:_cmd file:path];\n    [self writeInt:(int)st.st_size];\n    off_t pos = 0, chunk;\n    char buffer[MAX_PACKET];\n    while ((chunk = MIN(st.st_size-pos, sizeof buffer)) > 0 &&\n           (chunk = fread(buffer, 1, chunk, input)) > 0 &&\n           [self writeBytes:buffer length:chunk cmd:_cmd])\n        pos += chunk;\n    fclose(input);\n    return pos == st.st_size;\n}\n\n- (BOOL)recvFile:(NSString *)path {\n    FILE *output = fopen(path.UTF8String, \"w\");\n    if (!output) return [self failed:_cmd file:path];\n    off_t sz = [self readInt], pos = 0, chunk;\n    if (sz == INT_MAX)\n        return [self failed:_cmd file:[self readString]];\n    char buffer[MAX_PACKET];\n    while ((chunk = MIN(sz-pos, sizeof buffer)) > 0 &&\n           [self readBytes:buffer length:chunk cmd:_cmd] &&\n           (chunk = fwrite(buffer, 1, chunk, output)) > 0)\n        pos += chunk;\n    fclose(output);\n    return pos == sz;\n}\n\n- (void)dealloc {\n    close(clientSocket);\n}\n\n/// Hash used to differentiate InjectionNext users broadcasting.\n/// Hash derived from path to user's home directory determined\n/// from path to this source file in project's DerivedData or for\n/// pre-built bundles, home directory taken from a value patched\n/// into the bundle's Info.plist as it is copied into client app.\n+ (int)multicastHash {\n    #if SWIFT_PACKAGE\n    NSString *file = @__FILE__;\n    INJECTION_KEY = [file\n       stringByReplacingOccurrencesOfString: @\"(/Users/[^/]+).*\"\n           withString: @\"$1\" options: NSRegularExpressionSearch\n               range: NSMakeRange(0, file.length)];\n    #endif\n    const char *key = INJECTION_KEY.UTF8String;\n    int hash = 0;\n    for (size_t i=0, len = strlen(key); i<len; i++)\n        hash = hash*5 ^ (i+3)%15*key[i];\n    return hash;\n}\n\nstruct multicast_socket_packet {\n    int version, hash;\n    char host[256];\n};\n\n/// Used for HotReloading clients to find their controlling Mac.\n/// @param multicast MULTICAST address to use\n/// @param port Port identifier of form \":NNNN\"\n+ (void)multicastServe:(const char *)multicast port:(const char *)port {\n    #ifdef DEVELOPER_HOST\n    if (isdigit(DEVELOPER_HOST[0]))\n        return;\n    #endif\n\n    struct sockaddr_in addr;\n    memset(&addr, 0, sizeof addr);\n    addr.sin_family = AF_INET;\n    addr.sin_addr.s_addr = htonl(INADDR_ANY); /* N.B.: differs from sender */\n    if (const char *colon = index(port, ':'))\n        port = colon+1;\n    addr.sin_port = htons(atoi(port));\n\n    /* create what looks like an ordinary UDP socket */\n    int multicastSocket, yes = 1;\n    if ((multicastSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)\n        [self error:@\"Could not get mutlicast socket: %s\"];\n    else if (fcntl(multicastSocket, F_SETFD, FD_CLOEXEC) < 0)\n        [self error:@\"Could not set close exec: %s\"];\n    else if (setsockopt(multicastSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) < 0)\n        [self error:@\"Could not reuse mutlicast socket addr: %s\"];\n    else if (bind(multicastSocket, (struct sockaddr *)&addr, sizeof addr) < 0)\n        [self error:@\"Could not bind mutlicast socket addr: %s. \"\n         \"Once this starts occuring, a reboot may be necessary. \"\n         \"Or, you can hardcode the IP address of your Mac as the \"\n         \"the value for 'hostname' in HotReloading/Package.swift.\"];\n    else\n        [self performSelectorInBackground:@selector(multicastListen:)\n                               withObject:[NSNumber numberWithInt:multicastSocket]];\n}\n\n/// Listens for clients looking to connect and if the hash matches, replies.\n/// @param socket Multicast socket as NSNumber\n+ (void)multicastListen:(NSNumber *)socket {\n    int multicastSocket = [socket intValue];\n    while (multicastSocket) {\n        struct sockaddr_in addr;\n        socklen_t addrlen = sizeof addr;\n        struct multicast_socket_packet msgbuf;\n\n        if (recvfrom(multicastSocket, &msgbuf, sizeof msgbuf, 0,\n                     (struct sockaddr *)&addr, &addrlen) < sizeof msgbuf) {\n            [self error:@\"Could not receive from multicast: %s\"];\n            sleep(1);\n            continue;\n        }\n\n        NSLog(@\"%@: Multicast recvfrom %s (%s) %u c.f. %u\\n\",\n              self, msgbuf.host, inet_ntoa(addr.sin_addr),\n              [self multicastHash], msgbuf.hash);\n\n        gethostname(msgbuf.host, sizeof msgbuf.host);\n        if ([self multicastHash] == msgbuf.hash &&\n            sendto(multicastSocket, &msgbuf, sizeof msgbuf, 0,\n                   (struct sockaddr *)&addr, addrlen) < sizeof msgbuf) {\n            [self error:@\"Could not send to multicast: %s\"];\n            sleep(1);\n        }\n    }\n}\n\n/// Client end of multicast means of determining address of server\n/// @param multicast Multicast IP address to use.\n/// @param port Port number as string.\n/// @param format Format for connecting message.\n+ (NSString *)getMulticastService:(const char *)multicast\n    port:(const char *)port message:(const char *)format {\n    #ifdef DEVELOPER_HOST\n    if (isdigit(DEVELOPER_HOST[0]))\n        return @DEVELOPER_HOST;\n    #else\n    #define DEVELOPER_HOST \"127.0.0.1\"\n    #endif\n\n    static struct sockaddr_in addr;\n    addr.sin_family = AF_INET;\n    addr.sin_addr.s_addr = htonl(INADDR_ANY);\n    if (const char *colon = index(port, ':'))\n        port = colon+1;\n    addr.sin_port = 0;\n\n    // For a real device, we have to use multicast\n    // to locate the developer's Mac to connect to.\n    int multicastSocket, yes = 1;\n    if ((multicastSocket = socket(addr.sin_family, SOCK_DGRAM, 0)) < 0) {\n        [self error:@\"Could not get broadcast socket: %s\"];\n        return @DEVELOPER_HOST;\n    }\n    if (setsockopt(multicastSocket, SOL_SOCKET, SO_BROADCAST, &yes, sizeof yes) < 0) {\n        [self error:@\"Could not setsockopt: %s\"];\n        close(multicastSocket);\n        return @DEVELOPER_HOST;\n    }\n\n    struct multicast_socket_packet msgbuf;\n    msgbuf.version = 1;\n    msgbuf.hash = [self multicastHash];\n    gethostname(msgbuf.host, sizeof msgbuf.host);\n\n    addr.sin_port = htons(atoi(port));\n    [self forEachInterface:^(ifaddrs *ifa, in_addr_t laddr, in_addr_t nmask) {\n        switch (ntohl(laddr) >> 24) {\n            case 10: // mobile network\n//            case 172: // hotspot\n            case 127: // loopback\n                return;\n        }\n        int idx = if_nametoindex(ifa->ifa_name);\n        setsockopt(multicastSocket, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof idx);\n        addr.sin_addr.s_addr = laddr | ~nmask;\n        printf(\"Broadcasting to %s#%d:%s to locate Injection host...\\n\",\n               ifa->ifa_name, idx, inet_ntoa(addr.sin_addr));\n        if (sendto(multicastSocket, &msgbuf, sizeof msgbuf, 0,\n                   (struct sockaddr *)&addr, sizeof addr) < 0)\n            [self error:@\"Could not send broadcast ping: %s\"];\n        if (sendto(multicastSocket, &msgbuf, sizeof msgbuf, 0,\n                   (struct sockaddr *)&addr, sizeof addr) < 0)\n            [self error:@\"Could not send broadcast ping: %s\"];\n    }];\n\n    socklen_t addrlen = sizeof addr;\n    while (recvfrom(multicastSocket, &msgbuf, sizeof msgbuf, 0,\n                    (struct sockaddr *)&addr, &addrlen) < sizeof msgbuf) {\n        [self error:@\"%s: Error receiving from broadcast: %s\"];\n        sleep(1);\n    }\n\n    const char *ipaddr = inet_ntoa(addr.sin_addr);\n    printf(format, msgbuf.host, ipaddr);\n    close(multicastSocket);\n    return [NSString stringWithUTF8String:ipaddr];\n}\n\n@end\n\n@implementation SimpleService\n\nstatic NSMutableDictionary<NSString *,SimpleCallback> *callbacks;\n\n+ (void)startServer:(NSString *_Nonnull)address callback:(SimpleCallback)callback {\n    if (!callbacks)\n        callbacks = [NSMutableDictionary new];\n    callbacks[address] = callback;\n    [super startServer:address];\n}\n\n- (void)runInBackground {\n    sockaddr_union addr;\n    socklen_t len = sizeof addr;\n    if (getsockname(clientSocket, &addr.addr, &len) < 0)\n        [[self class] error:@\"getsockname failed %s\"];\n\n    NSString *address = [NSString stringWithFormat:@\"*:%d\", ntohs(addr.ip4.sin_port)];\n    if (SimpleCallback callback = callbacks[address])\n        callback(clientSocket);\n    else\n        [[self class] error:@\"Missing callback\"];\n}\n@end\n\n@implementation SimpleHTTP\n+ (void)startServer:(NSString *_Nonnull)address callback:(NSData *_Nullable (^_Nonnull)(char *_Nonnull header))callback {\n    [super startServer:address callback:^(int socket) {\n        FILE *stream = fdopen(socket, \"r+\");\n        size_t bsize = 1000, length;\n        char *header = (char *)malloc(bsize), *hptr = header;\n\n        while ((length = strlen(fgets(hptr, (int)(bsize - (hptr-header)),\n                    stream)?:\"\")) > 2 || (length && strcmp(hptr-2, \"\\r\\n\\r\\n\")))\n            if ((hptr += length)-header == bsize-1) {\n                char *newbuff = (char *)realloc(header, bsize *= 2);\n                hptr = newbuff + (hptr - header);\n                header = newbuff;\n            }\n\n        NSData *body = callback(header) ?: [NSData new];\n\n        fprintf(stream, \"HTTP/1.0 200 OK\\r\\nContent-Type: text/plain\\r\\n\"\n                \"Content-Length: %ld\\r\\n\\r\\n\", body.length);\n        fwrite(body.bytes, body.length, 1, stream);\n        fclose(stream);\n        free(header);\n    }];\n}\n@end\n#endif\n"
  },
  {
    "path": "Sources/InjectionNextC/include/InjectionClient.h",
    "content": "//\n//  InjectionClient.h\n//  InjectionBundle\n//\n//  Created by John Holdsworth on 06/11/2017.\n//  Copyright © 2017 John Holdsworth. All rights reserved.\n//\n//  $Id: //depot/InjectionNext/Sources/InjectionNextC/include/InjectionClient.h#60 $\n//\n//  Shared definitions between server and client.\n//\n\n#import <Foundation/Foundation.h>\n\n#define HOTRELOADING_PORT \":8887\"\n#define HOTRELOADING_MULTICAST \"239.255.255.239\"\n\n#define INJECTION_VERSION 4001\n#define COMMANDS_PORT \":8896\"\n#define INJECTION_ADDRESS HOTRELOADING_PORT\nextern NSString *INJECTION_KEY;\n#undef APP_NAME\n#define APP_NAME \"InjectionNext\"\n#define APP_PREFIX \"🔥 \"\n#define DYLIB_PREFIX \"/eval_injection_\" // Expected by DLKit.appImages\n\n#define INJECTION_APP_VERSION \"INJECTION_APP_VERSION\"\n#define INJECTION_DLOPEN_MODE \"INJECTION_DLOPEN_MODE\"\n#define UNSETENV_VALUE \"__NULL__\"\n\n@interface NSObject(HotReloading)\n+ (void)runXCTestCase:(Class)aTestCase;\n@end\n\n@interface NSProcessInfo(iOSAppOnMac)\n@property BOOL isiOSAppOnMac;\n@end\n\ntypedef NS_ENUM(int, InjectionCommand) {\n    // commands to InjectionNext package\n    InjectionLog,\n    InjectionLoad,\n    InjectionInject,\n    InjectionXcodePath,\n    InjectionSendFile,\n    InjectionMetrics,\n    InjectionSetenv,\n    InjectionEndenv,\n\n    InjectionInvalid = 1000,\n\n    InjectionEOF = ~0\n};\n\ntypedef NS_ENUM(int, InjectionResponse) {\n    // responses from InjectionNext package\n    InjectionPlatform,\n    InjectionInjected,\n    InjectionFailed,\n    InjectionTmpPath,\n    InjectionUnhide,\n    InjectionProjectRoot,\n    InjectionDetail,\n    InjectionBazelTarget,\n    InjectionExecutable,\n\n    InjectionExit = ~0\n};\n"
  },
  {
    "path": "Sources/InjectionNextC/include/SimpleSocket.h",
    "content": "//\n//  SimpleSocket.h\n//  InjectionIII\n//\n//  Created by John Holdsworth on 06/11/2017.\n//  Copyright © 2017 John Holdsworth. All rights reserved.\n//\n//  $Id: //depot/HotReloading/Sources/HotReloadingGuts/include/SimpleSocket.h#16 $\n//\n\n#import <Foundation/Foundation.h>\n#import <arpa/inet.h>\n\n@interface SimpleSocket : NSObject {\n@protected\n    int clientSocket;\n}\n\n@property BOOL isLocalClient;\n\n+ (void)startServer:(NSString *_Nonnull)address;\n+ (void)runServer:(NSString *_Nonnull)address;\n+ (int)error:(NSString *_Nonnull)message;\n+ (void)stopLastServer;\n\n+ (instancetype _Nullable)connectTo:(NSString *_Nonnull)address;\n+ (BOOL)parseV4Address:(NSString *_Nonnull)address into:(struct sockaddr_storage *_Nonnull)serverAddr;\n\n+ (void)multicastServe:(const char *_Nonnull)multicast port:(const char *_Nonnull)port;\n+ (NSString *_Nonnull)getMulticastService:(const char *_Nonnull)multicast\n                                     port:(const char *_Nonnull)port\n                                  message:(const char *_Nonnull)format;\n\n- (instancetype _Nonnull)initSocket:(int)socket;\n\n- (void)run;\n- (void)runInBackground;\n\n- (int)readInt;\n- (void * _Nullable)readPointer;\n- (NSData *_Nullable)readData;\n- (NSString *_Nullable)readString;\n- (BOOL)readBytes:(void * _Nonnull)buffer length:(size_t)length cmd:(SEL _Nonnull)cmd;\n\n- (BOOL)writeInt:(int)length;\n- (BOOL)writeCStr:(const char *_Nonnull)string;\n- (BOOL)writePointer:(void * _Nullable)pointer;\n- (BOOL)writeData:(NSData *_Nonnull)data;\n- (BOOL)writeString:(NSString *_Nonnull)string;\n- (BOOL)writeCommand:(int)command withString:(NSString *_Nullable)string;\n- (BOOL)sendFile:(NSString *_Nonnull)path;\n- (BOOL)recvFile:(NSString *_Nonnull)path;\n\n@end\n\n@interface SimpleService: SimpleSocket\ntypedef void (^_Nonnull SimpleCallback)(int socket);\n+ (void)startServer:(NSString *_Nonnull)address callback:(SimpleCallback)callback;\n@end\n\n@interface SimpleHTTP: SimpleService\n+ (void)startServer:(NSString *_Nonnull)address callback:(NSData *_Nullable (^_Nonnull)(char *_Nonnull header))callback;\n@end\n"
  },
  {
    "path": "Tests/InjectionNextTests/InjectionNextTests.swift",
    "content": "import XCTest\n@testable import InjectionBundle\n\nfinal class InjectionNextTests: XCTestCase {\n    func testExample() throws {\n        // XCTest Documentation\n        // https://developer.apple.com/documentation/xctest\n\n        // Defining Test Cases and Test Methods\n        // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods\n    }\n}\n"
  },
  {
    "path": "mcp-server/.gitignore",
    "content": "node_modules/\n"
  },
  {
    "path": "mcp-server/README.md",
    "content": "# InjectionNext MCP Server\n\nMCP (Model Context Protocol) server that lets AI agents control InjectionNext — start file watching, check status, read debug logs, toggle device injection, and more.\n\n## Prerequisites\n\n- **macOS** with Xcode installed\n- **Node.js** 18.14.1+\n- **InjectionNext.app** built from this repo (with ControlServer support)\n\n## Step 1: Build InjectionNext with ControlServer\n\n```bash\n# Clone and init submodules\ngit clone <repo-url>\ncd InjectionNext\ngit submodule update --init --recursive\n\n# Build the app (ad-hoc signing for local dev)\ncd App\nxcodebuild -project InjectionNext.xcodeproj \\\n  -scheme InjectionNext \\\n  -configuration Debug build \\\n  CODE_SIGN_IDENTITY=\"-\" \\\n  CODE_SIGNING_REQUIRED=NO \\\n  CODE_SIGNING_ALLOWED=NO\n\n# The built app is at:\n# ~/Library/Developer/Xcode/DerivedData/InjectionNext-*/Build/Products/Debug/InjectionNext.app\n```\n\nOptionally copy it to `/Applications`:\n\n```bash\ncp -R ~/Library/Developer/Xcode/DerivedData/InjectionNext-*/Build/Products/Debug/InjectionNext.app /Applications/\n```\n\n## Step 2: Enable the ControlServer\n\nThe TCP control server is **opt-in**. Enable it via a UserDefault before launching the app:\n\n```bash\ndefaults write com.johnholdsworth.InjectionNext mcpServer -bool true\n```\n\nTo disable it later:\n\n```bash\ndefaults delete com.johnholdsworth.InjectionNext mcpServer\n```\n\n## Step 3: Install the MCP server\n\n```bash\ncd mcp-server\nnpm install\n```\n\n## Step 4: Configure Cursor\n\nAdd to your Cursor MCP config at `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (per-project):\n\n```json\n{\n  \"mcpServers\": {\n    \"injection-next\": {\n      \"command\": \"node\",\n      \"args\": [\"/absolute/path/to/InjectionNext/mcp-server/index.js\"]\n    }\n  }\n}\n```\n\nReplace `/absolute/path/to` with the actual path to this repo.\n\n## Step 5: Launch InjectionNext\n\nStart the app before using the MCP tools:\n\n```bash\nopen /Applications/InjectionNext.app\n# or from DerivedData:\nopen ~/Library/Developer/Xcode/DerivedData/InjectionNext-*/Build/Products/Debug/InjectionNext.app\n```\n\nYou should see the InjectionNext icon in the menu bar.\n\n## Step 6: Test it\n\n### Quick test from terminal (no MCP needed)\n\n```bash\n# Check status\necho '{\"action\":\"status\"}' | nc -w 3 localhost 8919\n\n# Start watching a project\necho '{\"action\":\"watch_project\",\"path\":\"/path/to/your/project\"}' | nc -w 3 localhost 8919\n\n# Read debug logs\necho '{\"action\":\"get_logs\"}' | nc -w 3 localhost 8919\n\n# Stop watching\necho '{\"action\":\"stop_watching\"}' | nc -w 3 localhost 8919\n```\n\n### Test from Cursor\n\nAfter configuring the MCP server, open Cursor and ask the AI:\n\n> \"Use the injection-next MCP to check the status of InjectionNext\"\n\nor:\n\n> \"Watch my project at /path/to/project for hot reloading\"\n\nor:\n\n> \"Show me the InjectionNext debug logs\"\n\n## Available Tools\n\n| Tool | Description |\n|------|-------------|\n| `get_status` | Full app status: Xcode, watched dirs, compiler, clients |\n| `watch_project` | Start file-watching a directory for hot-reloading |\n| `stop_watching` | Stop all file watchers |\n| `launch_xcode` | Launch Xcode via InjectionNext with SourceKit logging |\n| `get_compiler_state` | Check if Swift compiler is intercepted |\n| `enable_devices` | Toggle device/simulator injection support |\n| `unhide_symbols` | Fix default-argument symbol visibility issues |\n| `get_last_error` | Get last compilation error |\n| `prepare_swiftui_source` | Add injection annotations to current SwiftUI file |\n| `prepare_swiftui_project` | Prepare all SwiftUI files in target |\n| `set_xcode_path` | Point to a different Xcode.app |\n| `get_logs` | Read debug console (supports `since` for polling) |\n| `clear_logs` | Clear the log buffer |\n\n## Architecture\n\n```\n┌─────────────┐       TCP :8919         ┌──────────────────────┐\n│  MCP Server │◄───────────────────────►│  InjectionNext.app   │\n│  (Node.js)  │   JSON commands/resp    │  ┌─────────────────┐ │\n│             │                         │  │  ControlServer  │ │\n│  stdio ↕    │                         │  │  (TCP listener) │ │\n│             │                         │  └────────┬────────┘ │\n│  Cursor /   │                         │           │          │\n│  AI Agent   │                         │  ┌────────▼────────┐ │\n└─────────────┘                         │  │  AppDelegate    │ │\n                                        │  │  IBActions      │ │\n                                        │  └────────┬────────┘ │\n                                        │           │          │\n                                        │  ┌────────▼────────┐ │\n                                        │   │  LogBuffer     │ │\n                                        │  │  (ring buffer)  │ │\n                                        │  └─────────────────┘ │\n                                        └──────────────────────┘\n```\n\n## Troubleshooting\n\n**\"Cannot connect to InjectionNext on port 8919\"**\n- Make sure InjectionNext.app is running (check menu bar icon)\n- Make sure you built the version with ControlServer support (from this repo)\n- Check: `lsof -i :8919` should show InjectionNext listening\n\n**Port already in use**\n- Kill any stale InjectionNext processes: `pkill -f InjectionNext`\n- Re-launch the app\n\n**Logs are empty**\n- Logs only capture events that happen while the app is running\n- Try `watch_project` to generate some activity, then `get_logs`\n"
  },
  {
    "path": "mcp-server/index.js",
    "content": "#!/usr/bin/env node\n\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport net from \"node:net\";\n\nconst CONTROL_PORT = 8919;\nconst CONTROL_HOST = \"127.0.0.1\";\n\nfunction sendCommand(action, params = {}) {\n  return new Promise((resolve, reject) => {\n    const client = new net.Socket();\n    const timeout = setTimeout(() => {\n      client.destroy();\n      reject(new Error(\"Connection timed out. Is InjectionNext running with ControlServer?\"));\n    }, 5000);\n\n    client.connect(CONTROL_PORT, CONTROL_HOST, () => {\n      const payload = JSON.stringify({ action, ...params }) + \"\\n\";\n      client.write(payload);\n    });\n\n    let data = \"\";\n    client.on(\"data\", (chunk) => {\n      data += chunk.toString();\n      if (data.includes(\"\\n\")) {\n        clearTimeout(timeout);\n        client.destroy();\n        try {\n          resolve(JSON.parse(data.trim()));\n        } catch {\n          reject(new Error(\"Invalid JSON response from InjectionNext\"));\n        }\n      }\n    });\n\n    client.on(\"error\", (err) => {\n      clearTimeout(timeout);\n      if (err.code === \"ECONNREFUSED\") {\n        reject(new Error(\n          \"Cannot connect to InjectionNext on port 8919. \" +\n          \"Make sure InjectionNext.app is running (build with ControlServer support).\"\n        ));\n      } else {\n        reject(err);\n      }\n    });\n  });\n}\n\nfunction formatResponse(result) {\n  if (!result.success) {\n    return { content: [{ type: \"text\", text: `Error: ${result.error}` }], isError: true };\n  }\n  const text = result.data\n    ? JSON.stringify(result.data, null, 2)\n    : \"OK\";\n  return { content: [{ type: \"text\", text }] };\n}\n\nconst server = new McpServer({\n  name: \"injection-next\",\n  version: \"1.0.0\",\n});\n\nserver.tool(\n  \"get_status\",\n  \"Get the current status of InjectionNext: Xcode state, watched directories, compiler interception, connected clients, and last error\",\n  {},\n  async () => {\n    const result = await sendCommand(\"status\");\n    return formatResponse(result);\n  }\n);\n\nserver.tool(\n  \"watch_project\",\n  \"Start file-watching a project directory for hot-reloading. This enables injection for Cursor/VS Code workflows without launching Xcode through the app.\",\n  { path: z.string().describe(\"Absolute path to the project directory to watch\") },\n  async ({ path }) => {\n    const result = await sendCommand(\"watch_project\", { path });\n    return formatResponse(result);\n  }\n);\n\nserver.tool(\n  \"stop_watching\",\n  \"Stop watching all project directories\",\n  {},\n  async () => {\n    const result = await sendCommand(\"stop_watching\");\n    return formatResponse(result);\n  }\n);\n\nserver.tool(\n  \"launch_xcode\",\n  \"Launch Xcode through InjectionNext with SOURCEKIT_LOGGING enabled for full injection support\",\n  {},\n  async () => {\n    const result = await sendCommand(\"launch_xcode\");\n    return formatResponse(result);\n  }\n);\n\nserver.tool(\n  \"get_compiler_state\",\n  \"Check whether the Swift compiler is currently intercepted (patched) by InjectionNext\",\n  {},\n  async () => {\n    const result = await sendCommand(\"intercept_compiler\");\n    return formatResponse(result);\n  }\n);\n\nserver.tool(\n  \"enable_devices\",\n  \"Enable or disable device injection support (opens TCP port for device/simulator connections)\",\n  { enable: z.boolean().describe(\"true to enable, false to disable\") },\n  async ({ enable }) => {\n    const result = await sendCommand(\"enable_devices\", { enable });\n    return formatResponse(result);\n  }\n);\n\nserver.tool(\n  \"unhide_symbols\",\n  \"Unhide default-argument symbols in the current build to fix injection loading failures\",\n  {},\n  async () => {\n    const result = await sendCommand(\"unhide_symbols\");\n    return formatResponse(result);\n  }\n);\n\nserver.tool(\n  \"get_last_error\",\n  \"Get the last compilation error from InjectionNext\",\n  {},\n  async () => {\n    const result = await sendCommand(\"get_last_error\");\n    return formatResponse(result);\n  }\n);\n\nserver.tool(\n  \"prepare_swiftui_source\",\n  \"Automatically add .enableInjection() and @ObserveInjection to the currently edited SwiftUI source file\",\n  {},\n  async () => {\n    const result = await sendCommand(\"prepare_swiftui_source\");\n    return formatResponse(result);\n  }\n);\n\nserver.tool(\n  \"prepare_swiftui_project\",\n  \"Prepare all SwiftUI source files in the current target for hot-reloading injection\",\n  {},\n  async () => {\n    const result = await sendCommand(\"prepare_swiftui_project\");\n    return formatResponse(result);\n  }\n);\n\nserver.tool(\n  \"set_xcode_path\",\n  \"Set the path to the Xcode installation to use\",\n  { path: z.string().describe(\"Absolute path to Xcode.app (e.g. /Applications/Xcode.app)\") },\n  async ({ path }) => {\n    const result = await sendCommand(\"set_xcode_path\", { path });\n    return formatResponse(result);\n  }\n);\n\nserver.tool(\n  \"get_logs\",\n  \"Read the InjectionNext debug console — returns recent log entries including injection events, compilation output, errors, file watcher activity, and client connections. Use 'since' (unix timestamp) to get only new logs since your last read.\",\n  {\n    since: z.number().optional().describe(\"Unix timestamp — only return logs after this time. Omit to get all recent logs.\"),\n    limit: z.number().optional().describe(\"Max entries to return (default 200, max 500)\"),\n  },\n  async ({ since, limit }) => {\n    const params = {};\n    if (since !== undefined) params.since = since;\n    if (limit !== undefined) params.limit = limit;\n    const result = await sendCommand(\"get_logs\", params);\n    if (!result.success) {\n      return { content: [{ type: \"text\", text: `Error: ${result.error}` }], isError: true };\n    }\n    const logs = result.data?.logs ?? [];\n    if (logs.length === 0) {\n      return { content: [{ type: \"text\", text: \"No new log entries.\" }] };\n    }\n    const lines = logs.map((e) => {\n      const ts = new Date(e.timestamp * 1000).toISOString().slice(11, 23);\n      const tag = e.level !== \"info\" ? ` [${e.level.toUpperCase()}]` : \"\";\n      return `${ts}${tag} ${e.message}`;\n    });\n    const header = `--- ${logs.length} log entries (${result.data.count} total buffered) ---`;\n    return { content: [{ type: \"text\", text: header + \"\\n\" + lines.join(\"\\n\") }] };\n  }\n);\n\nserver.tool(\n  \"clear_logs\",\n  \"Clear the InjectionNext log buffer\",\n  {},\n  async () => {\n    const result = await sendCommand(\"clear_logs\");\n    return formatResponse(result);\n  }\n);\n\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n"
  },
  {
    "path": "mcp-server/package.json",
    "content": "{\n  \"name\": \"injection-next-mcp\",\n  \"version\": \"1.0.0\",\n  \"description\": \"MCP server for controlling InjectionNext hot-reloading app\",\n  \"type\": \"module\",\n  \"main\": \"index.js\",\n  \"engines\": {\n    \"node\": \">=18.14.1\"\n  },\n  \"bin\": {\n    \"injection-next-mcp\": \"./index.js\"\n  },\n  \"scripts\": {\n    \"start\": \"node index.js\"\n  },\n  \"dependencies\": {\n    \"@modelcontextprotocol/sdk\": \"^1.12.1\",\n    \"zod\": \"^3.23.8\"\n  }\n}\n"
  }
]