Outer Loop is a specialized web browser focused on "backend" style apps, where you run your own backend and view it in a browser. It improves workflows where, previously, you were split between a terminal and a browser. It handles frontends, backend management, and backend logs all in one place. You can use it for localhost apps, and it uses SSH to connect to web apps running on private servers. It uses a custom SSH engine that is designed to work well on laptops. You can close your laptop lid, open it later, and everything will still be connected.
This is useful for:
- Scientific computing (Jupyter, Tensorboard, MLFlow, RStudio Server, etc.)
- Server / database administration (phpMyAdmin, Kubernetes Dashboard, etc.)
- Robot administration, aspirationally. Robots are just servers that can move.
Blog posts:
- Web apps over SSH can be surprisingly good
- Tip: Use services, not the terminal, to run local backends
Example
Here is Outer Loop showing a Jupyter Python notebook and a Tensorboard LLM training visualization.
Apps like Jupyter and Tensorboard are not typically visible to standard web browsers if they're running on remote servers, because it would be terribly unsafe to let the whole internet touch this app. Instead, they run on a local port on the server, which your computer can't access directly.
Classically, to get access to these, you had to open a new terminal and run:
ssh -L 24601:localhost:8889 mrcslws@lambda4.mycompany.com &
ssh -L 24602:localhost:6006 mrcslws@lambda4.mycompany.com &
then you would navigate to "localhost:24601" and "localhost:24602". This works, but it's not a great experience, and it's not reliable; for example, the connection often breaks if you close your laptop. Additionally, many would consider it insecure, because almost any app or user of your device can now access this port, without needing your SSH credentials.
In Outer Loop, each browser window is connected to a remote server. It can freely access remote ports and sockets. And, in addition to providing this better UI, the web view's connection to the server is much more reliable in Outer Loop than over the classic "ssh -L". Outer Loop's custom SSH engine embraces the transient nature of SSH sessions, rather than assuming that they are stable, which makes everything seamless, even after you close your laptop and reopen it later.
The design of Outer Loop is heavily shaped by security. Some design decisions:
- We avoid the potential security pitfalls of "ssh -L" or "ssh -D". Instead of simply relaying a local port's connections to the remote web app, Outer Loop implements forwarding at a different layer of the networking stack: a SOCKS proxy server. By using this approach, it is able to put a secret random password on the proxy so others can't use it (unless they can scan it from Outer Loop's memory, which macOS prevents via hardening).
- The app is divided into a two sub-apps with different levels of access. The main app that displays web content is unable to do anything else; it can't issue commands on the servers. If the app is ever compromised by web content, the servers will still be safe. Meanwhile, the sub-app that runs commands over SSH or on localhost never displays web content.
Hope you like it! And feel free to .
Release Notes
I'm doing a lot of rapid releases, building toward the next big release, where I'll invite others to come build their own outerframe apps. Here is a recent changelog:
0.9.21 (April 20, 2026)
Changes:
- Change the SSH engine so that it proxy-based. Previously, we used an approch similar to "ssh -L", which essentially replicates a remote server at a local port. Now, instead, internally we connect to fictional synthetic domains, and we rely on a local SOCKS proxy to map this to the remote server. This makes us more secure because proxies can be password-authenticated, and it also lets us forward to other things like local Unix sockets.
- Remove the ability to navigate to our forwarded ports from other browsers. It was a nice feature, but it's arguably a security hole; once the port was being forwarded, any app and user of the machine, including guest users, could use it.
- Finish adding the ability to connect to servers running on Unix sockets on localhost, e.g. "jupyter lab --sock"
0.9.20 (April 18, 2026)
Changes:
- Add initial support for connecting to Unix sockets on localhost. Make the bundled "Top" app us this capability.
- Adopt "http+unix://%2Fpath%2Fto%2Fsock.sock/request" URL format that others have used for this type of URL
Bugfixes / polish:
- Fix a race in Service Management that made it sometimes show "Loading services..." forever if no services were installed.
0.9.19 (April 17, 2026)
Changes:
- Support running backends on Unix sockets and connecting via SSH port forwarding. The built-in Top backend now uses a socket file rather than listening on a local port. This is often better for security, because it means other non-privileged users on the machine won't be able to access it. It also puts another barrier between the backend and the public internet (in case someone is sloppy with their firewall).
Bugfixes / polish:
- Support connecting to servers using "keyboard interactive" password
- Allow backend management on servers in the specific configuration where you're using password-based login and the password isn't saved to the Keychain
0.9.18 (April 15, 2026)
Changes:
- Stop compiling code on the remote device. Instead, we transfer compiled binaries to the device directly. This means all features of Outer Loop will now work when connected to devices without compilers.
- When you create a service, you now own the generated .sh file. It asks you where to save the file, rather than hiding it in a cryptic "~/.outeragent" (linux) or "~/Library" (macOS) location
- Simplified service .sh files that don't try anything too difficult. No more scanning STDOUT for URLs. Instead, tools should either do first-class announcing of frontends, or just hardcode the port.
- Backends don't need to be .sh scripts, they can be other types, e.g. they can be executable ".py" files with a "#!/usr/bin/python3" header.
Bugfixes / polish:
- Localhost: For the Jupyter recipe, listing Python candidates failed due to sandbox issues
- Support tabbing through text input boxes in the New Service UI
0.9.17 (April 9, 2026)
Backend awareness and localhost support. Outer Loop now uses the target operating system's service management (launchd on macOS, systemd on Linux) to manage backends. The idea is, apps like Jupyter and Tensorboard shouldn't be backed by a terminal, instead they should be backed by services. Outer Loop helps you set up your various commands that start backends to instead run as services. This is useful on both SSH and on localhost, so I've enabled support for localhost. Outer Loop is becoming "a browser for SSH and localhost", which I think is a funny niche.
0.9.14 (January 21, 2026)
Sandbox improvements. With this change, now most of Outer Loop runs inside an App Sandbox, while Outerframe content runs inside of classic Seatbelt sandboxes (similar to what Chrome uses). Before this change, SSH processes and Outerframe content used Seatbelt sandboxes, while the main app was not sandboxed. Now the few pieces of logic that need to run un-sandboxed are in a dedicated "OuterProcesses" process, the SSH processes inherit the App Sandbox of a "OuterSSH Launcher" process, and Outerframe content network acesss is proxied through an App Sandboxed "OuterNetworkProxy" process.
0.9.13 (January 17, 2026)
- Outerframe platform improvements
0.9.12 (January 16, 2026)
- Support for multiple clients connecting to the same app backends.
- Various outerframe platform improvements.
0.9.11 (January 14, 2026)
This introduces a native "Top" app, running via a new "outerframe" platform. Run it from the Start Page. See blog post "The web could use machine code" for more info on outerframes. I am working on making this platform available to everyone, so that Outer Loop becomes "a native frontend for servers".
0.9.10 (October 16, 2025)
- Add support for private key passphrases.
- Support authenticating via ssh-agent (Thanks for reporting, Subutai!)
- Improve the "empty" / first run experience: (Thanks, Nick C., for suggestions!)
- When adding a server, provide suggestions from ~/.ssh/config
- Put keyboard focus on address bar when opening new window / tab
- When the Start Page is empty, show some tutorial text.
- Fixed macOS 14 crash (Thanks for the bug report, Subutai!)