___ ___ ___ __ ___ ___ _____ ______
|\ \ / /|\ \|\ \ |\ \ / /|\ _ \ _ \
\ \ \/ / | \ \/ /|\ \ \ / / | \ \\\__\ \ \
\ \ / / \ \ ___ \ \ \/ / / \ \ \\|__| \ \
/ \/ \ \ \\ \ \ \ / / \ \ \ \ \ \
/ /\ \ \ \__\\ \__\ \__/ / \ \__\ \ \__\
/__/ /\ __\ \|__| \|__|\|__|/ \|__| \|__|
|__|/ \|__|
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.
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.deband.dylibforms. - 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.
| 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. |
xkvm tui # menu mode: answer the questions, no flags to rememberOr 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 installOne-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/xkvmCheck that it works:
xkvm --helpTab-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/nullOr, 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/xkvmzsh:
mkdir -p ~/.zfunc
xkvm completion zsh > ~/.zfunc/_xkvm
# add these lines to ~/.zshrc:
# fpath+=~/.zfunc
# autoload -Uz compinit && compinitfish:
xkvm completion fish > ~/.config/fish/completions/xkvm.fishIf you installed xkvm to a different location, make sure that location is on your PATH so the completion script can find it.
Inject a tweak into an app:
xkvm -i App.ipa -o Patched.ipa -f MyTweak.dylibInject several tweaks and fakesign (AppSync / TrollStore):
xkvm -i App.ipa -o Patched.ipa -f TweakA.dylib -f TweakB.deb -sExtract 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 → .debFetch a tweak from a Cydia repo:
xkvm -i App.ipa -o Patched.ipa --fetch com.example.tweakDownload 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| 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) |
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.
| 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.
- Pure-Go Mach-O editing and code signing — built on
blacktop/go-machoand itspkg/codesign, producing Apple-format signatures macOS itself validates. Noldidorinstall_name_toolneeded. - 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.
- ARCHITECTURE.md — design, milestones, and fidelity notes
- docs/HANDOFF.md — handoff doc: full architecture + current state, for a new agent/session
- docs/ellekit-build.md — building ElleKit for injection
- docs/roothide-install.md — installing converted packages on a roothide jailbreak
- docs/self-improve-protocol.md — the static + dynamic bug-hunting and code-cleanup loop
- feather-ellekit-spec.md — Feather-style ElleKit integration spec
| 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 |
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.
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
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.