Multi for macOS: Building Native Web App Shells
Create custom, lightweight macOS apps from websites
At a glance
- What is it?
- Multi turns configured websites into small macOS applications with tabs, separate windows, notifications, credentials, and custom web resources. It fits personal web tools and service desktops, but the README leaves important CLI and packaging details undocumented.
- Who is it for?
- Multi is appropriate for macOS developers who want a focused application shell for one or several websites and can accept credentials stored inside a local JSON configuration. It is a poor fit for users who need a polished offline client, a documented nonvisual application builder, or assured WebKit-independent operation.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 36 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 October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Multi's macOS App Model and Intended Users
Multi addresses a specific gap between opening a website in a general browser and maintaining a purpose-built native client. It creates a custom macOS app around one or more website URLs, allowing the result to appear in the application switcher, open as an independent bundle, and use macOS window behaviour rather than browser tabs alone. The target audience is developers and technical users who can edit JSON and, when necessary, supply CSS, JavaScript, cookies, and authentication credentials.
The README describes the resulting apps as lightweight, but it does not publish a memory footprint, startup measurement, binary comparison, or methodology for that description. Multi should therefore be judged as a web wrapper with selected native integration, not as proof that the resulting application is lighter than every browser or native alternative. It is most relevant for frequently used services such as Slack, Gmail, Google Calendar, Google Keep, WhatsApp, Grammarly, ChatGPT, or CyberChef, since the repository includes example configurations for those sites. Those examples do not establish that every site remains compatible with current WebKit behaviour.
How Multi Loads Websites Inside a macOS Bundle
Multi's architecture is visible through its Swift package structure, bundled application files, and configuration model. The repository contains `Sources/`, `Multi.app/`, and a `Package.swift`, while the Makefile builds a shared `libRuntime.dylib` and copies `Stub` and `App` into `Multi.app/Contents/MacOS`. This indicates a Swift build that assembles a macOS application bundle around runtime components. The repository topics identify WebKit as part of the project, and the README describes browser-like behaviour such as external-link handling and WebKit user-agent configuration.
At runtime, the documented data flow begins with `config.json`. Multi decodes the required `tabs` array, reads each tab's URL and optional per-site settings, and presents those URLs through the application. Custom JavaScript and CSS are injected through URL lists named `customJs` and `customCss`. Cookies use `customCookies`, with entries containing Foundation `HTTPCookiePropertyKey` values. Basic authentication credentials can be attached through `basicAuthUser` and `basicAuthPassword`, while `userAgent` changes the request identity used by WebKit.
The configuration also controls application lifecycle rather than page content alone. `windowed` selects separate windows, `alwaysNotify` controls notifications from an unfocused app, `alwaysOnTop` positions the window above others, and `terminateWithLastWindow` determines whether closing the final window ends the process. These options make the bundle more than a saved URL, although the README does not document deeper WebKit process settings or offline support.
Installing Multi and Creating a First Slack App
The README identifies Homebrew as the easiest installation route. This command installs the published cask on macOS:
brew install --cask multiThe README also allows users to download the latest `.dmg` from the repository's Releases page and run it. It does not describe the dialog choices, privilege requirements, or exact installation path in that workflow, so those details need to be checked in the release artifact.
After installation, the smallest documented app definition contains a Slack URL. Create an application named `Test`, place the following content in `/Applications/Multi/Test.app/Contents/Resources/config.json`, and then open the app:
{ "tabs": [{ "url": "https://app.slack.com/client" }] }The reader should see a Multi application presenting the Slack web client. The expected result is a focused app shell, not a native Slack implementation. The README names a CLI called `create-mac-app` for creating and updating apps, but it does not show the command syntax, executable name, flags, or update procedure. This tutorial therefore does not invent a CLI invocation. Users who need nonvisual app creation should confirm the command interface against the installed binary or source before relying on it.
Window Behaviour, Notifications, and External-Link Routing
Multi separates page layout from operating-system integration through seven top-level options. `windowed` starts every tab in its own window. The inverse layout, in which tabs share one application window, can be selected by leaving the documented option disabled. `alwaysNotify` permits macOS notifications even when the app is focused, while `alwaysOnTop` places its window above other windows. `terminateWithLastWindow` lets the process end when all configured windows have closed.
External navigation receives separate controls. `openNewWindowsInBackground` determines whether the browser app becomes active when an external link opens. `openNewWindowsWith` overrides the system default browser using an application bundle identifier. The README gives `com.apple.Safari`, `com.google.Chrome`, and `com.mozilla.firefox` as examples, but it does not explain how unknown or uninstalled bundle identifiers are handled.
{
"tabs": [{ "url": "https://app.slack.com/client" }],
"windowed": true,
"alwaysNotify": true,
"openNewWindowsInBackground": true,
"openNewWindowsWith": "com.apple.Safari"
}This configuration requests separate windows, notifications even when focused, background external-link handling, and Safari as the external browser. It is useful for a service that relies heavily on links to related sites. It can also fragment navigation across applications. Multi offers fewer documented isolation and profile controls than a full browser, so application selection must account for how the target service opens authentication flows, downloads, and cross-domain links.
Per-Site Credentials, Cookies, CSS, and JavaScript
Multi stores each app's complete configuration in one JSON file, which makes the shell easy to edit and copy. Per-tab resources include `customJs`, `customCss`, and `customCookies`. A tab may also supply a custom `userAgent`. These controls can correct a web interface that is poorly suited to a fixed window, but they also move sensitive data into a plain application resource.
The following example loads one stylesheet and one script for a tab:
{
"tabs": [
{
"title": "Walking",
"url": "https://kofi.sexy/cel-shading",
"customJs": [ "file:///Users/kofi/Documents/dotfiles/main/example.js" ],
"customCss": [ "https://example.com/custom.css" ]
}
]
}The same tab can include cookies defined with names, values, domains, and paths. Multi also accepts `basicAuthUser` and `basicAuthPassword` as strings. These fields are operationally significant. The README does not say how credentials are encrypted, whether they are excluded from backups, or whether file permissions are adjusted after editing. It also does not document protection against disclosure when copying an app bundle or committing its configuration. A configuration containing real passwords or session cookies should not enter an untrusted environment without review.
If JSON decoding fails, the README directs the user to the settings window to repair the configuration. That recovery path is helpful, but the documentation does not specify validation for every field, fallback behaviour for missing custom resources, or whether external CSS and JavaScript must use HTTPS. Any custom code runs inside the configured website context, so selectors and behaviour can break when the remote site's markup changes.
Multi Compared with Native Clients and Browser Profiles
A native macOS client implements platform interfaces directly and can provide controls independent of the service's website. Multi instead configures WebKit-hosted pages, so its main advantage is that it can reproduce an existing web service without access to the service's native source code. It can centralize several related pages in one app and apply JSON, CSS, and JavaScript without maintaining a complete Swift user interface.
The trade-off is that interface quality depends on the website. Features such as file upload, dialogs, and native notifications are listed as supported, but there is no claim that every web workflow works identically. Keyboard shortcuts, downloads, menus, accessibility behaviour, media playback, service workers, and offline operation are not documented in the README. Compatibility can also change when either the remote site or Multi changes.
Multi is different from adopting an official native application or maintaining a dedicated browser profile. An official client may offer deeper system integration and service-specific updates. A browser profile provides established navigation controls but less custom window and notification behaviour. Multi sits between them, offering a small app-bundle identity and web customization. That model is useful for internal tools and personal service wrappers, but unsuitable when predictable native controls are a requirement rather than an enhancement.
Release Cadence, Upgrades, and GPL-3.0 Obligations
The repository is not archived. Its last push was on 2026-09-17, and the listed release history includes Multi 3.0.2 on 2026-02-06, Multi 3.0.1 on 2024-07-06, and Multi 3.0.0 on 2023-07-24. These facts show recent repository work and a substantial gap between the two most recent listed releases. The README links to an article about the 3.0 rewrite, indicating that the current major version involved an architectural rewrite, although it does not summarize migration steps.
An installed Homebrew cask has a documented package-manager route, but the README does not explain configuration migration across Multi releases. Because apps store configuration inside their bundles under paths such as `/Applications/Multi/Test.app/Contents/Resources/config.json`, an upgrade or replacement may affect local app data. Users should preserve that file before changing versions, without assuming that it will survive automatically.
Multi is licensed under GPL-3.0. That matters for organizations that modify or redistribute the application, but this review does not provide legal advice. The license file is present as `COPYING`. Anyone embedding Multi in another distributed product should review the applicable GPL-3.0 terms for the exact distribution model. For local app creation, the immediate maintenance costs are WebKit compatibility, changes to remote HTML and CSS selectors, local scripts, cookies, and credentials stored in `config.json`.
Editorial conclusion
Multi is appropriate for macOS developers who want a focused application shell for one or several websites and can accept credentials stored inside a local JSON configuration. It is a poor fit for users who need a polished offline client, a documented nonvisual application builder, or assured WebKit-independent operation. Before adoption, verify that the target websites work with WebKit, review every URL and credential in `config.json`, and confirm that the required multiwindow and notification behaviour matches the intended use. The first concrete compatibility check should be a disposable app containing only the least sensitive target URL.
Frequently asked questions
How do I install Multi on macOS?
The README gives `brew install --cask multi` as the easiest method. It also allows users to download and run the latest `.dmg` from the repository's Releases page.
Where does Multi store an app's configuration?
For an app named `Test`, Multi stores its JSON configuration at `/Applications/Multi/Test.app/Contents/Resources/config.json`. The `tabs` field is required.
Can Multi add JavaScript, CSS, cookies, and authentication to a website?
Yes. Each tab supports `customJs`, `customCss`, `customCookies`, `basicAuthUser`, `basicAuthPassword`, and `userAgent`. The README does not document how stored credentials are encrypted.
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/kofigumbs-multi)Was this useful?