Skip to content

Latest commit

 

History

History
1669 lines (1094 loc) · 84.8 KB

File metadata and controls

1669 lines (1094 loc) · 84.8 KB

🛠️ Morphe Desktop Documentation

This is the complete documentation for Morphe Desktop. Morphe desktop offers both a GUI and a CLI. The GUI is how most people will use it, with a powerful CLI underneath for power users and automation. This documentation covers both, plus common workflows. If you’re brand new, start with the first-run guide, then come back here.

Now that you've done your first run, let's dig deeper into how the magic happens and how to make it even better.

📖 Table of contents

🤝 Prerequisites

  1. Java Runtime Environment 21 or above (Azul Zulu JRE, Temurin or OpenJDK).
  2. Morphe Desktop jar file (morphe-desktop-*-all.jar). Download the latest from here.
  3. If using CLI: Patches mpp file (patches-*.mpp). Download the latest Morphe official patch files from here.
  4. If using CLI: Desired app file (app.apk or app.apkm). Download your apk from APK Mirror.
  5. [Optional] Android Debug Bridge (ADB) If you want to install the patched APK file to your device directly from your computer.

📂 Where Morphe stores its files

Morphe keeps its runtime data: cached patch files, logs, scratch space for patching, and the default signing keystore in a single morphe-data/ folder. By default, this folder is created next to the JAR you run, so it survives upgrades and is easy to find. If that location isn't writable (e.g. running from an IDE, or from a read-only install path), Morphe falls back to ~/morphe/. The startup logs print which one is in use (look for Morphe data root: ...).

You can override the location entirely with the MORPHE_DATA_DIR environment variable. Point it at a writable directory and Morphe uses that as the data root, ahead of both the JAR-adjacent default and the ~/morphe/ fallback. This is meant for read-only or package-manager installs, where the JAR's own folder isn't writable and you'd rather choose the location than land in ~/morphe/. If the path you set isn't writable, Morphe logs a warning and ignores it.

morphe-data/
  patches/         # cached .mpp patch bundles
  logs/            # application logs
  tmp/             # per-run patching scratch (the default --temporary-files-path location)
  libs/            # GUI runtime (Skiko, JNA) downloaded on the first GUI launch
  morphe.keystore  # shared default signing key (see --keystore)
  config.json      # preferences + configured sources

Both the GUI and the CLI use this folder. In the GUI you can open it from Tools → Open App Data. On the CLI, --temporary-files-path defaults to tmp/ (override it to send scratch elsewhere) and --keystore defaults to morphe.keystore here.

The libs/ folder is special: it only appears once you open the GUI. Morphe ships as a single small jar, and to keep that download small it does not bundle the GUI's platform-specific rendering library (Skiko) or its native-access library (JNA). The first time you launch the GUI, Morphe downloads the correct builds for your operating system and architecture from Maven Central, verifies each one by checksum, and caches them here while showing a brief setup window. The CLI needs none of these, so running from a terminal never downloads anything. Every later GUI launch reuses this cache and works offline.

Tip

Choosing a custom location. If neither default suits you (for example, a package-manager install lands the JAR in a read-only, system-wide path), set the MORPHE_DATA_DIR environment variable to a writable directory. When it's set and usable, Morphe uses it as the data root ahead of everything else. If the value isn't a writable directory, Morphe logs a warning and ignores it. On Linux, if MORPHE_DATA_DIR is unset but XDG_DATA_HOME is exported, a fallback install uses $XDG_DATA_HOME/morphe. An existing ~/morphe/ folder is always kept as-is so upgrades never strand your data. Either way, the startup log line (Morphe data root: ...) tells you which location won.

GUI

The GUI is the window you get when you double-click the jar and for most people, it's the way to use Morphe. No flags to memorize, no quoting mistakes, no terminal history full of 47 almost-right commands. Point, click and patch.

In your first run you used the GUI's Quick mode, the beginner-friendly path. Below we go deeper, focusing on Expert mode, where you can do much more.

The two modes

The GUI can run in one of two modes:

Mode Who it's for What you control
Quick (default) First-timers, fast patches Just the APK: Morphe picks the patch source and the default patch set
Expert Regular users, Power users Everything: patch source & version, individual patches & their options, native-lib stripping, signing, and a live CLI-command preview

Quick mode home Expert mode home

On first launch you're in Quick mode. Switch anytime in Settings → Expert mode → Toggle ON. [Morphe will remember that.]

Expert mode toggle

Quick mode

Quick mode is the beginner path, covered step-by-step in the first-run guide: drop an APK, click Patch, watch it run, then install the patched app. Morphe chooses the patch source and the default patch set for you (by default). You can add additional sources here too. The rest of this section however focuses on Expert mode. That's where the GUI matches (and visualizes) everything the CLI can do.

Expert mode

Expert mode is a five-screen pipeline (for now): Home → Patch source → Patch selection → Patching → Result. Each screen below lists its controls (and the CLI flag it maps to, where there is one), then explains the details.

The TopBar

The home screen has a top bar (on the top):

Topbar

The sources pill sits in the center of the bar. It shows the loaded patches version and a N SOURCES count, with one small colored LED per source for the release channel it resolved to:

Control What it does
Sources pill (center) The loaded patches version + a N SOURCES count with one colored LED per source – see below.
Device indicator Shows the connected ADB device (or "No devices connected"). Click to choose the target device for installs.
Tools (wrench) One-off actions + reference info – see Tools.
Settings (gear) All your preferences – see Settings.
LED Channel Meaning
🟢 STABLE LATEST newest stable release – recommended
🟡 STABLE OLDER a stable release, but a newer one exists
🔵 DEV LATEST newest pre-release (experimental)
🔴 DEV OLDER a pre-release but behind
🩵 LOCAL a local .mpp file or folder source

A disabled source shows a dimmed LED, and a source that failed to load shows a red LED and raises an error banner. Those two states take priority over the channel color.

In Expert mode, click the pill to open the source manager – add, remove, refresh, or reorder sources (see Managing patch sources). In Quick mode it's informational. The same LED colors appear on each row inside the source manager.

The rest of the bar is the device indicator on the right (your ADB install target – more under Installing to a device), and the two icon buttons next to it: Tools (the wrench – logs, app data, clear cache, licenses; see Tools) and Settings (the gear – theme, modes, signing, strip libs, and more; see Settings).

1. Pick your APK

Control What it does CLI equivalent
Drag & drop /BROWSE FILES Choose the APK to patch (.apk, .apkm, .xapk, .apks) positional<apk> argument
SUPPORTED APPS list The apps your patches target, each tagged with a recommended version informational – compare withlist-versions
CHANGE APK Swap the selected file
CONTINUE / CONTINUE ANYWAY Proceed to patch selection --force (when it reads ANYWAY)

Drop an APK anywhere on the window (the zone reads DROP APK HERERELEASE TO DROP) or use BROWSE FILES. Split-APK bundles (.apkm / .xapk / .apks) are merged into a single APK automatically.

The SUPPORTED APPS list shows what the loaded patches can target, each with a version tag: STABLE LATEST, EXPERIMENTAL LATEST, ALSO STABLE, EXPERIMENTAL - so you know which APK version to download. Search it if it's long. A second tab, YOUR APPS, tracks everything you've already patched, see Your apps.

Supported Apps

Once an APK is dropped, Morphe reads its metadata (ANALYZING / "Reading app metadata…") and shows an info card with the app name, package, and version, plus CHANGE APK and CONTINUE.

Selected Apk

Tip

Each version tag in the SUPPORTED APPS list is a clickable shortcut. Click one to open that app's download page on APKMirror or other related sites. Grab the recommended version: matching versions means more patches apply.

Note

If your APK's version doesn't match what the patches expect, the button changes to CONTINUE ANYWAY. Proceeding is the GUI's equivalent of the CLI's --force. Incompatible patches are skipped, and the ones that do apply may or may not work. Newer-than-recommended versions are usually the riskiest.

Selected Apk with warning

2. Choose a patch source & version

Control What it does CLI equivalent
Release list (LATEST / STABLE / DEV / CACHED) + DOWNLOAD / SELECT Pick and fetch a patch release -p <repo-url> (+ --prerelease for DEV)
PATCH NOTES Read a release's changelog -
LOCAL PATCH FILE → BROWSE Use a.mpp already on disk -p <file.mpp>
EXPORT JSON Save anoptions.json for this bundle options-create / --options-file

Morphe fetches the available releases from your configured source and tags them: LATEST, STABLE, DEV (pre-release), and CACHED (already downloaded). Pick one and DOWNLOAD / SELECT it. Expand PATCH NOTES to read the changelog first. Already have a .mpp? LOCAL PATCH FILE → BROWSE points straight at it.

Release Screen

Note

EXPORT JSON writes an options file describing every patch and its settings – the same artifact the CLI's options-create produces. Edit it and feed it back via --options-file for repeatable, scriptable runs.

Managing patch sources

The sources Morphe fetches from are configurable: add community sources (GitHub / GitLab repos, or morphe.software/add-source links), remove them, or refresh them. Adding more than one source is the GUI counterpart to passing several -p URLs on the CLI: their patches show up together, grouped by bundle, on the next screen.

Reordering. Drag a source by its handle to change its position in the list. Order is load priority – sources higher in the list are loaded first. This usually doesn't matter, but it can: if two sources ship a class with the same name (common when both are forks of the same patches project), the one loaded first wins. Keeping your primary source on top is the safe default.

Channel badge. Each enabled source shows a small badge for the release it resolved to, color-coded by release channel, the same colors (and meanings) as the sources-pill LEDs in The TopBar.

When a source fails to load. Morphe no longer spins forever on a source it can't fetch or parse. It stops with an error, turns that source's badge and LED red, and shows a banner naming the source and the reason, so you can fix or remove it while the other sources still load.

Local sources. A source can also be a local .mpp file on disk. If you're building patches, enable Developer options to point a source at a folder instead. Morphe then always loads the newest .mpp in it, so a rebuild is picked up without having to re-select the file.

Sources sheet

3. Select patches

The full patch list from your selected bundle(s), with a running "N of M selected" count.

Control What it does CLI equivalent
Patch toggle Enable / disable a patch -e / -d (or --ei / --di)
Search Filter the list
Options editor Edit a patch's option values -O key=value
PATCH DEFAULTS / YOUR DEFAULTS Whether you've changed a patch's options
Strip-libs summary Which native-lib architectures will be kept --striplibs (set in Settings)
Continue patching even if a patch fails Keep going when a patch errors instead of aborting the whole run --continue-on-error
COMMAND PREVIEW (COPY / EXPAND / COMPACT) The exact CLI command for your selections – (itis the CLI command)
PATCH (N) Start patching the N selected patches runs thepatch command
  • Toggling & search: Flip patches on/off. Search filters the list (you'll see No patches match your search). If you added multiple sources, patches are grouped per bundle (No matches in this bundle when a filter empties one).

Patch Selection Screen

  • Options: Patches with configurable options show an options count. Click on this to expand and edit. Values are typed, see the Value Types Reference for how strings / booleans / lists are formatted. PATCH DEFAULTS means untouched. YOUR DEFAULTS means you've customized it. A few options are richer than a text box, notably custom icon option, which opens the Icon Studio instead.

Patch Selection Options

  • Strip libs: A summary chip shows whether native libs will be stripped (STRIPPING NATIVE LIBS / NO STRIPPING NEEDED / NO NATIVE LIBS). Change the kept architectures under Settings → Strip Libs.
  • Continue patching even if a patch fails: By default a failed patch aborts the whole run. Enable this to skip the failure and apply the rest. The GUI's equivalent of the CLI's --continue-on-error.
  • Command preview: The exact CLI invocation your choices produce. COPY it to reproduce this run in a terminal or drop it into a script. EXPAND / COMPACT toggles full vs condensed.

Command Preview

Tip

The Command Preview is the best way to learn the CLI: configure a patch visually, copy the command, and you've got a reproducible one-liner. Handy for scripting or sharing exactly what you ran.

Custom app icons (Icon Studio)

Some patches can replace the app's launcher icon. When a patch exposes a custom icon option (for example the Custom branding patch on the official Morphe patches), its row in the options editor shows action buttons instead of a plain text field:

Control What it does
DESIGN ICON / EDIT ICON Open the Icon Studio to build a new icon (or re-open the one you saved)
IMPORT FOLDER Point the option at an already-prepared icon folder. E.g. one exported from the Morphe Manager
DELETE Clear the icon and delete its saved project + generated files

The patch expects a specific icon folder on disk, but you never have to build that by hand. The Icon Studio generates it and sets the option to its path. The row reads Custom icon ready once set, No custom icon set otherwise.

Custom icon option row

Foreground vs. background. Android adaptive icons are two layers: an opaque background and a foreground on top (the foreground may be transparent). The launcher masks the combined result into whatever shape the device uses. The Icon Studio mirrors this with two panels:

  • FOREGROUND: Your logo/mark, built from stacked layers. Each layer is an IMAGE, TEXT, or a SHAPE (circle, square, rounded, triangle, and more). Per layer you get TRANSFORM (move / scale / rotate, with RESET POSITION), color, and effects like SHADOW, GLOW, STROKE. Text layers add BOLD / ITALIC / UNDERLINE / STRIKE; DUPLICATE copies a layer.
  • BACKGROUND: A SOLID color, a GRADIENT (LINEAR / RADIAL / CONIC), or an IMAGE.

Important

Transparency is the #1 reason a custom icon looks wrong, and the two layers have opposite rules:

  • The foreground should be transparent around your mark. That cut-out is what makes the monochrome and notification icons read as a shape. A fully opaque foreground turns them into a solid block. If you import an opaque image the Studio warns you but won't auto-edit it (that could mangle a real icon). Fix it yourself with a transparent PNG, or use a TEXT / SHAPE layer instead.
  • The background must be opaque. Adaptive backgrounds can't be see-through. Here the Studio handles it for you. A transparent background image is automatically flattened onto a solid base, so backgrounds just work. (Although it is highly recommended to use a proper, fully opaque background.)

Colors come from a picker with saveable swatches, TEMPLATES give you starting points, and UNDO / REDO cover mistakes. Your work autosaves (the header shows SAVED), so EDIT ICON reopens exactly where you left off.

Live previews. The right side shows how the icon renders in three real contexts:

  • ADAPTIVE – the normal launcher icon (foreground over background).
  • MONOCHROME – the themed/monochrome icon (Android 13+): a tinted silhouette of the foreground.
  • NOTIFICATION / STATUS BAR – the small white silhouette used in the status bar and notifications, again derived from the foreground.

Because the monochrome and notification icons come from the foreground's shape and transparency, a background-only icon shows nothing in those two previews. That's expected, and the Studio points it out.

Note

PREVIEW SHAPES (circle, squircle, rounded, square) are only a preview of how different launchers might mask your icon. You don't pick the final shape. The device's launcher decides that, so your icon just needs to look right under any of them.

Hit SAVE ICON to export the folder and wire it into the option (CANCEL discards the current session), then patch as usual – the new icon is applied during patching.

Icon Studio

4. Patching

Control What it does CLI equivalent
Live log + N/total counter Streams progress (same output the CLI prints)
COPY ALL Copy the full log
LOG FILE → REVEAL / VIEW Open the saved log on disk
CANCEL Stop the run

Morphe runs the pipeline and streams the same log lines the CLI prints, with a patched/total counter. The log is also saved to disk (morphe-data/logs/, reachable via Tools → Open Logs). On failure you'll see PATCHING FAILED with the error in the log; on success, PATCHING COMPLETED – LOADING RESULT… advances to the result screen. CANCEL stops mid-run.

Patching Screen

Tip

If a patch fails, the saved log has the full stack trace: LOG FILE → VIEW, or Tools → Open Logs. It's exactly what to attach to a bug report.

Patching Screen Error

5. Result

Control What it does CLI equivalent
OUTPUT FILE / OPEN FOLDER → Locate the patched APK output path is set by-o / --out
ADB INSTALL (+ device picker) Install straight to a device -i / utility install
PATCH ANOTHER Start over with a new APK
TEMPORARY FILES → CLEAN UP Free this run's scratch space auto-purged by default; --disable-purge to keep
  • OUTPUT FILE / OPEN FOLDER → – the finished APK and a button to reveal it in your file manager.
  • ADB INSTALL – with a device connected and ADB enabled, install directly. Pick a device (SELECT A DEVICE), wait for READY, install; you'll see INSTALLED ON <device> on success or RETRY on failure. Device states include UNAUTH (accept the USB-debugging prompt on the phone) and UNKNOWN. If ADB is off you'll see ENABLE ADB (turn on Auto-start ADB in Settings).
  • PATCH ANOTHER restarts the flow; TEMPORARY FILES → CLEAN UP frees this run's scratch space (it shows how much).

Patching Screen Error

Note

ADB is optional. Without it, just grab the APK from the output folder and install it however you like.

After installing to a device, Morphe can make the patched app handle its supported web links, so those links open in the patched app instead of your browser or the stock app. It's ADB-only and fully reversible.

Control What it does CLI equivalent
OPEN LINKS WITH PATCHED APP Route the app's supported web links to it utility install --route-links
Also stop <app> from opening these links Hand the stock app's links over too – only when a rename patch was used and the stock app is installed --disable-stock <stockPackage>

The LINK HANDLING section appears on the Result screen once the patched app is installed and a device is connected. On success, you'll see Links routed to patched app (or …, stock disabled); the change is reversible, restoring default link handling. To run it automatically after every ADB install, turn on Route links to patched app in Settings.

Link Handling toggle

Your apps

The home screen has two tabs: SUPPORTED APPS (what your patches can target) and YOUR APPS, a history of everything you've patched with Morphe. The "Your apps" tab carries a count badge, and when newer patches are available a banner ("N patched apps have updates available") jumps you there.

Your Apps section

Each entry is a card showing the app, the patched version, and when you patched it. Tap one for the full breakdown and actions:

Action What it does CLI equivalent
INSTALL Install the patched APK to the connected device (showsINSTALL READY when the build is ready) utility install
UPDATE Re-resolve patches and re-patch when a newer patch (or app version) is available re-runpatch
RE-PATCH Patch the same app again with your saved settings re-runpatch
UNINSTALL Remove the patched app from the connected device utility uninstall
FORGET Remove the entry from Your apps (history only – doesn't touch the device)

The detail view also lists the app and Morphe versions and a per-source version breakdown, and flags when a newer patch may bump the app version.

Uninstall vs. Forget. Uninstall removes the app from your phone. Its dialog has an "Also remove from Your apps" checkbox to clear the history entry at the same time. Forget only drops the history entry and leaves the installed app untouched.

Note

When Morphe installs over ADB it records a non-Play installer source, so the Play Store won't silently update (and overwrite) your patched app. This is automatic, there's no setting for it.

Your Apps details dialog

Settings

The gear icon opens Settings – Morphe's persistent preferences. Think of it as the GUI's equivalent of the CLI flag set: most settings map directly to a patch flag.

Setting What it does Default CLI equivalent
Theme App color scheme: Light, Dark, AMOLED, System System
Expert mode Switch between Quick and Expert Off (Quick)
Auto-cleanup temp files Delete scratch files after patching On On by default; --disable-purge to turn off
Auto-start ADB Start the ADB daemon on launch so devices are monitored Off enables-i / install features
Update channel Stable or Dev app updates Smart (Dev on dev builds, else Stable) --prerelease (loosely)
Output folder Default location for patched APKs The input APK's folder -o / --out
Signing Keystore + credentials used to sign Sharedmorphe.keystore, alias Morphe, key password Morphe, store password empty --keystore, --keystore-password, --keystore-entry-alias, --keystore-entry-password
Strip Libs Native-lib architectures to keep Keep all --striplibs
Patched app runtime logs Capture logcat from a device after a patched app misbehaves
Route links to patched app After an ADB install, auto-route the app's web links to it (with an optional "disable stock app's links") Off utility install --route-links
Developer options Unlock patch-developer workflows (currently: point a local source at a folder so its newest .mpp auto-loads) Off

Settings dialog

A couple of toggles worth expanding on:

  • Auto-start ADB - when off, Morphe never starts the ADB server and all install/push features are disabled. Turn it on to install patched APKs to your phone from Morphe.
  • Update channel - Dev surfaces pre-releases; Stable only stable ones. If you've never chosen, Morphe defaults smartly (Dev when you're running a dev build).
  • Route links to patched app - when on, every ADB install is followed by routing the app's supported web links to the patched app (the Link handling step, run automatically). A nested Disable stock app's links option also stops the original app from opening those links – only relevant when a rename patch was used and the stock app is still installed. Both are reversible and need a connected device.

Signing

This is the GUI face of the --keystore* flags. Morphe signs every patched APK so it's installable; by default it uses a single shared keystore in its data folder (see Where Morphe stores its files) and reuses it across runs – Android only lets you update an installed app with an APK signed by the same key, so a stable keystore keeps re-patches installable over old builds.

Control What it does
Keystore path +BROWSE Point at your own keystore file
RESET Revert to Morphe's auto-generated default keystore
KEYSTORE PASSWORD Password for the keystore file (default: empty)
KEY ALIAS The key entry's alias (default:Morphe)
KEY PASSWORD The key entry's password (default:Morphe)
VERIFY CREDENTIALS Check the keystore opens with the entered alias/passwords
GENERATE KEYSTORE Create a fresh keystore
EXPORT Save a copy of the keystore elsewhere

Keystore signing setting

Warning

If Morphe can't find the configured keystore it warns "Keystore not found – patching will fail until you restore it, pick another, or reset." Use RESET to fall back to the default, or BROWSE to a valid one.

Note

The signer only loads BKS keystores today. Support for pointing at PKCS12 (.p12 / .pfx) or JKS (.jks) keystores – auto-converted to BKS, original untouched – is coming in an upcoming release. (Same note as the CLI --keystore flag.)

Strip Libs

Choose which native-library architectures to keep in the patched APK; everything else is stripped, shrinking the file. This sets the default the Patch selection screen reports, and maps to the CLI's --striplibs.

Architecture Use it for
arm64-v8a ARM 64-bit – most modern phones
armeabi-v7a ARM 32-bit – older phones
x86_64 Intel 64-bit – emulators / Chromebooks
x86 Intel 32-bit – legacy emulators

Strip-libs setting

Warning

Only strip architectures your device doesn't use. If you keep just arm64-v8a and install on a 32-bit device (or the wrong emulator), the app won't run. When unsure, keep your phone's architecture (almost always arm64-v8a).

Patched app runtime logs

A debugging aid: capture logcat from a connected device after a patched app crashes or misbehaves, to attach to a bug report. CLEAR DEVICE LOGS wipes logcat before you reproduce the issue; SAVE DEVICE LOGS then pulls the filtered output to a file. Both require a connected, ADB-authorized device.

Logcat Logs

Developer options

This section is for people building patches and other developers. Off by default. Toggling it on unlocks a suite of workflow options to better assist you in your development. Please feel free to make a request in the issues tab if you feel a feature could be added here.

Folder sources. Normally a local source points at a single .mpp file. With Developer options on, the add/edit source dialog gains a FOLDER button next to FILE. Pick a folder and Morphe always loads the newest .mpp inside it. Point it at your patch build-output directory once and you never re-pick the file: each rebuild is used on the next load. The source sheet also gains a refresh button (top-right) that re-scans on demand, so a patch you just built shows up without leaving the screen. Build outputs like *-sources.mpp and *-javadoc.mpp are always ignored, and you can set your own exclude patterns for a folder source from the source manager.

Note

Existing folder sources keep working even if you later turn Developer options back off. The toggle only gates creating them.

Tools

The wrench icon opens Tools – one-off actions and reference info, kept out of Settings so a destructive action doesn't sit next to your preferences.

Action What it does
OPEN LOGS Open the logs folder (morphe-data/logs/)
OPEN APP DATA Open Morphe's data folder – themorphe-data/ directory (see Where Morphe stores its files)
CLEAR CACHE Delete downloaded patches and logs (they re-download as needed)
VIEW LICENSES Browse the open-source licenses of Morphe's dependencies
Version The running app version, plus the bundled Morphe Patcher and Morphe Library versions, are shown at the bottom

Tools Setting

Note

CLEAR CACHE asks for confirmation, then removes downloaded .mpp files and logs from morphe-data/. Nothing irreversible, patches re-download on the next run.

VIEW LICENSES opens a searchable browser of the open-source licenses for every third-party library Morphe bundles. Use the search box to filter by name – handy for license compliance, or just to see what's under the hood.

Licenses browser

Installing to a device (ADB)

Morphe can push patched APKs straight to your phone over ADB:

  1. Enable Auto-start ADB in Settings (off by default).
  2. Connect your phone via USB with USB debugging enabled, and accept the authorization prompt on the device.
  3. The device indicator in the top bar shows it; click to pick a device if several are connected.
  4. After patching, use ADB INSTALL on the Result screen.

Device Indicator

Device states you may see: READY (good to go), UNAUTH (accept the USB-debugging prompt on the phone), UNKNOWN (reconnect / check the cable), and No devices connected.

Note

ADB is entirely optional: it only powers install-to-device. You can always patch without it and install the output APK manually.

CLI

Prefer the terminal, or automating Morphe in a script or CI? The CLI exposes everything the GUI does – if you just want to patch an app, the GUI above is the easier path.

The CLI suite is an extremely powerful tool. It has some general flags but is mainly divided into 5 main sub-commands (and they all lived in harmony, until the fire nation attacked. Caught that reference?):

img.png

General flags

-h, --help:

Shows all the general flags and sub commands available.

java -jar morphe-desktop-*-all.jar --help

-V, --version:

Shows the current version of the morphe-desktop.jar

java -jar morphe-desktop-*-all.jar --version

Subcommand 1: patch

This is the most fundamental sub-command. Add the patch keyword to run this sub-command.

java -jar morphe-desktop-*-all.jar patch [flag/s]

Here is a quick lookup for all the flags under this subcommand:

Flag Description
-p, --patches Paths to .mpp files or GitHub or GitLab repo URLs (repeatable, one per bundle)
--prerelease Fetch latest dev pre-release instead of stable release
(positional arg) APK file to patch
-o, --out Path to save the patched APK to
-e, --enable Enable a patch by name
--ei Enable a patch by index
-d, --disable Disable a patch by name
--di Disable a patch by index
-O, --options Set patch option values (e.g.-Okey=value)
--exclusive Disable all patches except explicitly enabled ones
-f, --force Skip APK version compatibility check
-i, --install Install to ADB device (optional serial)
--mount Install by mounting over existing app (requires root)
--keystore Path to keystore file for signing
--keystore-password Keystore password
--keystore-entry-alias Alias of the key pair in the keystore
--keystore-entry-password Password for the keystore entry
--signer Signer name in the APK signature
--unsigned Skip signing the final APK
-t, --temporary-files-path Path to store temp files
--disable-purge Keep this run's scratch files (deleted after patching by default)
--striplibs Architectures to keep, comma-separated (e.g.arm64-v8a,x86)
--bytecode-mode Bytecode mode:FULL, STRIP_SAFE, or STRIP_FAST
--verify-with-sdk Verify the patched DEX/APK using an Android SDK
--continue-on-error Continue patching if a patch fails
--options-file Path to options JSON file
--options-update Auto-update options JSON file after patching
-r, --result-file Path to save patching result JSON

Note

The examples used for each flag below only show the usage of that specific flag, but in practice, you'll almost always combine multiple flags together to customize your patching. Here's an example of a more complete command:

java -jar morphe-desktop-*-all.jar patch -p patches.mpp -o your_app_patched.apk --striplibs arm64-v8a --force --continue-on-error -d "change package name" -d "spoof signature" "your_app.apk"

-p, --patches:

Required: Yes

Default: -

This flag specifies the patch file(s) to apply to your APK. You can pass local .mpp file paths or a GitHub or GitLab repository URL, and you can repeat -p to combine several bundles in one run (see Using multiple patch bundles below). When a URL is provided, Morphe automatically downloads the .mpp file from the latest release and caches it for future runs.

java -jar morphe-desktop-*-all.jar patch --patches patches-*.mpp your_app.apk

You can also pass a GitHub or GitLab repo URL:

java -jar morphe-desktop-*-all.jar patch --patches https://github.com/MorpheApp/morphe-patches your_app.apk
java -jar morphe-desktop-*-all.jar patch --patches https://gitlab.com/MorpheApp/morphe-patches your_app.apk

Or a specific release URL:

java -jar morphe-desktop-*-all.jar patch --patches https://github.com/MorpheApp/morphe-patches/releases/tag/v1.0.0 your_app.apk
Using multiple patch bundles

-p can be repeated to combine several .mpp bundles in a single run:

java -jar morphe-desktop-*-all.jar patch -p patches-a.mpp -p patches-b.mpp your_app.apk

The name-based selection flags (-e, -d, -O) apply to the bundle they follow. Each -p starts a new bundle, and the selections after it belong to that bundle until the next -p:

java -jar morphe-desktop-*-all.jar patch -p patches-a.mpp -e "A patch from bundle A" -p patches-b.mpp -d "A patch from bundle B" your_app.apk

Index-based selections (--ei/--di) are the exception. Their numbers refer to the combined list across all supplied bundles, not a single one. Run list-patches with the same set of -p files to see the combined numbering:

java -jar morphe-desktop-*-all.jar list-patches -p patches-a.mpp -p patches-b.mpp

Then enable/disable by those combined indices. The index points to a patch no matter which bundle it came from, so its position relative to each -p doesn't matter:

java -jar morphe-desktop-*-all.jar patch -p patches-a.mpp -p patches-b.mpp --ei 57 --di 12 your_app.apk

--prerelease:

Required: No

Default: false

When using a GitHub or GitLab repo URL with --patches, fetch the latest dev pre-release instead of the latest stable release.

java -jar morphe-desktop-*-all.jar patch --patches https://github.com/MorpheApp/morphe-patches --prerelease your_app.apk

Positional argument (APK file):

Required: Yes

Default: -

The APK file you want to patch. This is passed directly without a flag name, at the end of the command.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp your_app.apk

Note

Morphe also supports .apkm, .xapk, and .apks files (split APK bundles). If you pass one of these, Morphe will automatically merge the splits into a single APK before patching.

-o, --out:

Required: No

Default: a subfolder named after the app, created next to the input APK – <app>/<app>-Morphe-<appVersion>-patches-<patchesVersion>.apk

Specify a custom output path for the patched APK.

Note

<appVersion> in the default name is read from the APK's manifest (versionName). Patching two different versions of the same app therefore produces two differently-named files instead of overwriting each other, even when the input files happen to share a name (for example both called base.apk).

java -jar morphe-desktop-*-all.jar patch -p patches.mpp -o /path/to/output.apk your_app.apk

-e, --enable:

Required: No

Default: -

Enable a specific patch by its exact name. Can be used multiple times to enable several patches.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp -e "Patch name" -e "Another patch" your_app.apk

--ei:

Required: No

Default: -

Enable a specific patch by its index number. Can be used multiple times. Use list-patches to find the index of each patch.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --ei 1 --ei 5 your_app.apk

-d, --disable:

Required: No

Default: -

Disable a specific patch by its exact name. Can be used multiple times.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp -d "Patch name" your_app.apk

--di:

Required: No

Default: -

Disable a specific patch by its index number. Can be used multiple times. Use list-patches to find the index of each patch.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --di 456 your_app.apk

Tip

You can combine -e, -d, --ei, --di and --exclusive in the same command.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --exclusive -e "Patch name" --ei 123 your_app.apk

-O, --options:

Required: No

Default: -

Set option values for patches. Options are key-value pairs passed alongside patch enable flags. To set a value to null, omit the value.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp -e "Patch name" -Okey1=value1 -Okey2=value2 your_app.apk

To set an option to null:

java -jar morphe-desktop-*-all.jar patch -p patches.mpp -e "Patch name" -Okey1 your_app.apk

Warning

Option values are typed. Setting a value with the wrong type can cause the patch to fail. Use list-patches --with-options to see the expected types.

Common types: string, true/false, 123 (integer), 1.0 (double), [item1,item2] (list)

--exclusive:

Required: No

Default: false

Disable all patches except the ones you explicitly enable with -e or --ei. Useful when you only want a specific set of patches applied.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --exclusive -e "Patch name" your_app.apk

-f, --force:

Required: No

Default: false

Skip the APK version compatibility check. By default, Morphe will warn you and skip patches that aren't compatible with your APK's version. This flag forces all compatible patches to run regardless.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --force your_app.apk

Tip

Patches are built for specific app versions. If you're using versions that are newer or older than the recommended ones, Morphe will skip all the incompatible patches (which is almost all of them since the version don't match) by default. Use --force to apply them anyway - they may still work fine, especially on recent versions.

-i, --install:

Required: No

Default: -

Automatically install the patched APK to a connected ADB device after patching.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp -i your_app.apk

If no serial is provided, it installs to the first connected device. You can optionally specify a device serial.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp -i SERIAL123 your_app.apk

Tip

Make sure ADB is working before using this flag:

adb shell exit

--mount:

Required: No

Default: false

Install the patched APK by mounting it on top of the original app. Requires root access and the original app to be installed on the device.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp -i --mount your_app.apk

Note

Make sure you have root permissions:

adb shell su -c exit

--keystore:

Required: No

Default: the shared morphe-data/morphe.keystore (see Where Morphe stores its files)

Path to a keystore file containing a private key and certificate pair to sign the patched APK with. If not specified, Morphe uses a single shared keystore in its data folder – auto-creating it on the first run and reusing it afterwards. Reusing one keystore is intentional: Android only lets you update an installed app with an APK signed by the same key, so a stable keystore means you can re-patch and reinstall over a previous build.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --keystore /path/to/keystore.bks your_app.apk

Note

The patcher signs using BKS keystores. If you point --keystore at a PKCS12 (.p12/.pfx) or JKS (.jks) file, Morphe auto-detects the format from the file's contents (not its extension) and converts a BKS copy to sign with. Your original keystore file is never modified.

--keystore-password:

Required: No

Default: empty (no password)

Password to open the keystore file itself. Different from the key entry password (--keystore-entry-password). Morphe's auto-generated default keystore has an empty store password, so you typically only need this flag when supplying your own keystore that was created with one.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --keystore keystore.jks --keystore-password "mypassword" your_app.apk

Note

The CLI and the Morphe Manager Android app share the same keystore defaults (alias "Morphe", password "Morphe"), so a keystore generated by either tool works in the other without extra flags.

--keystore-entry-alias:

Required: No

Default: "Morphe"

The alias of the private key entry inside the keystore.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --keystore keystore.jks --keystore-entry-alias "my-alias" your_app.apk

--keystore-entry-password:

Required: No

Default: "Morphe"

Password for the specific keystore entry.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --keystore keystore.jks --keystore-entry-password "mypassword" your_app.apk

--signer:

Required: No

Default: "Morphe"

The name of the signer embedded in the APK signature.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --signer "My Signer" your_app.apk

--unsigned:

Required: No

Default: false

Skip signing the patched APK entirely. The output APK will not be signed and cannot be installed directly on a device without signing it separately.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --unsigned your_app.apk

-t, --temporary-files-path:

Required: No

Default: morphe-data/tmp/ next to the JAR (falls back to ~/morphe/tmp/)

Path to a directory where Morphe stores temporary files during patching.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp -t /tmp/morphe-temp your_app.apk

--disable-purge:

Required: No

Default: false

By default, this run's scratch files are deleted once patching finishes. Pass this flag to keep them instead — useful for debugging a failed patch. Does not affect cached patches, other sessions, or config.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --disable-purge your_app.apk

--striplibs:

Required: No

Default: -

Comma-separated list of native library architectures to keep. All other architectures will be stripped from the APK, reducing file size.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --striplibs arm64-v8a,armeabi-v7a your_app.apk

--bytecode-mode:

Required: No

Default: STRIP_FAST

Controls how Morphe processes the APK's bytecode (DEX) during patching. Trade-off between speed, output size, and safety.

Value Description
FULL Rebuilds and includes all bytecode. Largest output, slowest, safest - use if you hit runtime issues with the stripped modes.
STRIP_SAFE Strips bytecode that is provably unused, while keeping anything reachable via reflection or dynamic loading.
STRIP_FAST Default. Aggressively strips unused bytecode for the smallest, fastest build. May break apps that rely on reflection.
java -jar morphe-desktop-*-all.jar patch -p patches.mpp --bytecode-mode FULL your_app.apk

Tip

If a patched app crashes at startup or has odd missing-class errors, switch to STRIP_SAFE or FULL and see if it fixes things.

Note

On Windows, Morphe currently forces bytecode mode to FULL regardless of what you pass to this flag (workaround for a platform-specific issue). The flag still works as expected on macOS and Linux.

--verify-with-sdk:

Required: No

Default: - (verification is skipped)

Verify the patched DEX and APK files using a local Android SDK after patching. Helpful for catching corrupt output before installing on a device. Pass a path to your SDK install directory, or pass the flag with no value to let Morphe auto-discover one.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --verify-with-sdk /path/to/android-sdk your_app.apk
java -jar morphe-desktop-*-all.jar patch -p patches.mpp --verify-with-sdk your_app.apk

Note

When you pass --verify-with-sdk without a path, Morphe resolves the SDK in this order:

  1. $ANDROID_HOME
  2. $ANDROID_SDK_ROOT
  3. OS-default install location:
    • macOS: ~/Library/Android/sdk
    • Windows: ~/AppData/Local/Android/Sdk
    • Linux: ~/Android/Sdk

If none of those resolve to a real SDK, Morphe errors out with a hint to either set one of the env vars or supply a path explicitly.

--continue-on-error:

Required: No

Default: false

By default, patching stops on the first patch failure. This flag lets Morphe continue applying the remaining patches even if one fails.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --continue-on-error your_app.apk

--options-file:

Required: No

Default: -

Path to a JSON file that controls which patches are enabled/disabled and their option values. Generate one using the options-create subcommand.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --options-file options.json your_app.apk

Note

If the file you specify doesn't exist yet, Morphe will automatically generate one with default values at that path and use it for the current patch. This means you can skip options-create entirely - just pass a path to a non-existent file and Morphe will create it for you.

Tip

The options file is great for repeatable patching. Generate it once (either with options-create or by letting --options-file auto-generate it), tweak it, and reuse it every time you patch.

--options-update:

Required: No

Default: false

Automatically update the options JSON file after patching to reflect the current patches. Without this flag, the file is left unchanged. New patches get added, removed patches get cleaned up.

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --options-file options.json --options-update your_app.apk

-r, --result-file:

Required: No

Default: -

Path to save a JSON file containing the patching result. The file records:

  • the package name and version of the patched app
  • whether patching succeeded overall
  • the result of each patching step
  • the list of applied patches
  • the list of failed patches, with their error details
java -jar morphe-desktop-*-all.jar patch -p patches.mpp -r result.json your_app.apk

Subcommand 2: list-patches

Lists all available patches from the supplied MPP files. Useful for finding patch names, indices, compatible packages, and options before patching.

java -jar morphe-desktop-*-all.jar list-patches --patches patches.mpp [flag/s]

Here is a quick lookup for all the flags under this subcommand:

Flag Description
--patches Paths to .mpp files or GitHub or GitLab repo URLs
--prerelease Fetch latest dev pre-release instead of stable release
--out Write patch list to a file instead of stdout
-d, --with-descriptions Show patch descriptions
-p, --with-packages Show compatible packages
-v, --with-versions Show compatible versions
-o, --with-options Show patch options
-u, --with-universal-patches Include patches compatible with any app
-i, --index Show patch index
-f, --filter-package-name Filter patches by package name
-x, --include-experimental Include experimental app versions in the output

--patches:

Required: Yes

Default: -

One or more paths to .mpp patch files or GitHub or GitLab repository URLs to list patches from. When a URL is provided, Morphe downloads the .mpp file and caches it for future runs.

java -jar morphe-desktop-*-all.jar list-patches --patches patches.mpp
java -jar morphe-desktop-*-all.jar list-patches --patches https://github.com/MorpheApp/morphe-patches

--prerelease:

Required: No

Default: false

When using a GitHub or GitLab repo URL with --patches, fetch the latest dev pre-release instead of the latest stable release.

java -jar morphe-desktop-*-all.jar list-patches --patches https://github.com/MorpheApp/morphe-patches --prerelease

--out:

Required: No

Default: -

Write the patch list to a file instead of printing to stdout. Useful in environments where > redirection is not available.

java -jar morphe-desktop-*-all.jar list-patches --patches patches.mpp --out patches-list.txt

-d, --with-descriptions:

Required: No

Default: true

Show the description of each patch. Enabled by default - use --with-descriptions=false to hide them.

java -jar morphe-desktop-*-all.jar list-patches --patches patches.mpp --with-descriptions=false

-p, --with-packages:

Required: No

Default: false

Show the packages each patch is compatible with.

java -jar morphe-desktop-*-all.jar list-patches --patches patches.mpp --with-packages

-v, --with-versions:

Required: No

Default: false

Show the compatible app versions for each patch. Requires --with-packages to be useful.

java -jar morphe-desktop-*-all.jar list-patches --patches patches.mpp --with-packages --with-versions

-o, --with-options:

Required: No

Default: false

Show the configurable options for each patch, including their keys, types, default values, and possible values.

java -jar morphe-desktop-*-all.jar list-patches --patches patches.mpp --with-options

-u, --with-universal-patches:

Required: No

Default: true

Include patches that are compatible with any app (universal patches). Use --with-universal-patches=false to only show patches targeting specific packages.

java -jar morphe-desktop-*-all.jar list-patches --patches patches.mpp --with-universal-patches=false

-i, --index:

Required: No

Default: true

Show the index of each patch. The index can be used with --ei and --di in the patch subcommand.

java -jar morphe-desktop-*-all.jar list-patches --patches patches.mpp

-f, --filter-package-name:

Required: No

Default: -

Only show patches that are compatible with the specified package name.

java -jar morphe-desktop-*-all.jar list-patches --patches patches.mpp --filter-package-name com.google.android.youtube

-x, --include-experimental:

Required: No

Default: false

By default, only stable app versions are listed. Pass this flag to also include experimental versions.

java -jar morphe-desktop-*-all.jar list-patches --patches patches.mpp --include-experimental

Subcommand 3: list-versions

Lists the most common compatible app versions for the patches in the supplied MPP files. Useful for knowing which APK version to download before patching.

java -jar morphe-desktop-*-all.jar list-versions --patches patches.mpp [flag/s]

Here is a quick lookup for all the flags under this subcommand:

Flag Description
--patches Paths to .mpp files or GitHub or GitLab repo URLs
--prerelease Fetch latest dev pre-release instead of stable release
-f, --filter-package-names Filter by package names
-u, --count-unused-patches Include unused patches in the version count
-x, --include-experimental Include experimental app versions in the output

--patches:

Required: Yes

Default: -

One or more paths to .mpp patch files or GitHub or GitLab repository URLs. When a URL is provided, Morphe downloads the .mpp file and caches it for future runs.

java -jar morphe-desktop-*-all.jar list-versions --patches patches.mpp
java -jar morphe-desktop-*-all.jar list-versions --patches https://github.com/MorpheApp/morphe-patches

--prerelease:

Required: No

Default: false

When using a GitHub or GitLab repo URL with --patches, fetch the latest dev pre-release instead of the latest stable release.

java -jar morphe-desktop-*-all.jar list-versions --patches https://github.com/MorpheApp/morphe-patches --prerelease

-f, --filter-package-names:

Required: No

Default: -

Only show versions for the specified package names. Can be used to check versions for a specific app.

java -jar morphe-desktop-*-all.jar list-versions --patches patches.mpp -f com.google.android.youtube

-u, --count-unused-patches:

Required: No

Default: false

Include patches that are not enabled by default when calculating the most common compatible versions. By default, only patches that are enabled are counted.

java -jar morphe-desktop-*-all.jar list-versions --patches patches.mpp --count-unused-patches

-x, --include-experimental:

Required: No

Default: false

By default, only stable app versions are counted and shown. Pass this flag to also include experimental versions.

java -jar morphe-desktop-*-all.jar list-versions --patches patches.mpp --include-experimental

Subcommand 4: options-create

Creates or updates an options JSON file for controlling which patches are enabled/disabled and their option values. The generated file can be passed to the patch subcommand with --options-file.

java -jar morphe-desktop-*-all.jar options-create [flag/s]

Here is a quick lookup for all the flags under this subcommand:

Flag Description
-p, --patches Paths to .mpp files or GitHub or GitLab repo URLs
--prerelease Fetch latest dev pre-release instead of stable release
-o, --out Path to the output JSON file
-f, --filter-package-name Filter patches by package name

-p, --patches:

Required: Yes

Default: -

One or more paths to .mpp patch files or GitHub or GitLab repository URLs to generate options from. When a URL is provided, Morphe downloads the .mpp file and caches it for future runs.

java -jar morphe-desktop-*-all.jar options-create -p patches.mpp -o options.json
java -jar morphe-desktop-*-all.jar options-create -p https://github.com/MorpheApp/morphe-patches -o options.json

--prerelease:

Required: No

Default: false

When using a GitHub or GitLab repo URL with --patches, fetch the latest dev pre-release instead of the latest stable release.

java -jar morphe-desktop-*-all.jar options-create -p https://github.com/MorpheApp/morphe-patches --prerelease -o options.json

-o, --out:

Required: Yes

Default: -

Path to the output JSON file. If the file already exists, Morphe will merge the current patches into it - preserving your existing settings, adding new patches, and removing patches that no longer exist.

java -jar morphe-desktop-*-all.jar options-create -p patches.mpp -o options.json

Tip

Run this command again after updating your .mpp file to keep your options file in sync. Existing settings are preserved.

-f, --filter-package-name:

Required: No

Default: -

Only include patches compatible with the specified package name in the generated options file.

java -jar morphe-desktop-*-all.jar options-create -p patches.mpp -o options.json -f com.google.android.youtube

Options JSON Workflow

The options JSON file lets you save your patch preferences and reuse them across multiple patching sessions. Here's the typical workflow:

Step 1: Generate the options file

Use options-create to generate a JSON file with all available patches and their default settings:

java -jar morphe-desktop-*-all.jar options-create -p patches.mpp -o options.json

Step 2: Edit the file

Open options.json in any text editor. You can enable/disable patches and set option values. The file contains a list of patch bundles, each with patch entries that look like:

{
  "patchName": {
    "enabled": true,
    "options": {
      "optionKey": "optionValue"
    }
  }
}

Set "enabled": false to disable a patch, or change option values as needed.

Step 3: Patch using the options file

Pass your customized options file to the patch command:

java -jar morphe-desktop-*-all.jar patch -p patches.mpp --options-file options.json your_app.apk

Step 4: Keep the file in sync (optional)

When you update your .mpp file to a newer version, patches may be added or removed. You have two ways to sync:

  • Re-run options-create - this merges new patches in while preserving your existing settings:

    java -jar morphe-desktop-*-all.jar options-create -p patches.mpp -o options.json
    
  • Use --options-update during patching - this auto-updates the file after patching:

    java -jar morphe-desktop-*-all.jar patch -p patches.mpp --options-file options.json --options-update your_app.apk
    

Note

CLI flags (-e, -d, --ei, --di, -O) always take precedence over the options file. If you enable a patch via CLI that the options file disables, the CLI wins. Morphe will log when this happens.

Tip

You can also skip options-create entirely. If you pass --options-file with a path that doesn't exist yet, Morphe will auto-generate the file with defaults for you.


Subcommand 5: utility

Parent command for utility operations. It allows for things like manually installing or uninstalling apps via ADB, clearing the cache directory, etc. Has three sub-subcommands: install, uninstall, and clear-cache.

utility install

Manually install an APK file to one or more ADB-connected devices.

java -jar morphe-desktop-*-all.jar utility install [flag/s] [device-serial...]
Flag Description
-a, --apk APK file to install
-m, --mount Mount over an existing app (requires package name and root)
--route-links After installing, route the app's supported web links to it ("open with")
--disable-stock With--route-links: also stop the named stock package from handling them
(positional arg) ADB device serial(s)
-a, --apk:

Required: Yes

Default: -

Path to the APK file you want to install.

java -jar morphe-desktop-*-all.jar utility install -a patched_app.apk
-m, --mount:

Required: No

Default: -

Mount the APK on top of an existing app instead of a regular install. Pass the package name of the app to mount over. Requires root access.

java -jar morphe-desktop-*-all.jar utility install -a patched_app.apk -m com.google.android.youtube
--route-links:

Required: No

Default: -

After installing, route the app's supported web links to it ("open with"), so they open in the patched app instead of the browser or the stock app. The package name is read from the APK, so no value is needed.

java -jar morphe-desktop-*-all.jar utility install -a patched_app.apk --route-links
--disable-stock:

Required: No

Default: -

Use with --route-links. Also stops the named stock package from handling those links – needed when a rename patch was applied and the original app is still installed.

java -jar morphe-desktop-*-all.jar utility install -a patched_youtube.apk --route-links --disable-stock com.google.android.youtube
Positional argument (device serials):

Required: No

Default: First connected device

One or more ADB device serials to install to. If not provided, installs to the first connected device.

java -jar morphe-desktop-*-all.jar utility install -a patched_app.apk SERIAL1 SERIAL2

utility uninstall

Manually uninstall a patched app from one or more ADB-connected devices.

java -jar morphe-desktop-*-all.jar utility uninstall [flag/s] [device-serial...]
Flag Description
-p, --package-name Package name of the app to uninstall
-u, --unmount Unmount instead of uninstall
(positional arg) ADB device serial(s)
-p, --package-name:

Required: Yes

Default: -

The package name of the app to uninstall.

java -jar morphe-desktop-*-all.jar utility uninstall -p com.google.android.youtube
-u, --unmount:

Required: No

Default: false

If the app was installed by mounting (using --mount), use this flag to unmount it instead of a regular uninstall.

java -jar morphe-desktop-*-all.jar utility uninstall -p com.google.android.youtube --unmount
Positional argument (device serials):

Required: No

Default: First connected device

One or more ADB device serials to uninstall from. If not provided, uninstalls from the first connected device.

java -jar morphe-desktop-*-all.jar utility uninstall -p com.google.android.youtube SERIAL1 SERIAL2

utility clear-cache

Delete Morphe's cached data: downloaded patch files, logs, and temporary files. By default it prints a short confirmation message.

java -jar morphe-desktop-*-all.jar utility clear-cache [flag/s]
Flag Description
--info Show a per-category breakdown of what was cleared and the space freed
--info:

Required: No

Default: false

Show how much was cleared from each location (patches, logs, temp) with file counts and the total space freed, instead of just a confirmation line.

java -jar morphe-desktop-*-all.jar utility clear-cache --info

Value Types Reference

When setting patch options with -O or in an options JSON file, values are typed. Using the wrong type can cause a patch to fail. Here are the supported types and how to format them:

Type Example Notes
String string Plain text
Boolean true, false
Integer 123 Whole numbers
Double 1.0 Decimal numbers
Float 1.0f Decimal withf suffix
Long 1234567890, 1L Large numbers, optionalL suffix
List [item1,item2,item3] Comma-separated, no spaces
List (mixed types) [item1,123,true,1.0] Items are parsed by their type
Empty list (any type) []
Typed empty list int[] Empty list of a specific type
Nested empty list [int[]]
List with null/empty [null,'','"]

Escaping:

Quotes and commas inside strings need to be escaped with \:

  • \" - escaped double quote
  • \' - escaped single quote
  • \, - escaped comma (treated as part of the string, not a list separator)

List items are parsed recursively, so escaping works inside lists too:

What you want How to write it
Integer as a string [\'123\']
Boolean as a string [\'true\']
List as a string [\'[item1,item2]\']
Null as a string [\'null\']

Example command:

java -jar morphe-desktop-*-all.jar patch -p patches.mpp -e "Patch name" -OstringKey=\'1\' your_app.apk

This sets stringKey to the string "1" instead of the integer 1.

🔨️ Building

Want to build Morphe Desktop from source instead of grabbing a release? Here's how.

Requirements: Java Development Kit 17 (e.g. Azul Zulu or OpenJDK).

  1. Clone the repository:

    git clone git@github.com:MorpheApp/morphe-desktop.git
    cd morphe-desktop
  2. Build it:

    ./gradlew build

Note

If the build fails with an authentication error, you need to authenticate to GitHub Packages. Create a personal access token with the read:packages scope here, then add it to ~/.gradle/gradle.properties:

gpr.user = your-github-username
gpr.key = your-token

When the build finishes, the runnable JAR is at build/libs/morphe-desktop-<version>-all.jar.