├── .editorconfig ├── .gitattributes ├── .gitignore ├── Safari Private.xcodeproj └── project.pbxproj ├── Safari Private ├── App.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── icon_128x128_Normal.png │ │ ├── icon_128x128_Normal@2x.png │ │ ├── icon_16x16_Normal.png │ │ ├── icon_16x16_Normal@2x.png │ │ ├── icon_256x256_Normal.png │ │ ├── icon_256x256_Normal@2x.png │ │ ├── icon_32x32_Normal.png │ │ ├── icon_32x32_Normal@2x.png │ │ ├── icon_512x512_Normal.png │ │ └── icon_512x512_Normal@2x.png │ └── Contents.json ├── Info.plist ├── Safari_Private.entitlements └── Utilities.swift ├── license └── readme.md /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = tab 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | xcuserdata 2 | project.xcworkspace 3 | -------------------------------------------------------------------------------- /Safari Private.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 60; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E3F868D528B115BB00CD969D /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3F868D428B115BB00CD969D /* App.swift */; }; 11 | E3F868D928B115BC00CD969D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E3F868D828B115BC00CD969D /* Assets.xcassets */; }; 12 | E3F868E528B11F1D00CD969D /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3F868E428B11F1D00CD969D /* Utilities.swift */; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXFileReference section */ 16 | E3F868D128B115BB00CD969D /* Safari Private.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Safari Private.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 17 | E3F868D428B115BB00CD969D /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; }; 18 | E3F868D828B115BC00CD969D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 19 | E3F868DD28B115BC00CD969D /* Safari_Private.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Safari_Private.entitlements; sourceTree = ""; }; 20 | E3F868E328B1162200CD969D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = "Safari Private/Info.plist"; sourceTree = SOURCE_ROOT; }; 21 | E3F868E428B11F1D00CD969D /* Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utilities.swift; sourceTree = ""; }; 22 | /* End PBXFileReference section */ 23 | 24 | /* Begin PBXFrameworksBuildPhase section */ 25 | E3F868CE28B115BB00CD969D /* Frameworks */ = { 26 | isa = PBXFrameworksBuildPhase; 27 | buildActionMask = 2147483647; 28 | files = ( 29 | ); 30 | runOnlyForDeploymentPostprocessing = 0; 31 | }; 32 | /* End PBXFrameworksBuildPhase section */ 33 | 34 | /* Begin PBXGroup section */ 35 | E3F868C828B115BB00CD969D = { 36 | isa = PBXGroup; 37 | children = ( 38 | E3F868D328B115BB00CD969D /* Safari Private */, 39 | E3F868D228B115BB00CD969D /* Products */, 40 | ); 41 | sourceTree = ""; 42 | }; 43 | E3F868D228B115BB00CD969D /* Products */ = { 44 | isa = PBXGroup; 45 | children = ( 46 | E3F868D128B115BB00CD969D /* Safari Private.app */, 47 | ); 48 | name = Products; 49 | sourceTree = ""; 50 | }; 51 | E3F868D328B115BB00CD969D /* Safari Private */ = { 52 | isa = PBXGroup; 53 | children = ( 54 | E3F868D428B115BB00CD969D /* App.swift */, 55 | E3F868E428B11F1D00CD969D /* Utilities.swift */, 56 | E3F868D828B115BC00CD969D /* Assets.xcassets */, 57 | E3F868E328B1162200CD969D /* Info.plist */, 58 | E3F868DD28B115BC00CD969D /* Safari_Private.entitlements */, 59 | ); 60 | path = "Safari Private"; 61 | sourceTree = ""; 62 | }; 63 | /* End PBXGroup section */ 64 | 65 | /* Begin PBXNativeTarget section */ 66 | E3F868D028B115BB00CD969D /* Safari Private */ = { 67 | isa = PBXNativeTarget; 68 | buildConfigurationList = E3F868E028B115BC00CD969D /* Build configuration list for PBXNativeTarget "Safari Private" */; 69 | buildPhases = ( 70 | E3F868CD28B115BB00CD969D /* Sources */, 71 | E3F868CE28B115BB00CD969D /* Frameworks */, 72 | E3F868CF28B115BB00CD969D /* Resources */, 73 | ); 74 | buildRules = ( 75 | ); 76 | dependencies = ( 77 | ); 78 | name = "Safari Private"; 79 | productName = "Safari Private"; 80 | productReference = E3F868D128B115BB00CD969D /* Safari Private.app */; 81 | productType = "com.apple.product-type.application"; 82 | }; 83 | /* End PBXNativeTarget section */ 84 | 85 | /* Begin PBXProject section */ 86 | E3F868C928B115BB00CD969D /* Project object */ = { 87 | isa = PBXProject; 88 | attributes = { 89 | BuildIndependentTargetsInParallel = 1; 90 | LastSwiftUpdateCheck = 1340; 91 | LastUpgradeCheck = 1500; 92 | TargetAttributes = { 93 | E3F868D028B115BB00CD969D = { 94 | CreatedOnToolsVersion = 13.4.1; 95 | }; 96 | }; 97 | }; 98 | buildConfigurationList = E3F868CC28B115BB00CD969D /* Build configuration list for PBXProject "Safari Private" */; 99 | compatibilityVersion = "Xcode 15.0"; 100 | developmentRegion = en; 101 | hasScannedForEncodings = 0; 102 | knownRegions = ( 103 | en, 104 | Base, 105 | ); 106 | mainGroup = E3F868C828B115BB00CD969D; 107 | productRefGroup = E3F868D228B115BB00CD969D /* Products */; 108 | projectDirPath = ""; 109 | projectRoot = ""; 110 | targets = ( 111 | E3F868D028B115BB00CD969D /* Safari Private */, 112 | ); 113 | }; 114 | /* End PBXProject section */ 115 | 116 | /* Begin PBXResourcesBuildPhase section */ 117 | E3F868CF28B115BB00CD969D /* Resources */ = { 118 | isa = PBXResourcesBuildPhase; 119 | buildActionMask = 2147483647; 120 | files = ( 121 | E3F868D928B115BC00CD969D /* Assets.xcassets in Resources */, 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXResourcesBuildPhase section */ 126 | 127 | /* Begin PBXSourcesBuildPhase section */ 128 | E3F868CD28B115BB00CD969D /* Sources */ = { 129 | isa = PBXSourcesBuildPhase; 130 | buildActionMask = 2147483647; 131 | files = ( 132 | E3F868E528B11F1D00CD969D /* Utilities.swift in Sources */, 133 | E3F868D528B115BB00CD969D /* App.swift in Sources */, 134 | ); 135 | runOnlyForDeploymentPostprocessing = 0; 136 | }; 137 | /* End PBXSourcesBuildPhase section */ 138 | 139 | /* Begin XCBuildConfiguration section */ 140 | E3F868DE28B115BC00CD969D /* Debug */ = { 141 | isa = XCBuildConfiguration; 142 | buildSettings = { 143 | ALWAYS_SEARCH_USER_PATHS = NO; 144 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 145 | CLANG_ANALYZER_NONNULL = YES; 146 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 147 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 148 | CLANG_ENABLE_MODULES = YES; 149 | CLANG_ENABLE_OBJC_ARC = YES; 150 | CLANG_ENABLE_OBJC_WEAK = YES; 151 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 152 | CLANG_WARN_BOOL_CONVERSION = YES; 153 | CLANG_WARN_COMMA = YES; 154 | CLANG_WARN_CONSTANT_CONVERSION = YES; 155 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 156 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 157 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 158 | CLANG_WARN_EMPTY_BODY = YES; 159 | CLANG_WARN_ENUM_CONVERSION = YES; 160 | CLANG_WARN_INFINITE_RECURSION = YES; 161 | CLANG_WARN_INT_CONVERSION = YES; 162 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 163 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 164 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 165 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 166 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 167 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 168 | CLANG_WARN_STRICT_PROTOTYPES = YES; 169 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 170 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 171 | CLANG_WARN_UNREACHABLE_CODE = YES; 172 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 173 | COPY_PHASE_STRIP = NO; 174 | DEAD_CODE_STRIPPING = YES; 175 | DEBUG_INFORMATION_FORMAT = dwarf; 176 | ENABLE_STRICT_OBJC_MSGSEND = YES; 177 | ENABLE_TESTABILITY = YES; 178 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 179 | GCC_C_LANGUAGE_STANDARD = gnu11; 180 | GCC_DYNAMIC_NO_PIC = NO; 181 | GCC_NO_COMMON_BLOCKS = YES; 182 | GCC_OPTIMIZATION_LEVEL = 0; 183 | GCC_PREPROCESSOR_DEFINITIONS = ( 184 | "DEBUG=1", 185 | "$(inherited)", 186 | ); 187 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 188 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 189 | GCC_WARN_UNDECLARED_SELECTOR = YES; 190 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 191 | GCC_WARN_UNUSED_FUNCTION = YES; 192 | GCC_WARN_UNUSED_VARIABLE = YES; 193 | MACOSX_DEPLOYMENT_TARGET = 13.5; 194 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 195 | MTL_FAST_MATH = YES; 196 | ONLY_ACTIVE_ARCH = YES; 197 | SDKROOT = macosx; 198 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 199 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 200 | }; 201 | name = Debug; 202 | }; 203 | E3F868DF28B115BC00CD969D /* Release */ = { 204 | isa = XCBuildConfiguration; 205 | buildSettings = { 206 | ALWAYS_SEARCH_USER_PATHS = NO; 207 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 208 | CLANG_ANALYZER_NONNULL = YES; 209 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 210 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 211 | CLANG_ENABLE_MODULES = YES; 212 | CLANG_ENABLE_OBJC_ARC = YES; 213 | CLANG_ENABLE_OBJC_WEAK = YES; 214 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 215 | CLANG_WARN_BOOL_CONVERSION = YES; 216 | CLANG_WARN_COMMA = YES; 217 | CLANG_WARN_CONSTANT_CONVERSION = YES; 218 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 219 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 220 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 221 | CLANG_WARN_EMPTY_BODY = YES; 222 | CLANG_WARN_ENUM_CONVERSION = YES; 223 | CLANG_WARN_INFINITE_RECURSION = YES; 224 | CLANG_WARN_INT_CONVERSION = YES; 225 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 226 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 227 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 228 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 229 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 230 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 231 | CLANG_WARN_STRICT_PROTOTYPES = YES; 232 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 233 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 234 | CLANG_WARN_UNREACHABLE_CODE = YES; 235 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 236 | COPY_PHASE_STRIP = NO; 237 | DEAD_CODE_STRIPPING = YES; 238 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 239 | ENABLE_NS_ASSERTIONS = NO; 240 | ENABLE_STRICT_OBJC_MSGSEND = YES; 241 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 242 | GCC_C_LANGUAGE_STANDARD = gnu11; 243 | GCC_NO_COMMON_BLOCKS = YES; 244 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 245 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 246 | GCC_WARN_UNDECLARED_SELECTOR = YES; 247 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 248 | GCC_WARN_UNUSED_FUNCTION = YES; 249 | GCC_WARN_UNUSED_VARIABLE = YES; 250 | MACOSX_DEPLOYMENT_TARGET = 13.5; 251 | MTL_ENABLE_DEBUG_INFO = NO; 252 | MTL_FAST_MATH = YES; 253 | SDKROOT = macosx; 254 | SWIFT_COMPILATION_MODE = wholemodule; 255 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 256 | }; 257 | name = Release; 258 | }; 259 | E3F868E128B115BC00CD969D /* Debug */ = { 260 | isa = XCBuildConfiguration; 261 | buildSettings = { 262 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 263 | CODE_SIGN_ENTITLEMENTS = "Safari Private/Safari_Private.entitlements"; 264 | CODE_SIGN_IDENTITY = "Apple Development"; 265 | CODE_SIGN_STYLE = Automatic; 266 | COMBINE_HIDPI_IMAGES = YES; 267 | CURRENT_PROJECT_VERSION = 2; 268 | DEAD_CODE_STRIPPING = YES; 269 | DEVELOPMENT_TEAM = YG56YK5RN5; 270 | ENABLE_HARDENED_RUNTIME = YES; 271 | ENABLE_PREVIEWS = YES; 272 | GENERATE_INFOPLIST_FILE = YES; 273 | INFOPLIST_FILE = "Safari Private/Info.plist"; 274 | INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; 275 | INFOPLIST_KEY_NSAppleEventsUsageDescription = tg; 276 | LD_RUNPATH_SEARCH_PATHS = ( 277 | "$(inherited)", 278 | "@executable_path/../Frameworks", 279 | ); 280 | MARKETING_VERSION = 1.1.0; 281 | PRODUCT_BUNDLE_IDENTIFIER = "com.sindresorhus.Safari-Private"; 282 | PRODUCT_NAME = "$(TARGET_NAME)"; 283 | PROVISIONING_PROFILE_SPECIFIER = ""; 284 | SWIFT_EMIT_LOC_STRINGS = YES; 285 | SWIFT_VERSION = 5.0; 286 | }; 287 | name = Debug; 288 | }; 289 | E3F868E228B115BC00CD969D /* Release */ = { 290 | isa = XCBuildConfiguration; 291 | buildSettings = { 292 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 293 | CODE_SIGN_ENTITLEMENTS = "Safari Private/Safari_Private.entitlements"; 294 | CODE_SIGN_IDENTITY = "Apple Development"; 295 | CODE_SIGN_STYLE = Automatic; 296 | COMBINE_HIDPI_IMAGES = YES; 297 | CURRENT_PROJECT_VERSION = 2; 298 | DEAD_CODE_STRIPPING = YES; 299 | DEVELOPMENT_TEAM = YG56YK5RN5; 300 | ENABLE_HARDENED_RUNTIME = YES; 301 | ENABLE_PREVIEWS = YES; 302 | GENERATE_INFOPLIST_FILE = YES; 303 | INFOPLIST_FILE = "Safari Private/Info.plist"; 304 | INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; 305 | INFOPLIST_KEY_NSAppleEventsUsageDescription = tg; 306 | LD_RUNPATH_SEARCH_PATHS = ( 307 | "$(inherited)", 308 | "@executable_path/../Frameworks", 309 | ); 310 | MARKETING_VERSION = 1.1.0; 311 | PRODUCT_BUNDLE_IDENTIFIER = "com.sindresorhus.Safari-Private"; 312 | PRODUCT_NAME = "$(TARGET_NAME)"; 313 | PROVISIONING_PROFILE_SPECIFIER = ""; 314 | SWIFT_EMIT_LOC_STRINGS = YES; 315 | SWIFT_VERSION = 5.0; 316 | }; 317 | name = Release; 318 | }; 319 | /* End XCBuildConfiguration section */ 320 | 321 | /* Begin XCConfigurationList section */ 322 | E3F868CC28B115BB00CD969D /* Build configuration list for PBXProject "Safari Private" */ = { 323 | isa = XCConfigurationList; 324 | buildConfigurations = ( 325 | E3F868DE28B115BC00CD969D /* Debug */, 326 | E3F868DF28B115BC00CD969D /* Release */, 327 | ); 328 | defaultConfigurationIsVisible = 0; 329 | defaultConfigurationName = Release; 330 | }; 331 | E3F868E028B115BC00CD969D /* Build configuration list for PBXNativeTarget "Safari Private" */ = { 332 | isa = XCConfigurationList; 333 | buildConfigurations = ( 334 | E3F868E128B115BC00CD969D /* Debug */, 335 | E3F868E228B115BC00CD969D /* Release */, 336 | ); 337 | defaultConfigurationIsVisible = 0; 338 | defaultConfigurationName = Release; 339 | }; 340 | /* End XCConfigurationList section */ 341 | }; 342 | rootObject = E3F868C928B115BB00CD969D /* Project object */; 343 | } 344 | -------------------------------------------------------------------------------- /Safari Private/App.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | @main 4 | struct AppMain: App { 5 | @NSApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate 6 | 7 | var body: some Scene { 8 | Settings {} 9 | } 10 | } 11 | 12 | private final class AppDelegate: NSObject, NSApplicationDelegate { 13 | private var task: Task? 14 | 15 | func applicationDidFinishLaunching(_ notification: Notification) { 16 | _ = Permissions.Accessibility.requestAccess() 17 | scheduleQuit() 18 | } 19 | 20 | func application(_ application: NSApplication, open urls: [URL]) { 21 | guard Permissions.Accessibility.requestAccess() else { 22 | let alert = NSAlert() 23 | alert.messageText = "You need to allow Accessibility and Automation access in “System Settings › Privacy & Security”." 24 | alert.runModal() 25 | NSApp.terminate(nil) 26 | return 27 | } 28 | 29 | openPrivateSafariWindow(with: urls) 30 | scheduleQuit() 31 | } 32 | 33 | @MainActor 34 | private func scheduleQuit() { 35 | task?.cancel() 36 | 37 | task = Task { 38 | do { 39 | try await Task.sleep(for: .seconds(10)) 40 | NSApp.terminate(nil) 41 | } catch {} 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Safari Private/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icon_16x16_Normal.png", 5 | "idiom" : "mac", 6 | "scale" : "1x", 7 | "size" : "16x16" 8 | }, 9 | { 10 | "filename" : "icon_16x16_Normal@2x.png", 11 | "idiom" : "mac", 12 | "scale" : "2x", 13 | "size" : "16x16" 14 | }, 15 | { 16 | "filename" : "icon_32x32_Normal.png", 17 | "idiom" : "mac", 18 | "scale" : "1x", 19 | "size" : "32x32" 20 | }, 21 | { 22 | "filename" : "icon_32x32_Normal@2x.png", 23 | "idiom" : "mac", 24 | "scale" : "2x", 25 | "size" : "32x32" 26 | }, 27 | { 28 | "filename" : "icon_128x128_Normal.png", 29 | "idiom" : "mac", 30 | "scale" : "1x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "filename" : "icon_128x128_Normal@2x.png", 35 | "idiom" : "mac", 36 | "scale" : "2x", 37 | "size" : "128x128" 38 | }, 39 | { 40 | "filename" : "icon_256x256_Normal.png", 41 | "idiom" : "mac", 42 | "scale" : "1x", 43 | "size" : "256x256" 44 | }, 45 | { 46 | "filename" : "icon_256x256_Normal@2x.png", 47 | "idiom" : "mac", 48 | "scale" : "2x", 49 | "size" : "256x256" 50 | }, 51 | { 52 | "filename" : "icon_512x512_Normal.png", 53 | "idiom" : "mac", 54 | "scale" : "1x", 55 | "size" : "512x512" 56 | }, 57 | { 58 | "filename" : "icon_512x512_Normal@2x.png", 59 | "idiom" : "mac", 60 | "scale" : "2x", 61 | "size" : "512x512" 62 | } 63 | ], 64 | "info" : { 65 | "author" : "xcode", 66 | "version" : 1 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Safari Private/Assets.xcassets/AppIcon.appiconset/icon_128x128_Normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sindresorhus/Safari-Private/80884dee4ecdbcc095f85db476328c90f37959c1/Safari Private/Assets.xcassets/AppIcon.appiconset/icon_128x128_Normal.png -------------------------------------------------------------------------------- /Safari Private/Assets.xcassets/AppIcon.appiconset/icon_128x128_Normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sindresorhus/Safari-Private/80884dee4ecdbcc095f85db476328c90f37959c1/Safari Private/Assets.xcassets/AppIcon.appiconset/icon_128x128_Normal@2x.png -------------------------------------------------------------------------------- /Safari Private/Assets.xcassets/AppIcon.appiconset/icon_16x16_Normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sindresorhus/Safari-Private/80884dee4ecdbcc095f85db476328c90f37959c1/Safari Private/Assets.xcassets/AppIcon.appiconset/icon_16x16_Normal.png -------------------------------------------------------------------------------- /Safari Private/Assets.xcassets/AppIcon.appiconset/icon_16x16_Normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sindresorhus/Safari-Private/80884dee4ecdbcc095f85db476328c90f37959c1/Safari Private/Assets.xcassets/AppIcon.appiconset/icon_16x16_Normal@2x.png -------------------------------------------------------------------------------- /Safari Private/Assets.xcassets/AppIcon.appiconset/icon_256x256_Normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sindresorhus/Safari-Private/80884dee4ecdbcc095f85db476328c90f37959c1/Safari Private/Assets.xcassets/AppIcon.appiconset/icon_256x256_Normal.png -------------------------------------------------------------------------------- /Safari Private/Assets.xcassets/AppIcon.appiconset/icon_256x256_Normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sindresorhus/Safari-Private/80884dee4ecdbcc095f85db476328c90f37959c1/Safari Private/Assets.xcassets/AppIcon.appiconset/icon_256x256_Normal@2x.png -------------------------------------------------------------------------------- /Safari Private/Assets.xcassets/AppIcon.appiconset/icon_32x32_Normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sindresorhus/Safari-Private/80884dee4ecdbcc095f85db476328c90f37959c1/Safari Private/Assets.xcassets/AppIcon.appiconset/icon_32x32_Normal.png -------------------------------------------------------------------------------- /Safari Private/Assets.xcassets/AppIcon.appiconset/icon_32x32_Normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sindresorhus/Safari-Private/80884dee4ecdbcc095f85db476328c90f37959c1/Safari Private/Assets.xcassets/AppIcon.appiconset/icon_32x32_Normal@2x.png -------------------------------------------------------------------------------- /Safari Private/Assets.xcassets/AppIcon.appiconset/icon_512x512_Normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sindresorhus/Safari-Private/80884dee4ecdbcc095f85db476328c90f37959c1/Safari Private/Assets.xcassets/AppIcon.appiconset/icon_512x512_Normal.png -------------------------------------------------------------------------------- /Safari Private/Assets.xcassets/AppIcon.appiconset/icon_512x512_Normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sindresorhus/Safari-Private/80884dee4ecdbcc095f85db476328c90f37959c1/Safari Private/Assets.xcassets/AppIcon.appiconset/icon_512x512_Normal@2x.png -------------------------------------------------------------------------------- /Safari Private/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Safari Private/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDocumentTypes 6 | 7 | 8 | CFBundleTypeName 9 | HTML Document 10 | CFBundleTypeRole 11 | Viewer 12 | LSHandlerRank 13 | Default 14 | LSItemContentTypes 15 | 16 | public.html 17 | public.xhtml 18 | 19 | 20 | 21 | CFBundleURLTypes 22 | 23 | 24 | CFBundleTypeRole 25 | Viewer 26 | CFBundleURLSchemes 27 | 28 | https 29 | http 30 | file 31 | 32 | 33 | 34 | LSUIElement 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /Safari Private/Safari_Private.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.automation.apple-events 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Safari Private/Utilities.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | 4 | func openPrivateSafariWindow(with urls: [URL]) { 5 | runAppleScript( 6 | #""" 7 | tell application "Safari" to activate 8 | 9 | tell application "System Events" to tell its application process "Safari" 10 | set frontmost to true 11 | keystroke "n" using {shift down, command down} 12 | end tell 13 | 14 | tell application "Safari" 15 | delay 0.1 16 | \#(urls.map { #"open location "\#($0.absoluteString)""# }.joined(separator: "\n")) 17 | end tell 18 | """# 19 | ) 20 | } 21 | 22 | 23 | @discardableResult 24 | func runAppleScript(_ source: String) -> String? { 25 | NSAppleScript(source: source)?.executeAndReturnError(nil).stringValue 26 | } 27 | 28 | 29 | enum Permissions { 30 | enum Accessibility { 31 | static var hasAccess: Bool { AXIsProcessTrusted() } 32 | 33 | static func requestAccess() -> Bool { 34 | AXIsProcessTrustedWithOptions([ 35 | kAXTrustedCheckOptionPrompt.takeRetainedValue() as String: true 36 | ] as CFDictionary) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Sindre Sorhus (https://sindresorhus.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Safari Private 2 | 3 | > Open the given URL in a private Safari window 4 | 5 | This is a fake browser that simply opens the given URL in a private Safari window and then quits. 6 | 7 | The use-case is being able to open a URL in a private Safari window from a browser picker app like [Velja](https://sindresorhus.com/velja). 8 | 9 | ## Download 10 | 11 | [**Latest release**](https://github.com/sindresorhus/Safari-Private/releases/latest) 12 | 13 | Requires macOS 13 or later. 14 | 15 | ## Install 16 | 17 | - Download the app and unzip it. 18 | - Move the app into the `/Applications` folder. 19 | - Launch the app once to grant the required permissions. 20 | 21 | ## Usage 22 | 23 | Open a URL with the app like you would with normal Safari. 24 | 25 | For example, enable the “Safari Private” browser in the Velja settings and then select it in the browser prompt when clicking a link. 26 | 27 | ## Related 28 | 29 | - [Copy URL](https://github.com/sindresorhus/Copy-URL) - Adds copy functionality to browser picker apps 30 | 31 | ## Links 32 | 33 | - [My other apps](https://sindresorhus.com/apps) 34 | 35 | ## License 36 | 37 | The code is under MIT license. 38 | 39 | The Safari name and icon is trademarked by Apple. This project is not affiliated with Apple. 40 | --------------------------------------------------------------------------------