### Install and run with Bun Source: https://reseam.app/docs/api/install Installs dependencies and runs the server with Bun. The dev command restarts on changes; the start command runs production. The database is created at ./data/reseam.db and migrations run on startup. ```bash bun install bun run dev # restarts on changes bun run start # production ``` -------------------------------- ### settingsHost example Source: https://reseam.app/docs/authoring/settings Creates a settings host for the 'example' bundle, compatible with EXAMPLE_APP, using the exampleBrand. The install block runs after every patch that added settings, typically to add a row in the app's settings that calls openSettings(). ```kotlin val appSettings = settingsHost("example") { compatibleWith(EXAMPLE_APP) brand(exampleBrand) install { settingsRow.after { openSettings() } } } ``` -------------------------------- ### Apply patches with custom presets and enablement Source: https://reseam.app/docs/cli/patch Example of starting from no default patches and explicitly enabling specific patches by name. ```bash reseam patch app.apk --bundle patches.reseam --trust \ --preset none --enable "Hide ads" --enable "Allow screenshots" ``` -------------------------------- ### Linux: Install reseam binary Source: https://reseam.app/docs/cli/install Make the downloaded Linux binary executable, move it to ~/.local/bin, and verify the installation with reseam --version. ```bash chmod +x reseam-linux-x64 mv reseam-linux-x64 ~/.local/bin/reseam reseam --version ``` -------------------------------- ### Start with Docker and check health Source: https://reseam.app/docs/api/install Builds and starts the Docker container on port 4000 with a randomly generated admin token, then checks the health endpoint. Keep the ADMIN_TOKEN value for posting announcements; other configuration goes in the compose file or an .env file. ```bash ADMIN_TOKEN=$(openssl rand -hex 32) docker compose up -d --build curl http://localhost:4000/v1/health ``` -------------------------------- ### GET / Source: https://reseam.app/docs/api/endpoints Provides server metadata and main routes. ```APIDOC ## GET / ### Description Returns the server's name, version, and main routes. ### Method GET ### Endpoint `/` ### Response #### Success Response (200) - Server information including name, version, and main routes. ``` -------------------------------- ### Windows: Set JAVA_HOME and verify reseam Source: https://reseam.app/docs/cli/install Set JAVA_HOME to a JDK 21 path if Java is not on PATH, then verify the installation with reseam --version. ```powershell $env:JAVA_HOME = "C:\path\to\jdk-21" reseam --version ``` -------------------------------- ### Push a version tag to trigger the release workflow Source: https://reseam.app/docs/authoring/publishing Push a tag starting with v to trigger the template's release workflow. The example uses v0.1.0. ```bash git tag v0.1.0 git push origin v0.1.0 ``` -------------------------------- ### Run code at app start with appEntry Source: https://reseam.app/docs/authoring/changing_code Adds code that runs once when the app process starts, before any screen opens. `application` is the app's `Application` object. The manifest must name an `Application` class. ```kotlin appEntry { call(AdBlocker.init, application) } ``` -------------------------------- ### Template contents Source: https://reseam.app/docs/authoring/start Lists the files and directories in the template, including manifest.toml, settings.gradle.kts, example patches, and a release workflow. ```text manifest.toml bundle name, author, description settings.gradle.kts Reseam plugin version apps/example/patch/ two example patches in Kotlin apps/example/extensions/screenshots/ Java code one of them adds to the app .github/workflows/ a release workflow for GitHub ``` -------------------------------- ### GET /manager// Source: https://reseam.app/docs/api/endpoints Redirects to the actual manager binary location. ```APIDOC ## GET /manager// ### Description Redirects to the actual manager binary location. ### Method GET ### Endpoint `/manager//` ### Parameters #### Path Parameters - **tag** (string) - Required - The release tag. May contain letters, digits, `.`, `_`, `-`, and `+` (not first). - **file** (string) - Required - The file name. May contain letters, digits, `.`, `_`, `-`, and `+` (not first). ### Response #### Success Response (302) - Redirects to `MANAGER_BINARY_BASE_URL//`. #### Error Response (400) - Invalid characters in tag or file. ``` -------------------------------- ### Build and test the patch Source: https://reseam.app/docs/authoring/first_patch Commands to build the patch bundle, apply it to an APK, and install the patched APK. The log ends with one line per patch: applied, skipped, or failed. ```bash ./gradlew bundle reseam patch app.apk \ --bundle build/reseam/my-patches.reseam \ --trust \ --output patched.apk adb install patched.apk ``` -------------------------------- ### Create a point and add code before it with before() Source: https://reseam.app/docs/authoring/points Creates a point at the first instruction matching the given matcher and inserts code before it. The example picks the call to showBanner and makes the method return void before that call. ```kotlin val showBanner = loadFeed.point { invokeVirtual { name("showBanner") } } showBanner.before { returnVoid() } ``` -------------------------------- ### Iterate over all matches with points() and forEach() Source: https://reseam.app/docs/authoring/points Selects every matching instruction across methods with points() and iterates over matches. The example finds all findViewById calls with a specific argument, captures the resulting view, and calls hideAttribution after each one. ```kotlin methods("attribution") { literals(attributionId) } .points("findViewById") { invokeVirtual { name("findViewById") } argument(1) { literal(attributionId) } } .forEach { next { resultOf(Type.View) }.captureAs("view").after { call(Ads.hideAttribution, capture("view")) } } ``` -------------------------------- ### Move to a nearby instruction with previous() and callee() Source: https://reseam.app/docs/authoring/points Steps from a point to a nearby instruction using previous(), then turns a call into a target with callee(). The example finds the previous static call that returns Boolean and targets the method it calls. ```kotlin val premiumCheck = mainActivity .method("onCreate") { strings("premium_status") } .point { string("premium_status") } .previous { invokeStatic { returns(Type.Boolean) } } .callee() ``` -------------------------------- ### appEntry Source: https://reseam.app/docs/authoring/reference Injects code that runs once at process start within the Application's onCreate. ```APIDOC ## appEntry ### Description Emits code that runs once at process start, within the `onCreate()` of the final `Application`. Requires a manifest-declared `Application`. ### Syntax `appEntry { AppEntryScope }` ### Parameters - `AppEntryScope` (block) - Required - Code to run at process start. Provides `application` property (the `Application`); no `thisObject`. ### Errors Fails when the manifest declares no `Application`. ``` -------------------------------- ### GET /v1/ Source: https://reseam.app/docs/api/endpoints Fetches the latest stable release for the specified index. ```APIDOC ## GET /v1/ ### Description Returns the latest stable release for the given index type. ### Method GET ### Endpoint `/v1/` ### Parameters #### Path Parameters - **index** (string) - Required - The index type: `patches` or `manager`. ### Response #### Success Response (200) - **bundle** (object) - The bundle information. - **release** (object) - The latest stable release. #### Response Example ```json { "bundle": {}, "release": {} } ``` ``` -------------------------------- ### Run reseam with debug logging Source: https://reseam.app/docs/cli/install Set RUST_LOG=debug to get more detailed logs when running reseam patch. ```bash RUST_LOG=debug reseam patch app.apk --bundle patches.reseam --trust ``` -------------------------------- ### patches.json URL for users to add the bundle Source: https://reseam.app/docs/authoring/publishing Users add this URL in Reseam Manager to install and update your bundle. Replace and with your GitHub repository details. ```text https://github.com///releases/latest/download/patches.json ``` -------------------------------- ### Class and field targets Source: https://reseam.app/docs/authoring/finding_code Shows how to declare class targets by name or description, and how to get methods and fields from a class target. Class targets narrow method, field, and fieldOfType searches. ```kotlin val mainActivity = klass("com.example.app.MainActivity") val onResume = mainActivity.method("onResume") { params() } val prefs = mainActivity.fieldOfType("android.content.SharedPreferences") val adLoader = klass("adLoader") { strings("ad_unit_id", "ad_request_failed") } ``` -------------------------------- ### Declare extension dependencies in build.gradle.kts Source: https://reseam.app/docs/authoring/extensions Example build.gradle.kts for an extension module. Uses compileOnly for libraries expected in the app and implementation for libraries shipped inside the extension. ```groovy dependencies { compileOnly(project(":shared:player-stubs")) implementation("org.lsposed.hiddenapibypass:hiddenapibypass:6.1") } ``` -------------------------------- ### Brand definition example Source: https://reseam.app/docs/authoring/settings Defines a Brand with a name, light and dark ColorSchemes, a vector logo, a font, and custom typography. The brand controls the look of the settings screen and branded components, following the system theme. ```kotlin private object Files val exampleBrand = Brand( name = "Example", light = ColorScheme(primary = Color.hex("#296A48"), onPrimary = Color.hex("#FFFFFF"), ...), dark = ColorScheme(primary = Color.hex("#A2EBBD"), onPrimary = Color.hex("#000000"), ...), logo = Logo(Vector.svg(Files::class.java.getResource("/brand/logo.svg")!!.readText())), font = Font(Files::class.java.getResource("/brand/Inter.ttf")!!.readBytes()), typography = Typography(titleLarge = TextStyle(size = 22f, lineHeight = 28f, weight = 600)), ) ``` -------------------------------- ### Add, read, and edit resource strings and layouts Source: https://reseam.app/docs/authoring/app_files Adds a string resource, reads one back, gets a resource id, and edits a layout XML via editXml. Release builds may rename resources, so use id() cautiously. ```kotlin resources.addString("reseam_label", "Reseam") val appName = resources.getString("app_name") val id = resources.id("string", "app_name") resources.editXml("layout", "player_controls") { findByTag("ImageView").first()["android:layout_marginBottom"] = "6dp" } ``` -------------------------------- ### Build bundle with ./gradlew bundle Source: https://reseam.app/docs/authoring/bundles Build and sign the bundle. Output goes to build/reseam/.reseam; the build loads patches once to record metadata and fails if any patch fails at load time. ```bash ./gradlew bundle ``` -------------------------------- ### GET /openapi Source: https://reseam.app/docs/api/endpoints Retrieves the OpenAPI specification for this API. ```APIDOC ## GET /openapi ### Description Returns the OpenAPI documentation for the API. ### Method GET ### Endpoint `/openapi` ### Response #### Success Response (200) - OpenAPI specification document. ``` -------------------------------- ### Create a settings page and add a section Source: https://reseam.app/docs/authoring/settings Creates a settings page with an icon and order, then adds a section to it. Pages without settings from running patches are omitted. ```kotlin val mediaPage = SettingsPage("media", "Media", order = 10, summary = "Playback and quality", icon = media) settings(appSettings, section(mediaPage, "Playback", AppSettings.autoplay)) ``` -------------------------------- ### Build the bundle Source: https://reseam.app/docs/authoring/start Builds the bundle using Gradle. The output is written to build/reseam/example-patches.reseam. ```bash ./gradlew bundle ``` -------------------------------- ### Run reseam info on an APK Source: https://reseam.app/docs/cli/info Prints metadata from the given app file: name, package, version name and code, and counts of DEX files, APK components, classes, and methods. Fields the app doesn't have are left out. Also works with `.apkm` and `.xapk` files. ```bash reseam info app.apk ``` -------------------------------- ### GET /v1/announcements/ Source: https://reseam.app/docs/api/endpoints Fetches a single announcement by ID. ```APIDOC ## GET /v1/announcements/ ### Description Returns a single announcement by its ID. ### Method GET ### Endpoint `/v1/announcements/` ### Parameters #### Path Parameters - **id** (string) - Required - The announcement ID. ### Response #### Success Response (200) - The announcement object. ``` -------------------------------- ### GET /v1/announcements Source: https://reseam.app/docs/api/endpoints Fetches live announcements with optional filtering. ```APIDOC ## GET /v1/announcements ### Description Returns live announcements, newest first. Supports filtering by archived status and tag. ### Method GET ### Endpoint `/v1/announcements` ### Parameters #### Query Parameters - **archived** (boolean) - Optional - If `true`, includes archived announcements. - **tag** (string) - Optional - Filters announcements by tag. ### Response #### Success Response (200) - List of announcements, newest first. ``` -------------------------------- ### Run reseam perf with warmup and iterations Source: https://reseam.app/docs/cli/perf Runs the patch benchmark with 1 warmup run and 5 measured runs. Uses the same flags as `reseam patch` to select patches, plus perf-specific flags. Each measured run happens in a fresh process and writes to a temporary folder. ```bash reseam perf app.apk --bundle patches.reseam --trust --warmup 1 --iterations 5 ``` -------------------------------- ### GET /v1/patches/version/prerelease Source: https://reseam.app/docs/api/endpoints Retrieves the version of the latest prerelease for patches. ```APIDOC ## GET /v1/patches/version/prerelease ### Description Returns the version of the latest prerelease for the patches index. ### Method GET ### Endpoint `/v1/patches/version/prerelease` ### Response #### Success Response (200) - **version** (string) - The version of the latest prerelease. #### Response Example ```json { "version": "1.0.0-beta" } ``` ``` -------------------------------- ### GET /v1/health Source: https://reseam.app/docs/api/endpoints Health check endpoint returning server status and version. ```APIDOC ## GET /v1/health ### Description Returns health status and server version. ### Method GET ### Endpoint `/v1/health` ### Response #### Success Response (200) - **ok** (boolean) - Health status. - **version** (string) - Server version. #### Response Example ```json { "ok": true, "version": "1.0.0" } ``` ``` -------------------------------- ### Encode signing key to base64 for BUNDLE_SIGNING_KEY_B64 Source: https://reseam.app/docs/authoring/publishing Run this command to produce the base64-encoded signing key that you add as the repository secret BUNDLE_SIGNING_KEY_B64. The key file is expected at ~/.reseam/bundle-signing.key. ```bash base64 -w0 ~/.reseam/bundle-signing.key ``` -------------------------------- ### GET /patches// Source: https://reseam.app/docs/api/endpoints Redirects to the actual patch file location. ```APIDOC ## GET /patches// ### Description Redirects to the actual patch file location. ### Method GET ### Endpoint `/patches//` ### Parameters #### Path Parameters - **tag** (string) - Required - The release tag. May contain letters, digits, `.`, `_`, `-`, and `+` (not first). - **file** (string) - Required - The file name. May contain letters, digits, `.`, `_`, `-`, and `+` (not first). ### Response #### Success Response (302) - Redirects to `PATCHES_BUNDLE_BASE_URL//`. #### Error Response (400) - Invalid characters in tag or file. ``` -------------------------------- ### Build branded dialogs with Reseam.bundle().ui() Source: https://reseam.app/docs/authoring/settings Extensions can build their own screens and dialogs in the brand. Ui builds text in the brand's type roles, buttons, list items in groups, switches, search bars, outlined text fields, top bars, and dialogs, all in the system's current theme. ```java Ui ui = Reseam.bundle("my-patches").ui(activity); ui.dialog() .title("Download finished") .message("Saved to Downloads.") .dismissAction("Close") .action("Open", () -> open(file)) .show(); ``` -------------------------------- ### GET /v1/patches/keys Source: https://reseam.app/docs/api/endpoints Retrieves the public key used to sign patch bundles. ```APIDOC ## GET /v1/patches/keys ### Description Returns the public key of the bundle signer for patches. ### Method GET ### Endpoint `/v1/patches/keys` ### Response #### Success Response (200) - **public_key** (string) - The public key of the bundle signer. #### Response Example ```json { "public_key": "..." } ``` ``` -------------------------------- ### GET /v1/patches/history/prerelease Source: https://reseam.app/docs/api/endpoints Fetches the full release history including prereleases for patches. ```APIDOC ## GET /v1/patches/history/prerelease ### Description Returns every release, including prereleases, for the patches index. ### Method GET ### Endpoint `/v1/patches/history/prerelease` ### Response #### Success Response (200) - **bundle** (object) - The bundle information. - **releases** (array) - List of all releases, including prereleases. #### Response Example ```json { "bundle": {}, "releases": [] } ``` ``` -------------------------------- ### Build and publish a bundle manually Source: https://reseam.app/docs/authoring/publishing Builds the bundle with Gradle and publishes it with the reseam CLI. The --url flag specifies the bundle's download URL. This adds the release to patches.json in the current folder, or creates it. Keep that file between releases; each release keeps its own URL. ```bash ./gradlew bundle -PreleaseTag=v0.1.0 reseam publish patches build/reseam/my-patches.reseam \ --url https://example.com/my-patches-0.1.0.reseam ``` -------------------------------- ### reseam bundle pack Source: https://reseam.app/docs/cli/bundle Packs and signs a staging folder into a .reseam file. The staging folder contains manifest.toml, patch .jar and .dex files, and optional resources/. Requires Java. ```bash reseam bundle pack build/reseam/stage --key ~/.reseam/bundle-signing.key --out my-patches.reseam ``` -------------------------------- ### GET /v1//history Source: https://reseam.app/docs/api/endpoints Fetches the full history of stable releases. ```APIDOC ## GET /v1//history ### Description Returns every stable release for the given index type. ### Method GET ### Endpoint `/v1//history` ### Parameters #### Path Parameters - **index** (string) - Required - The index type: `patches` or `manager`. ### Response #### Success Response (200) - **bundle** (object) - The bundle information. - **releases** (array) - List of all stable releases. #### Response Example ```json { "bundle": {}, "releases": [] } ``` ``` -------------------------------- ### GET /v1//version Source: https://reseam.app/docs/api/endpoints Retrieves the version of the latest stable release. ```APIDOC ## GET /v1//version ### Description Returns the version of the latest stable release for the given index type. ### Method GET ### Endpoint `/v1//version` ### Parameters #### Path Parameters - **index** (string) - Required - The index type: `patches` or `manager`. ### Response #### Success Response (200) - **version** (string) - The version of the latest stable release. #### Response Example ```json { "version": "1.0.0" } ``` ``` -------------------------------- ### Build from source with cargo xtask Source: https://reseam.app/docs/cli/install Build the reseam-cli binary from the engine repository. Requires Rust toolchain, JDK, and BoltFFI CLI. ```bash cargo xtask regen patch-api cargo xtask runtime cargo build --release -p reseam-cli ``` -------------------------------- ### GET /v1//prerelease Source: https://reseam.app/docs/api/endpoints Fetches the latest prerelease for the specified index. ```APIDOC ## GET /v1//prerelease ### Description Returns the latest prerelease for the given index type. ### Method GET ### Endpoint `/v1//prerelease` ### Parameters #### Path Parameters - **index** (string) - Required - The index type: `patches` or `manager`. ### Response #### Success Response (200) - **bundle** (object) - The bundle information. - **release** (object) - The latest prerelease. #### Response Example ```json { "bundle": {}, "release": {} } ``` ``` -------------------------------- ### Define a target method with method() Source: https://reseam.app/docs/authoring/first_patch Creates a target that describes the method to patch. The label 'showRatePrompt' is only for error messages; the actual method name is obfuscated. The target matches a method that loads the string 'rate_prompt_shown' and returns void. ```kotlin package app.example.patches import app.reseam.patch.Type import app.reseam.patch.method val showRatePrompt = method("showRatePrompt") { strings("rate_prompt_shown") returns(Type.Void) } ``` -------------------------------- ### Write, copy, and delete files with files.* Source: https://reseam.app/docs/authoring/app_files Writes, copies from the bundle's resources folder, and deletes files in the APK. ```kotlin files.write("assets/reseam/logo.png", bytes) files.copy("resources/logo.png", "assets/logo.png") files.delete("assets/tracking.json") ``` -------------------------------- ### GET /.json Source: https://reseam.app/docs/api/endpoints Retrieves the entire index for a given index type. ```APIDOC ## GET /.json ### Description Returns the whole index for the given index type (`patches` or `manager`). ### Method GET ### Endpoint `/.json` ### Parameters #### Path Parameters - **index** (string) - Required - The index type: `patches` or `manager`. ### Response #### Success Response (200) - The full index content. #### Response Example ```json { "releases": [] } ``` ``` -------------------------------- ### Bundle project layout Source: https://reseam.app/docs/authoring/bundles Shows the required folder layout for a Reseam bundle project. Each app's patches compile to -patches.jar, a shared patch/ folder to -patches.jar, and each extension to a DEX file. ```text my-patches/ manifest.toml settings.gradle.kts apps//patch/ Kotlin patches for one app apps//extensions// Java code added to that app shared// Java code used by several apps shared//patch/ Kotlin used by several apps' patches (optional) resources/ files patches copy into apps (optional) ``` -------------------------------- ### Generate a bundle signing key Source: https://reseam.app/docs/authoring/start Creates a signing key for the bundle. The public key is printed; keep the key file private and out of the repository. ```bash reseam bundle keygen --out ~/.reseam/bundle-signing.key ``` -------------------------------- ### Add image resources with resources.addFile Source: https://reseam.app/docs/authoring/app_files Adds drawable and mipmap files as resources. The last argument is the configuration: empty for default, a density, 'night' or 'notnight', or 'vN'. XML passed this way is compiled. ```kotlin resources.addFile("drawable", "reseam_icon", "res/reseam_icon.png", bytes) resources.addFile("mipmap", "reseam_launcher", "res/mipmap-xxhdpi/reseam_launcher.png", png, "xxhdpi") ``` -------------------------------- ### Enum target by constants Source: https://reseam.app/docs/authoring/finding_code Finds an enum by its constant names and gets a specific constant field. Obfuscation renames enum fields but not the names their constants report. ```kotlin val plan = klass("plan") { enumConstants("FREE", "PREMIUM") } val premium = plan.enumConstant("PREMIUM") planGetter.replace { returnValue(staticField(premium)) } ``` -------------------------------- ### reseam publish patches: write release index Source: https://reseam.app/docs/cli/publish Writes or updates the release index for patches. Reads the bundle's name, author, public key, version, and patch list from the signed bundle, so the bundle must be packed with --version. A release with the same version is replaced, the newest release goes first, and only the newest release and newest prerelease keep their patch lists. The --url flag is required; use --out to change the output file (default patches.json). Refuses to change the public key already recorded in the index. ```bash reseam publish patches my-patches.reseam \ --url https://example.com/my-patches-1.2.0.reseam ``` -------------------------------- ### Target mismatch error message Source: https://reseam.app/docs/authoring/first_patch Example error message when no method matches the target. Shows the searched candidates and near misses, helping diagnose why the target did not match. ```text No method matched 'showRatePrompt'. Searched 3 candidate(s). Near misses: Lcom/example/a/b;->c()Z [missed: return type mismatch]; ... ``` -------------------------------- ### List bundle contents and patch an APK Source: https://reseam.app/docs/authoring/start Lists the contents of the built bundle, then patches an APK with the 'Enable debugging' patch, trusting the public key. The --enable flag is required because patches are off by default. ```bash reseam bundle list build/reseam/example-patches.reseam reseam patch app.apk \ --bundle build/reseam/example-patches.reseam \ --trust \ --enable "Enable debugging" \ --output patched.apk ``` -------------------------------- ### Internal patch without a name Source: https://reseam.app/docs/authoring/patches `patch { }` without a name creates an internal patch that users never see. It only runs when a patch that runs depends on it. Use it for shared setup. ```kotlin val adBlockerSetup = patch { compatibleWith(EXAMPLE_APP) execute { appEntry { call(AdBlocker.init, application) } } } ``` -------------------------------- ### Define a binding with bind() Source: https://reseam.app/docs/authoring/bindings Defines a binding named `post` that locates the source class via `fromField` and describes the path to a `videoUrl` string. The path uses steps like `member`, `listGetter`, `cast`, and `callInterface`. If any step is null, the result is null. ```kotlin val post = bind("post") { fromField("feedPostField") { owner(onPostClicked.owner) nearestObjectReadBeforeString("post_clicked") } string("videoUrl") { member("attributes") listGetter("videos") { rankBy("callers followed by cast") { callSitesFollowedByCast(VIDEO) } } first() cast(VIDEO) callInterface(VIDEO, "getUrl", "()Ljava/lang/String;") } } ```