Open-source project
cinit/QAuxiliary avatar
cinit/QAuxiliary

QAuxiliary: an Xposed module that patches QQ from the inside

QNotified phoenix - To make OICQ great again

5,791 stars422 forksJavaNOASSERTION

At a glance

What is it?
QAuxiliary is a QNotified-based Xposed module for QQ, TIM, QQLite and QQ HD. The interesting parts are the runtime patching it needs, the two release channels, and the list of features the maintainers have promised never to build.
Who is it for?
QAuxiliary is a serious piece of engineering attached to an unusual premise: that the host app is closed, obfuscated and updated without notice, so the module has to keep rediscovering it. The runtime patching story, the byte-buddy plus InMemoryDexClassLoader approach that keeps it off Google Play, and the deliberate refusal to ship money-related or abuse features all point the same way.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • cinit/QAuxiliary5,791 ★ · +14
Star history
Repository2026-10-072026-10-23
cinit/QAuxiliary5.8k5.8k

14 Stars in the last 16 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

An Xposed module for QQ and TIM, not an application of its own

The repository description is blunt about the lineage: QNotified phoenix, to make OICQ great again. QAuxiliary is built on top of QNotified, which is the framework that lets an Xposed module attach to another app's process and rewrite its behaviour at runtime. The README is written in Chinese, and the tree reflects that it is a full Android application project rather than a small library: `app/`, `build-logic/`, `libs/`, `loader/`, `docs/`, `gradle/`, `gradlew` and `settings.gradle.kts`.

The requirements are specific enough to be useful, which is more than most module READMEs manage. Android 7.0 or newer. QQ 8.2.0 or newer, TIM 2.2.0 or newer, QQLite 4.0 or newer, QQ HD 5.9.3 or newer. Once the module is activated you reach its settings by tapping QAuxiliary inside QQ's or TIM's own settings screen, which is the one bit of UI design that makes the project feel finished rather than experimental.

There is a second path for people without an Xposed environment. The README points at `docs/instruction-qauxv-frida.md` and explains that QAuxiliary can be loaded through Frida instead, on a rooted device. That is a meaningful fallback, because it removes the LSPosed dependency without removing the patching requirement.

The scale is substantial: about 5,755 stars, 416 forks, 266 open issues, topics `oicq`, `qnotified`, `qq`, `tim`, `xposed` and `xposed-module`, default branch `main`, last push on 2026-09-20. The license field reads NOASSERTION rather than a standard identifier, because the project ships its own EULA at `app/src/main/assets/eula.md` linking to a custom licence document, and the README's copyright block names gao_cai_sheng with a CC BY-NC-SA 4.0 grant over the licence text itself.

The features the maintainers promise never to build

Most project READMEs describe what a thing does. This one spends equal attention on what it will not do, and the list is short enough to quote in full: no grabbing red packets or other money-related features, no modifying chat history in ways that could be abused, no mass messaging, and nothing likely to interfere with other users' normal use, with crashes given as the example.

The stated reasoning is practical rather than moral. The project is permanently open source and welcomes pull requests, but a feature that becomes widely used for abuse, or that seriously degrades the experience of other people on the service, will be removed. That is a maintainer describing triage policy, and it explains a lot about the shape of the 266 open issues: a queue of bug fixes and compatibility work rather than a queue of feature requests.

The same section explains why the project takes no donations. Given the nature of the work, the team says it does not accept money in any form and would rather have more people contributing code. `.github/CONTRIBUTING.md` is the pointer for that, and `renovate.json` at the root suggests dependency updates are automated rather than hand-maintained.

The release notes reinforce the tone. Every one of the three most recent releases ends with a warning that QQ's risk control is currently severe, that only users still running the module should consider updating, and that each user should assess for themselves whether the module risks their account being flagged or frozen. A project that prints a risk disclaimer under its own changelog is not going to grow by promising you everything.

Rolling releases, two channels, and a five-part version number

QAuxiliary does not do scheduled releases. It rolls, and it publishes twice, to two different audiences.

The `CI` version is built automatically after a commit lands. The README is careful to say it may contain documentation or CI pipeline changes only, will never have release notes written for it, and may contain severe functionality or behaviour anomalies because it is compiled and published by an automated open-source pipeline. The `recommended CI` version is the one curated by the team: it bundles the significant feature changes and accumulated fixes since the last one, and deliberately excludes anything unstable or still in development. The team's position is that each user should pick a version matching their own tolerance.

The version number encodes all of this: `major.minor.bugfix.rev.commit`, where `rev` is a commit count and `commit` is the first seven characters of the commit hash that triggered the build. So v1.6.1's artifacts are named `QAuxv-v1.6.1.r3000.5310e4c-arm64.apk`, which tells you immediately that this is commit 3000, built from `5310e4c`. There is no ambiguity about what you installed.

Distribution is split the same way. Three Telegram channels are linked in the header: one for the recommended CI build, one for every CI build, and one general chat. GitHub releases carry only the recommended CI version. The LSPosed modules repository carries only the recommended CI version as well, which is the channel most people installing through a module manager will actually get.

Each release publishes sha256 checksums for four APK variants, arm32, arm64, armAll and universal, which is a more complete matrix than most Android projects bother with.

Why there is no Google Play listing

The README has a numbered list of distribution channels and then answers the question readers always ask, which is worth quoting because the answer is a genuine technical constraint rather than a policy dodge.

Google Play does not permit apps that dynamically load external code at runtime. QAuxiliary needs to do exactly that. To work with a host application whose class names are obfuscated and only resolvable at runtime, the module dynamically inherits the host's classes, generates code on the fly with byte-buddy, and loads it through InMemoryDexClassLoader so that no dex file is written to disk. That combination is precisely the behaviour Play prohibits.

This is the single most informative paragraph in the README, because it explains the project's architecture as a consequence of a constraint. Everything about QAuxiliary follows from the fact that it must work against a target that changes without warning: the runtime code generation, the in-memory class loading, the need to rediscover obfuscated members on every QQ update, and the rolling release cadence that ships a build per commit rather than waiting for a coordinated release.

It also frames the project differently from a typical Android app. There is no Play Store install, no Play Protect scanning, no automatic update channel and no stable public API to depend on. The trust model is checksummed APKs from Telegram and GitHub, plus the LSPosed repository, checked by hand.

Building it: JDK 17, Ninja 1.11 for C++20 modules, and ccache

The build documentation is the most practically useful section of the README, and it is unusually honest about how fussy the environment is.

You need git, Ninja 1.11 or newer, JDK 17 or newer (21 works), the Android SDK, and optionally ccache. The exact Android SDK, NDK and CMake versions are pointed at `build-logic/convention/src/main/kotlin/Version.kt`, which is the file to read before you start guessing. The Ninja version is not arbitrary: 1.11 is when Ninja gained C++20 module support, and the project uses that. If your Ninja lives somewhere unusual you can point Gradle at it by setting `qauxv.override.ninja.path` in `local.properties`.

Cloning is not a plain `git clone`, because the submodule tree contains second-level submodules that are unnecessary or not public. The README gives the exact incantation:

shell
git clone https://github.com/cinit/QAuxiliary
cd QAuxiliary
git submodule update --init
git -C "libs/LSPlant" config "submodule.test/src/main/jni/external/lsprism.update" none
git -C "libs/LSPlant" config "submodule.test/src/main/jni/external/lsparself.update" none
git -C "libs/LSPlant" config "submodule.docs/doxygen-awesome-css.update" none
git -C "libs/mmkv/MMKV" config "submodule.Python/pybind11.update" none
git submodule foreach git submodule update --init --recursive

After trimming, there are 14 submodules. If the clone hangs, the README's advice is to check your network and proxy configuration.

ccache is optional but recommended, with real caveats. If your ccache is older than 4.8, add `CCACHE_NOHASHDIR=true` to the gradle daemon's environment, or run `ccache -o hash_dir=false`, which the README flags as a persistent global setting. On Windows, the msys2 build of ccache is known to hang during the sync phase, so use the official build instead. To opt out entirely, set `ccacheExecutablePath` to `null` in `app/build.gradle.kts`.

Then it is two Gradle invocations:

shell
./gradlew :app:assembleDebug
./gradlew :app:synthesizeDistReleaseApksCI

The second is the one that produces the CI channel artifacts, which tells you the release pipeline and the local build share a task.

What the release notes reveal about the cost of patching a moving target

The changelogs are the best evidence for how this project actually ages, and they are worth reading as a list of collisions between a module and a host application.

v1.5.9, published 2025-08-20, includes a fix for the module randomly failing on QQ 9.2.5. That single line is the whole maintenance challenge in miniature. The module's functionality depends on internal QQ implementation details, QQ ships changes on its own schedule, and when it changes something the module was relying on, the module breaks in ways that are version-specific and hard to reproduce.

v1.6.0, from 2026-02-15, adds device type modification, notification channel management, chat photo sharing enhancements, voice message to text conversion, permission spoofing, and a batch of interface changes including hiding Qzone VIP, removing image preview limits and enabling chat summarisation. v1.6.1, from 2026-06-30, is heavier: tamper preview font size, hide Qzone ads, disable notification bubbles, re-sort the mention list, customise sticker panel columns on the new side, plus a repair list covering anti-recall, transparent avatars and stickers, forced tablet or phone mode, DPI modification, removing the nine-contact forward limit, card message text conversion and a custom splash screen.

Two of those items are worth pausing on as an engineer rather than a user. Forcing tablet mode and forcing phone mode is the module overriding the host's device-type detection, which is exactly the kind of behaviour that changes without notice. Forcing the default font similarly overrides a resource decision the app makes at runtime.

The pattern across all three releases is a mix of small interface conveniences and deep hooks, which is what you would expect from a project with 266 open issues and one author-scale team. The last push on 2026-09-20 and the 2026-06-30 release date suggest the project is actively maintained rather than limping.

Editorial conclusion

QAuxiliary is a serious piece of engineering attached to an unusual premise: that the host app is closed, obfuscated and updated without notice, so the module has to keep rediscovering it. The runtime patching story, the byte-buddy plus InMemoryDexClassLoader approach that keeps it off Google Play, and the deliberate refusal to ship money-related or abuse features all point the same way. If you run it, watch the release channels, because the 266 open issues and the risk warnings printed under every single release note are an accurate description of what you are signing up for.

Frequently asked questions

What is QAuxiliary and what does it need to run?

QAuxiliary is an open source Xposed module built on QNotified that patches QQ, TIM, QQLite and QQ HD. It needs Android 7.0 or newer plus QQ 8.2.0, TIM 2.2.0, QQLite 4.0 or QQ HD 5.9.3 or newer, and an Xposed environment, or root and Frida as described in `docs/instruction-qauxv-frida.md`. Once activated, its settings are reached from inside QQ's own settings screen.

Why is QAuxiliary not available on Google Play?

Google Play does not allow apps that dynamically load external code at runtime. Because QQ's class names are obfuscated and only knowable at runtime, QAuxiliary uses byte-buddy to generate code at runtime and loads it with InMemoryDexClassLoader so no dex file touches disk, which is exactly the behaviour Play prohibits. That is also why releases ship as checksummed APKs from GitHub releases, Telegram and the LSPosed modules repository.

How do I build QAuxiliary from source?

Install git, Ninja 1.11 or newer (needed for C++20 module support), JDK 17 or newer, the Android SDK, and optionally ccache, taking the exact SDK, NDK and CMake versions from `build-logic/convention/src/main/kotlin/Version.kt`. Clone with the README's submodule trimming commands so you end up with 14 submodules rather than the full private tree, then run `./gradlew :app:assembleDebug` or `./gradlew :app:synthesizeDistReleaseApksCI`.

What is the difference between the CI and recommended CI versions?

The `CI` version is published automatically after each commit, carries no release notes, and may contain severe anomalies because an automated pipeline builds it. The `recommended CI` version is curated by the team for significant feature changes and accumulated fixes, and is the only one sent to the main Telegram channel, to GitHub releases, and to the LSPosed repository. Versions are numbered `major.minor.bugfix.rev.commit`, with the commit hash truncated to seven characters.

Official sources

  1. cinit/QAuxiliary on GitHub
  2. Issues
  3. README
  4. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cinit-qauxiliary.svg)](https://hysenlabs.com/projects/cinit-qauxiliary)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/cinit-qauxiliary.svg)](https://hysenlabs.com/projects/cinit-qauxiliary)

Was this useful?