Skip to content

Repository files navigation

 ___    ___ ___  __    ___      ___ _____ ______
|\  \  /  /|\  \|\  \ |\  \    /  /|\   _ \  _   \
\ \  \/  / | \  \/  /|\ \  \  /  / | \  \\\__\ \  \
 \ \    / / \ \   ___  \ \  \/  / / \ \  \\|__| \  \
  /     \/   \ \  \\ \ \  \    / /   \ \  \    \ \  \
 /  /\   \    \ \__\\ \__\ \__/ /     \ \__\    \ \__\
/__/ /\ __\    \|__| \|__|\|__|/       \|__|     \|__|
|__|/ \|__|

The iOS tweak toolbox, in your terminal.

Inject tweaks into apps · extract them back out · convert jailbreak packages between formats.

New here? Run xkvm tui. It asks the same questions the flags do, one at a time, and runs the exact same engine under the hood.

CI Go License: MIT


What is xkvm?

xkvm is a command-line tool for sideloading iOS apps. Give it an app (.ipa, .tipa, or .app) and a tweak, and it handles the parts that are easy to get wrong: wiring the tweak so it loads, re-signing the result, and repacking the container.

With xkvm you can:

  • Inject tweaks into an app. Add a tweak (.dylib, .deb, framework, or bundle), wire it up so it loads, and re-sign everything so the app still installs.
  • Extract tweaks from an app. Pull the injected tweaks out of a modified app: dylibs, frameworks, bundles, app extensions.
  • Convert jailbreak packages. Translate a tweak package between the three jailbreak styles: rootful (classic), rootless (modern /var/jb), and roothide (jbroot), and between .deb and .dylib forms.
  • Fetch tweaks from Cydia repos. Resolve a tweak by its bundle id through Canister / MobileAPT, including its dependencies.
  • Fix sideloading problems. Inject a bundled set of App Store and keychain repair dylibs, and apply compatibility patches to apps that misbehave when sideloaded.

Everything is written in Go. No external tools are required for the heavy lifting. macOS is the primary platform; the core also builds and tests on Linux.

Features

Tweak injection Add dylibs, debs, frameworks, and bundles to an app, with correct load commands (@rpath, @executable_path) and re-signing.
Tweak extraction xkvm extract pulls every injected artifact back out of an app, recording where each one lived so re-injection is automatic.
Package conversion Ports of the ecosystem's own converters: rootful → rootless → roothide, and .deb to .dylib.
Repo fetching --fetch resolves tweaks by bundle id through Canister / MobileAPT, with dependency recursion.
Shareable configs .cyan files capture every option: generate with cgen, validate with cyan-check, apply with -z.
Sideload fixes --patch injects the bundled sideload-repair dylib set; --ellekit swaps in the real ElleKit hooking runtime.
Completeness checks xkvm check verifies every bundle-relative dependency resolves, so merged tweaks don't crash at launch.
Deterministic builds Same input, same output, with zip-slip-safe extraction and pure-Go Apple-format code signatures.

First run

xkvm tui          # menu mode: answer the questions, no flags to remember

Or straight to the command line:

xkvm -i App.ipa -f MyTweak.dylib -o App-Tweaked.ipa   # inject a tweak
xkvm extract -i App-Tweaked.ipa -o tweaks/            # pull tweaks back out
xkvm rootless -i tweak.deb -o tweak-rootless.deb      # convert a package
xkvm check -i App-Tweaked.ipa                         # find missing files before you install

Installation

One-shot install — downloads the latest release binary, no Go needed:

OS One-liner
macOS / Linux (Ubuntu, Arch, ...) curl -fsSL https://raw.githubusercontent.com/blessed0x/xkvm-ios-injector/main/scripts/install.sh | bash
Windows (PowerShell) irm https://raw.githubusercontent.com/blessed0x/xkvm-ios-injector/main/scripts/install.ps1 | iex
Any OS with Go go install github.com/blessed0x/xkvm-ios-injector/cmd/xkvm@latest

The installers detect your OS and architecture, download the matching release asset, and put xkvm on your PATH. Before the first release ships, they fall back to go install automatically. Set XKVM_PREFIX (bash) to choose the install location (default: ~/.local/bin, or /opt/homebrew/bin on Apple Silicon with Homebrew).

From source (requires Go 1.26+):

git clone https://github.com/blessed0x/xkvm-ios-injector.git
cd xkvm-ios-injector
make build          # produces ./bin/xkvm

Check that it works:

xkvm --help

Shell completion (optional)

Tab-completion for flags and subcommands is built in. Generate the script for your shell and load it from your config file:

bash:

xkvm completion bash | sudo tee /etc/bash_completion.d/xkvm > /dev/null

Or, if you use Homebrew's bash (or just want it per-user):

mkdir -p ~/.bash_completion.d
xkvm completion bash > ~/.bash_completion.d/xkvm
# add this line to ~/.bashrc:
# source ~/.bash_completion.d/xkvm

zsh:

mkdir -p ~/.zfunc
xkvm completion zsh > ~/.zfunc/_xkvm
# add these lines to ~/.zshrc:
# fpath+=~/.zfunc
# autoload -Uz compinit && compinit

fish:

xkvm completion fish > ~/.config/fish/completions/xkvm.fish

If you installed xkvm to a different location, make sure that location is on your PATH so the completion script can find it.

Quick start

Inject a tweak into an app:

xkvm -i App.ipa -o Patched.ipa -f MyTweak.dylib

Inject several tweaks and fakesign (AppSync / TrollStore):

xkvm -i App.ipa -o Patched.ipa -f TweakA.dylib -f TweakB.deb -s

Extract the tweaks from a modified app:

xkvm extract -i Patched.ipa -o extracted-tweaks/

Convert a tweak package for a different jailbreak:

xkvm rootless -i classic.deb -o modern.deb        # rootful → rootless
xkvm rootless -i classic.deb -o xina.deb --xina   # rootful → rootless, Xina style
xkvm rootful  -i modern.deb  -o classic.deb       # rootless → rootful (either style)
xkvm roothide -i modern.deb  -o jbroot.deb        # rootless → roothide
xkvm undeb    -i tweak.deb   -o artifacts/        # unpack a .deb
xkvm debify   -i MyTweak.dylib -o MyTweak.deb     # .dylib → .deb

Fetch a tweak from a Cydia repo:

xkvm -i App.ipa -o Patched.ipa --fetch com.example.tweak

Download an app from the App Store by Apple ID (the ipatool / PancakeStore flow):

xkvm decrypt 310633997 --apple-id you@example.com --password …   # latest version
xkvm decrypt https://apps.apple.com/us/app/…/id310633997          # …or a link or bundle id
xkvm decrypt --logout                                            # forget the saved login

Commands

Command What it does
xkvm -i <app> ... Inject tweaks, modify the app, and re-sign it
extract Pull tweaks (dylibs, frameworks, bundles, app extensions) out of an app
rootless Convert a rootful package to the modern rootless layout (--xina for the Xina short-path style)
rootful Convert a rootless package back to the classic rootful layout
roothide Convert a rootless package to a roothide-jailbreak package
debify Build a MobileSubstrate .deb from a dylib or payload directory
undeb Unpack a .deb into its tweak artifacts
check Verify bundle-relative dependencies resolve (merge completeness)
cyan-check Validate a .cyan config file before applying it
cgen Turn your flags into a shareable .cyan config file
decrypt Download an App Store app by Apple ID (with sinfs + metadata) for tweaking
device Control a connected iPhone/iPad: pair, info, install, launch, syslog (go-ios)

Device control in one breath

xkvm device list                  # who's plugged in
xkvm device pair                  # tap "Trust" on the phone, run again
xkvm device install App-Tweaked.ipa   # stream it straight onto the device
xkvm device launch com.example.app    # run it, print the pid
xkvm device syslog                # parsed logs, Ctrl-C to stop (--process/--contains)
xkvm device screenshot            # save a PNG of the screen
xkvm device watch                 # live attach/detach events
xkvm device devmode               # iOS 16+ Developer Mode switch status
xkvm device forward 8080 8080     # localhost -> device port (iproxy style)
xkvm device pasteboard get        # read the device clipboard
xkvm device omega                 # clear revoke + cert blacklists (Omega)

device omega is the jailbreak.party Omega blacklist remover, ported to the native stack: a partial-backup restore that replaces the revoke and certificate-validity databases with directories the system can't write to — Apple forgets every revoke. Version policy: iOS 16-18 and 26 are supported (26.1 live-verified), <16, 19-25 and >=27 are hard-blocked, and only future unreleased iOS (28+) gets the untested caution. Apple never released iOS 19-25: it moved 18 -> 26 with year-based versioning, so there was never a 19-25 untested gap; on iOS 27 the backup system changed and the restore could reset your data. Turn off Find My and back up first; it asks you to type CONTINUE. Same feature lives in the TUI under device → omega.

device is the other half of the loop: build the .ipa with inject, install it with device, watch its logs with device syslog — no SideStore or Xcode. Backed by go-ios (the same pure-Go talk-to-Apple stack as the Mach-O tooling). See docs/device-control.md for the full surface. The same control surface is in the TUI under the device category — pair, info, battery, apps (launch/uninstall the picked app), install, launch by bundle id, kill by pid, and a live syslog screen.

Note for iOS 17+: launch/kill/install/screenshot need a developer tunnel the same way pymobiledevice3 needs a mounted Developer Disk Image — so xkvm starts one for you in the background when an operation hits that gate, then retries over it (XKVM_NO_AUTO_TUNNEL=1 prints the manual command instead). syslog streams os_trace logs over that same tunnel on stock iOS 17+. pair/info/battery/apps work without any tunnel, and one physical phone showing up on both USB and WiFi counts as one device.

Common options

Flag What it does
-i, --input The app to modify (.ipa, .tipa, or .app)
-o, --output Where to write the result (defaults to overwriting the input)
-f, --file A tweak to inject — repeatable (dylibs, debs, frameworks, bundles)
-z, --cyan A .cyan config file to apply — repeatable
--fetch Fetch a tweak by bundle id via Canister / MobileAPT
--ellekit Use the real ElleKit hooking runtime
--patch Inject the bundled sideload-repair dylib set (implies --fakesign)
-s, --fakesign Fakesign all binaries (AppSync / TrollStore)
-b / -n / -v / -m Change bundle id, name, app version, or minimum OS version
-k, --icon Change the app icon

Run xkvm --help for the complete list.

How it works

  • Pure-Go Mach-O editing and code signing — built on blacktop/go-macho and its pkg/codesign, producing Apple-format signatures macOS itself validates. No ldid or install_name_tool needed.
  • Faithful package conversion — the converters are ports of the ecosystem's own tools (rootless-patcher, RootHidePatcher), pinned byte-for-byte against upstream output by golden tests.
  • Safety by default — zip-slip-safe container handling, deterministic builds, and a post-conversion audit that flags surviving rootful paths.

Documentation

Project status

Milestone Content Status
M0 Scaffold: CLI, logging, CI done
M1 Containers: ipa/deb/plist, extract command done
M2 Injection parity (hybrid toolchain) done (superseded by M3)
M3 Pure-Go Mach-O (go-macho / codesign) done
M4 Azule fetch: Canister / MobileAPT done
M5 iOS on-device: decrypt, cross-compile planned
M5.5 Device control: pair/install/launch/syslog (go-ios) done
M6 Ship: brew tap, releases, docs planned

Contributing

Contributions are welcome — bug reports, feature ideas, and pull requests. See CONTRIBUTING.md to get started. Every behavior change ships with a test; the house style is golden tests that pin converters byte-for-byte against upstream output.

Acknowledgments

xkvm descends from two lineages and borrows conventions from several more:

  • cyan / pyzule-rw (Unlicense) — the app-modifier / tweak-injector lineage xkvm descends from
  • Azule (archived) — repo fetching and App Store decryption ideas
  • Feather (GPL-3.0) — sideloading and ElleKit conventions
  • rootless-patcher (MIT) — rootless conversion semantics
  • RootHidePatcher (GPL) — roothide conversion semantics (reference only)
  • Derootifier (GPL-3.0) — format reference for --tweakinject
  • ElleKit — the hooking runtime
  • blacktop/go-macho (MIT) — Mach-O parsing and code signing

License

The xkvm source code is licensed under the MIT License.

xkvm also bundles third-party components (the ElleKit runtime, sideload-repair dylibs, and a Cephei framework) under their own licenses. See NOTICE for the full provenance.

About

Pure-Go IPA tweak injector. Inject dylibs into IPA files & sideload on iOS 17+. Byte-faithful pyzule/cyan rewrite.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages