Compare commits

...

12 commits
3.1.12 ... main

Author SHA1 Message Date
CelloSerenity
1256c52803
Fix DeepWiki embed
Some checks are pending
Build Debug IPA / Build IPA (push) Waiting to run
Build Debug IPA / Update website source (push) Blocked by required conditions
2026-10-15 11:41:27 -04:00
CelloSerenity
3422fc4725
3.1.15 2026-10-15 10:30:45 -04:00
CelloSerenity
734361bb9d fix: handle legacy and cryptex DDI service discovery 2026-10-14 23:26:00 -04:00
CelloSerenity
cd5e609387
Update README.md 2026-10-12 06:56:38 -06:00
CelloSerenity
e4665d74b5
Update SettingsView.swift 2026-10-12 06:56:17 -06:00
CelloSerenity
300ebff50b
3.1.14 2026-10-11 21:13:08 -06:00
CelloSerenity
775fba15f3
Update AutoScriptAssignments.swift 2026-10-10 17:53:12 -06:00
CelloSerenity
871f1461d9
Update README.md 2026-10-04 14:09:38 -06:00
CelloSerenity
4bdfc92aa7
3.1.13 2026-09-28 08:29:15 -06:00
CelloSerenity
4b3c8d6e88
Rename 'MeloCafe' to 'MeloCafé' 2026-09-28 08:24:29 -06:00
c03abcaa44
Update AutoScriptAssignments.swift 2026-09-28 07:32:03 -04:00
CelloSerenity
d4306e724b
3.1.12 ReadMe 2026-09-27 15:26:08 -06:00
7 changed files with 73 additions and 76 deletions

View file

@ -7,24 +7,17 @@
<p><i>An on-device debugger/JIT enabler for iOS versions 17.4+ powered by <a href="https://github.com/jkcoxson/idevice">idevice</a>.</i></p> <p><i>An on-device debugger/JIT enabler for iOS versions 17.4+ powered by <a href="https://github.com/jkcoxson/idevice">idevice</a>.</i></p>
</div> </div>
<h6 align="center"> <h3 align="center">
<a href="https://discord.gg/ZnNcrRT3M8"> <a href="https://discord.gg/ZnNcrRT3M8"><img src="https://img.shields.io/badge/Discord-join%20us-7289DA?logo=discord&logoColor=white&style=for-the-badge&labelColor=23272A" /></a>&nbsp;
<img src="https://img.shields.io/badge/Discord-join%20us-7289DA?logo=discord&logoColor=white&style=for-the-badge&labelColor=23272A" /> <a href="https://github.com/StikDebug/StikDebug/blob/main/LICENSE"><img src="https://img.shields.io/github/license/StikDebug/StikDebug?label=License&color=5865F2&style=for-the-badge&labelColor=23272A" /></a>&nbsp;
</a> <a href="https://github.com/StikDebug/StikDebug"><img src="https://img.shields.io/github/stars/StikDebug/StikDebug?label=Stars&color=FEE75C&style=for-the-badge&labelColor=23272A" /></a>&nbsp;
<a href="https://github.com/StikDebug/StikDebug/blob/main/LICENSE"> <a href="https://github.com/StikDebug/StikDebug/releases"><img src="https://img.shields.io/github/v/release/StikDebug/StikDebug?label=Latest&color=00BFFF&style=for-the-badge&labelColor=23272A" /></a>&nbsp;
<img src="https://img.shields.io/github/license/StikDebug/StikDebug?label=License&color=5865F2&style=for-the-badge&labelColor=23272A" /> <a href="https://deepwiki.com/StikDebug/StikDebug"><img src="https://img.shields.io/badge/Ask-DeepWiki-grey?style=for-the-badge&labelColor=23272A&color=007ec6" /></a>
</a> <br />
<a href="https://github.com/StikDebug/StikDebug/stargazers"> </h3>
<img src="https://img.shields.io/github/stars/StikDebug/StikDebug?label=Stars&color=FEE75C&style=for-the-badge&labelColor=23272A" />
</a>
<a href="https://github.com/StikDebug/StikDebug/releases">
<img src="https://img.shields.io/github/v/release/StikDebug/StikDebug?label=Latest&color=00BFFF&style=for-the-badge&labelColor=23272A" />
</a>
<br />
</h6>
## Features ## Features
- **JIT:** Enable Just In Time compilation for sideloaded apps that have the `get-task-allow` entitlement. - **JIT:** Enable Just-In-Time compilation for sideloaded apps that have the `get-task-allow` entitlement.
- **App Launching:** Launch every app installed on your device. - **App Launching:** Launch every app installed on your device.
- **Console:** Live app and system logs. - **Console:** Live app and system logs.
- **Scripts:** Manage automation scripts (mainly used for iOS 26 JIT). - **Scripts:** Manage automation scripts (mainly used for iOS 26 JIT).
@ -40,7 +33,7 @@
<h3 align="center"> <h3 align="center">
<a href="https://altdirect.app/?url=https://stikdebug.xyz/index.json" target="_blank"><img src="https://altdirect.app/assets/png/AltSource_Blue.png" alt="Add AltSource" width="200"></a> <a href="https://altdirect.app/?url=https://stikdebug.xyz/index.json" target="_blank"><img src="https://altdirect.app/assets/png/AltSource_Blue.png" alt="Add AltSource" width="200"></a>
&nbsp; &nbsp;
<a href="https://github.com/StikDebug/StikDebug/releases/download/3.1.9/StikDebug-3.1.9.ipa" target="_blank"><img src="https://altdirect.app/assets/png/Download_Blue.png" alt="Download .ipa" width="200"></a> <a href="https://github.com/StikDebug/StikDebug/releases/latest/download/StikDebug-3.1.15.ipa" target="_blank"><img src="https://altdirect.app/assets/png/Download_Blue.png" alt="Download .ipa" width="200"></a>
</h3> </h3>
## Compatibility ## Compatibility
@ -69,12 +62,12 @@ StikDebug enables **JIT** for sideloaded apps on iOS 17.4+ without needing a com
- Launch LocalDevVPN and enable the VPN. - Launch LocalDevVPN and enable the VPN.
4. **Enable JIT for an app** 4. **Enable JIT for an app**
- Launch StikDebug and tapp the `Enable JIT` button. - Launch StikDebug and tap the `Enable JIT` button.
- Select your sideloaded app from the list in StikDebug. - Select your sideloaded app from the list in StikDebug.
**Troubleshooting** **Troubleshooting**
- "Connection dropped" or loopback errors → Check iOS version compatibility / beta warnings. - "Connection dropped" or loopback errors → Check iOS version compatibility / beta warnings.
- Heartbeat errors → Ensure that the VPN is on and that you are connecected to Wi-Fi. It may be a pairing file issue. - Heartbeat errors → Ensure that the VPN is on and that you are connected to Wi-Fi. It may be a pairing file issue.
- Pairing file issues → Replace file with device unlocked & trusted. - Pairing file issues → Replace file with device unlocked & trusted.
- Still stuck? Join the [Discord](https://discord.gg/ZnNcrRT3M8) with logs/screenshots. - Still stuck? Join the [Discord](https://discord.gg/ZnNcrRT3M8) with logs/screenshots.
@ -147,13 +140,11 @@ To propose a new feature, open a feature request issue and provide:
### Code Contributions (Best Practices) ### Code Contributions (Best Practices)
- Follow normal Swift and SwiftUI style. - Follow normal Swift and SwiftUI style.
- Write clear and easy to understand code. - Write clear and easy-to-understand code.
- Keep your changes consistent with how the project is already set up. - Keep your changes consistent with how the project is already set up.
- Make sure everything builds and works without errors. - Make sure everything builds and works without errors.
We appreciate your time and effort in helping improve this project. We appreciate your time and effort in helping improve this project.
## Code Help
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/StikDebug/stikdebug)
## License ## License
StikDebug is licensed under **AGPL-3.0**. See [`LICENSE`](LICENSE) for details. StikDebug is licensed under **AGPL-3.0**. See [`LICENSE`](LICENSE) for details.

View file

@ -482,7 +482,7 @@
"$(PROJECT_DIR)/StikDebug/idevice", "$(PROJECT_DIR)/StikDebug/idevice",
); );
MACOSX_DEPLOYMENT_TARGET = 15.1; MACOSX_DEPLOYMENT_TARGET = 15.1;
MARKETING_VERSION = 3.1.12; MARKETING_VERSION = 3.1.15;
PRODUCT_BUNDLE_IDENTIFIER = com.stik.stikdebug; PRODUCT_BUNDLE_IDENTIFIER = com.stik.stikdebug;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@ -544,7 +544,7 @@
"$(PROJECT_DIR)/StikDebug/idevice", "$(PROJECT_DIR)/StikDebug/idevice",
); );
MACOSX_DEPLOYMENT_TARGET = 15.1; MACOSX_DEPLOYMENT_TARGET = 15.1;
MARKETING_VERSION = 3.1.12; MARKETING_VERSION = 3.1.15;
PRODUCT_BUNDLE_IDENTIFIER = com.stik.stikdebug; PRODUCT_BUNDLE_IDENTIFIER = com.stik.stikdebug;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";

View file

@ -39,7 +39,8 @@ private enum IdeviceBridge {
} }
let code = Int(ffiError.pointee.code) let code = Int(ffiError.pointee.code)
let message = string(from: ffiError.pointee.message) ?? fallback let detail = string(from: ffiError.pointee.message) ?? fallback
let message = detail == fallback ? fallback : "\(fallback): \(detail)"
idevice_error_free(ffiError) idevice_error_free(ffiError)
return makeError(domain: domain, code: code, message: message) return makeError(domain: domain, code: code, message: message)
} }
@ -264,45 +265,50 @@ private enum IdeviceBridge {
extension JITEnableContext { extension JITEnableContext {
func isDeveloperDiskImageMounted() throws -> Bool { func isDeveloperDiskImageMounted() throws -> Bool {
try IdeviceBridge.withTunnelHandles(for: self) { adapter, handshake in try IdeviceBridge.withTunnelHandles(for: self) { adapter, handshake in
var installed: UnsafeMutablePointer<InstalledCryptexC>? var cryptexQuerySucceeded = false
let ffiError = cryptexd_installed_ddi(adapter, handshake, &installed) var cryptexQueryError: NSError?
let queryError = ffiError.map { if DeveloperDiskImageService.usesCryptexDDI {
IdeviceBridge.consumeFFIError($0, fallback: "Failed to query installed DDI cryptex") var installed: UnsafeMutablePointer<InstalledCryptexC>?
} defer { cryptexd_free_installed_cryptex(installed) }
defer { cryptexd_free_installed_cryptex(installed) } if let ffiError = cryptexd_installed_ddi(adapter, handshake, &installed) {
if installed != nil { cryptexQueryError = IdeviceBridge.consumeFFIError(ffiError, fallback: "Failed to query installed DDI cryptex")
return true } else {
cryptexQuerySucceeded = true
if installed != nil {
return true
}
}
} }
let legacyMounted = (try? IdeviceBridge.withConnectedClient( do {
fallback: "Failed to connect to image mounter", return try IdeviceBridge.withConnectedClient(
missingClientMessage: "Image mounter client was not created", fallback: "Failed to connect to image mounter",
connect: { image_mounter_connect_rsd(adapter, handshake, $0) }, missingClientMessage: "Image mounter client was not created",
cleanup: { image_mounter_free($0) } connect: { image_mounter_connect_rsd(adapter, handshake, $0) },
) { client in cleanup: { image_mounter_free($0) }
var devices: UnsafeMutablePointer<plist_t?>? ) { client in
var deviceCount = 0 var devices: UnsafeMutablePointer<plist_t?>?
if let error = image_mounter_copy_devices(client, &devices, &deviceCount) { var deviceCount = 0
throw IdeviceBridge.consumeFFIError(error, fallback: "Failed to fetch mounted devices") if let error = image_mounter_copy_devices(client, &devices, &deviceCount) {
} throw IdeviceBridge.consumeFFIError(error, fallback: "Failed to fetch mounted devices")
if let devices {
for index in 0..<deviceCount {
plist_free(devices[index])
} }
idevice_data_free( if let devices {
UnsafeMutableRawPointer(devices).assumingMemoryBound(to: UInt8.self), for index in 0..<deviceCount {
UInt(deviceCount * MemoryLayout<plist_t?>.stride) plist_free(devices[index])
) }
idevice_data_free(
UnsafeMutableRawPointer(devices).assumingMemoryBound(to: UInt8.self),
UInt(deviceCount * MemoryLayout<plist_t?>.stride)
)
}
return deviceCount > 0
} }
return deviceCount > 0 } catch {
}) ?? false if cryptexQuerySucceeded {
if legacyMounted { return false
return true }
throw cryptexQueryError ?? (error as NSError)
} }
if let queryError {
throw queryError
}
return false
} }
} }

View file

@ -117,7 +117,8 @@ final class JITEnableContext {
guard let ffiError else { guard let ffiError else {
return makeError(fallback) return makeError(fallback)
} }
let message = nsString(from: ffiError.pointee.message, fallback: fallback) let detail = nsString(from: ffiError.pointee.message, fallback: fallback)
let message = detail == fallback ? fallback : "\(fallback): \(detail)"
let error = makeError(message, code: Int(ffiError.pointee.code)) let error = makeError(message, code: Int(ffiError.pointee.code))
idevice_error_free(ffiError) idevice_error_free(ffiError)
return error return error
@ -457,22 +458,19 @@ final class JITEnableContext {
private func withConnectedRemoteServer<T>( private func withConnectedRemoteServer<T>(
_ body: (OpaquePointer) throws -> T _ body: (OpaquePointer) throws -> T
) throws -> T { ) throws -> T {
try ensureTunnel() try withFreshDebugTunnel(hostname: "StikDebugRemoteServer") { adapter, handshake in
guard let adapter, let handshake else { var remoteServer: OpaquePointer?
throw makeError("Tunnel is not connected") if let ffiError = remote_server_connect_rsd(adapter, handshake, &remoteServer) {
} throw error(from: ffiError, fallback: "Failed to connect remote server")
}
var remoteServer: OpaquePointer? guard let remoteServer else {
if let ffiError = remote_server_connect_rsd(adapter, handshake, &remoteServer) { throw makeError("Remote server handle was not created")
throw error(from: ffiError, fallback: "Failed to connect remote server") }
}
guard let remoteServer else { defer { remote_server_free(remoteServer) }
throw makeError("Remote server handle was not created") return try body(remoteServer)
} }
defer { remote_server_free(remoteServer) }
return try body(remoteServer)
} }
private func withProcessControl<T>( private func withProcessControl<T>(

View file

@ -27,6 +27,7 @@ func checkMountStatus() -> MountCheckResult {
do { do {
return try JITEnableContext.shared.isDeveloperDiskImageMounted() ? .mounted : .notMounted return try JITEnableContext.shared.isDeveloperDiskImageMounted() ? .mounted : .notMounted
} catch { } catch {
LogManager.shared.addErrorLog("Failed to check DDI mount status: \(error.localizedDescription)")
return .unreachable return .unreachable
} }
} }

View file

@ -15,7 +15,7 @@ extension ScriptStore {
"Amethyst", "Amethyst",
"MeloNX", "MeloNX",
"XeniOS", "XeniOS",
"MeloCafe", "MeloCafé",
"Manic EMU", "Manic EMU",
"DukeX", "DukeX",
"TachyonU", "TachyonU",
@ -23,7 +23,8 @@ extension ScriptStore {
"HyperHLE", "HyperHLE",
"Applesauce", "Applesauce",
"RPCS3", "RPCS3",
"AetherPS4" "AetherPS4",
"Husk"
], ],
resource: ScriptResource(resourceName: "universal", fileName: "universal.js") resource: ScriptResource(resourceName: "universal", fileName: "universal.js")
), ),

View file

@ -7,7 +7,7 @@ import SwiftUI
import UIKit import UIKit
private enum SettingsLinks { private enum SettingsLinks {
static let githubStars = URL(string: "https://github.com/StikDebug/StikDebug/stargazers")! static let githubStars = URL(string: "https://github.com/StikDebug/StikDebug")!
static let pairingFileGuide = URL(string: "https://github.com/StikDebug/StikDebug-Guide/blob/main/pairing_file.md")! static let pairingFileGuide = URL(string: "https://github.com/StikDebug/StikDebug-Guide/blob/main/pairing_file.md")!
static let localDevVPN = URL(string: "https://apps.apple.com/us/app/localdevvpn/id6755608044")! static let localDevVPN = URL(string: "https://apps.apple.com/us/app/localdevvpn/id6755608044")!
static let discord = URL(string: "https://discord.gg/qahjXNTDwS")! static let discord = URL(string: "https://discord.gg/qahjXNTDwS")!