# RuntimeBrowser: browsing the Objective-C runtime on iOS and macOS

> RuntimeBrowser reads every class loaded into the Objective-C runtime and prints it back as a header file. It ships as an iOS app, a macOS app and a command line front end, and the README is explicit that each user is responsible for their own usage.

**nst/RuntimeBrowser** — Objective-C Runtime Browser, for Mac OS X and iOS

- Repository: https://github.com/nst/RuntimeBrowser
- Stars: 3,660 · Forks: 521
- Language: Objective-C
- License: not declared
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/nst-runtimebrowser

## What RuntimeBrowser is for

Apple's headers describe the API the framework authors intended to publish. The runtime holds everything that is actually loaded, which is a larger set. RuntimeBrowser is built for the second set. The README describes it as a class browser for the Objective-C runtime on iOS and OS X that gives full access to all classes loaded in the runtime, allows new modules and their classes to be loaded dynamically, shows every method implemented on each class, and displays that information in header (.h) file format.

The audience is narrow and specific. Someone debugging a private framework, someone checking which methods a class actually responds to before swizzling it, someone generating headers for a class that has no public declaration. The README calls it a useful development tool and then adds a sentence that matters: each user is responsible for their own usage. That is the project's own framing of the risk, and it is worth reading literally. Browsing private classes and invoking methods on them is the kind of thing that gets an app rejected or crashes a process, and the project does not pretend otherwise.

The project has a long history. The original version was released in April 2002 by Ezra Epstein, and Nicolas Seriot has maintained it since August 2008. That continuity is visible in the repository layout: OSX/, iOS/, UI/, model/, runtime_cli/ and tools/ sit side by side, with the model separated from the two user interfaces.

## How the model, the apps and runtime_cli fit together

The repository separates the runtime introspection logic into model/ and puts two front ends on top of it, one in iOS/ and one in OSX/, with UI/ holding shared interface code. The command line tool in runtime_cli/ is described as the command line front end of the model, which is the clearest statement of the architecture: the same code that powers the graphical browsers is reachable from a shell.

What the model does is read the runtime and render it. The README says the headers use the modern runtime, and that Swift classes, structs, properties and protocols appear alongside Objective-C ones. The iOS app browses by class tree, image or indexed list, searches class names, and serves headers over HTTP on port 10000. The macOS app browses by class tree, image, list or protocols, searches class contents, applies syntax colorization, and accepts drag and drop of frameworks and headers. Those are different affordances for the same underlying data, which is why the split makes sense.

The interesting design decision is the sweep. The README states that runtime_cli --sweep dir writes the headers and declarations of everything it can load from /System/Library, and that this is how the model is tested against the whole runtime: sweep before and after a change, then diff -r the two directories. That is a regression test built out of the operating system itself. It is also a test that can only run on a machine with that /System/Library, so it is inherently tied to a specific OS version.

## Installing the macOS build and running a first query

There is no package manager step in the README. The macOS version is distributed as a direct download: the latest build is dated 2026-09-08, named RuntimeBrowser-1.1.zip, 405 KB, universal, and the README says it requires macOS 10.13 or later. Download it from the link the README gives at seriot.ch, unzip it, and open the app. Because it is not notarised through a package manager, macOS Gatekeeper may object on first launch; the README does not discuss that, so treat it as something to expect rather than something documented.

The command line front end is the part worth scripting. The README gives these three invocations:

```bash
runtime_cli NSObject
runtime_cli --swift Foundation.Date
runtime_cli --sweep dir
```

The first prints a header for NSObject. The second prints a Swift declaration for Foundation.Date rather than an Objective-C header, which is the flag to reach for when the class you care about is Swift. The third writes headers and declarations for everything loadable from /System/Library into dir. A sweep of a full system library tree is not a fast operation and the README does not estimate a duration, so run it once and see how long it takes on your machine before putting it in a loop.

For the manual page, the README points at runtime_cli.1 in the repository. That file, not the README, is where the flag list lives.

On iOS the app is built from the iOS/ directory rather than downloaded, and its distinctive feature is the HTTP server: headers are retrieved through port 10000. That means a device running RuntimeBrowser can serve its runtime headers to another machine on the same network, which is a different workflow from copying files off the device.

## The limitations the README admits and the ones it does not

The clearest limitation is stated in one line: each user is responsible for their own usage. RuntimeBrowser instantiates most classes, including allocation of non-shared instances, and allows invocation of methods with parameters supplied at runtime. Those are not read-only operations. Calling an initialiser or a method on a class you do not own can change global state, start background work, or crash the process. The browsing side is safe; the invocation side is not, and the README does not draw a line between them.

A second limitation is scope. The tool shows what the runtime has loaded. Classes that are not loaded yet do not appear, which is why the README mentions dynamically loading new modules and their classes as a feature. If you are looking for a class that a framework only loads on demand, you have to trigger that load first.

A third is version drift. Headers generated from one OS build do not describe another. The sweep-and-diff workflow makes this explicit: the baseline is /System/Library on the machine you ran it on. Anyone treating a generated header as documentation for a different iOS or macOS release is reading a snapshot, not a contract.

Finally, the licence. The repository metadata carries no licence, and the top level entries listed are .gitignore, OSX/, README.md, UI/, art/, iOS/, model/, runtime_cli/ and tools/. There is no LICENSE file among them and the README does not state terms. That is a real gap for anyone considering reuse, and it is not something this article can resolve.

## Where class-dump and the Apple documentation differ

The obvious alternative for reading Objective-C metadata is class-dump, which parses Mach-O binaries on disk and emits headers without running the code. The difference in approach is fundamental. class-dump reads a file; RuntimeBrowser reads a running process. That means RuntimeBrowser sees classes that exist only after a plugin or bundle loads, and it can call into them, while class-dump sees everything statically present in the binary whether or not it is ever loaded.

For Apple's own frameworks, the official documentation and the public SDK headers are the right source, and RuntimeBrowser is not competing with them. The README's own framing, that it displays information in header file format, makes the point: these are generated headers, not published interfaces. They show what a class implements, not what it promises to keep implementing.

The comparison that matters most is with the sweep workflow itself. A tool that reads binaries gives you the same answer on any machine holding the binary. RuntimeBrowser gives you the answer for the running system, which is more accurate for that system and useless for any other. If your question is "what does this app call", class-dump is the better fit. If your question is "what is actually in the runtime right now, and what happens if I call it", RuntimeBrowser is the one that answers it.

## Maintenance, licence and upgrade cost

The last push to the repository was on 2026-09-10, and the macOS build linked from the README is dated 2026-09-08, so the downloadable binary and the source are close together. The project has been maintained by Nicolas Seriot since August 2008 and is not archived.

Upgrade cost is dominated by the sweep. Because the README describes testing the model by sweeping /System/Library before and after a change and diffing the two directories with diff -r, any change to the model is validated against a whole OS runtime. That is a strong safety net and an expensive one: it requires a machine with the target system library tree, and the diff after an OS update will be large for reasons that have nothing to do with your change.

On licensing, the honest answer is that no licence is stated anywhere in the repository information. No licence identifier appears in the repository metadata, no LICENSE file is listed among the top level entries, and the README states no terms. Anyone intending to redistribute the code, or generated headers, has to resolve that with the maintainer first. Generated headers of Apple's classes raise a separate question that this article cannot answer.

## Conclusion

RuntimeBrowser is for engineers who need to see what the Objective-C runtime actually contains on a device or a Mac: the macOS build is a 405 KB download from seriot.ch that the README says runs on macOS 10.13 or later, and runtime_cli is the piece to script against. It is not a shipping component and not a substitute for Apple's documentation, since the headers it prints are generated from whatever the runtime exposes. Before relying on it, verify two things: that runtime_cli --sweep dir completes without errors on your OS build, and what the repository's licence actually is, because no licence file appears in the top level entries and the README says nothing about terms.

## FAQ

### What is RuntimeBrowser used for?

It browses the Objective-C runtime on iOS and macOS, giving access to all classes loaded in the runtime, showing every method implemented on each class, and displaying the result in header file format. The README describes it as a development tool and notes that each user is responsible for their own usage.

### How do I install RuntimeBrowser on macOS?

The README points to a direct download rather than a package manager: RuntimeBrowser-1.1.zip, 405 KB, universal, for macOS 10.13 or later, linked from seriot.ch. The iOS version is built from the iOS/ directory instead.

### What is runtime_cli in RuntimeBrowser?

It is the command line front end of the model. The README gives three examples: runtime_cli NSObject prints a header, runtime_cli --swift Foundation.Date prints a Swift declaration, and runtime_cli --sweep dir writes headers and declarations for everything loadable from /System/Library.

### Does RuntimeBrowser work with Swift classes?

Yes. Both the iOS and macOS versions list Swift classes, structs, properties and protocols, and runtime_cli takes a --swift flag for printing a Swift declaration such as Foundation.Date.

### What licence does RuntimeBrowser use?

No licence is stated in the available repository information, and no LICENSE file appears among the top level entries. The README gives no terms, so this has to be confirmed with the maintainer.

## Sources

- [Issues](https://github.com/nst/RuntimeBrowser/issues)
- [nst/RuntimeBrowser on GitHub](https://github.com/nst/RuntimeBrowser)
- [README](https://github.com/nst/RuntimeBrowser/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/nst-runtimebrowser
