Merge pull request #14 from Averylamp/master

Xcode Playground Extension added
diff --git a/CLA-CORPORATE.md b/wsktools/CLA-CORPORATE.md
similarity index 100%
rename from CLA-CORPORATE.md
rename to wsktools/CLA-CORPORATE.md
diff --git a/CLA-INDIVIDUAL.md b/wsktools/CLA-INDIVIDUAL.md
similarity index 100%
rename from CLA-INDIVIDUAL.md
rename to wsktools/CLA-INDIVIDUAL.md
diff --git a/CONTRIBUTING.md b/wsktools/CONTRIBUTING.md
similarity index 100%
rename from CONTRIBUTING.md
rename to wsktools/CONTRIBUTING.md
diff --git a/LICENSE.txt b/wsktools/LICENSE.txt
similarity index 100%
rename from LICENSE.txt
rename to wsktools/LICENSE.txt
diff --git a/README.md b/wsktools/README.md
similarity index 100%
rename from README.md
rename to wsktools/README.md
diff --git a/WhiskSwiftTools-Bridging-Header.h b/wsktools/WhiskSwiftTools-Bridging-Header.h
similarity index 100%
rename from WhiskSwiftTools-Bridging-Header.h
rename to wsktools/WhiskSwiftTools-Bridging-Header.h
diff --git a/WhiskSwiftTools.xcodeproj/project.pbxproj b/wsktools/WhiskSwiftTools.xcodeproj/project.pbxproj
similarity index 100%
rename from WhiskSwiftTools.xcodeproj/project.pbxproj
rename to wsktools/WhiskSwiftTools.xcodeproj/project.pbxproj
diff --git a/WhiskSwiftTools.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/wsktools/WhiskSwiftTools.xcodeproj/project.xcworkspace/contents.xcworkspacedata
similarity index 100%
rename from WhiskSwiftTools.xcodeproj/project.xcworkspace/contents.xcworkspacedata
rename to wsktools/WhiskSwiftTools.xcodeproj/project.xcworkspace/contents.xcworkspacedata
diff --git a/WhiskSwiftTools.xcodeproj/project.xcworkspace/xcshareddata/WhiskSwiftTools.xcscmblueprint b/wsktools/WhiskSwiftTools.xcodeproj/project.xcworkspace/xcshareddata/WhiskSwiftTools.xcscmblueprint
similarity index 100%
rename from WhiskSwiftTools.xcodeproj/project.xcworkspace/xcshareddata/WhiskSwiftTools.xcscmblueprint
rename to wsktools/WhiskSwiftTools.xcodeproj/project.xcworkspace/xcshareddata/WhiskSwiftTools.xcscmblueprint
diff --git a/WhiskSwiftTools/ConsoleIO.swift b/wsktools/WhiskSwiftTools/ConsoleIO.swift
similarity index 100%
rename from WhiskSwiftTools/ConsoleIO.swift
rename to wsktools/WhiskSwiftTools/ConsoleIO.swift
diff --git a/WhiskSwiftTools/Git.swift b/wsktools/WhiskSwiftTools/Git.swift
similarity index 100%
rename from WhiskSwiftTools/Git.swift
rename to wsktools/WhiskSwiftTools/Git.swift
diff --git a/WhiskSwiftTools/ManifestReader.swift b/wsktools/WhiskSwiftTools/ManifestReader.swift
similarity index 100%
rename from WhiskSwiftTools/ManifestReader.swift
rename to wsktools/WhiskSwiftTools/ManifestReader.swift
diff --git a/WhiskSwiftTools/PBXProject.swift b/wsktools/WhiskSwiftTools/PBXProject.swift
similarity index 100%
rename from WhiskSwiftTools/PBXProject.swift
rename to wsktools/WhiskSwiftTools/PBXProject.swift
diff --git a/WhiskSwiftTools/ProjectManager.swift b/wsktools/WhiskSwiftTools/ProjectManager.swift
similarity index 100%
rename from WhiskSwiftTools/ProjectManager.swift
rename to wsktools/WhiskSwiftTools/ProjectManager.swift
diff --git a/WhiskSwiftTools/ProjectReader.swift b/wsktools/WhiskSwiftTools/ProjectReader.swift
similarity index 100%
rename from WhiskSwiftTools/ProjectReader.swift
rename to wsktools/WhiskSwiftTools/ProjectReader.swift
diff --git a/WhiskSwiftTools/SequenceCode.swift b/wsktools/WhiskSwiftTools/SequenceCode.swift
similarity index 100%
rename from WhiskSwiftTools/SequenceCode.swift
rename to wsktools/WhiskSwiftTools/SequenceCode.swift
diff --git a/WhiskSwiftTools/WhiskAPI.swift b/wsktools/WhiskSwiftTools/WhiskAPI.swift
similarity index 100%
rename from WhiskSwiftTools/WhiskAPI.swift
rename to wsktools/WhiskSwiftTools/WhiskAPI.swift
diff --git a/WhiskSwiftTools/WhiskInstaller.swift b/wsktools/WhiskSwiftTools/WhiskInstaller.swift
similarity index 100%
rename from WhiskSwiftTools/WhiskInstaller.swift
rename to wsktools/WhiskSwiftTools/WhiskInstaller.swift
diff --git a/WhiskSwiftTools/WhiskKit.swift b/wsktools/WhiskSwiftTools/WhiskKit.swift
similarity index 100%
rename from WhiskSwiftTools/WhiskKit.swift
rename to wsktools/WhiskSwiftTools/WhiskKit.swift
diff --git a/WhiskSwiftTools/WhiskTokenizer.swift b/wsktools/WhiskSwiftTools/WhiskTokenizer.swift
similarity index 100%
rename from WhiskSwiftTools/WhiskTokenizer.swift
rename to wsktools/WhiskSwiftTools/WhiskTokenizer.swift
diff --git a/WhiskSwiftTools/main.swift b/wsktools/WhiskSwiftTools/main.swift
similarity index 100%
rename from WhiskSwiftTools/main.swift
rename to wsktools/WhiskSwiftTools/main.swift
diff --git a/xcode-playgrounds-extension/OWPlaygrounds/EditFunctionCommand.swift b/xcode-playgrounds-extension/OWPlaygrounds/EditFunctionCommand.swift
new file mode 100644
index 0000000..3982056
--- /dev/null
+++ b/xcode-playgrounds-extension/OWPlaygrounds/EditFunctionCommand.swift
@@ -0,0 +1,319 @@
+    //
+    //  EditFunctionCommand.swift
+    //  ExtensionTest
+    //
+    //  Created by whisk on 1/13/17.
+    //  Copyright © 2017 whisk. All rights reserved.
+    //
+    
+    import Foundation
+    import XcodeKit
+    import AppKit
+    
+    class EditFunctionCommand: NSObject, XCSourceEditorCommand {
+        
+        func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void) {
+            let selections = invocation.buffer.selections
+            
+            for item in selections {
+                if let rangeElement = item as? XCSourceTextRange{
+                    let lineStart = rangeElement.start.line
+                    let lineEnd = rangeElement.end.line
+                    var curlyCount = 0
+                    var curlyCountActive = false
+                    
+                    var startFunc = -1
+                    var endFunc = -1
+                    
+                    // Checking for function header
+                    for lineNum in lineStart...lineEnd{
+                        let line = invocation.buffer.lines[lineNum] as! String
+                        if line.contains("func"){
+                            curlyCountActive = true
+                            startFunc = lineNum
+                            break
+                        }
+                    }
+                    
+                    if startFunc == -1{
+                        displayAlert(message: "No function signature detected.  Please select a function header.")
+                        completionHandler(nil)
+                        return
+                    }
+                    
+                    //Looking for end of function
+                    var lineNum = startFunc
+                    while lineNum < invocation.buffer.lines.count {
+                        let line = invocation.buffer.lines[lineNum] as! String
+                        if line.contains("{"){
+                            curlyCount += 1
+                        }
+                        if line.contains("}"){
+                            curlyCount -= 1
+                        }
+                        if curlyCount == 0 {
+                            endFunc = lineNum
+                            break
+                        }
+                        lineNum += 1
+                    }
+                    
+                    if endFunc == -1{
+                        displayAlert(message: "Error finding function")
+                        completionHandler(nil)
+                        return
+                    }
+                    var fullFunc = ""
+                    
+                    let paramValues = checkUpdateParameters(startLine: startFunc, endLine: endFunc, lines: invocation.buffer.lines)
+                    if paramValues.count > 0{
+                        // get the param values
+                        do{
+                            print("Params - \(paramValues["params"])")
+                            let jsonParamData =  try JSONSerialization.data(withJSONObject: paramValues["params"]!, options: .prettyPrinted)
+                            let jsonParamString = NSString(data: jsonParamData, encoding: String.Encoding.ascii.rawValue) as! String
+                            fullFunc += jsonParamString
+                            
+                            let jsonOutputData =  try JSONSerialization.data(withJSONObject: paramValues["expectedOut"], options: .prettyPrinted)
+                            let jsonOutputString = NSString(data: jsonOutputData, encoding: String.Encoding.ascii.rawValue) as! String
+                            fullFunc += jsonOutputString
+                            
+                            //Check if OWPlayground is open already
+                            let owPlaygroundFound = self.checkForOWPlayground()
+                            //Open OWPlayground Background version if it is not open
+                            if owPlaygroundFound == false{
+                                self.openOWPlayground()
+                            }
+                            
+                            // Get path to files to monitor
+                            //Comes from Info.plist
+                            let dictionary = Bundle.main.infoDictionary
+                            let playgroundPath = dictionary!["PLAYGROUND_PATH"] as! String
+                            print("Playground Path - \(playgroundPath)")
+                            print("Expected Output - \(jsonOutputString)")
+                            
+                            //open URL for OWPlayground
+                            let urlString : String = "http://localhost:6018/?name=\(playgroundPath)&paramaters=\(jsonParamString)&results=\(jsonOutputString)".replacingOccurrences(of: " ", with: "").replacingOccurrences(of: "\\", with: "").replacingOccurrences(of: "\n", with: "")
+                            let urlStringEncoded = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
+                            let url = URL(string: urlStringEncoded!)
+                            
+                            
+                            //Delays the opening of the url if the owPlayground isnt found
+                            
+                            let invokeGroup = DispatchGroup()
+                            invokeGroup.enter()
+                            //Fancy queues and functions to make the url open after the app is opened/server is running
+                            let queue = DispatchQueue(label: "OpenURLQueue", qos: DispatchQoS.userInitiated, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
+                            queue.async{
+                                while true {
+                                    var found = false
+                                    DispatchQueue.main.sync {
+                                        let OWFound = self.checkForOWPlayground()
+                                        if OWFound {
+                                            found = true
+                                            let timeAfterOpen = 1.0
+                                            DispatchQueue.main.asyncAfter(
+                                                deadline: DispatchTime.now() + Double(Int64(timeAfterOpen * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: {
+                                                    print("opening url")
+                                                    NSWorkspace.shared().open(url!)
+                                                    invokeGroup.leave()
+                                            })
+                                        }
+                                    }
+                                    if found {
+                                        break
+                                    }
+                                }
+                            }
+                            
+                            switch invokeGroup.wait(timeout: DispatchTime.now() + 10) {
+                            case DispatchTimeoutResult.success:
+                                break
+                            case DispatchTimeoutResult.timedOut:
+                                print("Unable to open url as server has not launched")
+                                break
+                            }
+                        }catch{
+                            print("Didn't work")
+                        }
+                    }else{
+                        // wait for user to fill out param values
+                    }
+                    print(fullFunc)
+                    //displayAlert(message: fullFunc)
+                }
+            }
+            completionHandler(nil)
+        }
+        
+        
+        
+        /// Checks for parameters above the function and adds parameters with initial values if none are found
+        ///
+        /// - Parameters:
+        ///   - startLine: the beginning of the function : 21123r1231
+        ///   - endLine: the end of the function
+        ///   - lines: the lines of the file
+        /// - Returns: return true if documentation was created, false if documentation existed already
+        func checkUpdateParameters(startLine: Int, endLine: Int, lines: NSMutableArray)-> [String: Any]{
+            
+            // - Look for args that are used
+            var argsFound = [String]()
+            for lineNum in startLine...endLine{
+                if let line = lines[lineNum] as? String {
+                    if let startRange = line.range(of:"args[\""),
+                        let substringFrom = line.substring(from: startRange.upperBound) as? String,
+                        let endRange = substringFrom.range(of: "\"]"),
+                        let finalParamater = substringFrom.substring(to:endRange.lowerBound) as? String {
+                        if !argsFound.contains(finalParamater){
+                            argsFound.append(finalParamater)
+                        }
+                    }
+                }
+            }
+            
+            if argsFound.count > 0 {
+                argsFound.sort()
+                // Determine if placeholders were already created
+                var lineNum = startLine - 1
+                var startDocumentation = -1
+                var createDocumentation = true
+                while lineNum > 0{
+                    if let line = lines[lineNum] as? String{
+                        if !line.contains("///"){
+                            startDocumentation = lineNum + 1
+                            break
+                        }
+                        lineNum -= 1
+                    }
+                }
+                
+                if startDocumentation == -1 {
+                    startDocumentation = 0
+                }
+                var paramsFound = 0
+                var paramFoundLines = [String]()
+                for lineNum in startDocumentation..<startLine {
+                    if let line = lines[lineNum] as? String{
+                        argsFound.forEach{
+                            if line.contains("- \($0):"){
+                                paramsFound += 1
+                                paramFoundLines.append(line)
+                            }
+                        }
+                    }
+                }
+                if paramsFound == argsFound.count{
+                    createDocumentation = false
+                    var paramValues = [String:Any]()
+                    var paramsDict = [String:String]()
+                    paramValues["params"] = paramsDict
+                    for paramLine in paramFoundLines{
+                        
+                        let components = paramLine.components(separatedBy: ":")
+                        if components.count == 3{
+                            //Strip Param documentation lines for values
+                            var testValue = components[2]
+                            ["\n", " ", "#>", "<#", "\""].forEach{
+                                testValue = testValue.replacingOccurrences(of: $0, with: "")
+                            }
+                            var paramName = components[0]
+                            ["/", " ", "-"].forEach{
+                                paramName = paramName.replacingOccurrences(of: $0, with: "")
+                            }
+                            paramsDict[paramName] = testValue
+                            
+                        }else{
+                            createDocumentation = true
+                            break
+                        }
+                    }
+                    paramValues["params"] = paramsDict
+                    if createDocumentation == false{
+                        // Look for expected output
+                        for lineNum in startDocumentation ..< startLine {
+                            if let line = lines[lineNum] as? String{
+                                if line.contains("Expected Output --"){
+                                    var expectedOutString = line.components(separatedBy: "--").last!
+                                    ["\n", " ", "#>", "<#"].forEach({
+                                        expectedOutString = expectedOutString.replacingOccurrences(of: $0, with: "")
+                                    })
+                                    do{
+                                        let expectedOutJSON = try JSONSerialization.jsonObject(with: expectedOutString.data(using: String.Encoding.utf8)!, options: .mutableContainers)
+                                        paramValues["expectedOut"] = expectedOutJSON as! [String : Any]
+                                    }catch{
+                                        print("Expected output could not be parsed")
+                                        paramValues["expectedOut"] = [:]
+                                    }
+                                }
+                            }
+                        }
+                        return paramValues
+                    }
+                }
+                
+                // Create documentation placeholders if placeholders not found
+                if createDocumentation{
+                    var indentation = ""
+                    let funcLine = lines[startLine] as! String
+                    let funcLineComponents = funcLine.components(separatedBy: "func")
+                    if funcLineComponents.count > 1 {
+                        indentation = funcLineComponents[0]
+                    }
+                    
+                    var textToAdd = ""
+                    textToAdd += "\(indentation)/// <#Description#> \n"
+                    textToAdd += "\(indentation)/// \n"
+                    if argsFound.count > 0{
+                        textToAdd += "\(indentation)/// - Parameters: \n"
+                        argsFound.forEach { textToAdd += "\(indentation)///   - \($0): <# description #> : <# test value #> \n" }
+                    }
+                    textToAdd += "\(indentation)/// - Returns: <# return value description #> \n"
+                    textToAdd += "\(indentation)/// - Expected Output -- <#Put expected JSON here (optional)#> \n"
+                    lines.insert(textToAdd, at: startLine)
+                    return [:]
+                }
+                return [:]
+            }else{
+                return [:]
+            }
+        }
+        
+        func checkForOWPlayground()->Bool{
+            let runningApps = NSWorkspace.shared().runningApplications
+            var OWPlaygroundFound = false
+            for app in runningApps{
+                if app.bundleIdentifier == "com.electron.openwhisk-playground-osx"{
+                    OWPlaygroundFound = true
+                }
+            }
+            return OWPlaygroundFound
+        }
+        
+        func openOWPlayground(){
+            
+            let args = [ "-a",  "openwhisk-playground-osx", "--args", "asdfasdfddd"]
+            let task = Process()
+            task.launchPath = "/usr/bin/open"
+            task.arguments = args
+            
+            task.launch()
+        }
+        
+        /// Displays a pop up alert for debugging
+        ///
+        /// - Parameter message: message description
+        func displayAlert(message: String){
+            DispatchQueue.main.sync {
+                let alert = NSAlert()
+                alert.messageText = message
+                alert.window.level = 999
+                
+                NSApp.beginModalSession(for: alert.window)
+                NSApp.activate(ignoringOtherApps: true)
+                alert.window.makeKeyAndOrderFront(nil)
+                alert.runModal()
+                
+            }
+        }
+    }
diff --git a/xcode-playgrounds-extension/OWPlaygrounds/Info.plist b/xcode-playgrounds-extension/OWPlaygrounds/Info.plist
new file mode 100644
index 0000000..7e15be9
--- /dev/null
+++ b/xcode-playgrounds-extension/OWPlaygrounds/Info.plist
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleDisplayName</key>
+	<string>OWPlaygrounds</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>XPC!</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>LSMinimumSystemVersion</key>
+	<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
+	<key>NSExtension</key>
+	<dict>
+		<key>NSExtensionAttributes</key>
+		<dict>
+			<key>XCSourceEditorExtensionPrincipalClass</key>
+			<string>$(PRODUCT_MODULE_NAME).SourceEditorExtension</string>
+		</dict>
+		<key>NSExtensionPointIdentifier</key>
+		<string>com.apple.dt.Xcode.extension.source-editor</string>
+	</dict>
+	<key>NSHumanReadableCopyright</key>
+	<string>Copyright © 2017 Avery Lamp. All rights reserved.</string>
+	<key>PLAYGROUND_PATH</key>
+	<string>$(PROJECT_DIR)</string>
+</dict>
+</plist>
diff --git a/xcode-playgrounds-extension/OWPlaygrounds/OWPlaygrounds.entitlements b/xcode-playgrounds-extension/OWPlaygrounds/OWPlaygrounds.entitlements
new file mode 100644
index 0000000..852fa1a
--- /dev/null
+++ b/xcode-playgrounds-extension/OWPlaygrounds/OWPlaygrounds.entitlements
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>com.apple.security.app-sandbox</key>
+	<true/>
+</dict>
+</plist>
diff --git a/xcode-playgrounds-extension/OWPlaygrounds/SourceEditorExtension.swift b/xcode-playgrounds-extension/OWPlaygrounds/SourceEditorExtension.swift
new file mode 100644
index 0000000..0969cf0
--- /dev/null
+++ b/xcode-playgrounds-extension/OWPlaygrounds/SourceEditorExtension.swift
@@ -0,0 +1,39 @@
+//
+//  SourceEditorExtension.swift
+//  OWPlaygrounds
+//
+//  Created by whisk on 1/30/17.
+//  Copyright © 2017 Avery Lamp. All rights reserved.
+//
+
+import Foundation
+import XcodeKit
+
+class SourceEditorExtension: NSObject, XCSourceEditorExtension {
+    
+    
+    func extensionDidFinishLaunching() {
+        print("Hello extension")
+        // If your extension needs to do any work at launch, implement this optional method.
+    }
+ 
+    
+    
+    var commandDefinitions: [[XCSourceEditorCommandDefinitionKey: Any]] {
+        // If your extension needs to return a collection of command definitions that differs from those in its Info.plist, implement this optional property getter.
+        let productIdentifier = Bundle.main.infoDictionary![kCFBundleIdentifierKey as String] as! String
+        
+        func definitionForClassNamed(_ className: String, commandName: String) -> [XCSourceEditorCommandDefinitionKey: Any] {
+            
+            return [XCSourceEditorCommandDefinitionKey.identifierKey: productIdentifier + className,
+                    XCSourceEditorCommandDefinitionKey.classNameKey: className,
+                    XCSourceEditorCommandDefinitionKey.nameKey: commandName]
+        }
+        
+        let myDefinitions : [[XCSourceEditorCommandDefinitionKey: Any]] = [definitionForClassNamed(EditFunctionCommand.className(),commandName: NSLocalizedString("Run function in OWPlayground", comment:""))]
+        
+        return myDefinitions
+    }
+ 
+    
+}
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftAppKit.dylib b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftAppKit.dylib
new file mode 100755
index 0000000..31447f2
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftAppKit.dylib
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftCore.dylib b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftCore.dylib
new file mode 100755
index 0000000..14deccf
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftCore.dylib
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftCoreData.dylib b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftCoreData.dylib
new file mode 100755
index 0000000..22bfde4
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftCoreData.dylib
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftCoreGraphics.dylib b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftCoreGraphics.dylib
new file mode 100755
index 0000000..f2ed077
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftCoreGraphics.dylib
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftCoreImage.dylib b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftCoreImage.dylib
new file mode 100755
index 0000000..c99d852
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftCoreImage.dylib
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftDarwin.dylib b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftDarwin.dylib
new file mode 100755
index 0000000..fe7e2e6
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftDarwin.dylib
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftDispatch.dylib b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftDispatch.dylib
new file mode 100755
index 0000000..db14706
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftDispatch.dylib
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftFoundation.dylib b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftFoundation.dylib
new file mode 100755
index 0000000..c14d41d
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftFoundation.dylib
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftIOKit.dylib b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftIOKit.dylib
new file mode 100755
index 0000000..90b7f39
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftIOKit.dylib
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftObjectiveC.dylib b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftObjectiveC.dylib
new file mode 100755
index 0000000..a11f00b
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftObjectiveC.dylib
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftQuartzCore.dylib b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftQuartzCore.dylib
new file mode 100755
index 0000000..bd40f8e
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftQuartzCore.dylib
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftXPC.dylib b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftXPC.dylib
new file mode 100755
index 0000000..c4aa2fe
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Frameworks/libswiftXPC.dylib
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Info.plist b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Info.plist
new file mode 100644
index 0000000..0e000ca
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Info.plist
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>BuildMachineOSBuild</key>
+	<string>16D32</string>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>OWXcodeExtension</string>
+	<key>CFBundleIconFile</key>
+	<string>AppIcon</string>
+	<key>CFBundleIdentifier</key>
+	<string>IBM.OWXcodeExtension</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>OWXcodeExtension</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSupportedPlatforms</key>
+	<array>
+		<string>MacOSX</string>
+	</array>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>DTCompiler</key>
+	<string>com.apple.compilers.llvm.clang.1_0</string>
+	<key>DTPlatformBuild</key>
+	<string>8C1002</string>
+	<key>DTPlatformVersion</key>
+	<string>GM</string>
+	<key>DTSDKBuild</key>
+	<string>16C58</string>
+	<key>DTSDKName</key>
+	<string>macosx10.12</string>
+	<key>DTXcode</key>
+	<string>0821</string>
+	<key>DTXcodeBuild</key>
+	<string>8C1002</string>
+	<key>LSMinimumSystemVersion</key>
+	<string>10.12</string>
+	<key>NSHumanReadableCopyright</key>
+	<string>Copyright © 2017 Avery Lamp. All rights reserved.</string>
+	<key>NSMainStoryboardFile</key>
+	<string>Main</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+</dict>
+</plist>
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/MacOS/OWXcodeExtension b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/MacOS/OWXcodeExtension
new file mode 100755
index 0000000..baa4e33
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/MacOS/OWXcodeExtension
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/PkgInfo b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/PkgInfo
new file mode 100644
index 0000000..bd04210
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/PkgInfo
@@ -0,0 +1 @@
+APPL????
\ No newline at end of file
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/PlugIns/OWPlaygrounds.appex/Contents/Info.plist b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/PlugIns/OWPlaygrounds.appex/Contents/Info.plist
new file mode 100644
index 0000000..b768a1a
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/PlugIns/OWPlaygrounds.appex/Contents/Info.plist
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>BuildMachineOSBuild</key>
+	<string>16D32</string>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleDisplayName</key>
+	<string>OWPlaygrounds</string>
+	<key>CFBundleExecutable</key>
+	<string>OWPlaygrounds</string>
+	<key>CFBundleIdentifier</key>
+	<string>IBM.OWXcodeExtension.OWPlaygrounds</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>OWPlaygrounds</string>
+	<key>CFBundlePackageType</key>
+	<string>XPC!</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSupportedPlatforms</key>
+	<array>
+		<string>MacOSX</string>
+	</array>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>DTCompiler</key>
+	<string>com.apple.compilers.llvm.clang.1_0</string>
+	<key>DTPlatformBuild</key>
+	<string>8C1002</string>
+	<key>DTPlatformVersion</key>
+	<string>GM</string>
+	<key>DTSDKBuild</key>
+	<string>16C58</string>
+	<key>DTSDKName</key>
+	<string>macosx10.12</string>
+	<key>DTXcode</key>
+	<string>0821</string>
+	<key>DTXcodeBuild</key>
+	<string>8C1002</string>
+	<key>LSMinimumSystemVersion</key>
+	<string>10.11</string>
+	<key>NSExtension</key>
+	<dict>
+		<key>NSExtensionAttributes</key>
+		<dict>
+			<key>XCSourceEditorExtensionPrincipalClass</key>
+			<string>OWPlaygrounds.SourceEditorExtension</string>
+		</dict>
+		<key>NSExtensionPointIdentifier</key>
+		<string>com.apple.dt.Xcode.extension.source-editor</string>
+	</dict>
+	<key>NSHumanReadableCopyright</key>
+	<string>Copyright © 2017 Avery Lamp. All rights reserved.</string>
+	<key>PLAYGROUND_PATH</key>
+	<string>/Users/whisk/Developer/Xcode/OWXcode/openwhisk-xcode</string>
+</dict>
+</plist>
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/PlugIns/OWPlaygrounds.appex/Contents/MacOS/OWPlaygrounds b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/PlugIns/OWPlaygrounds.appex/Contents/MacOS/OWPlaygrounds
new file mode 100755
index 0000000..1418419
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/PlugIns/OWPlaygrounds.appex/Contents/MacOS/OWPlaygrounds
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/PlugIns/OWPlaygrounds.appex/Contents/Resources/archived-expanded-entitlements.xcent b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/PlugIns/OWPlaygrounds.appex/Contents/Resources/archived-expanded-entitlements.xcent
new file mode 100644
index 0000000..852fa1a
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/PlugIns/OWPlaygrounds.appex/Contents/Resources/archived-expanded-entitlements.xcent
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>com.apple.security.app-sandbox</key>
+	<true/>
+</dict>
+</plist>
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/PlugIns/OWPlaygrounds.appex/Contents/_CodeSignature/CodeResources b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/PlugIns/OWPlaygrounds.appex/Contents/_CodeSignature/CodeResources
new file mode 100644
index 0000000..889d2c7
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/PlugIns/OWPlaygrounds.appex/Contents/_CodeSignature/CodeResources
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>files</key>
+	<dict>
+		<key>Resources/archived-expanded-entitlements.xcent</key>
+		<data>
+		EPWnZClCepLXTlRBQz8jOgCUyHo=
+		</data>
+	</dict>
+	<key>files2</key>
+	<dict>
+		<key>Resources/archived-expanded-entitlements.xcent</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			EPWnZClCepLXTlRBQz8jOgCUyHo=
+			</data>
+			<key>hash2</key>
+			<data>
+			t0bHSyAeavTghk+9H09in5YVan7EtyCLyZXQpQibtZI=
+			</data>
+		</dict>
+	</dict>
+	<key>rules</key>
+	<dict>
+		<key>^Resources/</key>
+		<true/>
+		<key>^Resources/.*\.lproj/</key>
+		<dict>
+			<key>optional</key>
+			<true/>
+			<key>weight</key>
+			<real>1000</real>
+		</dict>
+		<key>^Resources/.*\.lproj/locversion.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>1100</real>
+		</dict>
+		<key>^Resources/Base\.lproj/</key>
+		<dict>
+			<key>weight</key>
+			<real>1010</real>
+		</dict>
+		<key>^version.plist$</key>
+		<true/>
+	</dict>
+	<key>rules2</key>
+	<dict>
+		<key>.*\.dSYM($|/)</key>
+		<dict>
+			<key>weight</key>
+			<real>11</real>
+		</dict>
+		<key>^(.*/)?\.DS_Store$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>2000</real>
+		</dict>
+		<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
+		<dict>
+			<key>nested</key>
+			<true/>
+			<key>weight</key>
+			<real>10</real>
+		</dict>
+		<key>^.*</key>
+		<true/>
+		<key>^Info\.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^PkgInfo$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^Resources/</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^Resources/.*\.lproj/</key>
+		<dict>
+			<key>optional</key>
+			<true/>
+			<key>weight</key>
+			<real>1000</real>
+		</dict>
+		<key>^Resources/.*\.lproj/locversion.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>1100</real>
+		</dict>
+		<key>^Resources/Base\.lproj/</key>
+		<dict>
+			<key>weight</key>
+			<real>1010</real>
+		</dict>
+		<key>^[^/]+$</key>
+		<dict>
+			<key>nested</key>
+			<true/>
+			<key>weight</key>
+			<real>10</real>
+		</dict>
+		<key>^embedded\.provisionprofile$</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^version\.plist$</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+	</dict>
+</dict>
+</plist>
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/AppIcon.icns b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/AppIcon.icns
new file mode 100644
index 0000000..e1098f1
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/AppIcon.icns
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/Assets.car b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/Assets.car
new file mode 100644
index 0000000..11d0d8a
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/Assets.car
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/Base.lproj/Main.storyboardc/Info.plist b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/Base.lproj/Main.storyboardc/Info.plist
new file mode 100644
index 0000000..a549275
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/Base.lproj/Main.storyboardc/Info.plist
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/Base.lproj/Main.storyboardc/MainMenu.nib b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/Base.lproj/Main.storyboardc/MainMenu.nib
new file mode 100644
index 0000000..7f58b0c
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/Base.lproj/Main.storyboardc/MainMenu.nib
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/Base.lproj/Main.storyboardc/NSWindowController-B8D-0N-5wS.nib b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/Base.lproj/Main.storyboardc/NSWindowController-B8D-0N-5wS.nib
new file mode 100644
index 0000000..8a7214a
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/Base.lproj/Main.storyboardc/NSWindowController-B8D-0N-5wS.nib
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/Base.lproj/Main.storyboardc/XfG-lQ-9wD-view-m2S-Jp-Qdl.nib b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/Base.lproj/Main.storyboardc/XfG-lQ-9wD-view-m2S-Jp-Qdl.nib
new file mode 100644
index 0000000..56f4696
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/Resources/Base.lproj/Main.storyboardc/XfG-lQ-9wD-view-m2S-Jp-Qdl.nib
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/_CodeSignature/CodeResources b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/_CodeSignature/CodeResources
new file mode 100644
index 0000000..f6e7e5d
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.app/Contents/_CodeSignature/CodeResources
@@ -0,0 +1,300 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>files</key>
+	<dict>
+		<key>Resources/AppIcon.icns</key>
+		<data>
+		dHxc/x2GLynMqg3kD7EDqfNDkKE=
+		</data>
+		<key>Resources/Assets.car</key>
+		<data>
+		OFiIu74sNQMT/DGtoCHL6Htxnoo=
+		</data>
+		<key>Resources/Base.lproj/Main.storyboardc/Info.plist</key>
+		<data>
+		QAJFhikgqxe9+Moe5VgiCHs4Gek=
+		</data>
+		<key>Resources/Base.lproj/Main.storyboardc/MainMenu.nib</key>
+		<data>
+		Zr4/YcS0inbPkd3YnlHbNexGfMs=
+		</data>
+		<key>Resources/Base.lproj/Main.storyboardc/NSWindowController-B8D-0N-5wS.nib</key>
+		<data>
+		7tof6OtiTuiDLKizOFGI4e3VcYs=
+		</data>
+		<key>Resources/Base.lproj/Main.storyboardc/XfG-lQ-9wD-view-m2S-Jp-Qdl.nib</key>
+		<data>
+		I9gfZH2qriQ4jDgLPth2W4PW8vs=
+		</data>
+	</dict>
+	<key>files2</key>
+	<dict>
+		<key>Frameworks/libswiftAppKit.dylib</key>
+		<dict>
+			<key>cdhash</key>
+			<data>
+			ftrmbewJBFN53O8Vks98bPbezTs=
+			</data>
+			<key>requirement</key>
+			<string>identifier "com.apple.dt.runtime.swiftAppKit" and anchor apple generic and certificate leaf[subject.CN] = "Mac Developer: Avery Lamp (UU9P8M6946)" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
+		</dict>
+		<key>Frameworks/libswiftCore.dylib</key>
+		<dict>
+			<key>cdhash</key>
+			<data>
+			u0XO+HIqw6d+mNdoy1wsLiRYuqI=
+			</data>
+			<key>requirement</key>
+			<string>identifier "com.apple.dt.runtime.swiftCore" and anchor apple generic and certificate leaf[subject.CN] = "Mac Developer: Avery Lamp (UU9P8M6946)" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
+		</dict>
+		<key>Frameworks/libswiftCoreData.dylib</key>
+		<dict>
+			<key>cdhash</key>
+			<data>
+			OZAv3Pl9GJurrMhDPU7Y47NNuQQ=
+			</data>
+			<key>requirement</key>
+			<string>identifier "com.apple.dt.runtime.swiftCoreData" and anchor apple generic and certificate leaf[subject.CN] = "Mac Developer: Avery Lamp (UU9P8M6946)" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
+		</dict>
+		<key>Frameworks/libswiftCoreGraphics.dylib</key>
+		<dict>
+			<key>cdhash</key>
+			<data>
+			9vrUeKLDrALVX1cR0C9uUtGEf9A=
+			</data>
+			<key>requirement</key>
+			<string>identifier "com.apple.dt.runtime.swiftCoreGraphics" and anchor apple generic and certificate leaf[subject.CN] = "Mac Developer: Avery Lamp (UU9P8M6946)" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
+		</dict>
+		<key>Frameworks/libswiftCoreImage.dylib</key>
+		<dict>
+			<key>cdhash</key>
+			<data>
+			kxcDvwmYUHnevQwkgqFpG3LqS5Y=
+			</data>
+			<key>requirement</key>
+			<string>identifier "com.apple.dt.runtime.swiftCoreImage" and anchor apple generic and certificate leaf[subject.CN] = "Mac Developer: Avery Lamp (UU9P8M6946)" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
+		</dict>
+		<key>Frameworks/libswiftDarwin.dylib</key>
+		<dict>
+			<key>cdhash</key>
+			<data>
+			0mSlBAeDo5TlBca+zJZff08u7iQ=
+			</data>
+			<key>requirement</key>
+			<string>identifier "com.apple.dt.runtime.swiftDarwin" and anchor apple generic and certificate leaf[subject.CN] = "Mac Developer: Avery Lamp (UU9P8M6946)" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
+		</dict>
+		<key>Frameworks/libswiftDispatch.dylib</key>
+		<dict>
+			<key>cdhash</key>
+			<data>
+			bOjAZnbEUCUy+7kML7soj/2M20o=
+			</data>
+			<key>requirement</key>
+			<string>identifier "com.apple.dt.runtime.swiftDispatch" and anchor apple generic and certificate leaf[subject.CN] = "Mac Developer: Avery Lamp (UU9P8M6946)" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
+		</dict>
+		<key>Frameworks/libswiftFoundation.dylib</key>
+		<dict>
+			<key>cdhash</key>
+			<data>
+			7WQNf+2m4tQB+9eJz6xgI8ewJfA=
+			</data>
+			<key>requirement</key>
+			<string>identifier "com.apple.dt.runtime.swiftFoundation" and anchor apple generic and certificate leaf[subject.CN] = "Mac Developer: Avery Lamp (UU9P8M6946)" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
+		</dict>
+		<key>Frameworks/libswiftIOKit.dylib</key>
+		<dict>
+			<key>cdhash</key>
+			<data>
+			rUR+qFpRVp+7W1rLge5C2NNIMyc=
+			</data>
+			<key>requirement</key>
+			<string>identifier "com.apple.dt.runtime.swiftIOKit" and anchor apple generic and certificate leaf[subject.CN] = "Mac Developer: Avery Lamp (UU9P8M6946)" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
+		</dict>
+		<key>Frameworks/libswiftObjectiveC.dylib</key>
+		<dict>
+			<key>cdhash</key>
+			<data>
+			Aj2HjQrkbNrs0/oWuD0zLesic/I=
+			</data>
+			<key>requirement</key>
+			<string>identifier "com.apple.dt.runtime.swiftObjectiveC" and anchor apple generic and certificate leaf[subject.CN] = "Mac Developer: Avery Lamp (UU9P8M6946)" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
+		</dict>
+		<key>Frameworks/libswiftQuartzCore.dylib</key>
+		<dict>
+			<key>cdhash</key>
+			<data>
+			DgY0hrCMGQzfVk2sGgbjUSNjdiU=
+			</data>
+			<key>requirement</key>
+			<string>identifier "com.apple.dt.runtime.swiftQuartzCore" and anchor apple generic and certificate leaf[subject.CN] = "Mac Developer: Avery Lamp (UU9P8M6946)" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
+		</dict>
+		<key>Frameworks/libswiftXPC.dylib</key>
+		<dict>
+			<key>cdhash</key>
+			<data>
+			1WP/zDJyLZFJVf1r+KJSd5OCEp0=
+			</data>
+			<key>requirement</key>
+			<string>identifier "com.apple.dt.runtime.swiftXPC" and anchor apple generic and certificate leaf[subject.CN] = "Mac Developer: Avery Lamp (UU9P8M6946)" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
+		</dict>
+		<key>PlugIns/OWPlaygrounds.appex</key>
+		<dict>
+			<key>cdhash</key>
+			<data>
+			K/jbjicSVLEjN6bGLZusPEMyir4=
+			</data>
+			<key>requirement</key>
+			<string>identifier "IBM.OWXcodeExtension.OWPlaygrounds" and anchor apple generic and certificate leaf[subject.CN] = "Mac Developer: Avery Lamp (UU9P8M6946)" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
+		</dict>
+		<key>Resources/AppIcon.icns</key>
+		<dict>
+			<key>hash2</key>
+			<data>
+			yDbaW9GtKGNes/CcmFB8qQamvAYVOBnOUWPAg5/Qp8s=
+			</data>
+		</dict>
+		<key>Resources/Assets.car</key>
+		<dict>
+			<key>hash2</key>
+			<data>
+			b7yNLjGd0/FTlAExrwIJofhzetmaM+Kv2jb2tC9sw2E=
+			</data>
+		</dict>
+		<key>Resources/Base.lproj/Main.storyboardc/Info.plist</key>
+		<dict>
+			<key>hash2</key>
+			<data>
+			HzT/0rd37igBMY/5fa30xCABy2PnA+RUmfoDTsTBkCI=
+			</data>
+		</dict>
+		<key>Resources/Base.lproj/Main.storyboardc/MainMenu.nib</key>
+		<dict>
+			<key>hash2</key>
+			<data>
+			q15i5tbZJqanCRFvgKZUbIK7Le+dvL7oKxSFhP/oJD4=
+			</data>
+		</dict>
+		<key>Resources/Base.lproj/Main.storyboardc/NSWindowController-B8D-0N-5wS.nib</key>
+		<dict>
+			<key>hash2</key>
+			<data>
+			xbKIQ04M1Xl0xw2fnAYp4mVyTiIP/JnDuKuE2npnjnM=
+			</data>
+		</dict>
+		<key>Resources/Base.lproj/Main.storyboardc/XfG-lQ-9wD-view-m2S-Jp-Qdl.nib</key>
+		<dict>
+			<key>hash2</key>
+			<data>
+			rG1o5x8R0SCa2vcx48+8QyYvxxhReT8CPfHzXfvmcCM=
+			</data>
+		</dict>
+	</dict>
+	<key>rules</key>
+	<dict>
+		<key>^Resources/</key>
+		<true/>
+		<key>^Resources/.*\.lproj/</key>
+		<dict>
+			<key>optional</key>
+			<true/>
+			<key>weight</key>
+			<real>1000</real>
+		</dict>
+		<key>^Resources/.*\.lproj/locversion.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>1100</real>
+		</dict>
+		<key>^Resources/Base\.lproj/</key>
+		<dict>
+			<key>weight</key>
+			<real>1010</real>
+		</dict>
+		<key>^version.plist$</key>
+		<true/>
+	</dict>
+	<key>rules2</key>
+	<dict>
+		<key>.*\.dSYM($|/)</key>
+		<dict>
+			<key>weight</key>
+			<real>11</real>
+		</dict>
+		<key>^(.*/)?\.DS_Store$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>2000</real>
+		</dict>
+		<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
+		<dict>
+			<key>nested</key>
+			<true/>
+			<key>weight</key>
+			<real>10</real>
+		</dict>
+		<key>^.*</key>
+		<true/>
+		<key>^Info\.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^PkgInfo$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^Resources/</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^Resources/.*\.lproj/</key>
+		<dict>
+			<key>optional</key>
+			<true/>
+			<key>weight</key>
+			<real>1000</real>
+		</dict>
+		<key>^Resources/.*\.lproj/locversion.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>1100</real>
+		</dict>
+		<key>^Resources/Base\.lproj/</key>
+		<dict>
+			<key>weight</key>
+			<real>1010</real>
+		</dict>
+		<key>^[^/]+$</key>
+		<dict>
+			<key>nested</key>
+			<true/>
+			<key>weight</key>
+			<real>10</real>
+		</dict>
+		<key>^embedded\.provisionprofile$</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^version\.plist$</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+	</dict>
+</dict>
+</plist>
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.xcodeproj/project.pbxproj b/xcode-playgrounds-extension/OWXcodeExtension.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..de62160
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.xcodeproj/project.pbxproj
@@ -0,0 +1,687 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		7F185A281E3F897C002C62EC /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F185A271E3F897C002C62EC /* AppDelegate.swift */; };
+		7F185A2A1E3F897C002C62EC /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F185A291E3F897C002C62EC /* ViewController.swift */; };
+		7F185A2C1E3F897C002C62EC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7F185A2B1E3F897C002C62EC /* Assets.xcassets */; };
+		7F185A2F1E3F897C002C62EC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7F185A2D1E3F897C002C62EC /* Main.storyboard */; };
+		7F185A3A1E3F897C002C62EC /* OWXcodeExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F185A391E3F897C002C62EC /* OWXcodeExtensionTests.swift */; };
+		7F185A451E3F897C002C62EC /* OWXcodeExtensionUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F185A441E3F897C002C62EC /* OWXcodeExtensionUITests.swift */; };
+		7F185A591E3F8993002C62EC /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F185A581E3F8993002C62EC /* Cocoa.framework */; };
+		7F185A5E1E3F8993002C62EC /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F185A5D1E3F8993002C62EC /* SourceEditorExtension.swift */; };
+		7F185A641E3F8993002C62EC /* OWPlaygrounds.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 7F185A561E3F8993002C62EC /* OWPlaygrounds.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
+		7F4F2D131E3F8C2100A503E9 /* EditFunctionCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F4F2D121E3F8C2100A503E9 /* EditFunctionCommand.swift */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		7F185A361E3F897C002C62EC /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 7F185A1C1E3F897B002C62EC /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 7F185A231E3F897B002C62EC;
+			remoteInfo = OWXcodeExtension;
+		};
+		7F185A411E3F897C002C62EC /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 7F185A1C1E3F897B002C62EC /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 7F185A231E3F897B002C62EC;
+			remoteInfo = OWXcodeExtension;
+		};
+		7F185A621E3F8993002C62EC /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 7F185A1C1E3F897B002C62EC /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 7F185A551E3F8993002C62EC;
+			remoteInfo = OWPlaygrounds;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		7F185A681E3F8993002C62EC /* Embed App Extensions */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 13;
+			files = (
+				7F185A641E3F8993002C62EC /* OWPlaygrounds.appex in Embed App Extensions */,
+			);
+			name = "Embed App Extensions";
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		7F185A241E3F897C002C62EC /* OWXcodeExtension.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OWXcodeExtension.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		7F185A271E3F897C002C62EC /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
+		7F185A291E3F897C002C62EC /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
+		7F185A2B1E3F897C002C62EC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+		7F185A2E1E3F897C002C62EC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
+		7F185A301E3F897C002C62EC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		7F185A351E3F897C002C62EC /* OWXcodeExtensionTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OWXcodeExtensionTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+		7F185A391E3F897C002C62EC /* OWXcodeExtensionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWXcodeExtensionTests.swift; sourceTree = "<group>"; };
+		7F185A3B1E3F897C002C62EC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		7F185A401E3F897C002C62EC /* OWXcodeExtensionUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OWXcodeExtensionUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+		7F185A441E3F897C002C62EC /* OWXcodeExtensionUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWXcodeExtensionUITests.swift; sourceTree = "<group>"; };
+		7F185A461E3F897C002C62EC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		7F185A561E3F8993002C62EC /* OWPlaygrounds.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = OWPlaygrounds.appex; sourceTree = BUILT_PRODUCTS_DIR; };
+		7F185A581E3F8993002C62EC /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
+		7F185A5C1E3F8993002C62EC /* OWPlaygrounds.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = OWPlaygrounds.entitlements; sourceTree = "<group>"; };
+		7F185A5D1E3F8993002C62EC /* SourceEditorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorExtension.swift; sourceTree = "<group>"; };
+		7F185A611E3F8993002C62EC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		7F4F2D121E3F8C2100A503E9 /* EditFunctionCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditFunctionCommand.swift; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		7F185A211E3F897B002C62EC /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7F185A321E3F897C002C62EC /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7F185A3D1E3F897C002C62EC /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7F185A531E3F8993002C62EC /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				7F185A591E3F8993002C62EC /* Cocoa.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		7F185A1B1E3F897B002C62EC = {
+			isa = PBXGroup;
+			children = (
+				7F185A261E3F897C002C62EC /* OWXcodeExtension */,
+				7F185A381E3F897C002C62EC /* OWXcodeExtensionTests */,
+				7F185A431E3F897C002C62EC /* OWXcodeExtensionUITests */,
+				7F185A5A1E3F8993002C62EC /* OWPlaygrounds */,
+				7F185A571E3F8993002C62EC /* Frameworks */,
+				7F185A251E3F897C002C62EC /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		7F185A251E3F897C002C62EC /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				7F185A241E3F897C002C62EC /* OWXcodeExtension.app */,
+				7F185A351E3F897C002C62EC /* OWXcodeExtensionTests.xctest */,
+				7F185A401E3F897C002C62EC /* OWXcodeExtensionUITests.xctest */,
+				7F185A561E3F8993002C62EC /* OWPlaygrounds.appex */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		7F185A261E3F897C002C62EC /* OWXcodeExtension */ = {
+			isa = PBXGroup;
+			children = (
+				7F185A271E3F897C002C62EC /* AppDelegate.swift */,
+				7F185A291E3F897C002C62EC /* ViewController.swift */,
+				7F185A2B1E3F897C002C62EC /* Assets.xcassets */,
+				7F185A2D1E3F897C002C62EC /* Main.storyboard */,
+				7F185A301E3F897C002C62EC /* Info.plist */,
+			);
+			path = OWXcodeExtension;
+			sourceTree = "<group>";
+		};
+		7F185A381E3F897C002C62EC /* OWXcodeExtensionTests */ = {
+			isa = PBXGroup;
+			children = (
+				7F185A391E3F897C002C62EC /* OWXcodeExtensionTests.swift */,
+				7F185A3B1E3F897C002C62EC /* Info.plist */,
+			);
+			path = OWXcodeExtensionTests;
+			sourceTree = "<group>";
+		};
+		7F185A431E3F897C002C62EC /* OWXcodeExtensionUITests */ = {
+			isa = PBXGroup;
+			children = (
+				7F185A441E3F897C002C62EC /* OWXcodeExtensionUITests.swift */,
+				7F185A461E3F897C002C62EC /* Info.plist */,
+			);
+			path = OWXcodeExtensionUITests;
+			sourceTree = "<group>";
+		};
+		7F185A571E3F8993002C62EC /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				7F185A581E3F8993002C62EC /* Cocoa.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		7F185A5A1E3F8993002C62EC /* OWPlaygrounds */ = {
+			isa = PBXGroup;
+			children = (
+				7F185A5D1E3F8993002C62EC /* SourceEditorExtension.swift */,
+				7F4F2D121E3F8C2100A503E9 /* EditFunctionCommand.swift */,
+				7F185A611E3F8993002C62EC /* Info.plist */,
+				7F185A5B1E3F8993002C62EC /* Supporting Files */,
+			);
+			path = OWPlaygrounds;
+			sourceTree = "<group>";
+		};
+		7F185A5B1E3F8993002C62EC /* Supporting Files */ = {
+			isa = PBXGroup;
+			children = (
+				7F185A5C1E3F8993002C62EC /* OWPlaygrounds.entitlements */,
+			);
+			name = "Supporting Files";
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		7F185A231E3F897B002C62EC /* OWXcodeExtension */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 7F185A491E3F897C002C62EC /* Build configuration list for PBXNativeTarget "OWXcodeExtension" */;
+			buildPhases = (
+				7F185A201E3F897B002C62EC /* Sources */,
+				7F185A211E3F897B002C62EC /* Frameworks */,
+				7F185A221E3F897B002C62EC /* Resources */,
+				7F185A681E3F8993002C62EC /* Embed App Extensions */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				7F185A631E3F8993002C62EC /* PBXTargetDependency */,
+			);
+			name = OWXcodeExtension;
+			productName = OWXcodeExtension;
+			productReference = 7F185A241E3F897C002C62EC /* OWXcodeExtension.app */;
+			productType = "com.apple.product-type.application";
+		};
+		7F185A341E3F897C002C62EC /* OWXcodeExtensionTests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 7F185A4C1E3F897C002C62EC /* Build configuration list for PBXNativeTarget "OWXcodeExtensionTests" */;
+			buildPhases = (
+				7F185A311E3F897C002C62EC /* Sources */,
+				7F185A321E3F897C002C62EC /* Frameworks */,
+				7F185A331E3F897C002C62EC /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				7F185A371E3F897C002C62EC /* PBXTargetDependency */,
+			);
+			name = OWXcodeExtensionTests;
+			productName = OWXcodeExtensionTests;
+			productReference = 7F185A351E3F897C002C62EC /* OWXcodeExtensionTests.xctest */;
+			productType = "com.apple.product-type.bundle.unit-test";
+		};
+		7F185A3F1E3F897C002C62EC /* OWXcodeExtensionUITests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 7F185A4F1E3F897C002C62EC /* Build configuration list for PBXNativeTarget "OWXcodeExtensionUITests" */;
+			buildPhases = (
+				7F185A3C1E3F897C002C62EC /* Sources */,
+				7F185A3D1E3F897C002C62EC /* Frameworks */,
+				7F185A3E1E3F897C002C62EC /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				7F185A421E3F897C002C62EC /* PBXTargetDependency */,
+			);
+			name = OWXcodeExtensionUITests;
+			productName = OWXcodeExtensionUITests;
+			productReference = 7F185A401E3F897C002C62EC /* OWXcodeExtensionUITests.xctest */;
+			productType = "com.apple.product-type.bundle.ui-testing";
+		};
+		7F185A551E3F8993002C62EC /* OWPlaygrounds */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 7F185A651E3F8993002C62EC /* Build configuration list for PBXNativeTarget "OWPlaygrounds" */;
+			buildPhases = (
+				7F185A521E3F8993002C62EC /* Sources */,
+				7F185A531E3F8993002C62EC /* Frameworks */,
+				7F185A541E3F8993002C62EC /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = OWPlaygrounds;
+			productName = OWPlaygrounds;
+			productReference = 7F185A561E3F8993002C62EC /* OWPlaygrounds.appex */;
+			productType = "com.apple.product-type.xcode-extension";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		7F185A1C1E3F897B002C62EC /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastSwiftUpdateCheck = 0820;
+				LastUpgradeCheck = 0820;
+				ORGANIZATIONNAME = "Avery Lamp";
+				TargetAttributes = {
+					7F185A231E3F897B002C62EC = {
+						CreatedOnToolsVersion = 8.2.1;
+						DevelopmentTeam = 9XWYL3K4YT;
+						ProvisioningStyle = Automatic;
+					};
+					7F185A341E3F897C002C62EC = {
+						CreatedOnToolsVersion = 8.2.1;
+						ProvisioningStyle = Automatic;
+						TestTargetID = 7F185A231E3F897B002C62EC;
+					};
+					7F185A3F1E3F897C002C62EC = {
+						CreatedOnToolsVersion = 8.2.1;
+						ProvisioningStyle = Automatic;
+						TestTargetID = 7F185A231E3F897B002C62EC;
+					};
+					7F185A551E3F8993002C62EC = {
+						CreatedOnToolsVersion = 8.2.1;
+						DevelopmentTeam = 9XWYL3K4YT;
+						ProvisioningStyle = Automatic;
+					};
+				};
+			};
+			buildConfigurationList = 7F185A1F1E3F897B002C62EC /* Build configuration list for PBXProject "OWXcodeExtension" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = 7F185A1B1E3F897B002C62EC;
+			productRefGroup = 7F185A251E3F897C002C62EC /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				7F185A231E3F897B002C62EC /* OWXcodeExtension */,
+				7F185A341E3F897C002C62EC /* OWXcodeExtensionTests */,
+				7F185A3F1E3F897C002C62EC /* OWXcodeExtensionUITests */,
+				7F185A551E3F8993002C62EC /* OWPlaygrounds */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		7F185A221E3F897B002C62EC /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				7F185A2C1E3F897C002C62EC /* Assets.xcassets in Resources */,
+				7F185A2F1E3F897C002C62EC /* Main.storyboard in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7F185A331E3F897C002C62EC /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7F185A3E1E3F897C002C62EC /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7F185A541E3F8993002C62EC /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		7F185A201E3F897B002C62EC /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				7F185A2A1E3F897C002C62EC /* ViewController.swift in Sources */,
+				7F185A281E3F897C002C62EC /* AppDelegate.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7F185A311E3F897C002C62EC /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				7F185A3A1E3F897C002C62EC /* OWXcodeExtensionTests.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7F185A3C1E3F897C002C62EC /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				7F185A451E3F897C002C62EC /* OWXcodeExtensionUITests.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7F185A521E3F8993002C62EC /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				7F185A5E1E3F8993002C62EC /* SourceEditorExtension.swift in Sources */,
+				7F4F2D131E3F8C2100A503E9 /* EditFunctionCommand.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		7F185A371E3F897C002C62EC /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 7F185A231E3F897B002C62EC /* OWXcodeExtension */;
+			targetProxy = 7F185A361E3F897C002C62EC /* PBXContainerItemProxy */;
+		};
+		7F185A421E3F897C002C62EC /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 7F185A231E3F897B002C62EC /* OWXcodeExtension */;
+			targetProxy = 7F185A411E3F897C002C62EC /* PBXContainerItemProxy */;
+		};
+		7F185A631E3F8993002C62EC /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 7F185A551E3F8993002C62EC /* OWPlaygrounds */;
+			targetProxy = 7F185A621E3F8993002C62EC /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+		7F185A2D1E3F897C002C62EC /* Main.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				7F185A2E1E3F897C002C62EC /* Base */,
+			);
+			name = Main.storyboard;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		7F185A471E3F897C002C62EC /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "-";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.12;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = macosx;
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+			};
+			name = Debug;
+		};
+		7F185A481E3F897C002C62EC /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "-";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.12;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				SDKROOT = macosx;
+				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+			};
+			name = Release;
+		};
+		7F185A4A1E3F897C002C62EC /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				CODE_SIGN_IDENTITY = "Mac Developer";
+				COMBINE_HIDPI_IMAGES = YES;
+				DEVELOPMENT_TEAM = 9XWYL3K4YT;
+				INFOPLIST_FILE = OWXcodeExtension/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = IBM.OWXcodeExtension;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_VERSION = 3.0;
+			};
+			name = Debug;
+		};
+		7F185A4B1E3F897C002C62EC /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				CODE_SIGN_IDENTITY = "Mac Developer";
+				COMBINE_HIDPI_IMAGES = YES;
+				DEVELOPMENT_TEAM = 9XWYL3K4YT;
+				INFOPLIST_FILE = OWXcodeExtension/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = IBM.OWXcodeExtension;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_VERSION = 3.0;
+			};
+			name = Release;
+		};
+		7F185A4D1E3F897C002C62EC /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+				BUNDLE_LOADER = "$(TEST_HOST)";
+				COMBINE_HIDPI_IMAGES = YES;
+				INFOPLIST_FILE = OWXcodeExtensionTests/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = IBM.OWXcodeExtensionTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_VERSION = 3.0;
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/OWXcodeExtension.app/Contents/MacOS/OWXcodeExtension";
+			};
+			name = Debug;
+		};
+		7F185A4E1E3F897C002C62EC /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+				BUNDLE_LOADER = "$(TEST_HOST)";
+				COMBINE_HIDPI_IMAGES = YES;
+				INFOPLIST_FILE = OWXcodeExtensionTests/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = IBM.OWXcodeExtensionTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_VERSION = 3.0;
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/OWXcodeExtension.app/Contents/MacOS/OWXcodeExtension";
+			};
+			name = Release;
+		};
+		7F185A501E3F897C002C62EC /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+				COMBINE_HIDPI_IMAGES = YES;
+				INFOPLIST_FILE = OWXcodeExtensionUITests/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = IBM.OWXcodeExtensionUITests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_VERSION = 3.0;
+				TEST_TARGET_NAME = OWXcodeExtension;
+			};
+			name = Debug;
+		};
+		7F185A511E3F897C002C62EC /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+				COMBINE_HIDPI_IMAGES = YES;
+				INFOPLIST_FILE = OWXcodeExtensionUITests/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = IBM.OWXcodeExtensionUITests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_VERSION = 3.0;
+				TEST_TARGET_NAME = OWXcodeExtension;
+			};
+			name = Release;
+		};
+		7F185A661E3F8993002C62EC /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CODE_SIGN_ENTITLEMENTS = OWPlaygrounds/OWPlaygrounds.entitlements;
+				CODE_SIGN_IDENTITY = "Mac Developer";
+				COMBINE_HIDPI_IMAGES = YES;
+				DEVELOPMENT_TEAM = 9XWYL3K4YT;
+				INFOPLIST_FILE = OWPlaygrounds/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
+				MACOSX_DEPLOYMENT_TARGET = 10.11;
+				PRODUCT_BUNDLE_IDENTIFIER = IBM.OWXcodeExtension.OWPlaygrounds;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SKIP_INSTALL = YES;
+				SWIFT_VERSION = 3.0;
+			};
+			name = Debug;
+		};
+		7F185A671E3F8993002C62EC /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CODE_SIGN_ENTITLEMENTS = OWPlaygrounds/OWPlaygrounds.entitlements;
+				CODE_SIGN_IDENTITY = "Mac Developer";
+				COMBINE_HIDPI_IMAGES = YES;
+				DEVELOPMENT_TEAM = 9XWYL3K4YT;
+				INFOPLIST_FILE = OWPlaygrounds/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
+				MACOSX_DEPLOYMENT_TARGET = 10.11;
+				PRODUCT_BUNDLE_IDENTIFIER = IBM.OWXcodeExtension.OWPlaygrounds;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SKIP_INSTALL = YES;
+				SWIFT_VERSION = 3.0;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		7F185A1F1E3F897B002C62EC /* Build configuration list for PBXProject "OWXcodeExtension" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				7F185A471E3F897C002C62EC /* Debug */,
+				7F185A481E3F897C002C62EC /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		7F185A491E3F897C002C62EC /* Build configuration list for PBXNativeTarget "OWXcodeExtension" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				7F185A4A1E3F897C002C62EC /* Debug */,
+				7F185A4B1E3F897C002C62EC /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		7F185A4C1E3F897C002C62EC /* Build configuration list for PBXNativeTarget "OWXcodeExtensionTests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				7F185A4D1E3F897C002C62EC /* Debug */,
+				7F185A4E1E3F897C002C62EC /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		7F185A4F1E3F897C002C62EC /* Build configuration list for PBXNativeTarget "OWXcodeExtensionUITests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				7F185A501E3F897C002C62EC /* Debug */,
+				7F185A511E3F897C002C62EC /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		7F185A651E3F8993002C62EC /* Build configuration list for PBXNativeTarget "OWPlaygrounds" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				7F185A661E3F8993002C62EC /* Debug */,
+				7F185A671E3F8993002C62EC /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 7F185A1C1E3F897B002C62EC /* Project object */;
+}
diff --git a/xcode-playgrounds-extension/OWXcodeExtension.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/xcode-playgrounds-extension/OWXcodeExtension.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..77653a7
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:OWXcodeExtension.xcodeproj">
+   </FileRef>
+</Workspace>
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/AppDelegate.swift b/xcode-playgrounds-extension/OWXcodeExtension/AppDelegate.swift
new file mode 100644
index 0000000..11aa028
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/AppDelegate.swift
@@ -0,0 +1,26 @@
+//
+//  AppDelegate.swift
+//  OWXcodeExtension
+//
+//  Created by whisk on 1/30/17.
+//  Copyright © 2017 Avery Lamp. All rights reserved.
+//
+
+import Cocoa
+
+@NSApplicationMain
+class AppDelegate: NSObject, NSApplicationDelegate {
+
+
+
+    func applicationDidFinishLaunching(_ aNotification: Notification) {
+        // Insert code here to initialize your application
+    }
+
+    func applicationWillTerminate(_ aNotification: Notification) {
+        // Insert code here to tear down your application
+    }
+
+
+}
+
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/Contents.json b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..7170631
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,68 @@
+{
+  "images" : [
+    {
+      "size" : "16x16",
+      "idiom" : "mac",
+      "filename" : "openwhisk_hero_large 2-9.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "16x16",
+      "idiom" : "mac",
+      "filename" : "openwhisk_hero_large 2-8.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "32x32",
+      "idiom" : "mac",
+      "filename" : "openwhisk_hero_large 2-7.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "32x32",
+      "idiom" : "mac",
+      "filename" : "openwhisk_hero_large 2-6.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "128x128",
+      "idiom" : "mac",
+      "filename" : "openwhisk_hero_large 2-5.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "128x128",
+      "idiom" : "mac",
+      "filename" : "openwhisk_hero_large 2-4.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "256x256",
+      "idiom" : "mac",
+      "filename" : "openwhisk_hero_large 2-3.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "256x256",
+      "idiom" : "mac",
+      "filename" : "openwhisk_hero_large 2-2.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "512x512",
+      "idiom" : "mac",
+      "filename" : "openwhisk_hero_large 2-1.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "512x512",
+      "idiom" : "mac",
+      "filename" : "openwhisk_hero_large 2.png",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-1.png b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-1.png
new file mode 100644
index 0000000..b67425a
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-1.png
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-2.png b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-2.png
new file mode 100644
index 0000000..b67425a
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-2.png
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-3.png b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-3.png
new file mode 100644
index 0000000..b67425a
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-3.png
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-4.png b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-4.png
new file mode 100644
index 0000000..b67425a
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-4.png
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-5.png b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-5.png
new file mode 100644
index 0000000..b67425a
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-5.png
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-6.png b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-6.png
new file mode 100644
index 0000000..b67425a
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-6.png
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-7.png b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-7.png
new file mode 100644
index 0000000..b67425a
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-7.png
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-8.png b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-8.png
new file mode 100644
index 0000000..b67425a
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-8.png
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-9.png b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-9.png
new file mode 100644
index 0000000..b67425a
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2-9.png
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2.png b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2.png
new file mode 100644
index 0000000..b67425a
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/AppIcon.appiconset/openwhisk_hero_large 2.png
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/Contents.json b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/Contents.json
new file mode 100644
index 0000000..da4a164
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/openwhiskLogo.imageset/Contents.json b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/openwhiskLogo.imageset/Contents.json
new file mode 100644
index 0000000..bc0a2fb
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/openwhiskLogo.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "openwhisk_hero_medium.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/openwhiskLogo.imageset/openwhisk_hero_medium.png b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/openwhiskLogo.imageset/openwhisk_hero_medium.png
new file mode 100644
index 0000000..8d7c950
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/Assets.xcassets/openwhiskLogo.imageset/openwhisk_hero_medium.png
Binary files differ
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/Base.lproj/Main.storyboard b/xcode-playgrounds-extension/OWXcodeExtension/Base.lproj/Main.storyboard
new file mode 100644
index 0000000..8bd42de
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/Base.lproj/Main.storyboard
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11762"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--Application-->
+        <scene sceneID="JPo-4y-FX3">
+            <objects>
+                <application id="hnw-xV-0zn" sceneMemberID="viewController">
+                    <menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
+                        <items>
+                            <menuItem title="OWXcodeExtension" id="1Xt-HY-uBw">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <menu key="submenu" title="OWXcodeExtension" systemMenu="apple" id="uQy-DD-JDr">
+                                    <items>
+                                        <menuItem title="About OWXcodeExtension" id="5kV-Vb-QxS">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <connections>
+                                                <action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
+                                        <menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
+                                        <menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
+                                        <menuItem title="Services" id="NMo-om-nkz">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
+                                        </menuItem>
+                                        <menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
+                                        <menuItem title="Hide OWXcodeExtension" keyEquivalent="h" id="Olw-nP-bQN">
+                                            <connections>
+                                                <action selector="hide:" target="Ady-hI-5gd" id="PnN-Uc-m68"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
+                                            <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+                                            <connections>
+                                                <action selector="hideOtherApplications:" target="Ady-hI-5gd" id="VT4-aY-XCT"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="Show All" id="Kd2-mp-pUS">
+                                            <modifierMask key="keyEquivalentModifierMask"/>
+                                            <connections>
+                                                <action selector="unhideAllApplications:" target="Ady-hI-5gd" id="Dhg-Le-xox"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
+                                        <menuItem title="Quit OWXcodeExtension" keyEquivalent="q" id="4sb-4s-VLi">
+                                            <connections>
+                                                <action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
+                                            </connections>
+                                        </menuItem>
+                                    </items>
+                                </menu>
+                            </menuItem>
+                        </items>
+                    </menu>
+                    <connections>
+                        <outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
+                    </connections>
+                </application>
+                <customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="OWXcodeExtension" customModuleProvider="target"/>
+                <customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="75" y="0.0"/>
+        </scene>
+        <!--Window Controller-->
+        <scene sceneID="R2V-B0-nI4">
+            <objects>
+                <windowController id="B8D-0N-5wS" sceneMemberID="viewController">
+                    <window key="window" title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
+                        <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
+                        <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
+                        <rect key="contentRect" x="196" y="240" width="600" height="450"/>
+                        <rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
+                        <value key="minSize" type="size" width="600" height="450"/>
+                    </window>
+                    <connections>
+                        <segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/>
+                    </connections>
+                </windowController>
+                <customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="75" y="250"/>
+        </scene>
+        <!--View Controller-->
+        <scene sceneID="hIz-AP-VOD">
+            <objects>
+                <viewController id="XfG-lQ-9wD" customClass="ViewController" customModule="OWXcodeExtension" customModuleProvider="target" sceneMemberID="viewController">
+                    <view key="view" wantsLayer="YES" id="m2S-Jp-Qdl">
+                        <rect key="frame" x="0.0" y="0.0" width="600" height="450"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                        <subviews>
+                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Tpt-yE-Kxs">
+                                <rect key="frame" x="2" y="380" width="596" height="50"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="50" id="tw1-mJ-1Zn"/>
+                                </constraints>
+                                <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="Welcome to the OpenWhisk Playgrounds Extension" id="TJZ-hQ-FiQ">
+                                    <font key="font" size="25" name="AvenirNext-Regular"/>
+                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                    <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+                                </textFieldCell>
+                            </textField>
+                            <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="zjN-xL-Eye">
+                                <rect key="frame" x="100" y="170" width="400" height="200"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="400" id="KmU-NG-b2E"/>
+                                    <constraint firstAttribute="height" constant="200" id="sIU-BR-46N"/>
+                                </constraints>
+                                <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="openwhiskLogo" id="ZXU-an-qGj"/>
+                            </imageView>
+                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WJ0-jc-iHF">
+                                <rect key="frame" x="2" y="60" width="596" height="100"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="100" id="cRX-R6-pRc"/>
+                                </constraints>
+                                <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" id="yHG-78-w0l">
+                                    <font key="font" size="19" name="AvenirNext-Regular"/>
+                                    <string key="title">Your extension is now installed.  
In order to uninstall the extension delete the app or
+go to System Preferences -&gt; Extensions and deactivate it.


+

 </string>
+                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                    <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+                                </textFieldCell>
+                            </textField>
+                            <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="uTJ-gO-vuq">
+                                <rect key="frame" x="96" y="19" width="408" height="31"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="30" id="dc4-Ye-BFc"/>
+                                </constraints>
+                                <buttonCell key="cell" type="roundRect" title="For instructions on how to use the extension click here" bezelStyle="roundedRect" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="icM-x2-46w">
+                                    <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                    <font key="font" size="16" name="AvenirNext-Regular"/>
+                                </buttonCell>
+                                <connections>
+                                    <action selector="instructionsClicked:" target="XfG-lQ-9wD" id="VN0-Jo-Zgv"/>
+                                </connections>
+                            </button>
+                        </subviews>
+                        <constraints>
+                            <constraint firstItem="zjN-xL-Eye" firstAttribute="centerX" secondItem="m2S-Jp-Qdl" secondAttribute="centerX" id="1bu-mC-VxU"/>
+                            <constraint firstItem="uTJ-gO-vuq" firstAttribute="centerX" secondItem="m2S-Jp-Qdl" secondAttribute="centerX" id="4km-U3-jfx"/>
+                            <constraint firstItem="zjN-xL-Eye" firstAttribute="top" secondItem="Tpt-yE-Kxs" secondAttribute="bottom" constant="10" id="4lz-Xg-2vt"/>
+                            <constraint firstItem="Tpt-yE-Kxs" firstAttribute="centerX" secondItem="m2S-Jp-Qdl" secondAttribute="centerX" id="5VR-xY-wnb"/>
+                            <constraint firstItem="WJ0-jc-iHF" firstAttribute="width" secondItem="Tpt-yE-Kxs" secondAttribute="width" id="D8Y-dz-49I"/>
+                            <constraint firstItem="WJ0-jc-iHF" firstAttribute="centerX" secondItem="m2S-Jp-Qdl" secondAttribute="centerX" id="JU0-Jj-C3V"/>
+                            <constraint firstItem="Tpt-yE-Kxs" firstAttribute="top" secondItem="m2S-Jp-Qdl" secondAttribute="top" constant="20" id="S4l-qN-Exl"/>
+                            <constraint firstAttribute="bottom" secondItem="uTJ-gO-vuq" secondAttribute="bottom" constant="20" id="nMr-Bp-fX1"/>
+                            <constraint firstItem="WJ0-jc-iHF" firstAttribute="top" secondItem="zjN-xL-Eye" secondAttribute="bottom" constant="10" id="vfh-s0-o41"/>
+                        </constraints>
+                    </view>
+                </viewController>
+                <customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="75" y="779"/>
+        </scene>
+    </scenes>
+    <resources>
+        <image name="openwhiskLogo" width="300" height="192"/>
+    </resources>
+</document>
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/Info.plist b/xcode-playgrounds-extension/OWXcodeExtension/Info.plist
new file mode 100644
index 0000000..4b8f3e8
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/Info.plist
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIconFile</key>
+	<string></string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>LSMinimumSystemVersion</key>
+	<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
+	<key>NSHumanReadableCopyright</key>
+	<string>Copyright © 2017 Avery Lamp. All rights reserved.</string>
+	<key>NSMainStoryboardFile</key>
+	<string>Main</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+</dict>
+</plist>
diff --git a/xcode-playgrounds-extension/OWXcodeExtension/ViewController.swift b/xcode-playgrounds-extension/OWXcodeExtension/ViewController.swift
new file mode 100644
index 0000000..6d44c35
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtension/ViewController.swift
@@ -0,0 +1,31 @@
+//
+//  ViewController.swift
+//  OWXcodeExtension
+//
+//  Created by whisk on 1/30/17.
+//  Copyright © 2017 Avery Lamp. All rights reserved.
+//
+
+import Cocoa
+
+class ViewController: NSViewController {
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+
+        // Do any additional setup after loading the view.
+    }
+    @IBAction func instructionsClicked(_ sender: Any) {
+        let url = URL(string: "https://github.ibm.com/Avery-Lamp/openwhisk-xcode")
+        NSWorkspace.shared().open(url!)
+    }
+
+    override var representedObject: Any? {
+        didSet {
+        // Update the view, if already loaded.
+        }
+    }
+
+
+}
+
diff --git a/xcode-playgrounds-extension/OWXcodeExtensionTests/Info.plist b/xcode-playgrounds-extension/OWXcodeExtensionTests/Info.plist
new file mode 100644
index 0000000..6c6c23c
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtensionTests/Info.plist
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>BNDL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+</dict>
+</plist>
diff --git a/xcode-playgrounds-extension/OWXcodeExtensionTests/OWXcodeExtensionTests.swift b/xcode-playgrounds-extension/OWXcodeExtensionTests/OWXcodeExtensionTests.swift
new file mode 100644
index 0000000..23ce593
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtensionTests/OWXcodeExtensionTests.swift
@@ -0,0 +1,36 @@
+//
+//  OWXcodeExtensionTests.swift
+//  OWXcodeExtensionTests
+//
+//  Created by whisk on 1/30/17.
+//  Copyright © 2017 Avery Lamp. All rights reserved.
+//
+
+import XCTest
+@testable import OWXcodeExtension
+
+class OWXcodeExtensionTests: XCTestCase {
+    
+    override func setUp() {
+        super.setUp()
+        // Put setup code here. This method is called before the invocation of each test method in the class.
+    }
+    
+    override func tearDown() {
+        // Put teardown code here. This method is called after the invocation of each test method in the class.
+        super.tearDown()
+    }
+    
+    func testExample() {
+        // This is an example of a functional test case.
+        // Use XCTAssert and related functions to verify your tests produce the correct results.
+    }
+    
+    func testPerformanceExample() {
+        // This is an example of a performance test case.
+        self.measure {
+            // Put the code you want to measure the time of here.
+        }
+    }
+    
+}
diff --git a/xcode-playgrounds-extension/OWXcodeExtensionUITests/Info.plist b/xcode-playgrounds-extension/OWXcodeExtensionUITests/Info.plist
new file mode 100644
index 0000000..6c6c23c
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtensionUITests/Info.plist
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>BNDL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+</dict>
+</plist>
diff --git a/xcode-playgrounds-extension/OWXcodeExtensionUITests/OWXcodeExtensionUITests.swift b/xcode-playgrounds-extension/OWXcodeExtensionUITests/OWXcodeExtensionUITests.swift
new file mode 100644
index 0000000..ad9bbe0
--- /dev/null
+++ b/xcode-playgrounds-extension/OWXcodeExtensionUITests/OWXcodeExtensionUITests.swift
@@ -0,0 +1,36 @@
+//
+//  OWXcodeExtensionUITests.swift
+//  OWXcodeExtensionUITests
+//
+//  Created by whisk on 1/30/17.
+//  Copyright © 2017 Avery Lamp. All rights reserved.
+//
+
+import XCTest
+
+class OWXcodeExtensionUITests: XCTestCase {
+        
+    override func setUp() {
+        super.setUp()
+        
+        // Put setup code here. This method is called before the invocation of each test method in the class.
+        
+        // In UI tests it is usually best to stop immediately when a failure occurs.
+        continueAfterFailure = false
+        // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
+        XCUIApplication().launch()
+
+        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
+    }
+    
+    override func tearDown() {
+        // Put teardown code here. This method is called after the invocation of each test method in the class.
+        super.tearDown()
+    }
+    
+    func testExample() {
+        // Use recording to get started writing UI tests.
+        // Use XCTAssert and related functions to verify your tests produce the correct results.
+    }
+    
+}
diff --git a/xcode-playgrounds-extension/README.md b/xcode-playgrounds-extension/README.md
new file mode 100644
index 0000000..4576720
--- /dev/null
+++ b/xcode-playgrounds-extension/README.md
@@ -0,0 +1,42 @@
+# OpenWhisk Xcode Extension
+> An Xcode Extension to run Swift OpenWhisk Functions in Playgrounds
+
+
+## Installation
+
+## Usage Example
+
+To invoke the extension, simply select the function header then run the extension.
+
+![Highlighting function](/Readme_Images/SelectFunction.png)
+
+The extension can be found in the Editor Menu, under OWPlaygrounds.  
+![Run Extension from Editor menu](/Readme_Images/RunExtension.png)
+
+The first time the extension is run, it will create documentation for the function to populate the test.  
+
+#### Parameters
+To input test values into the playground, the format `- paramName : description of parameter (optional) : param value for playground ` is used.  
+The parser looks only for `- paramName : : value`.  The description is not necessary, but the colons (:) seperating the paramName : Description : and test value are.  
+
+![Placeholders parameter example](/Readme_Images/DocumentationPlaceholders.png)
+
+If the extension does not find all of the  paramaters that are used in the function inside the documentation, it will recreate the documentation header.  
+
+#### Expected Output (Optional)
+
+The expected output part of the documentation is optional. The playground can be used as a unit tester if a value is provided inside the expected output.  To provide a value, type any valid json after the `--`.  If the json can be parsed, it will input it into the playground and check with the results recieved after running the function with the specified parameter values.
+
+`Note -`  The ` - Returns:` documentation line is not read by the extension and has no impact on the playgrounds.  It is created for personal documentation use.
+
+## Running the Playground
+
+The second time the extension is run, it check the function for all of the parameters used with `args["param"]`.  If it finds all of the parameters used in the function inside the documentation header, it will then attempt to open the OpenWhisk Playgrounds app, which spins up a server for testing functions.  
+
+When looking to open up the playground, the extension looks for an app called `openwhisk-playground-osx.app`.  If you do not have the playground app, you will need to install it (instructions in [Installation](https://github.ibm.com/Avery-Lamp/openwhisk-xcode#installation) above).  The playground app will run the server for testing functions in the background, while the extension will open up http://localhost:6018 with the correct parameters to test the function.
+
+## Tips and Tricks
+
+One way to easily improve the speed of invoking the extension is to create a shortcut for it.  To do this, open Xcode Preferences -> Key Bindings, then search for OWPlaygrounds.  You can create your own shortcut to invoke the action.
+
+
diff --git a/xcode-playgrounds-extension/Readme_Images/DocumentationPlaceholders.png b/xcode-playgrounds-extension/Readme_Images/DocumentationPlaceholders.png
new file mode 100644
index 0000000..82db062
--- /dev/null
+++ b/xcode-playgrounds-extension/Readme_Images/DocumentationPlaceholders.png
Binary files differ
diff --git a/xcode-playgrounds-extension/Readme_Images/RunExtension.png b/xcode-playgrounds-extension/Readme_Images/RunExtension.png
new file mode 100644
index 0000000..6f83988
--- /dev/null
+++ b/xcode-playgrounds-extension/Readme_Images/RunExtension.png
Binary files differ
diff --git a/xcode-playgrounds-extension/Readme_Images/SelectFunction.png b/xcode-playgrounds-extension/Readme_Images/SelectFunction.png
new file mode 100644
index 0000000..3c543cd
--- /dev/null
+++ b/xcode-playgrounds-extension/Readme_Images/SelectFunction.png
Binary files differ