Skip to content
marioparaschivPublic

About

馃摫 Cross-platform mobile Discord client modification focused on control, stability, and customisation.

Resources

Stars

113 stars

Watchers

5 watching

Forks

Latest commit

聽

History

72 Commits

Folders and files

NameName
Last commit message
Last commit date
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽
聽

Repository files navigation

Unbound logo

Unbound

A client modification for Discord on mobile.

Install plugins, themes, fonts, and icon packs on the official Discord app, on both iOS and Android.


Stars Release Discord License

Documentation 路 Contributing

Contents


What Is Unbound?

Unbound is a client modification for the official Discord mobile app. It loads inside Discord and wraps the app's internals in a stable API, so you can install plugins, themes, fonts, and icon packs without patching Discord by hand.

Running inside Discord gives add-ons direct access to the same modules, state, and UI the app itself uses. Unbound builds on that with tools for patching Discord's internals, both its behavior and its React components, so add-ons can change how the app works and how it looks. All of it is reversible: add-ons run behind error boundaries and can be torn down completely, so disabling one returns Discord to stock. That is what makes hot-reloading safe.

Unbound runs on both iOS and Android through a single native bridge, so the client behaves the same on each without platform-specific code paths. iOS is the primary target; Android is supported.

This repository holds the client source. The native loaders that install Unbound onto a device live in separate repositories. To install it, see the sections below.


Features

  • Add-ons: plugins, themes, fonts, and icon packs on top of the stock Discord app.
  • Safe hot-reloading: add-ons update at runtime without restarting Discord.
  • Error isolation: a broken add-on is caught and recorded instead of crashing the app.
  • Recovery mode: a reliable path back to a stock Discord when something goes wrong.
  • Cross-platform: native iOS and Android through a single bridge, with matching behavior.
  • Typed SDK: @unbound-app/api gives autocomplete across the entire client API.

Installation

Follow the loader docs for your platform:

If you're new to loaders, start with the loader introduction.


Creating Add-ons

Every add-on uses the same manifest format and declares a type that tells the client how to load it:

  • Plugins change how Discord behaves, through commands, UI, and patches. They're written against the typed @unbound-app/api SDK and have a start() / stop() lifecycle that the client runs for you.
  • Themes override colors and can set custom backgrounds.
  • Fonts register custom font families natively.
  • Icon packs replace Discord's built-in assets.

Scaffold a new add-on with the CLI:

bunx @unbound-app/cli create

Installing @unbound-app/api gives you typed access to the client API (unbound.metro, unbound.storage, unbound.toasts, and the rest), with autocomplete for everything it exposes. The add-on documentation covers the manifest, the lifecycle, the SDK, and publishing.


Architecture

A platform-specific native loader patches Discord to get JavaScript execution, then injects the client bundle. On boot the client traps Discord's Metro registry (__r/__d) and wraps every module factory, which gives it a searchable view of Discord's internal modules. Unbound can then look modules up through that Metro layer (findByProps, findByName, findStore) and patch them, both plain functions and React components, using possess.

The native side is bidirectional. The client calls into the loader for native capabilities (reload, filesystem, evaluateBytecode)

flowchart LR
    Loader["Platform Native Loader<br/><i>reload 路 filesystem 路 evaluateBytecode</i>"] <-->|native bridge| Core

    subgraph Core["Core"]
        direction TB
        Managers["Addon Managers<br/><i>plugins 路 themes 路 fonts 路 icon packs</i>"] --> APIs["APIs<br/><i>storage 路 toasts 路 assets</i>"]
        Managers --> Patcher["Patcher<br/><i>possess</i>"]
        APIs --> Metro
        Patcher --> Metro["Metro Layer<br/><i>findByProps 路 findByName 路 findStore</i>"]
    end

    Metro <-->|find / patch| Discord["Discord Internals<br/><i>modules 路 React UI</i>"]
Loading

The client is the runtime that ships into Discord. Everything else is a small package that supports it.

Package What it is
packages/client The Unbound runtime, the bundle that ships into Discord.
packages/cli The ubd CLI for scaffolding and managing add-on projects.
packages/debugger A REPL/CLI that connects to a running client to eval code, stream logs, and push add-on bundles.
packages/api Public type declarations that add-on developers build against.
packages/logger A small, dependency-free scoped logger with ANSI colors.
packages/utils Per-file utilities, each imported individually for tree-shaking.
packages/types Shared TypeScript types used across the project.

The client runs on a single initialize / shutdown lifecycle. Each manager brings its add-ons up on startup and tears them down on shutdown, and settings are persisted before the global is cleared.


Getting Started

You'll need Bun and an existing Unbound installation on a device or emulator to load your bundle into.

git clone https://github.com/marioparaschiv/unbound
cd unbound

bun install        # install workspace dependencies
bun run build      # build the bundle once
bun run dev        # or rebuild automatically on every change

These scripts live in packages/client. Run them from that directory, or from the repo root by prefixing them with bun --filter @unbound-app/client run.

To test your bundle, serve it over the local network, then point your Unbound installation's custom bundle URL at your machine and restart Discord (see the docs for the exact steps):

bun serve [PORT]   # serves ./dist

Repo-wide checks from the root:

bun run lint       # oxlint
bun run fmt        # oxfmt (write); fmt:check to verify

Contributing

Contributions are welcome. Before opening a PR, read the contribution guide, since formatting and lint rules are enforced. Keep PRs focused, write clear commit messages, make sure the project builds, and stay current with main.


Acknowledgements

Unbound wouldn't exist without the work of:


Star History


License

Unbound is licensed under the GNU General Public License v3.0.

About

馃摫 Cross-platform mobile Discord client modification focused on control, stability, and customisation.

Resources

Stars

113 stars

Watchers

5 watching

Forks

Releases

Used by

Contributors

Languages