Wormholy: the demo switches tracking off for the session it then builds, and only one install path guards production
iOS network debugging, like a wizard 🧙♂️
At a glance
- What is it?
- An iOS network inspector that hooks URLSession so you can read requests, responses and headers by shaking the phone, with no code to write. It is small, MIT licensed and honest about its limits, including the one that matters most: background sessions cannot be captured at all. The rough edges are in the example, which ends mid comment and turns tracking off for the very session it creates.
- Who is it for?
- This fits an iOS developer who wants to see what an app actually sends without rebuilding it around a logging layer, especially one debugging a third party SDK or a library they do not control. It does not fit anyone auditing non URLSession traffic, since raw sockets and background sessions are structurally out of reach.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 58 days ago.
- What is it written in?
- Mainly Swift, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- pmusolino/Wormholy2,627 ★ · +9
| Repository | 2026-10-04 | 2026-11-14 |
|---|---|---|
| pmusolino/Wormholy | 2.6k | 2.6k |
9 Stars in the last 41 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Only traffic that goes through NSURLSession is visible
The scope is stated in one feature line: it records all app traffic that uses NSURLSession. Everything the tool can show you flows through that one API, which is what makes the no code to write claim possible. There is no swizzling of your networking layer and no wrapper to adopt, because the hook goes in underneath the session abstraction instead of around your calls.
Even inside that boundary the coverage is partial, and the readme is precise about it. Wormholy automatically hooks two configuration classes, the default one and the ephemeral one. Any other configuration has to be opted into explicitly, through a session specific call made before the session is created, which is a real ordering constraint rather than a formality.
The harder boundary is background sessions. The readme states the reason plainly: Apple does not support custom URLProtocol classes with a background configuration, so Wormholy cannot be injected there through protocolClasses. That is an operating system restriction, not a missing feature, and it means background uploads and downloads produce no records at all. Any debugging question whose answer lives in background traffic is outside what this tool can answer.
The example disables the session it then creates
The configuration example is the first thing a new user copies, and it does not do what its own comments say. Here is the whole block:
func configureWormholy() {
Wormholy.ignoredHosts = ["example.com", "analytics.internal"]
Wormholy.limit = 200
Wormholy.defaultFilter = "status:500"
Wormholy.shakeEnabled = true
// Global tracking for URLSession traffic.
Wormholy.setEnabled(true)
// Use the session-specific API when you want to override behavior
// for a particular configuration instance.
let configuration = URLSessionConfiguration.default
Wormholy.setEnabled(false, sessionConfiguration: configuration)
let session = URLSession(configuration: configuration)
// Wormholy.clearRequests { // RemovThree things are wrong with it. It enables tracking globally, then disables it for the default configuration, then builds a session from that disabled configuration. A reader who follows it literally gets a session that records nothing, while the global switch sits there looking like it did something. And the final line is a comment cut off mid word, after the letters Remov, with the function's closing brace never printed.
Two more defaults are demonstrated without explanation. The filter is preset to a server error status, so the first shake shows only failures rather than all traffic, and the log limit is set to two hundred without any statement of what it defaults to when unset.
One ignored host silences a whole domain tree
The exclusion list matches on suffix rather than on exact host. The readme gives the example: set the list to example.com and Wormholy will ignore requests to example.com and to subdomains such as api.example.com.
That is convenient until it is not. Analytics and error reporting traffic is exactly the traffic you want while debugging something else, and the way to remove it is to add a hostname. Because the match is a suffix match, adding a hostname that happens to share a suffix with a host you care about removes both. A debugging session that appears to be missing traffic is far more likely to be caused by this list than by a capture bug, so it is worth checking before investigating anything else.
The rest of the configuration surface is small and deliberately flat, all of it as static properties or static methods on one type. There is a property to cap how many logs are retained, which the readme frames as memory management, and one to control the shake gesture. Tracking can be toggled globally, or per configuration instance, and there is a read only check for whether global tracking is currently enabled.
Only one of the two install paths is scoped to debug
The readme is unusually direct about how this library should not be used. It is recommended to install it only in debug mode, not to integrate it into production, and to remove it before sending apps to production. That advice is underlined, and it is correct, since the tool exists to read the contents of requests and responses.
The CocoaPods instruction is the one that enforces it, in a single line:
pod 'Wormholy', :configurations => ['Debug']The configurations key restricts the dependency to the Debug configuration, so a release archive never links it. The next paragraph offers the Swift Package Manager as an alternative and stops there. No equivalent product or configuration condition is given for that route, which means the two paths offered side by side do not have the same safety properties, and the package manager route is the one a newer project is more likely to reach for.
That gap is worth closing in your own project rather than in the library. Whichever route you take, the reliable check is whether the symbol is absent from a release build rather than whether a configuration flag was set.
It shows HTTPS payloads in the clear, which is both the point and the risk
One feature line reads no headaches with SSL certificates on HTTPS calls. That is the technical heart of the library. Because the hook sits at the URLProtocol layer inside the session, the content it records is the content your app receives after decryption, so a response body and its headers are readable without installing a certificate, without changing server configuration, and without touching the app's own code.
The same property is what makes it valuable and what makes it dangerous. There is no certificate warning, because from the app's point of view nothing about the trust evaluation changed. Anyone who can shake the device, in a debug build, can read every request the app makes, including tokens in headers and bodies containing personal data, and the export features push that material further: requests can be exported as a Postman collection or shared as cURL representations, which means captured secrets can leave the device entirely.
That is the reasoning behind the debug only rule, and it is why the shake gesture and the export options deserve to be treated as access controls rather than conveniences.
Two ways to open it, and one of them is documented in a blog post
The primary interaction is shaking the device or the simulator, and the readme's claim of needing no code and no imports depends on that gesture being available. Everything else is an alternative to it.
There is a runtime property to control the gesture, and there is also an environment variable, WORMHOLY_SHAKE_ENABLED, set to the value NO to switch it off. Those are two different mechanisms for the same decision at two different times, one after launch and one before it, and a project that disables the gesture for its own reasons still has the environment variable available.
The manual trigger is a notification. Posting a notification named wormholy_fire opens the interface from anywhere in the app, which is how you would wire it to a debug menu item instead of a shake. The example for that is three lines long and needs no library import.
One documentation detail is worth flagging. The environment variable is introduced with a link to an article about custom environment variables in Xcode, hosted on a personal blog. That makes the only written explanation of the variable's scope someone else's post rather than something the project maintains.
Three release lines, two tags an hour apart, and an asymmetry in the API
The tags tell a slightly untidy story. Version 2.3.0 was published in January 2026. Then 1.8.0 and 2.4.0 were both published on the same day in March, about seventy five minutes apart, with 2.4.0 second. So the second newest release by date is a lower version on what looks like a maintained 1.x branch, published alongside the current line rather than before it. Alongside those sits an instruction to use the 1.7.x series if you need support for a device older than iOS 16. Three supported lines for one small library is generous, and it means the version you install should be chosen deliberately rather than by taking whatever appears newest.
The tags carry no prefix, so they read as plain version numbers, and the same library is distributed three ways: as a Swift package, as a pod, and as a checked in Xcode project alongside a demo application.
The API has one asymmetry worth knowing. There is a method to inspect whether global tracking is enabled, and no equivalent to read back the state of a session specific override. The per configuration flag is write only from the outside, so once you disable tracking for a particular configuration you cannot ask the library what it thinks, and the observable behaviour is silence.
Editorial conclusion
This fits an iOS developer who wants to see what an app actually sends without rebuilding it around a logging layer, especially one debugging a third party SDK or a library they do not control. It does not fit anyone auditing non URLSession traffic, since raw sockets and background sessions are structurally out of reach. Before you adopt it, wire it in the way the readme recommends, which is a debug only dependency removed before production, because the tool reads HTTPS payloads in the clear and the CocoaPods line that enforces this has no counterpart in the Swift Package Manager instructions. Also fix the example before copying it, set the session specific flag with the outcome you want rather than the opposite, and pick your host exclusions knowing that one entry silences every subdomain.
Frequently asked questions
What does pmusolino/Wormholy record?
App traffic that uses NSURLSession, automatically for the default and ephemeral session configurations, with requests, responses and headers revealed by shaking the device. Captured requests can be exported as a Postman collection or shared as cURL. Background sessions are not supported.
How do I keep Wormholy out of my production build?
The readme says to install it only in debug mode and remove it before production. The CocoaPods line does this with pod 'Wormholy', :configurations => ['Debug'], and the Swift Package Manager instructions offer no equivalent condition, so with that route you need to scope it yourself.
What does the slang term "worm hole" mean?
Nothing in this repository addresses that. It is an MIT licensed iOS network debugging library written in Swift with Objective-C compatibility, and the name is the only thing it shares with the physics term.
Do wormholes actually exist?
Not a question this project answers. The repository contains a debugging tool for observing HTTP traffic inside an iOS application, with no content about physics or spacetime.
Is wormhole trustworthy?
For an iOS debugging library the relevant facts are the MIT licence and the readme's own instruction to keep it out of production builds. The name collision with wormholes in physics makes this an easy repository to find by accident, so check that you have the one written in Swift.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pmusolino-wormholy)Star history chart for your README
[](https://hysenlabs.com/projects/pmusolino-wormholy)Was this useful?