├── README.md ├── passage.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── swiftpm │ │ └── Package.resolved └── project.pbxproj ├── LICENSE ├── .gitignore └── passage ├── Prompt.swift ├── main.swift └── PromptExecutor.swift /README.md: -------------------------------------------------------------------------------- 1 | # Passage 2 | -------------------------------------------------------------------------------- /passage.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /passage.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "originHash" : "b473f03a46d97c888cde0764ad3582d8bba7a93d94d06028851a2d553c1e8899", 3 | "pins" : [ 4 | { 5 | "identity" : "swift-argument-parser", 6 | "kind" : "remoteSourceControl", 7 | "location" : "https://github.com/apple/swift-argument-parser.git", 8 | "state" : { 9 | "revision" : "41982a3656a71c768319979febd796c6fd111d5c", 10 | "version" : "1.5.0" 11 | } 12 | }, 13 | { 14 | "identity" : "yams", 15 | "kind" : "remoteSourceControl", 16 | "location" : "https://github.com/jpsim/Yams", 17 | "state" : { 18 | "revision" : "b4b8042411dc7bbb696300a34a4bf3ba1b7ad19b", 19 | "version" : "5.3.1" 20 | } 21 | } 22 | ], 23 | "version" : 3 24 | } 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Tyler Hall 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## User settings 6 | xcuserdata/ 7 | 8 | ## Obj-C/Swift specific 9 | *.hmap 10 | 11 | ## App packaging 12 | *.ipa 13 | *.dSYM.zip 14 | *.dSYM 15 | 16 | ## Playgrounds 17 | timeline.xctimeline 18 | playground.xcworkspace 19 | 20 | # Swift Package Manager 21 | # 22 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 23 | # Packages/ 24 | # Package.pins 25 | # Package.resolved 26 | # *.xcodeproj 27 | # 28 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 29 | # hence it is not needed unless you have added a package configuration file to your project 30 | # .swiftpm 31 | 32 | .build/ 33 | 34 | # CocoaPods 35 | # 36 | # We recommend against adding the Pods directory to your .gitignore. However 37 | # you should judge for yourself, the pros and cons are mentioned at: 38 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 39 | # 40 | # Pods/ 41 | # 42 | # Add this line if you want to avoid checking in source code from the Xcode workspace 43 | # *.xcworkspace 44 | 45 | # Carthage 46 | # 47 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 48 | # Carthage/Checkouts 49 | 50 | Carthage/Build/ 51 | 52 | # fastlane 53 | # 54 | # It is recommended to not store the screenshots in the git repo. 55 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 56 | # For more information about the recommended setup visit: 57 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 58 | 59 | fastlane/report.xml 60 | fastlane/Preview.html 61 | fastlane/screenshots/**/*.png 62 | fastlane/test_output 63 | .DS_Store 64 | -------------------------------------------------------------------------------- /passage/Prompt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Prompt.swift 3 | // Passage 4 | // 5 | // Created by Tyler Hall on 2/14/25. 6 | // 7 | 8 | import Foundation 9 | import Yams 10 | 11 | struct Prompt: Codable { 12 | var name: String? 13 | var apiBaseURL: String? 14 | var apiToken: String? 15 | var model: String? 16 | var outputs: [Output] 17 | var text: String = "" 18 | 19 | enum CodingKeys: String, CodingKey { 20 | case name 21 | case model 22 | case outputs 23 | } 24 | 25 | enum OutputType: String, Codable { 26 | case stdout 27 | case variable 28 | case file 29 | } 30 | 31 | enum OutputMethod: String, Codable { 32 | case replace 33 | case append 34 | case prepend 35 | } 36 | 37 | struct Output: Codable { 38 | var type: OutputType 39 | var name: String? 40 | var method: OutputMethod? 41 | } 42 | 43 | init?(fileURL: URL) { 44 | do { 45 | let str = try String(contentsOf: fileURL, encoding: .utf8) 46 | let lines = str.components(separatedBy: .newlines) 47 | 48 | var parsingHeader = true 49 | var headerArr = [String]() 50 | var textArr = [String]() 51 | 52 | for line in lines { 53 | if parsingHeader { 54 | if line.hasPrefix("---") { 55 | parsingHeader = false 56 | } else { 57 | headerArr.append(line) 58 | } 59 | } else { 60 | textArr.append(line) 61 | } 62 | } 63 | 64 | guard let yamlData = headerArr.joined(separator: "\n").data(using: .utf8) else { return nil } 65 | let yaml = try YAMLDecoder().decode(Prompt.self, from: yamlData) 66 | self = yaml 67 | 68 | text = textArr.joined(separator: "\n") 69 | } catch { 70 | print(error) 71 | return nil 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /passage/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // Passage 4 | // 5 | // Created by Tyler Hall on 2/14/25. 6 | // 7 | 8 | import Foundation 9 | import ArgumentParser 10 | 11 | struct Passage: ParsableCommand { 12 | 13 | @Argument(help: "Path to the folder of text prompts") 14 | var promptsFolder: String 15 | 16 | @Option(name: .shortAndLong, help: "Path to initial text input") 17 | var inputFile: String? 18 | 19 | @Option(name: .shortAndLong, help: "Path to output folder") 20 | var outputFolder: String? 21 | 22 | func run() throws { 23 | var initialInput: String 24 | if let inputFile = inputFile { 25 | guard let str = try? String(contentsOfFile: inputFile, encoding: .utf8) else { 26 | print("Could not read input file at", inputFile) 27 | Passage.exit() 28 | } 29 | initialInput = str 30 | } else { 31 | let stdin = FileHandle.standardInput.readDataToEndOfFile() 32 | guard let str = String(data: stdin, encoding: .utf8) else { 33 | print("Could not read stdin") 34 | Passage.exit() 35 | } 36 | initialInput = str 37 | } 38 | 39 | var prompts = [Prompt]() 40 | let urls = try textFiles(in: promptsFolder) 41 | for url in urls { 42 | if let prompt = Prompt(fileURL: url) { 43 | prompts.append(prompt) 44 | } 45 | } 46 | 47 | let executor = PromptExecutor(initialInput: initialInput, prompts: prompts, ouputFolder: outputFolder) 48 | executor.runPrompts() 49 | } 50 | 51 | private func textFiles(in folderPath: String) throws -> [URL] { 52 | let textFileExtensions = ["txt", "md", "mdown", "markdown", "yml", "yaml"] 53 | let fileManager = FileManager.default 54 | let enumerator = fileManager.enumerator(atPath: folderPath) 55 | var urls: [URL] = [] 56 | 57 | while let element = enumerator?.nextObject() as? String { 58 | let url = URL(fileURLWithPath: folderPath).appendingPathComponent(element) 59 | let ext = url.pathExtension.lowercased() 60 | if textFileExtensions.contains(ext) { 61 | urls.append(url) 62 | } 63 | } 64 | 65 | return urls.sorted { $0.path < $1.path } 66 | } 67 | } 68 | 69 | Passage.main() 70 | -------------------------------------------------------------------------------- /passage/PromptExecutor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PromptExecutor.swift 3 | // Passage 4 | // 5 | // Created by Tyler Hall on 2/14/25. 6 | // 7 | 8 | import Foundation 9 | 10 | class PromptExecutor { 11 | 12 | private let defaultAPIBaseURLStr = "http://127.0.0.1:1234/v1" 13 | private let defaultAPIKey = "12345" 14 | 15 | private var initialInput: String 16 | private var prompts: [Prompt] 17 | private var memory: [String: String] = [:] 18 | private var outputFolder: String? 19 | 20 | init(initialInput: String, prompts: [Prompt], ouputFolder: String? = nil) { 21 | self.initialInput = initialInput 22 | self.prompts = prompts 23 | self.outputFolder = ouputFolder 24 | } 25 | 26 | func runPrompts() { 27 | for prompt in prompts { 28 | var message = prompt.text.replacingOccurrences(of: "{{input}}", with: initialInput) 29 | for (key, val) in memory { 30 | let needle = "{{\(key)}}" 31 | message = message.replacingOccurrences(of: needle, with: val) 32 | } 33 | 34 | var response: String 35 | if let model = prompt.model { 36 | response = synchronousLLMRequest(message: message, prompt: prompt, model: model) 37 | } else { // If no model, passthrough 38 | response = message 39 | } 40 | 41 | for output in prompt.outputs { 42 | switch output.type { 43 | case .stdout: 44 | print(response) 45 | case .variable: 46 | if let name = output.name, let method = output.method { 47 | switch method { 48 | case .replace: 49 | memory[name] = response 50 | case .append: 51 | memory[name] = (memory[name] == nil) ? response : (memory[name]! + "\n" + response) 52 | case .prepend: 53 | memory[name] = (memory[name] == nil) ? response : (response + "\n" + memory[name]!) 54 | } 55 | } 56 | case .file: 57 | if let filename = output.name, let method = output.method { 58 | switch method { 59 | case .replace: 60 | writeToFile(filename: filename, content: response) 61 | case .append: 62 | appendToFile(filename: filename, content: response) 63 | case .prepend: 64 | prependToFile(filename: filename, content: response) 65 | } 66 | } 67 | } 68 | } 69 | } 70 | } 71 | 72 | private func synchronousLLMRequest(message: String, prompt: Prompt, model: String) -> String { 73 | let apiBaseURLStr = prompt.apiBaseURL ?? defaultAPIBaseURLStr 74 | let apiKey = prompt.apiToken ?? defaultAPIKey 75 | 76 | guard let url = URL(string: "\(apiBaseURLStr)/chat/completions") else { 77 | print("Invalid apiBaseURL: \(apiBaseURLStr)") 78 | exit(EXIT_FAILURE) 79 | } 80 | 81 | var request = URLRequest(url: url) 82 | request.httpMethod = "POST" 83 | request.addValue("application/json", forHTTPHeaderField: "Content-Type") 84 | request.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") 85 | 86 | let payload: [String: Any] = [ 87 | "model": model, 88 | "messages": [ 89 | ["role": "user", "content": message] 90 | ] 91 | ] 92 | 93 | do { 94 | request.httpBody = try JSONSerialization.data(withJSONObject: payload, options: []) 95 | } catch { 96 | print("Failed to parse JSON response", error) 97 | exit(EXIT_FAILURE) 98 | } 99 | 100 | let semaphore = DispatchSemaphore(value: 0) 101 | var result = "" 102 | 103 | let config = URLSessionConfiguration.default 104 | config.timeoutIntervalForRequest = TimeInterval.infinity 105 | config.timeoutIntervalForResource = TimeInterval.infinity 106 | let session = URLSession(configuration: config) 107 | 108 | let task = session.dataTask(with: request) { data, response, error in 109 | defer { semaphore.signal() } 110 | 111 | if let error = error { 112 | print("Request error:", error) 113 | exit(EXIT_FAILURE) 114 | } 115 | 116 | guard let data = data else { 117 | print("No response data") 118 | exit(EXIT_FAILURE) 119 | } 120 | 121 | do { 122 | if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], 123 | let choices = json["choices"] as? [[String: Any]], 124 | let message = choices.first?["message"] as? [String: Any], 125 | let content = message["content"] as? String { 126 | result = content.trimmingCharacters(in: .whitespacesAndNewlines) 127 | } else { 128 | print("Unexpected response format", error ?? "") 129 | exit(EXIT_FAILURE) 130 | } 131 | } catch { 132 | print("Failed to parse response:", error) 133 | exit(EXIT_FAILURE) 134 | } 135 | } 136 | 137 | task.resume() 138 | semaphore.wait() 139 | 140 | return result 141 | } 142 | 143 | private func writeToFile(filename: String, content: String) { 144 | let folderPath = outputFolder ?? FileManager.default.currentDirectoryPath 145 | let fileURL = URL(filePath: folderPath).appending(path: filename, directoryHint: .notDirectory) 146 | do { 147 | try content.write(to: fileURL, atomically: true, encoding: .utf8) 148 | } catch { 149 | print("Failed to write output to", fileURL.path) 150 | exit(EXIT_FAILURE) 151 | } 152 | } 153 | 154 | private func appendToFile(filename: String, content: String) { 155 | let folderPath = outputFolder ?? FileManager.default.currentDirectoryPath 156 | let fileURL = URL(filePath: folderPath).appending(path: filename, directoryHint: .notDirectory) 157 | 158 | var newContents: String 159 | if let existingFileContents = try? String(contentsOf: fileURL, encoding: .utf8) { 160 | newContents = existingFileContents + "\n" + content 161 | } else { 162 | newContents = content 163 | } 164 | writeToFile(filename: filename, content: newContents) 165 | } 166 | 167 | private func prependToFile(filename: String, content: String) { 168 | let folderPath = outputFolder ?? FileManager.default.currentDirectoryPath 169 | let fileURL = URL(filePath: folderPath).appending(path: filename, directoryHint: .notDirectory) 170 | 171 | var newContents: String 172 | if let existingFileContents = try? String(contentsOf: fileURL, encoding: .utf8) { 173 | newContents = content + "\n" + existingFileContents 174 | } else { 175 | newContents = content 176 | } 177 | writeToFile(filename: filename, content: newContents) 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /passage.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 77; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | BAD8129A2DA83D6E0059983F /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = BAD812992DA83D6E0059983F /* ArgumentParser */; }; 11 | C6EF60452DAB685F008FFBD7 /* Yams in Frameworks */ = {isa = PBXBuildFile; productRef = C6EF60442DAB685F008FFBD7 /* Yams */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXCopyFilesBuildPhase section */ 15 | BAD8128C2DA83C240059983F /* CopyFiles */ = { 16 | isa = PBXCopyFilesBuildPhase; 17 | buildActionMask = 2147483647; 18 | dstPath = /usr/share/man/man1/; 19 | dstSubfolderSpec = 0; 20 | files = ( 21 | ); 22 | runOnlyForDeploymentPostprocessing = 1; 23 | }; 24 | /* End PBXCopyFilesBuildPhase section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | BAD8128E2DA83C240059983F /* passage */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = passage; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFileSystemSynchronizedRootGroup section */ 31 | BAD812902DA83C240059983F /* passage */ = { 32 | isa = PBXFileSystemSynchronizedRootGroup; 33 | path = passage; 34 | sourceTree = ""; 35 | }; 36 | /* End PBXFileSystemSynchronizedRootGroup section */ 37 | 38 | /* Begin PBXFrameworksBuildPhase section */ 39 | BAD8128B2DA83C240059983F /* Frameworks */ = { 40 | isa = PBXFrameworksBuildPhase; 41 | buildActionMask = 2147483647; 42 | files = ( 43 | C6EF60452DAB685F008FFBD7 /* Yams in Frameworks */, 44 | BAD8129A2DA83D6E0059983F /* ArgumentParser in Frameworks */, 45 | ); 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXFrameworksBuildPhase section */ 49 | 50 | /* Begin PBXGroup section */ 51 | BAD812852DA83C240059983F = { 52 | isa = PBXGroup; 53 | children = ( 54 | BAD812902DA83C240059983F /* passage */, 55 | BAD8128F2DA83C240059983F /* Products */, 56 | ); 57 | sourceTree = ""; 58 | }; 59 | BAD8128F2DA83C240059983F /* Products */ = { 60 | isa = PBXGroup; 61 | children = ( 62 | BAD8128E2DA83C240059983F /* passage */, 63 | ); 64 | name = Products; 65 | sourceTree = ""; 66 | }; 67 | /* End PBXGroup section */ 68 | 69 | /* Begin PBXNativeTarget section */ 70 | BAD8128D2DA83C240059983F /* passage */ = { 71 | isa = PBXNativeTarget; 72 | buildConfigurationList = BAD812952DA83C240059983F /* Build configuration list for PBXNativeTarget "passage" */; 73 | buildPhases = ( 74 | BAD8128A2DA83C240059983F /* Sources */, 75 | BAD8128B2DA83C240059983F /* Frameworks */, 76 | BAD8128C2DA83C240059983F /* CopyFiles */, 77 | ); 78 | buildRules = ( 79 | ); 80 | dependencies = ( 81 | ); 82 | fileSystemSynchronizedGroups = ( 83 | BAD812902DA83C240059983F /* passage */, 84 | ); 85 | name = passage; 86 | packageProductDependencies = ( 87 | BAD812992DA83D6E0059983F /* ArgumentParser */, 88 | C6EF60442DAB685F008FFBD7 /* Yams */, 89 | ); 90 | productName = prompter; 91 | productReference = BAD8128E2DA83C240059983F /* passage */; 92 | productType = "com.apple.product-type.tool"; 93 | }; 94 | /* End PBXNativeTarget section */ 95 | 96 | /* Begin PBXProject section */ 97 | BAD812862DA83C240059983F /* Project object */ = { 98 | isa = PBXProject; 99 | attributes = { 100 | BuildIndependentTargetsInParallel = 1; 101 | LastSwiftUpdateCheck = 1630; 102 | LastUpgradeCheck = 1630; 103 | TargetAttributes = { 104 | BAD8128D2DA83C240059983F = { 105 | CreatedOnToolsVersion = 16.3; 106 | }; 107 | }; 108 | }; 109 | buildConfigurationList = BAD812892DA83C240059983F /* Build configuration list for PBXProject "passage" */; 110 | developmentRegion = en; 111 | hasScannedForEncodings = 0; 112 | knownRegions = ( 113 | en, 114 | Base, 115 | ); 116 | mainGroup = BAD812852DA83C240059983F; 117 | minimizedProjectReferenceProxies = 1; 118 | packageReferences = ( 119 | BAD812982DA83D6E0059983F /* XCRemoteSwiftPackageReference "swift-argument-parser" */, 120 | C6EF60432DAB685F008FFBD7 /* XCRemoteSwiftPackageReference "Yams" */, 121 | ); 122 | preferredProjectObjectVersion = 77; 123 | productRefGroup = BAD8128F2DA83C240059983F /* Products */; 124 | projectDirPath = ""; 125 | projectRoot = ""; 126 | targets = ( 127 | BAD8128D2DA83C240059983F /* passage */, 128 | ); 129 | }; 130 | /* End PBXProject section */ 131 | 132 | /* Begin PBXSourcesBuildPhase section */ 133 | BAD8128A2DA83C240059983F /* Sources */ = { 134 | isa = PBXSourcesBuildPhase; 135 | buildActionMask = 2147483647; 136 | files = ( 137 | ); 138 | runOnlyForDeploymentPostprocessing = 0; 139 | }; 140 | /* End PBXSourcesBuildPhase section */ 141 | 142 | /* Begin XCBuildConfiguration section */ 143 | BAD812932DA83C240059983F /* Debug */ = { 144 | isa = XCBuildConfiguration; 145 | buildSettings = { 146 | ALWAYS_SEARCH_USER_PATHS = NO; 147 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 148 | CLANG_ANALYZER_NONNULL = YES; 149 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 150 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 151 | CLANG_ENABLE_MODULES = YES; 152 | CLANG_ENABLE_OBJC_ARC = YES; 153 | CLANG_ENABLE_OBJC_WEAK = YES; 154 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 155 | CLANG_WARN_BOOL_CONVERSION = YES; 156 | CLANG_WARN_COMMA = YES; 157 | CLANG_WARN_CONSTANT_CONVERSION = YES; 158 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 159 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 160 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 161 | CLANG_WARN_EMPTY_BODY = YES; 162 | CLANG_WARN_ENUM_CONVERSION = YES; 163 | CLANG_WARN_INFINITE_RECURSION = YES; 164 | CLANG_WARN_INT_CONVERSION = YES; 165 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 166 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 167 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 168 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 169 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 170 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 171 | CLANG_WARN_STRICT_PROTOTYPES = YES; 172 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 173 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 174 | CLANG_WARN_UNREACHABLE_CODE = YES; 175 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 176 | COPY_PHASE_STRIP = NO; 177 | DEBUG_INFORMATION_FORMAT = dwarf; 178 | ENABLE_STRICT_OBJC_MSGSEND = YES; 179 | ENABLE_TESTABILITY = YES; 180 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 181 | GCC_C_LANGUAGE_STANDARD = gnu17; 182 | GCC_DYNAMIC_NO_PIC = NO; 183 | GCC_NO_COMMON_BLOCKS = YES; 184 | GCC_OPTIMIZATION_LEVEL = 0; 185 | GCC_PREPROCESSOR_DEFINITIONS = ( 186 | "DEBUG=1", 187 | "$(inherited)", 188 | ); 189 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 190 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 191 | GCC_WARN_UNDECLARED_SELECTOR = YES; 192 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 193 | GCC_WARN_UNUSED_FUNCTION = YES; 194 | GCC_WARN_UNUSED_VARIABLE = YES; 195 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 196 | MACOSX_DEPLOYMENT_TARGET = 15.4; 197 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 198 | MTL_FAST_MATH = YES; 199 | ONLY_ACTIVE_ARCH = YES; 200 | SDKROOT = macosx; 201 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; 202 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 203 | }; 204 | name = Debug; 205 | }; 206 | BAD812942DA83C240059983F /* Release */ = { 207 | isa = XCBuildConfiguration; 208 | buildSettings = { 209 | ALWAYS_SEARCH_USER_PATHS = NO; 210 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 211 | CLANG_ANALYZER_NONNULL = YES; 212 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 213 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 214 | CLANG_ENABLE_MODULES = YES; 215 | CLANG_ENABLE_OBJC_ARC = YES; 216 | CLANG_ENABLE_OBJC_WEAK = YES; 217 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 218 | CLANG_WARN_BOOL_CONVERSION = YES; 219 | CLANG_WARN_COMMA = YES; 220 | CLANG_WARN_CONSTANT_CONVERSION = YES; 221 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 222 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 223 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 224 | CLANG_WARN_EMPTY_BODY = YES; 225 | CLANG_WARN_ENUM_CONVERSION = YES; 226 | CLANG_WARN_INFINITE_RECURSION = YES; 227 | CLANG_WARN_INT_CONVERSION = YES; 228 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 229 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 230 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 231 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 232 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 233 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 234 | CLANG_WARN_STRICT_PROTOTYPES = YES; 235 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 236 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 237 | CLANG_WARN_UNREACHABLE_CODE = YES; 238 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 239 | COPY_PHASE_STRIP = NO; 240 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 241 | ENABLE_NS_ASSERTIONS = NO; 242 | ENABLE_STRICT_OBJC_MSGSEND = YES; 243 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 244 | GCC_C_LANGUAGE_STANDARD = gnu17; 245 | GCC_NO_COMMON_BLOCKS = YES; 246 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 247 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 248 | GCC_WARN_UNDECLARED_SELECTOR = YES; 249 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 250 | GCC_WARN_UNUSED_FUNCTION = YES; 251 | GCC_WARN_UNUSED_VARIABLE = YES; 252 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 253 | MACOSX_DEPLOYMENT_TARGET = 15.4; 254 | MTL_ENABLE_DEBUG_INFO = NO; 255 | MTL_FAST_MATH = YES; 256 | SDKROOT = macosx; 257 | SWIFT_COMPILATION_MODE = wholemodule; 258 | }; 259 | name = Release; 260 | }; 261 | BAD812962DA83C240059983F /* Debug */ = { 262 | isa = XCBuildConfiguration; 263 | buildSettings = { 264 | CODE_SIGN_STYLE = Automatic; 265 | MACOSX_DEPLOYMENT_TARGET = 14.6; 266 | PRODUCT_NAME = "$(TARGET_NAME)"; 267 | SWIFT_VERSION = 5.0; 268 | }; 269 | name = Debug; 270 | }; 271 | BAD812972DA83C240059983F /* Release */ = { 272 | isa = XCBuildConfiguration; 273 | buildSettings = { 274 | CODE_SIGN_STYLE = Automatic; 275 | MACOSX_DEPLOYMENT_TARGET = 14.6; 276 | PRODUCT_NAME = "$(TARGET_NAME)"; 277 | SWIFT_VERSION = 5.0; 278 | }; 279 | name = Release; 280 | }; 281 | /* End XCBuildConfiguration section */ 282 | 283 | /* Begin XCConfigurationList section */ 284 | BAD812892DA83C240059983F /* Build configuration list for PBXProject "passage" */ = { 285 | isa = XCConfigurationList; 286 | buildConfigurations = ( 287 | BAD812932DA83C240059983F /* Debug */, 288 | BAD812942DA83C240059983F /* Release */, 289 | ); 290 | defaultConfigurationIsVisible = 0; 291 | defaultConfigurationName = Release; 292 | }; 293 | BAD812952DA83C240059983F /* Build configuration list for PBXNativeTarget "passage" */ = { 294 | isa = XCConfigurationList; 295 | buildConfigurations = ( 296 | BAD812962DA83C240059983F /* Debug */, 297 | BAD812972DA83C240059983F /* Release */, 298 | ); 299 | defaultConfigurationIsVisible = 0; 300 | defaultConfigurationName = Release; 301 | }; 302 | /* End XCConfigurationList section */ 303 | 304 | /* Begin XCRemoteSwiftPackageReference section */ 305 | BAD812982DA83D6E0059983F /* XCRemoteSwiftPackageReference "swift-argument-parser" */ = { 306 | isa = XCRemoteSwiftPackageReference; 307 | repositoryURL = "https://github.com/apple/swift-argument-parser.git"; 308 | requirement = { 309 | kind = upToNextMajorVersion; 310 | minimumVersion = 1.5.0; 311 | }; 312 | }; 313 | C6EF60432DAB685F008FFBD7 /* XCRemoteSwiftPackageReference "Yams" */ = { 314 | isa = XCRemoteSwiftPackageReference; 315 | repositoryURL = "https://github.com/jpsim/Yams"; 316 | requirement = { 317 | kind = upToNextMajorVersion; 318 | minimumVersion = 5.3.1; 319 | }; 320 | }; 321 | /* End XCRemoteSwiftPackageReference section */ 322 | 323 | /* Begin XCSwiftPackageProductDependency section */ 324 | BAD812992DA83D6E0059983F /* ArgumentParser */ = { 325 | isa = XCSwiftPackageProductDependency; 326 | package = BAD812982DA83D6E0059983F /* XCRemoteSwiftPackageReference "swift-argument-parser" */; 327 | productName = ArgumentParser; 328 | }; 329 | C6EF60442DAB685F008FFBD7 /* Yams */ = { 330 | isa = XCSwiftPackageProductDependency; 331 | package = C6EF60432DAB685F008FFBD7 /* XCRemoteSwiftPackageReference "Yams" */; 332 | productName = Yams; 333 | }; 334 | /* End XCSwiftPackageProductDependency section */ 335 | }; 336 | rootObject = BAD812862DA83C240059983F /* Project object */; 337 | } 338 | --------------------------------------------------------------------------------