{"owner":"SimoneAvogadro","repo":"android-reverse-engineering-skill","hasSkills":true,"totalSkillsCount":10,"totalTokensCount":13243,"categories":["marketplace","plugin-manifest","anthropic-skill","command-prompt"],"hasMcp":false,"mcpConfig":null,"found":[".claude-plugin/marketplace.json","plugins/android-reverse-engineering/.claude-plugin/plugin.json","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/fernflower-usage.md","plugins/android-reverse-engineering/commands/decompile.md","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/api-extraction-patterns.md","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/call-flow-analysis.md","plugins/android-reverse-engineering/skills/android-reverse-engineering/SKILL.md","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/jadx-usage.md","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/kotlin-name-recovery.md","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/setup-guide.md"],"skills":{".claude-plugin/marketplace.json":"{\n  \"$schema\": \"https://anthropic.com/claude-code/marketplace.schema.json\",\n  \"name\": \"android-reverse-engineering-skill\",\n  \"description\": \"Claude Code plugins for Android reverse engineering\",\n  \"owner\": {\n    \"name\": \"Simone Avogadro\"\n  },\n  \"metadata\": {\n    \"description\": \"Claude Code plugins for Android reverse engineering\",\n    \"version\": \"1.5.0\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"android-reverse-engineering\",\n      \"source\": \"./plugins/android-reverse-engineering\",\n      \"description\": \"Decompile Android APK/JAR/AAR with jadx, trace call flows through libraries, and document extracted APIs.\",\n      \"version\": \"1.5.0\",\n      \"author\": {\n        \"name\": \"Simone Avogadro\"\n      },\n      \"repository\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill\",\n      \"license\": \"Apache-2.0\",\n      \"keywords\": [\"android\", \"reverse-engineering\", \"apk\", \"jadx\", \"decompile\", \"api-extraction\"],\n      \"category\": \"security\"\n    }\n  ]\n}\n","plugins/android-reverse-engineering/.claude-plugin/plugin.json":"{\n  \"name\": \"android-reverse-engineering\",\n  \"version\": \"1.5.0\",\n  \"description\": \"Decompile Android APK/JAR/AAR with jadx, trace call flows through libraries, and document extracted APIs.\",\n  \"author\": {\n    \"name\": \"Simone Avogadro\"\n  },\n  \"homepage\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill\",\n  \"repository\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill\",\n  \"documentationUrl\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill#readme\",\n  \"license\": \"Apache-2.0\",\n  \"supportUrl\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill/issues/new\",\n  \"termsOfServiceUrl\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/master/LICENSE\",\n  \"privacyPolicyUrl\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/master/PRIVACY.md\",\n  \"keywords\": [\"android\", \"reverse-engineering\", \"apk\", \"jadx\", \"decompile\", \"api-extraction\"],\n  \"skills\": \"./skills/\",\n  \"commands\": \"./commands/\"\n}\n","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/fernflower-usage.md":"# Fernflower / Vineflower CLI Reference\n\nFernflower is the JetBrains analytical Java decompiler. [Vineflower](https://github.com/Vineflower/vineflower) is the actively maintained community fork with better output quality and published releases. They share the same CLI interface.\n\n## When to Use Fernflower vs jadx\n\n| Scenario | Recommended |\n|---|---|\n| APK with resources needed | jadx |\n| Standard Java JAR/library | Fernflower |\n| jadx output has warnings/errors on specific classes | Fernflower on those classes |\n| Complex lambdas, generics, streams | Fernflower |\n| Large APK (>50MB), quick overview | jadx |\n| Obfuscated Android app | jadx first, Fernflower on problem areas |\n| Both decompilers available | Use `--engine both` and compare |\n\n## Basic Usage\n\n```bash\njava -jar fernflower.jar [options] <source>... <destination>\n```\n\n- `<source>` — JAR file, class file, or directory containing class files\n- `<destination>` — output directory\n\nFor a JAR input, Fernflower produces a JAR in the destination containing `.java` source files. Extract it with `unzip` to browse the sources.\n\n## Key Options\n\nOptions use the format `-<key>=<value>`. Boolean options: `1` = enabled, `0` = disabled.\n\n| Option | Default | Description |\n|---|---|---|\n| `-dgs=1` | 0 | Decompile generic signatures (recommended) |\n| `-ren=1` | 0 | Rename obfuscated identifiers |\n| `-mpm=60` | 0 | Max seconds per method — prevents hangs (recommended) |\n| `-hes=0` | 1 | Show empty super() calls |\n| `-hdc=0` | 1 | Show empty default constructors |\n| `-udv=1` | 1 | Use debug variable names if available |\n| `-ump=1` | 1 | Use debug parameter names if available |\n| `-lit=1` | 0 | Output numeric literals as-is |\n| `-asc=1` | 0 | Encode non-ASCII as unicode escapes |\n| `-lac=1` | 0 | Decompile lambdas as anonymous classes |\n| `-log=WARN` | INFO | Reduce output verbosity |\n| `-e=<lib>` | — | Add library for context (not decompiled, improves type resolution) |\n\n## Recommended Presets\n\n### General use\n\n```bash\njava -jar fernflower.jar -dgs=1 -mpm=60 input.jar output/\n```\n\n### Obfuscated code\n\n```bash\njava -jar fernflower.jar -dgs=1 -ren=1 -mpm=60 input.jar output/\n```\n\n### Maximum detail\n\n```bash\njava -jar fernflower.jar -dgs=1 -hes=0 -hdc=0 -mpm=60 input.jar output/\n```\n\n### With Android SDK context (better type resolution)\n\n```bash\njava -jar fernflower.jar -dgs=1 -mpm=60 -e=$ANDROID_HOME/platforms/android-34/android.jar input.jar output/\n```\n\n## Working with APK Files\n\nFernflower cannot read APK/DEX files directly. Use dex2jar first:\n\n```bash\n# Step 1: Convert DEX to JAR\nd2j-dex2jar -f -o app-converted.jar app.apk\n\n# Step 2: Decompile with Fernflower\njava -jar fernflower.jar -dgs=1 -mpm=60 app-converted.jar output/\n\n# Step 3: Extract the resulting source JAR\nunzip -o output/app-converted.jar -d output/sources/\n```\n\nThe `decompile.sh --engine fernflower` script automates these steps.\n\n## Supported Input Formats\n\n| Format | Direct support | Via dex2jar |\n|---|---|---|\n| `.jar` | Yes | — |\n| `.class` | Yes | — |\n| `.zip` (with classes) | Yes | — |\n| `.apk` | No | Yes |\n| `.dex` | No | Yes |\n| `.aar` | No | Yes |\n\n## Output Format\n\n- **JAR input** → Produces `<destination>/<input-name>.jar` containing `.java` files\n- **Class file input** → Produces `.java` files directly in the destination\n- **No resource decoding** — Fernflower only produces Java source, never XML/resources\n\n## Fernflower vs Vineflower\n\nVineflower is the recommended fork. Improvements over upstream Fernflower:\n\n- Published releases on GitHub and Maven Central\n- Better handling of modern Java (records, sealed classes, pattern matching)\n- More accurate lambda and switch expression decompilation\n- Active bug fixes and community maintenance\n- Same CLI interface — drop-in replacement\n","plugins/android-reverse-engineering/commands/decompile.md":"---\nallowed-tools: Bash(bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh), Bash(bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh *), Read, Glob, Grep\ndescription: Decompile an Android APK/XAPK/JAR/AAR and analyze its structure\nuser-invocable: true\nargument-hint: <path to APK, XAPK, JAR, or AAR file>\nargument: path to APK, XAPK, JAR, or AAR file (optional)\n---\n\n# /decompile\n\nDecompile an Android application and perform initial structure analysis.\n\n## Instructions\n\nYou are starting the Android reverse engineering workflow. Follow these steps:\n\n### Step 1: Get the target file\n\nIf the user provided a file path as an argument, use that. Otherwise, ask the user for the path to the APK, XAPK, JAR, or AAR file they want to decompile.\n\n### Step 2: Check and install dependencies\n\nRun the dependency check:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh\n```\n\nParse the output looking for `INSTALL_REQUIRED:` and `INSTALL_OPTIONAL:` lines.\n\n**If required dependencies are missing**, install them one by one:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/install-dep.sh java\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/install-dep.sh jadx\n```\n\nThe install script auto-detects the OS and installs without sudo when possible (user-local install to `~/.local/`). If sudo is needed, it will prompt — if the user declines or sudo is unavailable, the script prints exact manual instructions (exit code 2). Show those instructions to the user and stop.\n\n**For optional dependencies** (`INSTALL_OPTIONAL:vineflower`, `INSTALL_OPTIONAL:dex2jar`, etc.), ask the user if they want to install them. Recommend vineflower and dex2jar for better results.\n\nAfter any installations, re-run `check-deps.sh` to verify. Do not proceed until all required dependencies pass.\n\n### Step 3: Decompile\n\nRun the decompile script on the target file. Choose the engine based on the input:\n\n- **APK or XAPK** → use jadx first (handles resources natively; XAPK is auto-extracted):\n\n  ```bash\n  bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh <file>\n  ```\n\n- **JAR/AAR** and Fernflower is available → prefer fernflower for better Java output:\n\n  ```bash\n  bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh --engine fernflower <file>\n  ```\n\n- **If jadx output has warnings** or the user wants the best quality → run both and compare:\n\n  ```bash\n  bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh --engine both <file>\n  ```\n\nFor obfuscated apps (if the user mentions it or you detect single-letter package names), add `--deobf`:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh --deobf <file>\n```\n\n### Step 4: Analyze structure\n\nAfter decompilation completes:\n\n1. Read `AndroidManifest.xml` from the resources directory. For XAPK, check the base APK's output first.\n2. If XAPK, review `xapk-manifest.json` in the output directory to understand the split structure.\n3. List the top-level package structure\n4. Identify the app's main Activity, Application class, and architecture pattern\n5. Report a summary to the user\n\n### Step 5: Offer next steps\n\nTell the user what they can do next:\n\n- **Trace call flows**: \"I can follow the execution flow from any Activity to its API calls\"\n- **Extract APIs**: \"I can search for all HTTP endpoints and document them\"\n- **Analyze specific classes**: \"Point me to a specific class or feature to analyze\"\n- **Re-decompile with Fernflower**: If jadx output has warnings, offer to re-run with `--engine both` for comparison\n\nRefer to the full skill documentation in `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/SKILL.md` for the complete workflow.\n","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/api-extraction-patterns.md":"# API Extraction Patterns\n\nPatterns and grep commands for finding HTTP API calls in decompiled Android source code.\n\n## Retrofit\n\nRetrofit is the most common HTTP client in Android apps. API endpoints are declared as annotated interface methods.\n\n### Annotations to search for\n\n```bash\n# HTTP method annotations\ngrep -rn '@GET\\|@POST\\|@PUT\\|@DELETE\\|@PATCH\\|@HEAD' sources/\n\n# Parameter annotations\ngrep -rn '@Query\\|@QueryMap\\|@Path\\|@Body\\|@Field\\|@FieldMap\\|@Part\\|@Header\\|@HeaderMap' sources/\n\n# Headers annotation (static headers)\ngrep -rn '@Headers' sources/\n\n# Base URL configuration\ngrep -rn 'baseUrl\\|\\.baseUrl(' sources/\n```\n\n### Typical Retrofit interface\n\n```java\npublic interface ApiService {\n    @GET(\"users/{id}\")\n    Call<User> getUser(@Path(\"id\") String userId);\n\n    @POST(\"auth/login\")\n    @Headers({\"Content-Type: application/json\"})\n    Call<LoginResponse> login(@Body LoginRequest request);\n}\n```\n\nWhen documenting, capture: HTTP method, path, path parameters, query parameters, request body type, response type, and any static headers.\n\n## OkHttp\n\nOkHttp is often used directly or as the transport layer for Retrofit.\n\n```bash\n# Request building\ngrep -rn 'Request\\.Builder\\|Request.Builder\\|\\.url(\\|\\.post(\\|\\.put(\\|\\.delete(\\|\\.patch(' sources/\n\n# URL construction\ngrep -rn 'HttpUrl\\|\\.addQueryParameter\\|\\.addPathSegment' sources/\n\n# Interceptors (often add auth headers)\ngrep -rn 'Interceptor\\|addInterceptor\\|addNetworkInterceptor\\|intercept(' sources/\n\n# Response handling\ngrep -rn '\\.execute()\\|\\.enqueue(' sources/\n```\n\n## Ktor (Kotlin)\n\nKtor is the dominant HTTP client in Kotlin Multiplatform and modern\nKotlin-only Android apps. Unlike Retrofit, Ktor does **not** use annotations\nto declare endpoints — paths appear as plain string arguments to\n`client.get(...)` / `client.post(...)`, often inside an extension function.\n\n```bash\n# Calls\ngrep -rn '\\b\\(client\\|httpClient\\|HttpClient\\)\\.\\(get\\|post\\|put\\|delete\\|patch\\|head\\|request\\)\\s*[<(]' sources/\n\n# Default request / base URL configuration\ngrep -rn 'HttpRequestBuilder\\|defaultRequest\\s*{\\|\\burl\\s*(\\s*\"\\|URLBuilder' sources/\n\n# Auth plugin (bearer / refresh)\ngrep -rn '\\bbearer\\s*{\\|BearerTokens\\s*(\\|loadTokens\\s*{\\|refreshTokens\\s*{' sources/\n```\n\nTypical Ktor call (after decompile):\n\n```java\nclient.get(\"api/v1/users/profile\") {\n    parameter(\"locale\", \"en-US\");\n}\n```\n\nThe base URL is usually applied via `defaultRequest { url { host = \"...\" } }`\nin the client builder. Search for `host =` and `URLProtocol.HTTPS` references\nto pin it down.\n\n**Note on obfuscation:** in heavily R8-shrunk apps the call site\n`client.get(\"path\")` is inlined to something like `aVar.a(dVar, \"path\")`\nand the `client.<verb>(` regex misses it. The path string itself is **not**\nobfuscated, however — fall back to the generic path-literal search\n(`--paths`) for the endpoint inventory in those cases. Ktor library\ninternals (`BearerTokens`, `loadTokens`, `refreshTokens`, `URLProtocol`)\nremain searchable because Ktor keeps these on its public API.\n\nKtor's authentication plugin uses the\n[`Auth { bearer { loadTokens { ... }; refreshTokens { ... } } }`](https://ktor.io/docs/auth.html)\nDSL — bearer access tokens with automatic refresh. After R8, the DSL\nlambdas appear as `Function2`/`Function3` impls referencing\n`BearerTokens(...)` calls.\n\n## Apollo Kotlin (GraphQL)\n\n```bash\n# Client setup\ngrep -rn 'ApolloClient\\|\\.serverUrl(\\|HttpNetworkTransport' sources/\n\n# Operations (queries / mutations / subscriptions)\ngrep -rn '\\.query(\\s*[A-Z]\\|\\.mutation(\\s*[A-Z]\\|\\.subscription(\\s*[A-Z]' sources/\n```\n\nApollo generates one class per operation under a generated package; once you\nfind the GraphQL endpoint URL via `ApolloClient.serverUrl(\"...\")`, use the\noperation classes themselves as the API documentation — each carries its\nGraphQL document text in `OPERATION_DOCUMENT`.\n\n## Volley\n\n```bash\ngrep -rn 'StringRequest\\|JsonObjectRequest\\|JsonArrayRequest\\|Volley\\.newRequestQueue\\|RequestQueue' sources/\n```\n\nVolley requests typically pass the URL as a constructor argument and override `getHeaders()` or `getParams()` for custom headers/parameters.\n\n## HttpURLConnection (legacy)\n\n```bash\ngrep -rn 'HttpURLConnection\\|HttpsURLConnection\\|openConnection\\|setRequestMethod\\|setRequestProperty' sources/\n```\n\n## WebView\n\n```bash\ngrep -rn 'loadUrl\\|evaluateJavascript\\|addJavascriptInterface\\|WebViewClient\\|shouldOverrideUrlLoading' sources/\n```\n\nWebView-based apps may load API endpoints via JavaScript bridges. Look for `@JavascriptInterface` annotated methods.\n\n## Endpoint-Shaped Path Literals (obfuscation-resistant)\n\nWhen the HTTP client cannot be identified (custom abstraction, heavy\ninlining, KMP shared module), or the call sites are obfuscated to\n`a.b(c, \"path\")`, fall back to extracting the path string literals\nthemselves. R8 does not obfuscate string contents, so paths leak through.\n\n```bash\n# All quoted strings shaped like an API path, deduplicated\ngrep -rhoE '\"(/[A-Za-z0-9_{}.\\-]+(/[A-Za-z0-9_{}.\\-]+)+/?|(api|v[0-9]+|graphql|users?|account|auth|sso|oauth|profile|cart|basket|order|product|inventory|search|category|address|location|delivery|payment|invoice|favo[u]?rites?)(/[A-Za-z0-9_{}.\\-]+)+/?)\"' sources/ \\\n    | grep -Ev '^\"(image|video|audio|text|application|content)/|^\"/(proc|sys|dev|tmp|etc)/' \\\n    | sort -u\n```\n\nThe skill ships this as `find-api-calls.sh --paths`, which prints both a\ndeduplicated inventory and the full list of call sites. On real-world\nKotlin apps this single command typically produces 100–300 distinct\nendpoint paths, which is the most useful first artifact for documentation.\n\n## Hardcoded URLs and Secrets\n\n```bash\n# HTTP/HTTPS URLs\ngrep -rn '\"https\\?://[^\"]*\"' sources/\n\n# API keys and tokens\ngrep -rni 'api[_-]\\?key\\|api[_-]\\?secret\\|auth[_-]\\?token\\|bearer\\|access[_-]\\?token\\|client[_-]\\?secret' sources/\n\n# Base URL constants\ngrep -rni 'BASE_URL\\|API_URL\\|SERVER_URL\\|ENDPOINT\\|API_BASE' sources/\n```\n\n## Documentation Template\n\nFor each discovered API endpoint, document it using this template:\n\n```markdown\n### `METHOD /path/to/endpoint`\n\n- **Source**: `com.example.app.api.ApiService` (file:line)\n- **Base URL**: `https://api.example.com/v1`\n- **Full URL**: `https://api.example.com/v1/path/to/endpoint`\n- **Path parameters**: `id` (String)\n- **Query parameters**: `page` (int), `limit` (int)\n- **Headers**:\n  - `Authorization: Bearer <token>`\n  - `Content-Type: application/json`\n- **Request body**: `LoginRequest { email: String, password: String }`\n- **Response type**: `ApiResponse<User>`\n- **Notes**: Called from `LoginActivity.onLoginClicked()`\n```\n\n## Search Strategy\n\n1. Start with **base URL constants** — find where the API root is configured\n2. Search for **Retrofit interfaces** — they give the clearest picture of all endpoints\n3. Check **interceptors** — they reveal auth schemes and common headers\n4. Search for **hardcoded URLs** — catch any one-off API calls outside the main client\n5. Look for **WebView URLs** — some apps use hybrid web/native approaches\n","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/call-flow-analysis.md":"# Call Flow Analysis\n\nTechniques for tracing execution flows in decompiled Android applications, from entry points down to network calls.\n\n## 1. Start from AndroidManifest.xml\n\nThe manifest declares all entry points. After decompilation, find it at:\n\n```\n<output-dir>/resources/AndroidManifest.xml\n```\n\nKey elements to look for:\n\n```bash\n# Activities (UI screens)\ngrep -n 'android:name=.*Activity' resources/AndroidManifest.xml\n\n# Services (background work)\ngrep -n 'android:name=.*Service' resources/AndroidManifest.xml\n\n# BroadcastReceivers\ngrep -n '<receiver' resources/AndroidManifest.xml\n\n# ContentProviders\ngrep -n '<provider' resources/AndroidManifest.xml\n\n# Launcher activity (main entry point)\ngrep -A5 'MAIN' resources/AndroidManifest.xml | grep 'android:name'\n```\n\n## 2. Follow the Android Lifecycle\n\nTypical call chain from UI to network:\n\n```\nActivity.onCreate()\n  → setContentView(R.layout.activity_main)\n  → findViewById() / View Binding\n  → button.setOnClickListener()\n    → onClick()\n      → viewModel.doSomething()\n        → repository.fetchData()\n          → apiService.getEndpoint()\n            → HTTP request\n```\n\nKey lifecycle methods to search:\n\n```bash\ngrep -rn 'onCreate\\|onResume\\|onStart\\|onViewCreated' sources/\n```\n\n## 3. Identify Click Handlers\n\nUser interactions trigger API calls. Common patterns:\n\n```bash\n# XML onClick\ngrep -rn 'setOnClickListener\\|onClick\\|OnClickListener' sources/\n\n# Data Binding\ngrep -rn '@BindingAdapter\\|android:onClick' sources/ resources/\n\n# Navigation actions\ngrep -rn 'findNavController\\|NavController\\|navigate(' sources/\n```\n\n## 4. Application Class Initialization\n\nThe `Application` subclass initializes global singletons (HTTP clients, DI frameworks, analytics):\n\n```bash\n# Find Application subclass\ngrep -rn 'extends Application\\|: Application()' sources/\n\n# Check onCreate for initialization\n# Then read the class to see what gets configured at startup\n```\n\nLook for:\n- Retrofit/OkHttp client setup\n- Dagger/Hilt component initialization\n- Firebase/analytics initialization\n- Base URL configuration\n\n## 5. Dependency Injection\n\n### Dagger / Hilt\n\n```bash\n# Hilt modules\ngrep -rn '@Module\\|@InstallIn\\|@Provides\\|@Binds' sources/\n\n# Hilt entry points\ngrep -rn '@HiltAndroidApp\\|@AndroidEntryPoint\\|@HiltViewModel' sources/\n\n# Dagger components\ngrep -rn '@Component\\|@Subcomponent' sources/\n\n# Injected fields\ngrep -rn '@Inject' sources/\n```\n\n### Koin\n\nKoin is the dominant DI framework in Kotlin Multiplatform and a large\nshare of Kotlin-only Android apps. It uses a runtime DSL rather than\ncompile-time generated factories, so the search patterns are different:\n\n```bash\n# Confirm Koin is actually wired up\ngrep -rn 'org\\.koin\\.' sources/\n\n# DI module declarations\ngrep -rn 'fun [A-Za-z]\\+Module\\|module\\s*{\\|module(' sources/\n\n# Bindings inside a module DSL\ngrep -rn 'single\\s*[<{(]\\|factory\\s*[<{(]\\|viewModel\\s*[<{(]\\|scoped\\s*[<{(]\\|singleOf\\|factoryOf' sources/\n\n# Resolution call-sites (where a binding is consumed)\ngrep -rn '\\bget\\s*<\\|\\binject\\s*<\\|by\\s\\+inject\\b\\|by\\s\\+viewModel\\b\\|getKoin' sources/\n```\n\nAfter R8, every binding lambda becomes an anonymous\n`Function2<Scope, ParametersHolder, T>` impl. To find the binding for an\ninterface `Foo`, look for files that contain both a Koin import / module\nDSL marker and a reference to `Foo`:\n\n```bash\ngrep -rln 'org\\.koin\\.core\\.module' sources/ | xargs grep -l 'Foo'\n```\n\n### Trace through DI\n\n1. Find where an interface is used (e.g. `ApiService` injected into a\n   repository).\n2. Find the `@Provides` / `@Binds` method (Hilt) **or** the\n   `single { ... }` / `factory { ... }` block (Koin) that creates the\n   implementation.\n3. Follow the implementation to the actual HTTP call.\n\n## 6. Find Constants and Configuration\n\nHardcoded values are rarely obfuscated:\n\n```bash\n# Base URLs\ngrep -rni 'BASE_URL\\|API_URL\\|SERVER_URL\\|HOST' sources/\n\n# API keys\ngrep -rni 'API_KEY\\|CLIENT_ID\\|APP_KEY\\|SECRET' sources/\n\n# BuildConfig values\ngrep -rn 'BuildConfig\\.' sources/\n\n# SharedPreferences keys (runtime config)\ngrep -rn 'getSharedPreferences\\|getString(\\|putString(' sources/\n```\n\n## 7. Navigating Obfuscated Code\n\nWhen code is obfuscated (ProGuard/R8):\n\n### What gets obfuscated\n- Class names → `a`, `b`, `c`\n- Method names → `a()`, `b()`, `c()`\n- Field names → `f1234a`, `f1235b`\n\n### What does NOT get obfuscated\n- **String literals** — URLs, keys, error messages remain readable\n- **Android framework classes** — `Activity`, `Fragment`, `Intent` keep their names\n- **Library public APIs** — Retrofit annotations, OkHttp builders retain names\n- **AndroidManifest entries** — Activity/Service names must be real\n\n### Strategy for obfuscated code\n\n1. **Start from strings**: Search for URLs, error messages, and known constants\n2. **Start from framework classes**: Activities and Fragments are named in the manifest\n3. **Follow library calls**: Retrofit `@GET`/`@POST` annotations are readable even when the interface class name is obfuscated\n4. **Recover original Kotlin names from metadata**: `@DebugMetadata` and `@Metadata.d2` strings preserve the original FQNs even after R8 obfuscation. Run `scripts/recover-kotlin-names.sh` to build an `obf -> real` map (typically recovers 30-50% of classes — and almost 100% of `*Repository` / `*ViewModel` / `*Impl`). See [`kotlin-name-recovery.md`](./kotlin-name-recovery.md). This is the single highest-leverage step on any Kotlin app.\n5. **Cross-reference**: If `class a` calls `Retrofit.create(b.class)`, then `b` is a Retrofit service interface\n6. **`--deobf` is rarely enough on its own**: jadx's `--deobf` renames obfuscated symbols with synthetic placeholders (`p001a`, `C0123Foo`) — useful for disambiguation but it does **not** recover original names. Pair it with the metadata recovery above.\n\n## 8. Tracing a Complete Call Flow: Example\n\nGoal: Find how login works in an obfuscated app.\n\n```\n1. grep for \"login\" in strings → find \"auth/login\" URL in class `c.a.b.d`\n2. Class `c.a.b.d` has @POST(\"auth/login\") → it's a Retrofit interface\n3. grep for `c.a.b.d` usage → class `c.a.b.f` calls it (the repository)\n4. grep for `c.a.b.f` usage → class `c.a.a.g` calls it (the ViewModel)\n5. grep for `c.a.a.g` usage → `LoginActivity` has a field of this type\n6. Read LoginActivity.onCreate() → sets click listener → calls ViewModel method\n```\n\nResult: `LoginActivity → ViewModel → Repository → Retrofit @POST(\"auth/login\")`\n\n## 9. Tools and Commands Summary\n\n| Goal | Command |\n|---|---|\n| Find entry points | `grep 'android:name' resources/AndroidManifest.xml` |\n| Find lifecycle methods | `grep -rn 'onCreate\\|onResume' sources/` |\n| Find click handlers | `grep -rn 'setOnClickListener\\|onClick' sources/` |\n| Find DI bindings | `grep -rn '@Provides\\|@Binds\\|@Inject' sources/` |\n| Find constants | `grep -rni 'BASE_URL\\|API_KEY' sources/` |\n| Find usages of a class | `grep -rn 'ClassName' sources/` |\n| Follow a string | `grep -rn '\"some text\"' sources/` |\n","plugins/android-reverse-engineering/skills/android-reverse-engineering/SKILL.md":"---\nname: android-reverse-engineering\ndescription: Decompile Android APK, XAPK, JAR, and AAR files using jadx or Fernflower/Vineflower. Reverse engineer Android apps, extract HTTP API endpoints (Retrofit, OkHttp, Volley), and trace call flows from UI to network layer. Use when the user wants to decompile, analyze, or reverse engineer Android packages, find API endpoints, or follow call flows. 中文触发词：反编译APK、安卓逆向、提取API、分析安卓应用、反编译安卓、逆向工程、追踪调用链、提取接口\ntrigger: decompile APK|decompile XAPK|reverse engineer Android|extract API|analyze Android|jadx|fernflower|vineflower|follow call flow|decompile JAR|decompile AAR|Android reverse engineering|find API endpoints|反编译APK|安卓逆向|提取API|分析安卓应用\n---\n\n# Android Reverse Engineering\n\nDecompile Android APK, XAPK, JAR, and AAR files using jadx and Fernflower/Vineflower, trace call flows through application code and libraries, and produce structured documentation of extracted APIs. Two decompiler engines are supported — jadx for broad Android coverage and Fernflower for higher-quality output on complex Java code — and can be used together for comparison.\n\n## Prerequisites\n\nThis skill requires **Java JDK 17+** and **jadx** to be installed. **Fernflower/Vineflower** and **dex2jar** are optional but recommended for better decompilation quality. Run the dependency checker to verify:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.ps1\"\n```\n\nIf anything is missing, follow the installation instructions in `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/setup-guide.md`.\n\n## Workflow\n\n### Phase 0: Fingerprint the App (recommended before anything else)\n\nBefore installing tools or decompiling, run a fast triage to determine what\nkind of app you are looking at. **Decompiling Java is mostly useless for\nFlutter, React Native, Cordova/Capacitor, and Xamarin apps** — the real code\nlives elsewhere. The fingerprint script tells you which.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/fingerprint.sh <file.apk|file.xapk>\n```\n\nIt prints, in one screen:\n\n- **Mobile framework** (Flutter / React Native / Cordova / Xamarin / Native Kotlin / etc.) with the file marker that triggered the verdict.\n- **HTTP stack** (Retrofit, OkHttp, Ktor, Apollo, Volley) detected via DEX string scan — works even when class names are obfuscated.\n- **DI / serialization** signals (Hilt, Dagger, Koin, kotlinx.serialization, Moshi, Gson, Jackson).\n- **Obfuscation level** estimate based on root-level short-named packages.\n- **Notable third-party SDKs** (AppsFlyer, Datadog, Sentry, Firebase, payment SDKs, support/chat SDKs, etc.).\n- **Consolidated native libraries** across the base APK and all splits — XAPK split bundles often place `.so` files in `config.<abi>.apk`, not in `base.apk`.\n- **Recommended next step**, which differs by framework (e.g. for Flutter the script suggests `blutter` / `strings libapp.so` rather than jadx).\n\nIf the fingerprint says the app is Flutter / RN / Cordova / Xamarin, **stop**\nand switch to the framework-appropriate tooling. Phases 1–5 below assume a\nnative (Java/Kotlin) Android app.\n\n### Phase 1: Verify and Install Dependencies\n\nBefore decompiling, confirm that the required tools are available — and install any that are missing.\n\n**Action**: Run the dependency check script.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.ps1\"\n```\n\nThe output contains machine-readable lines:\n- `INSTALL_REQUIRED:<dep>` — must be installed before proceeding\n- `INSTALL_OPTIONAL:<dep>` — recommended but not blocking\n\n**If required dependencies are missing** (exit code 1), install them automatically:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/install-dep.sh <dep>\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/install-dep.ps1\" <dep>\n```\n\nThe install script detects the OS and package manager, then:\n- Installs without sudo when possible (downloads to `~/.local/share/`, symlinks in `~/.local/bin/`)\n- Uses sudo and the system package manager when necessary (apt, dnf, pacman)\n- If sudo is needed but unavailable or the user declines, it prints the exact manual command and exits with code 2 — show these instructions to the user\n\n**Windows notes**: The PowerShell install script uses `winget`, `scoop`, or `choco` (in that order). If none are available, it downloads directly to `%USERPROFILE%\\.local\\share\\` and adds the directory to the user's PATH. After running `install-dep.ps1`, the PATH is persisted but the current terminal session may not see it. The `check-deps.ps1` and `decompile.ps1` scripts automatically refresh PATH from the user environment, so re-running them will find newly installed tools without restarting the terminal.\n\n**For optional dependencies**, ask the user if they want to install them. Vineflower and dex2jar are recommended for best results.\n\nAfter installation, re-run `check-deps.sh` to confirm everything is in place. Do not proceed to Phase 2 until all required dependencies are OK.\n\n### Phase 2: Decompile\n\nUse the decompile wrapper script to process the target file. The script supports three engines: `jadx`, `fernflower`, and `both`.\n\n**Action**: Choose the engine and run the decompile script. The script handles APK, XAPK, JAR, and AAR files.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh [OPTIONS] <file>\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.ps1\" [OPTIONS] <file>\n```\n\nFor **XAPK** files (ZIP bundles containing multiple APKs, used by APKPure and similar stores): the script automatically extracts the archive, identifies all APK files inside (base + split APKs), and decompiles each one into a separate subdirectory. The XAPK manifest is copied to the output for reference.\n\n**Split/bundled APK detection**: Some APKs are actually bundle wrappers — the outer APK contains `base.apk` plus `split_config.*.apk` files inside its resources directory. When this happens, jadx will decompile the thin wrapper and produce very few Java files. The decompile scripts automatically detect this (≤10 Java files + inner APKs present) and re-decompile `base.apk` into an `<output>/base/` subdirectory. Config-only splits (ABI, language, density) are skipped. The main decompiled source will be in `<output>/base/sources/`.\n\nOptions:\n- `-o <dir>` — Custom output directory (default: `<filename>-decompiled`)\n- `--deobf` — Enable deobfuscation (recommended for obfuscated apps)\n- `--no-res` — Skip resources, decompile code only (faster)\n- `--engine ENGINE` — `jadx` (default), `fernflower`, or `both`\n\n**Engine selection strategy**:\n\n| Situation | Engine |\n|---|---|\n| First pass on any APK | `jadx` (fastest, handles resources) |\n| JAR/AAR library analysis | `fernflower` (better Java output) |\n| jadx output has warnings/broken code | `both` (compare and pick best per class) |\n| Complex lambdas, generics, streams | `fernflower` |\n| Quick overview of a large APK | `jadx --no-res` |\n\nWhen using `--engine both`, the outputs go into `<output>/jadx/` and `<output>/fernflower/` respectively, with a comparison summary at the end showing file counts and jadx warning counts. Review classes with jadx warnings in the Fernflower output for better code.\n\nFor APK files with Fernflower, the script automatically uses dex2jar as an intermediate step. dex2jar must be installed for this to work.\n\nSee `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/jadx-usage.md` and `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/fernflower-usage.md` for the full CLI references.\n\n### Phase 3: Analyze Structure\n\nNavigate the decompiled output to understand the app's architecture.\n\n**Actions**:\n\n1. **Read AndroidManifest.xml** from `<output>/resources/AndroidManifest.xml`:\n   - Identify the main launcher Activity\n   - List all Activities, Services, BroadcastReceivers, ContentProviders\n   - Note permissions (especially `INTERNET`, `ACCESS_NETWORK_STATE`)\n   - Find the application class (`android:name` on `<application>`)\n\n2. **Survey the package structure** under `<output>/sources/`:\n   - Identify the main app package and sub-packages\n   - Distinguish app code from third-party libraries\n   - Look for packages named `api`, `network`, `data`, `repository`, `service`, `retrofit`, `http` — these are where API calls live\n\n3. **Read every `BuildConfig.java`** — these are almost never obfuscated and frequently leak the highest-signal constants in the entire APK (base URLs, flavor names, build type, third-party API keys, feature flags):\n   ```bash\n   find <output>/sources -name BuildConfig.java -exec grep -H '=' {} \\;\n   ```\n   Each Gradle module emits its own `BuildConfig`, so expect 1–N hits. Read all of them.\n\n4. **Identify the architecture pattern**:\n   - MVP: look for `Presenter` classes\n   - MVVM: look for `ViewModel` classes and `LiveData`/`StateFlow`\n   - Clean Architecture: look for `domain`, `data`, `presentation` packages\n   - This informs where to look for network calls in the next phases\n\n### Phase 3.5: Recover Kotlin Class Names (only for obfuscated Kotlin apps)\n\nIf Phase 0 reported moderate / high obfuscation **and** the app is Kotlin\n(Compose / kotlin_module markers detected), run the metadata recovery\nscript before tracing call flows. R8 obfuscates JVM symbols but cannot\nstrip Kotlin metadata strings, so original FQNs leak through\n`@DebugMetadata` and `@Metadata.d2`.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/recover-kotlin-names.sh \\\n    <output>/sources <output>/mapping\n```\n\nThen use the lookup helper instead of plain grep — every hit comes\nannotated with the owning class's real name:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/lookup-name.sh \\\n    <output>/mapping --grep '\"/api/' <output>/sources\n```\n\nTypical recovery on a real-world Kotlin app: ~100% of `*Repository` /\n`*ViewModel` / `*UseCase` / `*Impl` classes, ~80% of DTOs.\n\nSee `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/kotlin-name-recovery.md`\nfor the full technique and limitations.\n\n### Phase 4: Trace Call Flows\n\nFollow execution paths from user-facing entry points down to network calls.\n\n**Actions**:\n\n1. **Start from entry points**: Read the main Activity or Application class identified in Phase 3.\n\n2. **Follow the initialization chain**: Application.onCreate() often sets up the HTTP client, base URL, and DI framework. Read this first.\n\n3. **Trace user actions**: From an Activity, follow:\n   - `onCreate()` → view setup → click listeners\n   - Click handler → ViewModel/Presenter method\n   - ViewModel → Repository → API service interface\n   - API service → actual HTTP call\n\n4. **Map DI bindings** (if Dagger/Hilt is used): Find `@Module` classes to understand which implementations are provided for which interfaces.\n\n5. **Handle obfuscated code**: When class names are mangled, use string literals and library API calls as anchors. Retrofit annotations and URL strings are never obfuscated.\n\nSee `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/call-flow-analysis.md` for detailed techniques and grep commands.\n\n### Phase 5: Extract and Document APIs\n\nFind all API endpoints and produce structured documentation.\n\n**Action**: Run the API search script for a broad sweep.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.sh <output>/sources/\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.ps1\" <output>/sources/\n```\n\nTargeted searches:\n```bash\n# Only Retrofit\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.sh <output>/sources/ --retrofit\n\n# Only hardcoded URLs\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.sh <output>/sources/ --urls\n\n# Only auth patterns\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.sh <output>/sources/ --auth\n```\n\nOn Windows (PowerShell):\n```powershell\n# Only Retrofit\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.ps1\" <output>/sources/ -Retrofit\n\n# Only hardcoded URLs\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.ps1\" <output>/sources/ -Urls\n\n# Only auth patterns\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.ps1\" <output>/sources/ -AuthPatterns\n```\n\nDocument the endpoints in **two tiers** — going deep on every endpoint is\nprohibitively expensive on apps with 100+ paths, and most of them do not\nwarrant it. Always produce Tier 1; expand Tier 2 only for the endpoints\nthat matter.\n\n#### Tier 1 — flat inventory (always)\n\nA single table covering every discovered endpoint. Aim for one line each;\nif you cannot determine a column, write `?`.\n\n| Host | Method | Path | Auth | Source file |\n|------|--------|------|------|-------------|\n| `api.example.com` | GET | `/v1/users/profile` | Bearer | `com/example/api/UserApi.java` |\n| `api.example.com` | POST | `/v1/auth/login` | none | `com/example/api/AuthApi.java` |\n\nThis table answers \"what does the backend look like\" in one screen and\ntakes ~5 minutes to produce from the `--paths` output even on a large app.\n\n#### Tier 2 — per-endpoint detail (only for high-value endpoints)\n\nReserve the detailed format for the few endpoints that actually need it:\n\n- the entire authentication flow (login, refresh, logout, OTP/SMS, anonymous, registration)\n- payment / checkout / order-creation endpoints\n- anything the user explicitly asked about\n- anything that looked unusual during the scan (custom signing, undocumented headers, etc.)\n\n```markdown\n### `METHOD /path`\n\n- **Source**: `com.example.api.ApiService` (ApiService.java:42)\n- **Base URL**: `https://api.example.com/v1`\n- **Path params**: `id` (String)\n- **Query params**: `page` (int), `limit` (int)\n- **Headers**: `Authorization: Bearer <token>`\n- **Request body**: `{ \"email\": \"string\", \"password\": \"string\" }`\n- **Response**: `ApiResponse<User>`\n- **Called from**: `LoginActivity → LoginViewModel → UserRepository → ApiService`\n```\n\nAs a default, do not produce Tier 2 entries for more than ~10 endpoints\nunless the user explicitly asks for more — Tier 1 plus a Tier 2 deep dive\non auth + 1-2 key flows is what most consumers of this work actually want.\n\nSee `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/api-extraction-patterns.md` for library-specific search patterns and the full documentation template.\n\n## Output\n\nAt the end of the workflow, deliver:\n\n1. **Decompiled source** in the output directory\n2. **Architecture summary** — app structure, main packages, pattern used\n3. **API documentation** — all discovered endpoints in the format above\n4. **Call flow map** — key paths from UI to network (especially authentication and main features)\n\n## References\n\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/setup-guide.md` — Installing Java, jadx, Fernflower/Vineflower, dex2jar, and optional tools\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/jadx-usage.md` — jadx CLI options and workflows\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/fernflower-usage.md` — Fernflower/Vineflower CLI options, when to use, APK workflow\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/api-extraction-patterns.md` — Library-specific search patterns and documentation template\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/call-flow-analysis.md` — Techniques for tracing call flows in decompiled code\n","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/jadx-usage.md":"# jadx CLI Reference\n\n## Basic Usage\n\n```bash\njadx [options] <input-file>\n```\n\nInput can be an `.apk`, `.jar`, `.aar`, `.dex`, or `.zip` file.\n\n## Key Options\n\n| Option | Description |\n|---|---|\n| `-d <dir>` | Output directory for decompiled sources |\n| `--deobf` | Enable deobfuscation — renames obfuscated classes/methods to readable names |\n| `--show-bad-code` | Show partially decompiled code instead of error comments |\n| `--no-res` | Skip resource decoding — faster when you only need code |\n| `--no-src` | Skip source decompilation — only decode resources |\n| `--export-gradle` | Generate a Gradle project structure (useful for importing into IDE) |\n| `-e` | Same as `--export-gradle` |\n| `--threads-count <N>` | Number of processing threads (default: CPU count) |\n| `-Xmx<size>` | Set maximum Java heap (e.g., `-Xmx4g` for large APKs) |\n\n## Decompiling Different File Types\n\n### APK (Android Application Package)\n\n```bash\njadx -d output-dir app.apk\n```\n\nProduces:\n- `output-dir/sources/` — Decompiled Java source files\n- `output-dir/resources/` — Decoded resources (AndroidManifest.xml, layouts, drawables, etc.)\n\n### JAR (Java Archive)\n\n```bash\njadx -d output-dir library.jar\n```\n\nUseful for analyzing third-party libraries bundled within an APK.\n\n### AAR (Android Archive)\n\n```bash\njadx -d output-dir library.aar\n```\n\nAAR files contain both compiled code and Android resources. jadx handles them directly.\n\n## Handling Obfuscated Code\n\nApps built with ProGuard or R8 produce obfuscated bytecode with single-letter class and method names.\n\n### Strategies\n\n1. **Use `--deobf`** to generate readable replacement names:\n   ```bash\n   jadx --deobf -d output-dir app.apk\n   ```\n   jadx creates a mapping file at `output-dir/deobf-mapping.txt` that maps original obfuscated names to generated names.\n\n2. **Use the ProGuard mapping file** if available (sometimes shipped in the APK under `assets/` or obtainable from build artifacts):\n   ```bash\n   jadx --deobf-map mapping.txt -d output-dir app.apk\n   ```\n\n3. **Focus on string constants and API calls** rather than class names when navigating obfuscated code. URL strings, annotation values, and library classes are not obfuscated.\n\n## jadx-gui\n\nFor interactive exploration, use the GUI version:\n\n```bash\njadx-gui app.apk\n```\n\nFeatures:\n- Full-text search across all decompiled sources\n- Click-through navigation (jump to definition)\n- Deobfuscation with live renaming\n- Smali view alongside Java\n\njadx-gui is included in the same distribution as the CLI tool.\n\n## Common Workflows\n\n### Code-only decompilation (fastest)\n\n```bash\njadx --no-res --show-bad-code -d output app.apk\n```\n\n### Full decompilation with deobfuscation\n\n```bash\njadx --deobf --show-bad-code -d output app.apk\n```\n\n### Export as Gradle project for IDE import\n\n```bash\njadx -e -d output app.apk\n# Then open output/ in Android Studio or IntelliJ\n```\n\n### Decompile a specific DEX from a multi-dex APK\n\nExtract the APK (it's a ZIP), then target individual DEX files:\n\n```bash\nunzip app.apk -d extracted/\njadx -d output extracted/classes2.dex\n```\n","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/kotlin-name-recovery.md":"# Recovering Original Class Names from Kotlin Metadata\n\nWhen R8/ProGuard obfuscates a Kotlin app, JVM symbols are renamed but the\n**Kotlin metadata strings cannot be stripped** — the Kotlin runtime depends\non them at runtime for reflection, coroutines, and `data class` features.\n\nTwo annotations leak the original fully-qualified names:\n\n## `@DebugMetadata`\n\nGenerated for nearly every Kotlin coroutine `SuspendLambda` (i.e. almost\nevery `suspend` function in a modern app):\n\n```java\n@DebugMetadata(\n    c  = \"com.example.feature.account.AccountRepositoryImpl$fetch$1\",\n    f  = \"AccountRepositoryImpl.kt\",\n    l  = {42, 51},\n    m  = \"invokeSuspend\"\n)\npublic final class a extends SuspendLambda implements Function2<...> { ... }\n```\n\nThe `c =` field carries the original outer class FQN (with a `$` suffix\nfor inner / lambda scopes — strip everything after the first `$` to get the\ndeclaring class).\n\n## `@Metadata.d2`\n\nEvery Kotlin class carries a top-level `@Metadata` annotation. The `d2`\narray lists internal class refs in JVM type-descriptor format\n(`Lcom/example/Foo;`):\n\n```java\n@Metadata(d1 = {\"...\"},\n          d2 = {\"...\",\"Lcom/example/feature/account/AccountRepositoryImpl;\",\"...\"})\npublic final class b implements ... { ... }\n```\n\nThe first non-stdlib descriptor in `d2` is usually the file's primary\nclass.\n\n## How to mine them\n\nThe skill ships two scripts:\n\n```bash\n# Build a mapping from a decompiled sources directory:\nbash scripts/recover-kotlin-names.sh <output>/sources [mapping-dir]\n\n# Outputs:\n#   <mapping-dir>/mapping.tsv        obf_fqn  real_fqn  file\n#   <mapping-dir>/mapping.json       same data, JSON\n#   <mapping-dir>/by_package/        per-real-package index files\n\n# Query the mapping:\nbash scripts/lookup-name.sh <mapping-dir> Repository                 # search\nbash scripts/lookup-name.sh <mapping-dir> -o ab.cd                   # obf -> real\nbash scripts/lookup-name.sh <mapping-dir> -p com.example.feature     # list package\nbash scripts/lookup-name.sh <mapping-dir> --grep '\"api/' <output>/sources\n   # ^ greps decompiled code and appends '// real.fqn' to each hit\n```\n\n## What you typically recover\n\nOn a real-world obfuscated Kotlin app the script recovers **30 – 50 % of\nclasses** — but more importantly, **almost 100 % of the classes you\nactually want to read**:\n\n| Class kind                | Recovery rate |\n|---------------------------|---------------|\n| `*Repository` / `*Impl`   | ~100 %        |\n| `*ViewModel`              | ~100 %        |\n| `*UseCase` / `*Interactor`| ~100 %        |\n| Plain `data class` DTOs   | ~80 %         |\n| Pure-Java helper classes  | low (no Kotlin metadata) |\n| Anonymous inner classes   | sometimes recovered as the parent FQN |\n\n## Why `jadx --deobf` is not enough\n\n`--deobf` renames obfuscated identifiers using internal heuristics, but the\noutput is still synthetic (`p001a`, `C0123Foo`). It does **not** recover\nthe *original* names. Kotlin metadata recovery is the only reliable way to\nmap back to the names the developer actually wrote, and it costs essentially\nnothing — just a regex pass over the decompiled sources.\n\nRun both: `--deobf` for fields/methods that have no metadata source, plus\nthe recovery script for class names.\n\n## Limitations\n\n- **Method names and field names** are not recovered. Kotlin metadata only\n  preserves class-level FQNs and a few signatures. For method names you\n  still need jadx-gui's interactive rename or pattern inference.\n- **Pure-Java classes** carry no `@Metadata`, so they remain obfuscated.\n- **Heavily inlined classes** (`@JvmInline value class`, top-level fun\n  files compiled into shared `*Kt.class` synthetic classes) sometimes show\n  up under the wrong filename — treat results as a strong hint, not gospel.\n\n## Reading flow with the mapping\n\n1. Run `recover-kotlin-names.sh` once after decompiling.\n2. Use `lookup-name.sh --grep '<pattern>' <sources>` instead of plain `grep`\n   so every hit comes annotated with the real owning class.\n3. When you hit an obfuscated FQN in code (e.g. `nq.e`), resolve it with\n   `lookup-name.sh <mapping-dir> -o nq.e` — you will often see siblings\n   (`nq.d`, `nq.f`, ...) that are the same class's split lambdas/inner\n   classes, which is useful context.\n","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/setup-guide.md":"# Setup Guide: Dependencies for Android Reverse Engineering\n\n## Java JDK 17+\n\njadx requires Java 17 or later.\n\n### Ubuntu / Debian\n\n```bash\nsudo apt update\nsudo apt install openjdk-17-jdk\n```\n\n### Fedora\n\n```bash\nsudo dnf install java-17-openjdk-devel\n```\n\n### Arch Linux\n\n```bash\nsudo pacman -S jdk17-openjdk\n```\n\n### macOS (Homebrew)\n\n```bash\nbrew install openjdk@17\n```\n\nAfter installation on macOS, follow the symlink instructions printed by Homebrew, or add to your shell profile:\n\n```bash\nexport PATH=\"/opt/homebrew/opt/openjdk@17/bin:$PATH\"\n```\n\n### Verify\n\n```bash\njava -version\n# Should show version 17.x or higher\n```\n\n---\n\n## jadx\n\njadx is the Java decompiler used to convert APK/JAR/AAR files to readable Java source.\n\n### Option 1: GitHub Releases (recommended)\n\n1. Go to <https://github.com/skylot/jadx/releases/latest>\n2. Download the `jadx-<version>.zip` file (not the source archive)\n3. Extract and add to PATH:\n\n```bash\nunzip jadx-*.zip -d ~/jadx\nexport PATH=\"$HOME/jadx/bin:$PATH\"\n# Add the export line to your ~/.bashrc or ~/.zshrc for persistence\n```\n\n### Option 2: Homebrew (macOS / Linux)\n\n```bash\nbrew install jadx\n```\n\n### Option 3: Build from source\n\n```bash\ngit clone https://github.com/skylot/jadx.git\ncd jadx\n./gradlew dist\n# Binaries will be in build/jadx/bin/\nexport PATH=\"$(pwd)/build/jadx/bin:$PATH\"\n```\n\n### Verify\n\n```bash\njadx --version\n```\n\n---\n\n## Fernflower / Vineflower (optional, recommended)\n\nFernflower is the JetBrains Java decompiler. It produces better output than jadx on complex Java constructs, lambdas, and generics. [Vineflower](https://github.com/Vineflower/vineflower) is the actively maintained community fork with published releases — prefer it over upstream Fernflower.\n\n### Option 1: Vineflower from GitHub Releases (recommended)\n\n1. Go to <https://github.com/Vineflower/vineflower/releases/latest>\n2. Download `vineflower-<version>.jar`\n3. Place it and set the environment variable:\n\n```bash\nmkdir -p ~/vineflower\nmv vineflower-*.jar ~/vineflower/vineflower.jar\nexport FERNFLOWER_JAR_PATH=\"$HOME/vineflower/vineflower.jar\"\n# Add the export to ~/.bashrc or ~/.zshrc for persistence\n```\n\n### Option 2: Build Fernflower from source\n\n```bash\ngit clone https://github.com/JetBrains/fernflower.git\ncd fernflower\n./gradlew jar\n# Produces: build/libs/fernflower.jar\nexport FERNFLOWER_JAR_PATH=\"$(pwd)/build/libs/fernflower.jar\"\n```\n\n### Option 3: Homebrew (Vineflower)\n\n```bash\nbrew install vineflower\n```\n\n### Verify\n\n```bash\njava -jar \"$FERNFLOWER_JAR_PATH\" --version\n```\n\n> **Note**: Fernflower only works on JVM bytecode (JAR, class files). For APK/DEX files, you also need **dex2jar** (see below) as an intermediate conversion step.\n\n---\n\n## dex2jar (optional, needed for Fernflower on APK files)\n\nConverts Android DEX bytecode to standard Java JAR files.\n\n### GitHub Releases\n\n1. Go to <https://github.com/ThexXTURBOXx/dex2jar/releases/latest>\n2. Download and extract:\n\n```bash\nunzip dex-tools-*.zip -d ~/dex2jar\nexport PATH=\"$HOME/dex2jar:$PATH\"\n```\n\n### Homebrew\n\n```bash\nbrew install dex2jar\n```\n\n### Verify\n\n```bash\nd2j-dex2jar --help\n```\n\n### Usage\n\n```bash\n# Convert APK (or DEX) to JAR\nd2j-dex2jar -f -o output.jar app.apk\n\n# Then decompile with Fernflower\njava -jar vineflower.jar output.jar decompiled/\n```\n\n---\n\n## Optional Tools\n\n### apktool\n\nUseful for decoding resources (XML layouts, drawables) that jadx sometimes handles poorly.\n\n```bash\n# Ubuntu/Debian\nsudo apt install apktool\n\n# macOS\nbrew install apktool\n\n# Manual: https://apktool.org/docs/install\n```\n\n### adb (Android Debug Bridge)\n\nUseful for pulling APKs directly from a connected Android device.\n\n```bash\n# Ubuntu/Debian\nsudo apt install adb\n\n# macOS\nbrew install android-platform-tools\n```\n\nPull an APK from a device:\n\n```bash\n# List installed packages\nadb shell pm list packages | grep <keyword>\n\n# Get APK path\nadb shell pm path com.example.app\n\n# Pull the APK\nadb pull /data/app/com.example.app-xxxx/base.apk ./app.apk\n```\n\n---\n\n## Troubleshooting\n\n| Problem | Solution |\n|---|---|\n| `jadx: command not found` | Ensure the jadx `bin/` directory is in your `$PATH` |\n| `Error: Could not find or load main class` | Java is missing or wrong version — verify with `java -version` |\n| jadx runs out of memory on large APKs | Increase heap: `jadx -Xmx4g -d output app.apk` or set `JAVA_OPTS=\"-Xmx4g\"` |\n| Decompiled code has many `// Error` comments | Try `--show-bad-code` to see partial output, or use `--deobf` for obfuscated apps |\n| Fernflower hangs on a method | Use `-mpm=60` to set a 60-second timeout per method |\n| Fernflower JAR not found | Set `FERNFLOWER_JAR_PATH` env variable to the full path of the JAR |\n| dex2jar fails with `ZipException` | The APK may have a non-standard ZIP structure — try `jadx` instead |\n"},"files":{".claude-plugin/marketplace.json":"{\n  \"$schema\": \"https://anthropic.com/claude-code/marketplace.schema.json\",\n  \"name\": \"android-reverse-engineering-skill\",\n  \"description\": \"Claude Code plugins for Android reverse engineering\",\n  \"owner\": {\n    \"name\": \"Simone Avogadro\"\n  },\n  \"metadata\": {\n    \"description\": \"Claude Code plugins for Android reverse engineering\",\n    \"version\": \"1.5.0\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"android-reverse-engineering\",\n      \"source\": \"./plugins/android-reverse-engineering\",\n      \"description\": \"Decompile Android APK/JAR/AAR with jadx, trace call flows through libraries, and document extracted APIs.\",\n      \"version\": \"1.5.0\",\n      \"author\": {\n        \"name\": \"Simone Avogadro\"\n      },\n      \"repository\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill\",\n      \"license\": \"Apache-2.0\",\n      \"keywords\": [\"android\", \"reverse-engineering\", \"apk\", \"jadx\", \"decompile\", \"api-extraction\"],\n      \"category\": \"security\"\n    }\n  ]\n}\n","plugins/android-reverse-engineering/.claude-plugin/plugin.json":"{\n  \"name\": \"android-reverse-engineering\",\n  \"version\": \"1.5.0\",\n  \"description\": \"Decompile Android APK/JAR/AAR with jadx, trace call flows through libraries, and document extracted APIs.\",\n  \"author\": {\n    \"name\": \"Simone Avogadro\"\n  },\n  \"homepage\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill\",\n  \"repository\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill\",\n  \"documentationUrl\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill#readme\",\n  \"license\": \"Apache-2.0\",\n  \"supportUrl\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill/issues/new\",\n  \"termsOfServiceUrl\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/master/LICENSE\",\n  \"privacyPolicyUrl\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/master/PRIVACY.md\",\n  \"keywords\": [\"android\", \"reverse-engineering\", \"apk\", \"jadx\", \"decompile\", \"api-extraction\"],\n  \"skills\": \"./skills/\",\n  \"commands\": \"./commands/\"\n}\n","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/fernflower-usage.md":"# Fernflower / Vineflower CLI Reference\n\nFernflower is the JetBrains analytical Java decompiler. [Vineflower](https://github.com/Vineflower/vineflower) is the actively maintained community fork with better output quality and published releases. They share the same CLI interface.\n\n## When to Use Fernflower vs jadx\n\n| Scenario | Recommended |\n|---|---|\n| APK with resources needed | jadx |\n| Standard Java JAR/library | Fernflower |\n| jadx output has warnings/errors on specific classes | Fernflower on those classes |\n| Complex lambdas, generics, streams | Fernflower |\n| Large APK (>50MB), quick overview | jadx |\n| Obfuscated Android app | jadx first, Fernflower on problem areas |\n| Both decompilers available | Use `--engine both` and compare |\n\n## Basic Usage\n\n```bash\njava -jar fernflower.jar [options] <source>... <destination>\n```\n\n- `<source>` — JAR file, class file, or directory containing class files\n- `<destination>` — output directory\n\nFor a JAR input, Fernflower produces a JAR in the destination containing `.java` source files. Extract it with `unzip` to browse the sources.\n\n## Key Options\n\nOptions use the format `-<key>=<value>`. Boolean options: `1` = enabled, `0` = disabled.\n\n| Option | Default | Description |\n|---|---|---|\n| `-dgs=1` | 0 | Decompile generic signatures (recommended) |\n| `-ren=1` | 0 | Rename obfuscated identifiers |\n| `-mpm=60` | 0 | Max seconds per method — prevents hangs (recommended) |\n| `-hes=0` | 1 | Show empty super() calls |\n| `-hdc=0` | 1 | Show empty default constructors |\n| `-udv=1` | 1 | Use debug variable names if available |\n| `-ump=1` | 1 | Use debug parameter names if available |\n| `-lit=1` | 0 | Output numeric literals as-is |\n| `-asc=1` | 0 | Encode non-ASCII as unicode escapes |\n| `-lac=1` | 0 | Decompile lambdas as anonymous classes |\n| `-log=WARN` | INFO | Reduce output verbosity |\n| `-e=<lib>` | — | Add library for context (not decompiled, improves type resolution) |\n\n## Recommended Presets\n\n### General use\n\n```bash\njava -jar fernflower.jar -dgs=1 -mpm=60 input.jar output/\n```\n\n### Obfuscated code\n\n```bash\njava -jar fernflower.jar -dgs=1 -ren=1 -mpm=60 input.jar output/\n```\n\n### Maximum detail\n\n```bash\njava -jar fernflower.jar -dgs=1 -hes=0 -hdc=0 -mpm=60 input.jar output/\n```\n\n### With Android SDK context (better type resolution)\n\n```bash\njava -jar fernflower.jar -dgs=1 -mpm=60 -e=$ANDROID_HOME/platforms/android-34/android.jar input.jar output/\n```\n\n## Working with APK Files\n\nFernflower cannot read APK/DEX files directly. Use dex2jar first:\n\n```bash\n# Step 1: Convert DEX to JAR\nd2j-dex2jar -f -o app-converted.jar app.apk\n\n# Step 2: Decompile with Fernflower\njava -jar fernflower.jar -dgs=1 -mpm=60 app-converted.jar output/\n\n# Step 3: Extract the resulting source JAR\nunzip -o output/app-converted.jar -d output/sources/\n```\n\nThe `decompile.sh --engine fernflower` script automates these steps.\n\n## Supported Input Formats\n\n| Format | Direct support | Via dex2jar |\n|---|---|---|\n| `.jar` | Yes | — |\n| `.class` | Yes | — |\n| `.zip` (with classes) | Yes | — |\n| `.apk` | No | Yes |\n| `.dex` | No | Yes |\n| `.aar` | No | Yes |\n\n## Output Format\n\n- **JAR input** → Produces `<destination>/<input-name>.jar` containing `.java` files\n- **Class file input** → Produces `.java` files directly in the destination\n- **No resource decoding** — Fernflower only produces Java source, never XML/resources\n\n## Fernflower vs Vineflower\n\nVineflower is the recommended fork. Improvements over upstream Fernflower:\n\n- Published releases on GitHub and Maven Central\n- Better handling of modern Java (records, sealed classes, pattern matching)\n- More accurate lambda and switch expression decompilation\n- Active bug fixes and community maintenance\n- Same CLI interface — drop-in replacement\n","plugins/android-reverse-engineering/commands/decompile.md":"---\nallowed-tools: Bash(bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh), Bash(bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh *), Read, Glob, Grep\ndescription: Decompile an Android APK/XAPK/JAR/AAR and analyze its structure\nuser-invocable: true\nargument-hint: <path to APK, XAPK, JAR, or AAR file>\nargument: path to APK, XAPK, JAR, or AAR file (optional)\n---\n\n# /decompile\n\nDecompile an Android application and perform initial structure analysis.\n\n## Instructions\n\nYou are starting the Android reverse engineering workflow. Follow these steps:\n\n### Step 1: Get the target file\n\nIf the user provided a file path as an argument, use that. Otherwise, ask the user for the path to the APK, XAPK, JAR, or AAR file they want to decompile.\n\n### Step 2: Check and install dependencies\n\nRun the dependency check:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh\n```\n\nParse the output looking for `INSTALL_REQUIRED:` and `INSTALL_OPTIONAL:` lines.\n\n**If required dependencies are missing**, install them one by one:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/install-dep.sh java\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/install-dep.sh jadx\n```\n\nThe install script auto-detects the OS and installs without sudo when possible (user-local install to `~/.local/`). If sudo is needed, it will prompt — if the user declines or sudo is unavailable, the script prints exact manual instructions (exit code 2). Show those instructions to the user and stop.\n\n**For optional dependencies** (`INSTALL_OPTIONAL:vineflower`, `INSTALL_OPTIONAL:dex2jar`, etc.), ask the user if they want to install them. Recommend vineflower and dex2jar for better results.\n\nAfter any installations, re-run `check-deps.sh` to verify. Do not proceed until all required dependencies pass.\n\n### Step 3: Decompile\n\nRun the decompile script on the target file. Choose the engine based on the input:\n\n- **APK or XAPK** → use jadx first (handles resources natively; XAPK is auto-extracted):\n\n  ```bash\n  bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh <file>\n  ```\n\n- **JAR/AAR** and Fernflower is available → prefer fernflower for better Java output:\n\n  ```bash\n  bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh --engine fernflower <file>\n  ```\n\n- **If jadx output has warnings** or the user wants the best quality → run both and compare:\n\n  ```bash\n  bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh --engine both <file>\n  ```\n\nFor obfuscated apps (if the user mentions it or you detect single-letter package names), add `--deobf`:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh --deobf <file>\n```\n\n### Step 4: Analyze structure\n\nAfter decompilation completes:\n\n1. Read `AndroidManifest.xml` from the resources directory. For XAPK, check the base APK's output first.\n2. If XAPK, review `xapk-manifest.json` in the output directory to understand the split structure.\n3. List the top-level package structure\n4. Identify the app's main Activity, Application class, and architecture pattern\n5. Report a summary to the user\n\n### Step 5: Offer next steps\n\nTell the user what they can do next:\n\n- **Trace call flows**: \"I can follow the execution flow from any Activity to its API calls\"\n- **Extract APIs**: \"I can search for all HTTP endpoints and document them\"\n- **Analyze specific classes**: \"Point me to a specific class or feature to analyze\"\n- **Re-decompile with Fernflower**: If jadx output has warnings, offer to re-run with `--engine both` for comparison\n\nRefer to the full skill documentation in `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/SKILL.md` for the complete workflow.\n","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/api-extraction-patterns.md":"# API Extraction Patterns\n\nPatterns and grep commands for finding HTTP API calls in decompiled Android source code.\n\n## Retrofit\n\nRetrofit is the most common HTTP client in Android apps. API endpoints are declared as annotated interface methods.\n\n### Annotations to search for\n\n```bash\n# HTTP method annotations\ngrep -rn '@GET\\|@POST\\|@PUT\\|@DELETE\\|@PATCH\\|@HEAD' sources/\n\n# Parameter annotations\ngrep -rn '@Query\\|@QueryMap\\|@Path\\|@Body\\|@Field\\|@FieldMap\\|@Part\\|@Header\\|@HeaderMap' sources/\n\n# Headers annotation (static headers)\ngrep -rn '@Headers' sources/\n\n# Base URL configuration\ngrep -rn 'baseUrl\\|\\.baseUrl(' sources/\n```\n\n### Typical Retrofit interface\n\n```java\npublic interface ApiService {\n    @GET(\"users/{id}\")\n    Call<User> getUser(@Path(\"id\") String userId);\n\n    @POST(\"auth/login\")\n    @Headers({\"Content-Type: application/json\"})\n    Call<LoginResponse> login(@Body LoginRequest request);\n}\n```\n\nWhen documenting, capture: HTTP method, path, path parameters, query parameters, request body type, response type, and any static headers.\n\n## OkHttp\n\nOkHttp is often used directly or as the transport layer for Retrofit.\n\n```bash\n# Request building\ngrep -rn 'Request\\.Builder\\|Request.Builder\\|\\.url(\\|\\.post(\\|\\.put(\\|\\.delete(\\|\\.patch(' sources/\n\n# URL construction\ngrep -rn 'HttpUrl\\|\\.addQueryParameter\\|\\.addPathSegment' sources/\n\n# Interceptors (often add auth headers)\ngrep -rn 'Interceptor\\|addInterceptor\\|addNetworkInterceptor\\|intercept(' sources/\n\n# Response handling\ngrep -rn '\\.execute()\\|\\.enqueue(' sources/\n```\n\n## Ktor (Kotlin)\n\nKtor is the dominant HTTP client in Kotlin Multiplatform and modern\nKotlin-only Android apps. Unlike Retrofit, Ktor does **not** use annotations\nto declare endpoints — paths appear as plain string arguments to\n`client.get(...)` / `client.post(...)`, often inside an extension function.\n\n```bash\n# Calls\ngrep -rn '\\b\\(client\\|httpClient\\|HttpClient\\)\\.\\(get\\|post\\|put\\|delete\\|patch\\|head\\|request\\)\\s*[<(]' sources/\n\n# Default request / base URL configuration\ngrep -rn 'HttpRequestBuilder\\|defaultRequest\\s*{\\|\\burl\\s*(\\s*\"\\|URLBuilder' sources/\n\n# Auth plugin (bearer / refresh)\ngrep -rn '\\bbearer\\s*{\\|BearerTokens\\s*(\\|loadTokens\\s*{\\|refreshTokens\\s*{' sources/\n```\n\nTypical Ktor call (after decompile):\n\n```java\nclient.get(\"api/v1/users/profile\") {\n    parameter(\"locale\", \"en-US\");\n}\n```\n\nThe base URL is usually applied via `defaultRequest { url { host = \"...\" } }`\nin the client builder. Search for `host =` and `URLProtocol.HTTPS` references\nto pin it down.\n\n**Note on obfuscation:** in heavily R8-shrunk apps the call site\n`client.get(\"path\")` is inlined to something like `aVar.a(dVar, \"path\")`\nand the `client.<verb>(` regex misses it. The path string itself is **not**\nobfuscated, however — fall back to the generic path-literal search\n(`--paths`) for the endpoint inventory in those cases. Ktor library\ninternals (`BearerTokens`, `loadTokens`, `refreshTokens`, `URLProtocol`)\nremain searchable because Ktor keeps these on its public API.\n\nKtor's authentication plugin uses the\n[`Auth { bearer { loadTokens { ... }; refreshTokens { ... } } }`](https://ktor.io/docs/auth.html)\nDSL — bearer access tokens with automatic refresh. After R8, the DSL\nlambdas appear as `Function2`/`Function3` impls referencing\n`BearerTokens(...)` calls.\n\n## Apollo Kotlin (GraphQL)\n\n```bash\n# Client setup\ngrep -rn 'ApolloClient\\|\\.serverUrl(\\|HttpNetworkTransport' sources/\n\n# Operations (queries / mutations / subscriptions)\ngrep -rn '\\.query(\\s*[A-Z]\\|\\.mutation(\\s*[A-Z]\\|\\.subscription(\\s*[A-Z]' sources/\n```\n\nApollo generates one class per operation under a generated package; once you\nfind the GraphQL endpoint URL via `ApolloClient.serverUrl(\"...\")`, use the\noperation classes themselves as the API documentation — each carries its\nGraphQL document text in `OPERATION_DOCUMENT`.\n\n## Volley\n\n```bash\ngrep -rn 'StringRequest\\|JsonObjectRequest\\|JsonArrayRequest\\|Volley\\.newRequestQueue\\|RequestQueue' sources/\n```\n\nVolley requests typically pass the URL as a constructor argument and override `getHeaders()` or `getParams()` for custom headers/parameters.\n\n## HttpURLConnection (legacy)\n\n```bash\ngrep -rn 'HttpURLConnection\\|HttpsURLConnection\\|openConnection\\|setRequestMethod\\|setRequestProperty' sources/\n```\n\n## WebView\n\n```bash\ngrep -rn 'loadUrl\\|evaluateJavascript\\|addJavascriptInterface\\|WebViewClient\\|shouldOverrideUrlLoading' sources/\n```\n\nWebView-based apps may load API endpoints via JavaScript bridges. Look for `@JavascriptInterface` annotated methods.\n\n## Endpoint-Shaped Path Literals (obfuscation-resistant)\n\nWhen the HTTP client cannot be identified (custom abstraction, heavy\ninlining, KMP shared module), or the call sites are obfuscated to\n`a.b(c, \"path\")`, fall back to extracting the path string literals\nthemselves. R8 does not obfuscate string contents, so paths leak through.\n\n```bash\n# All quoted strings shaped like an API path, deduplicated\ngrep -rhoE '\"(/[A-Za-z0-9_{}.\\-]+(/[A-Za-z0-9_{}.\\-]+)+/?|(api|v[0-9]+|graphql|users?|account|auth|sso|oauth|profile|cart|basket|order|product|inventory|search|category|address|location|delivery|payment|invoice|favo[u]?rites?)(/[A-Za-z0-9_{}.\\-]+)+/?)\"' sources/ \\\n    | grep -Ev '^\"(image|video|audio|text|application|content)/|^\"/(proc|sys|dev|tmp|etc)/' \\\n    | sort -u\n```\n\nThe skill ships this as `find-api-calls.sh --paths`, which prints both a\ndeduplicated inventory and the full list of call sites. On real-world\nKotlin apps this single command typically produces 100–300 distinct\nendpoint paths, which is the most useful first artifact for documentation.\n\n## Hardcoded URLs and Secrets\n\n```bash\n# HTTP/HTTPS URLs\ngrep -rn '\"https\\?://[^\"]*\"' sources/\n\n# API keys and tokens\ngrep -rni 'api[_-]\\?key\\|api[_-]\\?secret\\|auth[_-]\\?token\\|bearer\\|access[_-]\\?token\\|client[_-]\\?secret' sources/\n\n# Base URL constants\ngrep -rni 'BASE_URL\\|API_URL\\|SERVER_URL\\|ENDPOINT\\|API_BASE' sources/\n```\n\n## Documentation Template\n\nFor each discovered API endpoint, document it using this template:\n\n```markdown\n### `METHOD /path/to/endpoint`\n\n- **Source**: `com.example.app.api.ApiService` (file:line)\n- **Base URL**: `https://api.example.com/v1`\n- **Full URL**: `https://api.example.com/v1/path/to/endpoint`\n- **Path parameters**: `id` (String)\n- **Query parameters**: `page` (int), `limit` (int)\n- **Headers**:\n  - `Authorization: Bearer <token>`\n  - `Content-Type: application/json`\n- **Request body**: `LoginRequest { email: String, password: String }`\n- **Response type**: `ApiResponse<User>`\n- **Notes**: Called from `LoginActivity.onLoginClicked()`\n```\n\n## Search Strategy\n\n1. Start with **base URL constants** — find where the API root is configured\n2. Search for **Retrofit interfaces** — they give the clearest picture of all endpoints\n3. Check **interceptors** — they reveal auth schemes and common headers\n4. Search for **hardcoded URLs** — catch any one-off API calls outside the main client\n5. Look for **WebView URLs** — some apps use hybrid web/native approaches\n","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/call-flow-analysis.md":"# Call Flow Analysis\n\nTechniques for tracing execution flows in decompiled Android applications, from entry points down to network calls.\n\n## 1. Start from AndroidManifest.xml\n\nThe manifest declares all entry points. After decompilation, find it at:\n\n```\n<output-dir>/resources/AndroidManifest.xml\n```\n\nKey elements to look for:\n\n```bash\n# Activities (UI screens)\ngrep -n 'android:name=.*Activity' resources/AndroidManifest.xml\n\n# Services (background work)\ngrep -n 'android:name=.*Service' resources/AndroidManifest.xml\n\n# BroadcastReceivers\ngrep -n '<receiver' resources/AndroidManifest.xml\n\n# ContentProviders\ngrep -n '<provider' resources/AndroidManifest.xml\n\n# Launcher activity (main entry point)\ngrep -A5 'MAIN' resources/AndroidManifest.xml | grep 'android:name'\n```\n\n## 2. Follow the Android Lifecycle\n\nTypical call chain from UI to network:\n\n```\nActivity.onCreate()\n  → setContentView(R.layout.activity_main)\n  → findViewById() / View Binding\n  → button.setOnClickListener()\n    → onClick()\n      → viewModel.doSomething()\n        → repository.fetchData()\n          → apiService.getEndpoint()\n            → HTTP request\n```\n\nKey lifecycle methods to search:\n\n```bash\ngrep -rn 'onCreate\\|onResume\\|onStart\\|onViewCreated' sources/\n```\n\n## 3. Identify Click Handlers\n\nUser interactions trigger API calls. Common patterns:\n\n```bash\n# XML onClick\ngrep -rn 'setOnClickListener\\|onClick\\|OnClickListener' sources/\n\n# Data Binding\ngrep -rn '@BindingAdapter\\|android:onClick' sources/ resources/\n\n# Navigation actions\ngrep -rn 'findNavController\\|NavController\\|navigate(' sources/\n```\n\n## 4. Application Class Initialization\n\nThe `Application` subclass initializes global singletons (HTTP clients, DI frameworks, analytics):\n\n```bash\n# Find Application subclass\ngrep -rn 'extends Application\\|: Application()' sources/\n\n# Check onCreate for initialization\n# Then read the class to see what gets configured at startup\n```\n\nLook for:\n- Retrofit/OkHttp client setup\n- Dagger/Hilt component initialization\n- Firebase/analytics initialization\n- Base URL configuration\n\n## 5. Dependency Injection\n\n### Dagger / Hilt\n\n```bash\n# Hilt modules\ngrep -rn '@Module\\|@InstallIn\\|@Provides\\|@Binds' sources/\n\n# Hilt entry points\ngrep -rn '@HiltAndroidApp\\|@AndroidEntryPoint\\|@HiltViewModel' sources/\n\n# Dagger components\ngrep -rn '@Component\\|@Subcomponent' sources/\n\n# Injected fields\ngrep -rn '@Inject' sources/\n```\n\n### Koin\n\nKoin is the dominant DI framework in Kotlin Multiplatform and a large\nshare of Kotlin-only Android apps. It uses a runtime DSL rather than\ncompile-time generated factories, so the search patterns are different:\n\n```bash\n# Confirm Koin is actually wired up\ngrep -rn 'org\\.koin\\.' sources/\n\n# DI module declarations\ngrep -rn 'fun [A-Za-z]\\+Module\\|module\\s*{\\|module(' sources/\n\n# Bindings inside a module DSL\ngrep -rn 'single\\s*[<{(]\\|factory\\s*[<{(]\\|viewModel\\s*[<{(]\\|scoped\\s*[<{(]\\|singleOf\\|factoryOf' sources/\n\n# Resolution call-sites (where a binding is consumed)\ngrep -rn '\\bget\\s*<\\|\\binject\\s*<\\|by\\s\\+inject\\b\\|by\\s\\+viewModel\\b\\|getKoin' sources/\n```\n\nAfter R8, every binding lambda becomes an anonymous\n`Function2<Scope, ParametersHolder, T>` impl. To find the binding for an\ninterface `Foo`, look for files that contain both a Koin import / module\nDSL marker and a reference to `Foo`:\n\n```bash\ngrep -rln 'org\\.koin\\.core\\.module' sources/ | xargs grep -l 'Foo'\n```\n\n### Trace through DI\n\n1. Find where an interface is used (e.g. `ApiService` injected into a\n   repository).\n2. Find the `@Provides` / `@Binds` method (Hilt) **or** the\n   `single { ... }` / `factory { ... }` block (Koin) that creates the\n   implementation.\n3. Follow the implementation to the actual HTTP call.\n\n## 6. Find Constants and Configuration\n\nHardcoded values are rarely obfuscated:\n\n```bash\n# Base URLs\ngrep -rni 'BASE_URL\\|API_URL\\|SERVER_URL\\|HOST' sources/\n\n# API keys\ngrep -rni 'API_KEY\\|CLIENT_ID\\|APP_KEY\\|SECRET' sources/\n\n# BuildConfig values\ngrep -rn 'BuildConfig\\.' sources/\n\n# SharedPreferences keys (runtime config)\ngrep -rn 'getSharedPreferences\\|getString(\\|putString(' sources/\n```\n\n## 7. Navigating Obfuscated Code\n\nWhen code is obfuscated (ProGuard/R8):\n\n### What gets obfuscated\n- Class names → `a`, `b`, `c`\n- Method names → `a()`, `b()`, `c()`\n- Field names → `f1234a`, `f1235b`\n\n### What does NOT get obfuscated\n- **String literals** — URLs, keys, error messages remain readable\n- **Android framework classes** — `Activity`, `Fragment`, `Intent` keep their names\n- **Library public APIs** — Retrofit annotations, OkHttp builders retain names\n- **AndroidManifest entries** — Activity/Service names must be real\n\n### Strategy for obfuscated code\n\n1. **Start from strings**: Search for URLs, error messages, and known constants\n2. **Start from framework classes**: Activities and Fragments are named in the manifest\n3. **Follow library calls**: Retrofit `@GET`/`@POST` annotations are readable even when the interface class name is obfuscated\n4. **Recover original Kotlin names from metadata**: `@DebugMetadata` and `@Metadata.d2` strings preserve the original FQNs even after R8 obfuscation. Run `scripts/recover-kotlin-names.sh` to build an `obf -> real` map (typically recovers 30-50% of classes — and almost 100% of `*Repository` / `*ViewModel` / `*Impl`). See [`kotlin-name-recovery.md`](./kotlin-name-recovery.md). This is the single highest-leverage step on any Kotlin app.\n5. **Cross-reference**: If `class a` calls `Retrofit.create(b.class)`, then `b` is a Retrofit service interface\n6. **`--deobf` is rarely enough on its own**: jadx's `--deobf` renames obfuscated symbols with synthetic placeholders (`p001a`, `C0123Foo`) — useful for disambiguation but it does **not** recover original names. Pair it with the metadata recovery above.\n\n## 8. Tracing a Complete Call Flow: Example\n\nGoal: Find how login works in an obfuscated app.\n\n```\n1. grep for \"login\" in strings → find \"auth/login\" URL in class `c.a.b.d`\n2. Class `c.a.b.d` has @POST(\"auth/login\") → it's a Retrofit interface\n3. grep for `c.a.b.d` usage → class `c.a.b.f` calls it (the repository)\n4. grep for `c.a.b.f` usage → class `c.a.a.g` calls it (the ViewModel)\n5. grep for `c.a.a.g` usage → `LoginActivity` has a field of this type\n6. Read LoginActivity.onCreate() → sets click listener → calls ViewModel method\n```\n\nResult: `LoginActivity → ViewModel → Repository → Retrofit @POST(\"auth/login\")`\n\n## 9. Tools and Commands Summary\n\n| Goal | Command |\n|---|---|\n| Find entry points | `grep 'android:name' resources/AndroidManifest.xml` |\n| Find lifecycle methods | `grep -rn 'onCreate\\|onResume' sources/` |\n| Find click handlers | `grep -rn 'setOnClickListener\\|onClick' sources/` |\n| Find DI bindings | `grep -rn '@Provides\\|@Binds\\|@Inject' sources/` |\n| Find constants | `grep -rni 'BASE_URL\\|API_KEY' sources/` |\n| Find usages of a class | `grep -rn 'ClassName' sources/` |\n| Follow a string | `grep -rn '\"some text\"' sources/` |\n","plugins/android-reverse-engineering/skills/android-reverse-engineering/SKILL.md":"---\nname: android-reverse-engineering\ndescription: Decompile Android APK, XAPK, JAR, and AAR files using jadx or Fernflower/Vineflower. Reverse engineer Android apps, extract HTTP API endpoints (Retrofit, OkHttp, Volley), and trace call flows from UI to network layer. Use when the user wants to decompile, analyze, or reverse engineer Android packages, find API endpoints, or follow call flows. 中文触发词：反编译APK、安卓逆向、提取API、分析安卓应用、反编译安卓、逆向工程、追踪调用链、提取接口\ntrigger: decompile APK|decompile XAPK|reverse engineer Android|extract API|analyze Android|jadx|fernflower|vineflower|follow call flow|decompile JAR|decompile AAR|Android reverse engineering|find API endpoints|反编译APK|安卓逆向|提取API|分析安卓应用\n---\n\n# Android Reverse Engineering\n\nDecompile Android APK, XAPK, JAR, and AAR files using jadx and Fernflower/Vineflower, trace call flows through application code and libraries, and produce structured documentation of extracted APIs. Two decompiler engines are supported — jadx for broad Android coverage and Fernflower for higher-quality output on complex Java code — and can be used together for comparison.\n\n## Prerequisites\n\nThis skill requires **Java JDK 17+** and **jadx** to be installed. **Fernflower/Vineflower** and **dex2jar** are optional but recommended for better decompilation quality. Run the dependency checker to verify:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.ps1\"\n```\n\nIf anything is missing, follow the installation instructions in `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/setup-guide.md`.\n\n## Workflow\n\n### Phase 0: Fingerprint the App (recommended before anything else)\n\nBefore installing tools or decompiling, run a fast triage to determine what\nkind of app you are looking at. **Decompiling Java is mostly useless for\nFlutter, React Native, Cordova/Capacitor, and Xamarin apps** — the real code\nlives elsewhere. The fingerprint script tells you which.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/fingerprint.sh <file.apk|file.xapk>\n```\n\nIt prints, in one screen:\n\n- **Mobile framework** (Flutter / React Native / Cordova / Xamarin / Native Kotlin / etc.) with the file marker that triggered the verdict.\n- **HTTP stack** (Retrofit, OkHttp, Ktor, Apollo, Volley) detected via DEX string scan — works even when class names are obfuscated.\n- **DI / serialization** signals (Hilt, Dagger, Koin, kotlinx.serialization, Moshi, Gson, Jackson).\n- **Obfuscation level** estimate based on root-level short-named packages.\n- **Notable third-party SDKs** (AppsFlyer, Datadog, Sentry, Firebase, payment SDKs, support/chat SDKs, etc.).\n- **Consolidated native libraries** across the base APK and all splits — XAPK split bundles often place `.so` files in `config.<abi>.apk`, not in `base.apk`.\n- **Recommended next step**, which differs by framework (e.g. for Flutter the script suggests `blutter` / `strings libapp.so` rather than jadx).\n\nIf the fingerprint says the app is Flutter / RN / Cordova / Xamarin, **stop**\nand switch to the framework-appropriate tooling. Phases 1–5 below assume a\nnative (Java/Kotlin) Android app.\n\n### Phase 1: Verify and Install Dependencies\n\nBefore decompiling, confirm that the required tools are available — and install any that are missing.\n\n**Action**: Run the dependency check script.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.ps1\"\n```\n\nThe output contains machine-readable lines:\n- `INSTALL_REQUIRED:<dep>` — must be installed before proceeding\n- `INSTALL_OPTIONAL:<dep>` — recommended but not blocking\n\n**If required dependencies are missing** (exit code 1), install them automatically:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/install-dep.sh <dep>\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/install-dep.ps1\" <dep>\n```\n\nThe install script detects the OS and package manager, then:\n- Installs without sudo when possible (downloads to `~/.local/share/`, symlinks in `~/.local/bin/`)\n- Uses sudo and the system package manager when necessary (apt, dnf, pacman)\n- If sudo is needed but unavailable or the user declines, it prints the exact manual command and exits with code 2 — show these instructions to the user\n\n**Windows notes**: The PowerShell install script uses `winget`, `scoop`, or `choco` (in that order). If none are available, it downloads directly to `%USERPROFILE%\\.local\\share\\` and adds the directory to the user's PATH. After running `install-dep.ps1`, the PATH is persisted but the current terminal session may not see it. The `check-deps.ps1` and `decompile.ps1` scripts automatically refresh PATH from the user environment, so re-running them will find newly installed tools without restarting the terminal.\n\n**For optional dependencies**, ask the user if they want to install them. Vineflower and dex2jar are recommended for best results.\n\nAfter installation, re-run `check-deps.sh` to confirm everything is in place. Do not proceed to Phase 2 until all required dependencies are OK.\n\n### Phase 2: Decompile\n\nUse the decompile wrapper script to process the target file. The script supports three engines: `jadx`, `fernflower`, and `both`.\n\n**Action**: Choose the engine and run the decompile script. The script handles APK, XAPK, JAR, and AAR files.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh [OPTIONS] <file>\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.ps1\" [OPTIONS] <file>\n```\n\nFor **XAPK** files (ZIP bundles containing multiple APKs, used by APKPure and similar stores): the script automatically extracts the archive, identifies all APK files inside (base + split APKs), and decompiles each one into a separate subdirectory. The XAPK manifest is copied to the output for reference.\n\n**Split/bundled APK detection**: Some APKs are actually bundle wrappers — the outer APK contains `base.apk` plus `split_config.*.apk` files inside its resources directory. When this happens, jadx will decompile the thin wrapper and produce very few Java files. The decompile scripts automatically detect this (≤10 Java files + inner APKs present) and re-decompile `base.apk` into an `<output>/base/` subdirectory. Config-only splits (ABI, language, density) are skipped. The main decompiled source will be in `<output>/base/sources/`.\n\nOptions:\n- `-o <dir>` — Custom output directory (default: `<filename>-decompiled`)\n- `--deobf` — Enable deobfuscation (recommended for obfuscated apps)\n- `--no-res` — Skip resources, decompile code only (faster)\n- `--engine ENGINE` — `jadx` (default), `fernflower`, or `both`\n\n**Engine selection strategy**:\n\n| Situation | Engine |\n|---|---|\n| First pass on any APK | `jadx` (fastest, handles resources) |\n| JAR/AAR library analysis | `fernflower` (better Java output) |\n| jadx output has warnings/broken code | `both` (compare and pick best per class) |\n| Complex lambdas, generics, streams | `fernflower` |\n| Quick overview of a large APK | `jadx --no-res` |\n\nWhen using `--engine both`, the outputs go into `<output>/jadx/` and `<output>/fernflower/` respectively, with a comparison summary at the end showing file counts and jadx warning counts. Review classes with jadx warnings in the Fernflower output for better code.\n\nFor APK files with Fernflower, the script automatically uses dex2jar as an intermediate step. dex2jar must be installed for this to work.\n\nSee `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/jadx-usage.md` and `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/fernflower-usage.md` for the full CLI references.\n\n### Phase 3: Analyze Structure\n\nNavigate the decompiled output to understand the app's architecture.\n\n**Actions**:\n\n1. **Read AndroidManifest.xml** from `<output>/resources/AndroidManifest.xml`:\n   - Identify the main launcher Activity\n   - List all Activities, Services, BroadcastReceivers, ContentProviders\n   - Note permissions (especially `INTERNET`, `ACCESS_NETWORK_STATE`)\n   - Find the application class (`android:name` on `<application>`)\n\n2. **Survey the package structure** under `<output>/sources/`:\n   - Identify the main app package and sub-packages\n   - Distinguish app code from third-party libraries\n   - Look for packages named `api`, `network`, `data`, `repository`, `service`, `retrofit`, `http` — these are where API calls live\n\n3. **Read every `BuildConfig.java`** — these are almost never obfuscated and frequently leak the highest-signal constants in the entire APK (base URLs, flavor names, build type, third-party API keys, feature flags):\n   ```bash\n   find <output>/sources -name BuildConfig.java -exec grep -H '=' {} \\;\n   ```\n   Each Gradle module emits its own `BuildConfig`, so expect 1–N hits. Read all of them.\n\n4. **Identify the architecture pattern**:\n   - MVP: look for `Presenter` classes\n   - MVVM: look for `ViewModel` classes and `LiveData`/`StateFlow`\n   - Clean Architecture: look for `domain`, `data`, `presentation` packages\n   - This informs where to look for network calls in the next phases\n\n### Phase 3.5: Recover Kotlin Class Names (only for obfuscated Kotlin apps)\n\nIf Phase 0 reported moderate / high obfuscation **and** the app is Kotlin\n(Compose / kotlin_module markers detected), run the metadata recovery\nscript before tracing call flows. R8 obfuscates JVM symbols but cannot\nstrip Kotlin metadata strings, so original FQNs leak through\n`@DebugMetadata` and `@Metadata.d2`.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/recover-kotlin-names.sh \\\n    <output>/sources <output>/mapping\n```\n\nThen use the lookup helper instead of plain grep — every hit comes\nannotated with the owning class's real name:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/lookup-name.sh \\\n    <output>/mapping --grep '\"/api/' <output>/sources\n```\n\nTypical recovery on a real-world Kotlin app: ~100% of `*Repository` /\n`*ViewModel` / `*UseCase` / `*Impl` classes, ~80% of DTOs.\n\nSee `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/kotlin-name-recovery.md`\nfor the full technique and limitations.\n\n### Phase 4: Trace Call Flows\n\nFollow execution paths from user-facing entry points down to network calls.\n\n**Actions**:\n\n1. **Start from entry points**: Read the main Activity or Application class identified in Phase 3.\n\n2. **Follow the initialization chain**: Application.onCreate() often sets up the HTTP client, base URL, and DI framework. Read this first.\n\n3. **Trace user actions**: From an Activity, follow:\n   - `onCreate()` → view setup → click listeners\n   - Click handler → ViewModel/Presenter method\n   - ViewModel → Repository → API service interface\n   - API service → actual HTTP call\n\n4. **Map DI bindings** (if Dagger/Hilt is used): Find `@Module` classes to understand which implementations are provided for which interfaces.\n\n5. **Handle obfuscated code**: When class names are mangled, use string literals and library API calls as anchors. Retrofit annotations and URL strings are never obfuscated.\n\nSee `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/call-flow-analysis.md` for detailed techniques and grep commands.\n\n### Phase 5: Extract and Document APIs\n\nFind all API endpoints and produce structured documentation.\n\n**Action**: Run the API search script for a broad sweep.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.sh <output>/sources/\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.ps1\" <output>/sources/\n```\n\nTargeted searches:\n```bash\n# Only Retrofit\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.sh <output>/sources/ --retrofit\n\n# Only hardcoded URLs\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.sh <output>/sources/ --urls\n\n# Only auth patterns\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.sh <output>/sources/ --auth\n```\n\nOn Windows (PowerShell):\n```powershell\n# Only Retrofit\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.ps1\" <output>/sources/ -Retrofit\n\n# Only hardcoded URLs\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.ps1\" <output>/sources/ -Urls\n\n# Only auth patterns\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.ps1\" <output>/sources/ -AuthPatterns\n```\n\nDocument the endpoints in **two tiers** — going deep on every endpoint is\nprohibitively expensive on apps with 100+ paths, and most of them do not\nwarrant it. Always produce Tier 1; expand Tier 2 only for the endpoints\nthat matter.\n\n#### Tier 1 — flat inventory (always)\n\nA single table covering every discovered endpoint. Aim for one line each;\nif you cannot determine a column, write `?`.\n\n| Host | Method | Path | Auth | Source file |\n|------|--------|------|------|-------------|\n| `api.example.com` | GET | `/v1/users/profile` | Bearer | `com/example/api/UserApi.java` |\n| `api.example.com` | POST | `/v1/auth/login` | none | `com/example/api/AuthApi.java` |\n\nThis table answers \"what does the backend look like\" in one screen and\ntakes ~5 minutes to produce from the `--paths` output even on a large app.\n\n#### Tier 2 — per-endpoint detail (only for high-value endpoints)\n\nReserve the detailed format for the few endpoints that actually need it:\n\n- the entire authentication flow (login, refresh, logout, OTP/SMS, anonymous, registration)\n- payment / checkout / order-creation endpoints\n- anything the user explicitly asked about\n- anything that looked unusual during the scan (custom signing, undocumented headers, etc.)\n\n```markdown\n### `METHOD /path`\n\n- **Source**: `com.example.api.ApiService` (ApiService.java:42)\n- **Base URL**: `https://api.example.com/v1`\n- **Path params**: `id` (String)\n- **Query params**: `page` (int), `limit` (int)\n- **Headers**: `Authorization: Bearer <token>`\n- **Request body**: `{ \"email\": \"string\", \"password\": \"string\" }`\n- **Response**: `ApiResponse<User>`\n- **Called from**: `LoginActivity → LoginViewModel → UserRepository → ApiService`\n```\n\nAs a default, do not produce Tier 2 entries for more than ~10 endpoints\nunless the user explicitly asks for more — Tier 1 plus a Tier 2 deep dive\non auth + 1-2 key flows is what most consumers of this work actually want.\n\nSee `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/api-extraction-patterns.md` for library-specific search patterns and the full documentation template.\n\n## Output\n\nAt the end of the workflow, deliver:\n\n1. **Decompiled source** in the output directory\n2. **Architecture summary** — app structure, main packages, pattern used\n3. **API documentation** — all discovered endpoints in the format above\n4. **Call flow map** — key paths from UI to network (especially authentication and main features)\n\n## References\n\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/setup-guide.md` — Installing Java, jadx, Fernflower/Vineflower, dex2jar, and optional tools\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/jadx-usage.md` — jadx CLI options and workflows\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/fernflower-usage.md` — Fernflower/Vineflower CLI options, when to use, APK workflow\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/api-extraction-patterns.md` — Library-specific search patterns and documentation template\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/call-flow-analysis.md` — Techniques for tracing call flows in decompiled code\n","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/jadx-usage.md":"# jadx CLI Reference\n\n## Basic Usage\n\n```bash\njadx [options] <input-file>\n```\n\nInput can be an `.apk`, `.jar`, `.aar`, `.dex`, or `.zip` file.\n\n## Key Options\n\n| Option | Description |\n|---|---|\n| `-d <dir>` | Output directory for decompiled sources |\n| `--deobf` | Enable deobfuscation — renames obfuscated classes/methods to readable names |\n| `--show-bad-code` | Show partially decompiled code instead of error comments |\n| `--no-res` | Skip resource decoding — faster when you only need code |\n| `--no-src` | Skip source decompilation — only decode resources |\n| `--export-gradle` | Generate a Gradle project structure (useful for importing into IDE) |\n| `-e` | Same as `--export-gradle` |\n| `--threads-count <N>` | Number of processing threads (default: CPU count) |\n| `-Xmx<size>` | Set maximum Java heap (e.g., `-Xmx4g` for large APKs) |\n\n## Decompiling Different File Types\n\n### APK (Android Application Package)\n\n```bash\njadx -d output-dir app.apk\n```\n\nProduces:\n- `output-dir/sources/` — Decompiled Java source files\n- `output-dir/resources/` — Decoded resources (AndroidManifest.xml, layouts, drawables, etc.)\n\n### JAR (Java Archive)\n\n```bash\njadx -d output-dir library.jar\n```\n\nUseful for analyzing third-party libraries bundled within an APK.\n\n### AAR (Android Archive)\n\n```bash\njadx -d output-dir library.aar\n```\n\nAAR files contain both compiled code and Android resources. jadx handles them directly.\n\n## Handling Obfuscated Code\n\nApps built with ProGuard or R8 produce obfuscated bytecode with single-letter class and method names.\n\n### Strategies\n\n1. **Use `--deobf`** to generate readable replacement names:\n   ```bash\n   jadx --deobf -d output-dir app.apk\n   ```\n   jadx creates a mapping file at `output-dir/deobf-mapping.txt` that maps original obfuscated names to generated names.\n\n2. **Use the ProGuard mapping file** if available (sometimes shipped in the APK under `assets/` or obtainable from build artifacts):\n   ```bash\n   jadx --deobf-map mapping.txt -d output-dir app.apk\n   ```\n\n3. **Focus on string constants and API calls** rather than class names when navigating obfuscated code. URL strings, annotation values, and library classes are not obfuscated.\n\n## jadx-gui\n\nFor interactive exploration, use the GUI version:\n\n```bash\njadx-gui app.apk\n```\n\nFeatures:\n- Full-text search across all decompiled sources\n- Click-through navigation (jump to definition)\n- Deobfuscation with live renaming\n- Smali view alongside Java\n\njadx-gui is included in the same distribution as the CLI tool.\n\n## Common Workflows\n\n### Code-only decompilation (fastest)\n\n```bash\njadx --no-res --show-bad-code -d output app.apk\n```\n\n### Full decompilation with deobfuscation\n\n```bash\njadx --deobf --show-bad-code -d output app.apk\n```\n\n### Export as Gradle project for IDE import\n\n```bash\njadx -e -d output app.apk\n# Then open output/ in Android Studio or IntelliJ\n```\n\n### Decompile a specific DEX from a multi-dex APK\n\nExtract the APK (it's a ZIP), then target individual DEX files:\n\n```bash\nunzip app.apk -d extracted/\njadx -d output extracted/classes2.dex\n```\n","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/kotlin-name-recovery.md":"# Recovering Original Class Names from Kotlin Metadata\n\nWhen R8/ProGuard obfuscates a Kotlin app, JVM symbols are renamed but the\n**Kotlin metadata strings cannot be stripped** — the Kotlin runtime depends\non them at runtime for reflection, coroutines, and `data class` features.\n\nTwo annotations leak the original fully-qualified names:\n\n## `@DebugMetadata`\n\nGenerated for nearly every Kotlin coroutine `SuspendLambda` (i.e. almost\nevery `suspend` function in a modern app):\n\n```java\n@DebugMetadata(\n    c  = \"com.example.feature.account.AccountRepositoryImpl$fetch$1\",\n    f  = \"AccountRepositoryImpl.kt\",\n    l  = {42, 51},\n    m  = \"invokeSuspend\"\n)\npublic final class a extends SuspendLambda implements Function2<...> { ... }\n```\n\nThe `c =` field carries the original outer class FQN (with a `$` suffix\nfor inner / lambda scopes — strip everything after the first `$` to get the\ndeclaring class).\n\n## `@Metadata.d2`\n\nEvery Kotlin class carries a top-level `@Metadata` annotation. The `d2`\narray lists internal class refs in JVM type-descriptor format\n(`Lcom/example/Foo;`):\n\n```java\n@Metadata(d1 = {\"...\"},\n          d2 = {\"...\",\"Lcom/example/feature/account/AccountRepositoryImpl;\",\"...\"})\npublic final class b implements ... { ... }\n```\n\nThe first non-stdlib descriptor in `d2` is usually the file's primary\nclass.\n\n## How to mine them\n\nThe skill ships two scripts:\n\n```bash\n# Build a mapping from a decompiled sources directory:\nbash scripts/recover-kotlin-names.sh <output>/sources [mapping-dir]\n\n# Outputs:\n#   <mapping-dir>/mapping.tsv        obf_fqn  real_fqn  file\n#   <mapping-dir>/mapping.json       same data, JSON\n#   <mapping-dir>/by_package/        per-real-package index files\n\n# Query the mapping:\nbash scripts/lookup-name.sh <mapping-dir> Repository                 # search\nbash scripts/lookup-name.sh <mapping-dir> -o ab.cd                   # obf -> real\nbash scripts/lookup-name.sh <mapping-dir> -p com.example.feature     # list package\nbash scripts/lookup-name.sh <mapping-dir> --grep '\"api/' <output>/sources\n   # ^ greps decompiled code and appends '// real.fqn' to each hit\n```\n\n## What you typically recover\n\nOn a real-world obfuscated Kotlin app the script recovers **30 – 50 % of\nclasses** — but more importantly, **almost 100 % of the classes you\nactually want to read**:\n\n| Class kind                | Recovery rate |\n|---------------------------|---------------|\n| `*Repository` / `*Impl`   | ~100 %        |\n| `*ViewModel`              | ~100 %        |\n| `*UseCase` / `*Interactor`| ~100 %        |\n| Plain `data class` DTOs   | ~80 %         |\n| Pure-Java helper classes  | low (no Kotlin metadata) |\n| Anonymous inner classes   | sometimes recovered as the parent FQN |\n\n## Why `jadx --deobf` is not enough\n\n`--deobf` renames obfuscated identifiers using internal heuristics, but the\noutput is still synthetic (`p001a`, `C0123Foo`). It does **not** recover\nthe *original* names. Kotlin metadata recovery is the only reliable way to\nmap back to the names the developer actually wrote, and it costs essentially\nnothing — just a regex pass over the decompiled sources.\n\nRun both: `--deobf` for fields/methods that have no metadata source, plus\nthe recovery script for class names.\n\n## Limitations\n\n- **Method names and field names** are not recovered. Kotlin metadata only\n  preserves class-level FQNs and a few signatures. For method names you\n  still need jadx-gui's interactive rename or pattern inference.\n- **Pure-Java classes** carry no `@Metadata`, so they remain obfuscated.\n- **Heavily inlined classes** (`@JvmInline value class`, top-level fun\n  files compiled into shared `*Kt.class` synthetic classes) sometimes show\n  up under the wrong filename — treat results as a strong hint, not gospel.\n\n## Reading flow with the mapping\n\n1. Run `recover-kotlin-names.sh` once after decompiling.\n2. Use `lookup-name.sh --grep '<pattern>' <sources>` instead of plain `grep`\n   so every hit comes annotated with the real owning class.\n3. When you hit an obfuscated FQN in code (e.g. `nq.e`), resolve it with\n   `lookup-name.sh <mapping-dir> -o nq.e` — you will often see siblings\n   (`nq.d`, `nq.f`, ...) that are the same class's split lambdas/inner\n   classes, which is useful context.\n","plugins/android-reverse-engineering/skills/android-reverse-engineering/references/setup-guide.md":"# Setup Guide: Dependencies for Android Reverse Engineering\n\n## Java JDK 17+\n\njadx requires Java 17 or later.\n\n### Ubuntu / Debian\n\n```bash\nsudo apt update\nsudo apt install openjdk-17-jdk\n```\n\n### Fedora\n\n```bash\nsudo dnf install java-17-openjdk-devel\n```\n\n### Arch Linux\n\n```bash\nsudo pacman -S jdk17-openjdk\n```\n\n### macOS (Homebrew)\n\n```bash\nbrew install openjdk@17\n```\n\nAfter installation on macOS, follow the symlink instructions printed by Homebrew, or add to your shell profile:\n\n```bash\nexport PATH=\"/opt/homebrew/opt/openjdk@17/bin:$PATH\"\n```\n\n### Verify\n\n```bash\njava -version\n# Should show version 17.x or higher\n```\n\n---\n\n## jadx\n\njadx is the Java decompiler used to convert APK/JAR/AAR files to readable Java source.\n\n### Option 1: GitHub Releases (recommended)\n\n1. Go to <https://github.com/skylot/jadx/releases/latest>\n2. Download the `jadx-<version>.zip` file (not the source archive)\n3. Extract and add to PATH:\n\n```bash\nunzip jadx-*.zip -d ~/jadx\nexport PATH=\"$HOME/jadx/bin:$PATH\"\n# Add the export line to your ~/.bashrc or ~/.zshrc for persistence\n```\n\n### Option 2: Homebrew (macOS / Linux)\n\n```bash\nbrew install jadx\n```\n\n### Option 3: Build from source\n\n```bash\ngit clone https://github.com/skylot/jadx.git\ncd jadx\n./gradlew dist\n# Binaries will be in build/jadx/bin/\nexport PATH=\"$(pwd)/build/jadx/bin:$PATH\"\n```\n\n### Verify\n\n```bash\njadx --version\n```\n\n---\n\n## Fernflower / Vineflower (optional, recommended)\n\nFernflower is the JetBrains Java decompiler. It produces better output than jadx on complex Java constructs, lambdas, and generics. [Vineflower](https://github.com/Vineflower/vineflower) is the actively maintained community fork with published releases — prefer it over upstream Fernflower.\n\n### Option 1: Vineflower from GitHub Releases (recommended)\n\n1. Go to <https://github.com/Vineflower/vineflower/releases/latest>\n2. Download `vineflower-<version>.jar`\n3. Place it and set the environment variable:\n\n```bash\nmkdir -p ~/vineflower\nmv vineflower-*.jar ~/vineflower/vineflower.jar\nexport FERNFLOWER_JAR_PATH=\"$HOME/vineflower/vineflower.jar\"\n# Add the export to ~/.bashrc or ~/.zshrc for persistence\n```\n\n### Option 2: Build Fernflower from source\n\n```bash\ngit clone https://github.com/JetBrains/fernflower.git\ncd fernflower\n./gradlew jar\n# Produces: build/libs/fernflower.jar\nexport FERNFLOWER_JAR_PATH=\"$(pwd)/build/libs/fernflower.jar\"\n```\n\n### Option 3: Homebrew (Vineflower)\n\n```bash\nbrew install vineflower\n```\n\n### Verify\n\n```bash\njava -jar \"$FERNFLOWER_JAR_PATH\" --version\n```\n\n> **Note**: Fernflower only works on JVM bytecode (JAR, class files). For APK/DEX files, you also need **dex2jar** (see below) as an intermediate conversion step.\n\n---\n\n## dex2jar (optional, needed for Fernflower on APK files)\n\nConverts Android DEX bytecode to standard Java JAR files.\n\n### GitHub Releases\n\n1. Go to <https://github.com/ThexXTURBOXx/dex2jar/releases/latest>\n2. Download and extract:\n\n```bash\nunzip dex-tools-*.zip -d ~/dex2jar\nexport PATH=\"$HOME/dex2jar:$PATH\"\n```\n\n### Homebrew\n\n```bash\nbrew install dex2jar\n```\n\n### Verify\n\n```bash\nd2j-dex2jar --help\n```\n\n### Usage\n\n```bash\n# Convert APK (or DEX) to JAR\nd2j-dex2jar -f -o output.jar app.apk\n\n# Then decompile with Fernflower\njava -jar vineflower.jar output.jar decompiled/\n```\n\n---\n\n## Optional Tools\n\n### apktool\n\nUseful for decoding resources (XML layouts, drawables) that jadx sometimes handles poorly.\n\n```bash\n# Ubuntu/Debian\nsudo apt install apktool\n\n# macOS\nbrew install apktool\n\n# Manual: https://apktool.org/docs/install\n```\n\n### adb (Android Debug Bridge)\n\nUseful for pulling APKs directly from a connected Android device.\n\n```bash\n# Ubuntu/Debian\nsudo apt install adb\n\n# macOS\nbrew install android-platform-tools\n```\n\nPull an APK from a device:\n\n```bash\n# List installed packages\nadb shell pm list packages | grep <keyword>\n\n# Get APK path\nadb shell pm path com.example.app\n\n# Pull the APK\nadb pull /data/app/com.example.app-xxxx/base.apk ./app.apk\n```\n\n---\n\n## Troubleshooting\n\n| Problem | Solution |\n|---|---|\n| `jadx: command not found` | Ensure the jadx `bin/` directory is in your `$PATH` |\n| `Error: Could not find or load main class` | Java is missing or wrong version — verify with `java -version` |\n| jadx runs out of memory on large APKs | Increase heap: `jadx -Xmx4g -d output app.apk` or set `JAVA_OPTS=\"-Xmx4g\"` |\n| Decompiled code has many `// Error` comments | Try `--show-bad-code` to see partial output, or use `--deobf` for obfuscated apps |\n| Fernflower hangs on a method | Use `-mpm=60` to set a 60-second timeout per method |\n| Fernflower JAR not found | Set `FERNFLOWER_JAR_PATH` env variable to the full path of the JAR |\n| dex2jar fails with `ZipException` | The APK may have a non-standard ZIP structure — try `jadx` instead |\n"},"items":[{"name":"api-extraction-patterns.md","path":"plugins/android-reverse-engineering/skills/android-reverse-engineering/references/api-extraction-patterns.md","rawUrl":"https://raw.githubusercontent.com/SimoneAvogadro/android-reverse-engineering-skill/HEAD/plugins/android-reverse-engineering/skills/android-reverse-engineering/references/api-extraction-patterns.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# API Extraction Patterns\n\nPatterns and grep commands for finding HTTP API calls in decompiled Android source code.\n\n## Retrofit\n\nRetrofit is the most common HTTP client in Android apps. API endpoints are declared as annotated interface methods.\n\n### Annotations to search for\n\n```bash\n# HTTP method annotations\ngrep -rn '@GET\\|@POST\\|@PUT\\|@DELETE\\|@PATCH\\|@HEAD' sources/\n\n# Parameter annotations\ngrep -rn '@Query\\|@QueryMap\\|@Path\\|@Body\\|@Field\\|@FieldMap\\|@Part\\|@Header\\|@HeaderMap' sources/\n\n# Headers annotation (static headers)\ngrep -rn '@Headers' sources/\n\n# Base URL configuration\ngrep -rn 'baseUrl\\|\\.baseUrl(' sources/\n```\n\n### Typical Retrofit interface\n\n```java\npublic interface ApiService {\n    @GET(\"users/{id}\")\n    Call<User> getUser(@Path(\"id\") String userId);\n\n    @POST(\"auth/login\")\n    @Headers({\"Content-Type: application/json\"})\n    Call<LoginResponse> login(@Body LoginRequest request);\n}\n```\n\nWhen documenting, capture: HTTP method, path, path parameters, query parameters, request body type, response type, and any static headers.\n\n## OkHttp\n\nOkHttp is often used directly or as the transport layer for Retrofit.\n\n```bash\n# Request building\ngrep -rn 'Request\\.Builder\\|Request.Builder\\|\\.url(\\|\\.post(\\|\\.put(\\|\\.delete(\\|\\.patch(' sources/\n\n# URL construction\ngrep -rn 'HttpUrl\\|\\.addQueryParameter\\|\\.addPathSegment' sources/\n\n# Interceptors (often add auth headers)\ngrep -rn 'Interceptor\\|addInterceptor\\|addNetworkInterceptor\\|intercept(' sources/\n\n# Response handling\ngrep -rn '\\.execute()\\|\\.enqueue(' sources/\n```\n\n## Ktor (Kotlin)\n\nKtor is the dominant HTTP client in Kotlin Multiplatform and modern\nKotlin-only Android apps. Unlike Retrofit, Ktor does **not** use annotations\nto declare endpoints — paths appear as plain string arguments to\n`client.get(...)` / `client.post(...)`, often inside an extension function.\n\n```bash\n# Calls\ngrep -rn '\\b\\(client\\|httpClient\\|HttpClient\\)\\.\\(get\\|post\\|put\\|delete\\|patch\\|head\\|request\\)\\s*[<(]' sources/\n\n# Default request / base URL configuration\ngrep -rn 'HttpRequestBuilder\\|defaultRequest\\s*{\\|\\burl\\s*(\\s*\"\\|URLBuilder' sources/\n\n# Auth plugin (bearer / refresh)\ngrep -rn '\\bbearer\\s*{\\|BearerTokens\\s*(\\|loadTokens\\s*{\\|refreshTokens\\s*{' sources/\n```\n\nTypical Ktor call (after decompile):\n\n```java\nclient.get(\"api/v1/users/profile\") {\n    parameter(\"locale\", \"en-US\");\n}\n```\n\nThe base URL is usually applied via `defaultRequest { url { host = \"...\" } }`\nin the client builder. Search for `host =` and `URLProtocol.HTTPS` references\nto pin it down.\n\n**Note on obfuscation:** in heavily R8-shrunk apps the call site\n`client.get(\"path\")` is inlined to something like `aVar.a(dVar, \"path\")`\nand the `client.<verb>(` regex misses it. The path string itself is **not**\nobfuscated, however — fall back to the generic path-literal search\n(`--paths`) for the endpoint inventory in those cases. Ktor library\ninternals (`BearerTokens`, `loadTokens`, `refreshTokens`, `URLProtocol`)\nremain searchable because Ktor keeps these on its public API.\n\nKtor's authentication plugin uses the\n[`Auth { bearer { loadTokens { ... }; refreshTokens { ... } } }`](https://ktor.io/docs/auth.html)\nDSL — bearer access tokens with automatic refresh. After R8, the DSL\nlambdas appear as `Function2`/`Function3` impls referencing\n`BearerTokens(...)` calls.\n\n## Apollo Kotlin (GraphQL)\n\n```bash\n# Client setup\ngrep -rn 'ApolloClient\\|\\.serverUrl(\\|HttpNetworkTransport' sources/\n\n# Operations (queries / mutations / subscriptions)\ngrep -rn '\\.query(\\s*[A-Z]\\|\\.mutation(\\s*[A-Z]\\|\\.subscription(\\s*[A-Z]' sources/\n```\n\nApollo generates one class per operation under a generated package; once you\nfind the GraphQL endpoint URL via `ApolloClient.serverUrl(\"...\")`, use the\noperation classes themselves as the API documentation — each carries its\nGraphQL document text in `OPERATION_DOCUMENT`.\n\n## Volley\n\n```bash\ngrep -rn 'StringRequest\\|JsonObjectRequest\\|JsonArrayRequest\\|Volley\\.newRequestQueue\\|RequestQueue' sources/\n```\n\nVolley requests typically pass the URL as a constructor argument and override `getHeaders()` or `getParams()` for custom headers/parameters.\n\n## HttpURLConnection (legacy)\n\n```bash\ngrep -rn 'HttpURLConnection\\|HttpsURLConnection\\|openConnection\\|setRequestMethod\\|setRequestProperty' sources/\n```\n\n## WebView\n\n```bash\ngrep -rn 'loadUrl\\|evaluateJavascript\\|addJavascriptInterface\\|WebViewClient\\|shouldOverrideUrlLoading' sources/\n```\n\nWebView-based apps may load API endpoints via JavaScript bridges. Look for `@JavascriptInterface` annotated methods.\n\n## Endpoint-Shaped Path Literals (obfuscation-resistant)\n\nWhen the HTTP client cannot be identified (custom abstraction, heavy\ninlining, KMP shared module), or the call sites are obfuscated to\n`a.b(c, \"path\")`, fall back to extracting the path string literals\nthemselves. R8 does not obfuscate string contents, so paths leak through.\n\n```bash\n# All quoted strings shaped like an API path, deduplicated\ngrep -rhoE '\"(/[A-Za-z0-9_{}.\\-]+(/[A-Za-z0-9_{}.\\-]+)+/?|(api|v[0-9]+|graphql|users?|account|auth|sso|oauth|profile|cart|basket|order|product|inventory|search|category|address|location|delivery|payment|invoice|favo[u]?rites?)(/[A-Za-z0-9_{}.\\-]+)+/?)\"' sources/ \\\n    | grep -Ev '^\"(image|video|audio|text|application|content)/|^\"/(proc|sys|dev|tmp|etc)/' \\\n    | sort -u\n```\n\nThe skill ships this as `find-api-calls.sh --paths`, which prints both a\ndeduplicated inventory and the full list of call sites. On real-world\nKotlin apps this single command typically produces 100–300 distinct\nendpoint paths, which is the most useful first artifact for documentation.\n\n## Hardcoded URLs and Secrets\n\n```bash\n# HTTP/HTTPS URLs\ngrep -rn '\"https\\?://[^\"]*\"' sources/\n\n# API keys and tokens\ngrep -rni 'api[_-]\\?key\\|api[_-]\\?secret\\|auth[_-]\\?token\\|bearer\\|access[_-]\\?token\\|client[_-]\\?secret' sources/\n\n# Base URL constants\ngrep -rni 'BASE_URL\\|API_URL\\|SERVER_URL\\|ENDPOINT\\|API_BASE' sources/\n```\n\n## Documentation Template\n\nFor each discovered API endpoint, document it using this template:\n\n```markdown\n### `METHOD /path/to/endpoint`\n\n- **Source**: `com.example.app.api.ApiService` (file:line)\n- **Base URL**: `https://api.example.com/v1`\n- **Full URL**: `https://api.example.com/v1/path/to/endpoint`\n- **Path parameters**: `id` (String)\n- **Query parameters**: `page` (int), `limit` (int)\n- **Headers**:\n  - `Authorization: Bearer <token>`\n  - `Content-Type: application/json`\n- **Request body**: `LoginRequest { email: String, password: String }`\n- **Response type**: `ApiResponse<User>`\n- **Notes**: Called from `LoginActivity.onLoginClicked()`\n```\n\n## Search Strategy\n\n1. Start with **base URL constants** — find where the API root is configured\n2. Search for **Retrofit interfaces** — they give the clearest picture of all endpoints\n3. Check **interceptors** — they reveal auth schemes and common headers\n4. Search for **hardcoded URLs** — catch any one-off API calls outside the main client\n5. Look for **WebView URLs** — some apps use hybrid web/native approaches\n","isInternal":false,"tokens":1846,"sizeBytes":7030},{"name":"call-flow-analysis.md","path":"plugins/android-reverse-engineering/skills/android-reverse-engineering/references/call-flow-analysis.md","rawUrl":"https://raw.githubusercontent.com/SimoneAvogadro/android-reverse-engineering-skill/HEAD/plugins/android-reverse-engineering/skills/android-reverse-engineering/references/call-flow-analysis.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Call Flow Analysis\n\nTechniques for tracing execution flows in decompiled Android applications, from entry points down to network calls.\n\n## 1. Start from AndroidManifest.xml\n\nThe manifest declares all entry points. After decompilation, find it at:\n\n```\n<output-dir>/resources/AndroidManifest.xml\n```\n\nKey elements to look for:\n\n```bash\n# Activities (UI screens)\ngrep -n 'android:name=.*Activity' resources/AndroidManifest.xml\n\n# Services (background work)\ngrep -n 'android:name=.*Service' resources/AndroidManifest.xml\n\n# BroadcastReceivers\ngrep -n '<receiver' resources/AndroidManifest.xml\n\n# ContentProviders\ngrep -n '<provider' resources/AndroidManifest.xml\n\n# Launcher activity (main entry point)\ngrep -A5 'MAIN' resources/AndroidManifest.xml | grep 'android:name'\n```\n\n## 2. Follow the Android Lifecycle\n\nTypical call chain from UI to network:\n\n```\nActivity.onCreate()\n  → setContentView(R.layout.activity_main)\n  → findViewById() / View Binding\n  → button.setOnClickListener()\n    → onClick()\n      → viewModel.doSomething()\n        → repository.fetchData()\n          → apiService.getEndpoint()\n            → HTTP request\n```\n\nKey lifecycle methods to search:\n\n```bash\ngrep -rn 'onCreate\\|onResume\\|onStart\\|onViewCreated' sources/\n```\n\n## 3. Identify Click Handlers\n\nUser interactions trigger API calls. Common patterns:\n\n```bash\n# XML onClick\ngrep -rn 'setOnClickListener\\|onClick\\|OnClickListener' sources/\n\n# Data Binding\ngrep -rn '@BindingAdapter\\|android:onClick' sources/ resources/\n\n# Navigation actions\ngrep -rn 'findNavController\\|NavController\\|navigate(' sources/\n```\n\n## 4. Application Class Initialization\n\nThe `Application` subclass initializes global singletons (HTTP clients, DI frameworks, analytics):\n\n```bash\n# Find Application subclass\ngrep -rn 'extends Application\\|: Application()' sources/\n\n# Check onCreate for initialization\n# Then read the class to see what gets configured at startup\n```\n\nLook for:\n- Retrofit/OkHttp client setup\n- Dagger/Hilt component initialization\n- Firebase/analytics initialization\n- Base URL configuration\n\n## 5. Dependency Injection\n\n### Dagger / Hilt\n\n```bash\n# Hilt modules\ngrep -rn '@Module\\|@InstallIn\\|@Provides\\|@Binds' sources/\n\n# Hilt entry points\ngrep -rn '@HiltAndroidApp\\|@AndroidEntryPoint\\|@HiltViewModel' sources/\n\n# Dagger components\ngrep -rn '@Component\\|@Subcomponent' sources/\n\n# Injected fields\ngrep -rn '@Inject' sources/\n```\n\n### Koin\n\nKoin is the dominant DI framework in Kotlin Multiplatform and a large\nshare of Kotlin-only Android apps. It uses a runtime DSL rather than\ncompile-time generated factories, so the search patterns are different:\n\n```bash\n# Confirm Koin is actually wired up\ngrep -rn 'org\\.koin\\.' sources/\n\n# DI module declarations\ngrep -rn 'fun [A-Za-z]\\+Module\\|module\\s*{\\|module(' sources/\n\n# Bindings inside a module DSL\ngrep -rn 'single\\s*[<{(]\\|factory\\s*[<{(]\\|viewModel\\s*[<{(]\\|scoped\\s*[<{(]\\|singleOf\\|factoryOf' sources/\n\n# Resolution call-sites (where a binding is consumed)\ngrep -rn '\\bget\\s*<\\|\\binject\\s*<\\|by\\s\\+inject\\b\\|by\\s\\+viewModel\\b\\|getKoin' sources/\n```\n\nAfter R8, every binding lambda becomes an anonymous\n`Function2<Scope, ParametersHolder, T>` impl. To find the binding for an\ninterface `Foo`, look for files that contain both a Koin import / module\nDSL marker and a reference to `Foo`:\n\n```bash\ngrep -rln 'org\\.koin\\.core\\.module' sources/ | xargs grep -l 'Foo'\n```\n\n### Trace through DI\n\n1. Find where an interface is used (e.g. `ApiService` injected into a\n   repository).\n2. Find the `@Provides` / `@Binds` method (Hilt) **or** the\n   `single { ... }` / `factory { ... }` block (Koin) that creates the\n   implementation.\n3. Follow the implementation to the actual HTTP call.\n\n## 6. Find Constants and Configuration\n\nHardcoded values are rarely obfuscated:\n\n```bash\n# Base URLs\ngrep -rni 'BASE_URL\\|API_URL\\|SERVER_URL\\|HOST' sources/\n\n# API keys\ngrep -rni 'API_KEY\\|CLIENT_ID\\|APP_KEY\\|SECRET' sources/\n\n# BuildConfig values\ngrep -rn 'BuildConfig\\.' sources/\n\n# SharedPreferences keys (runtime config)\ngrep -rn 'getSharedPreferences\\|getString(\\|putString(' sources/\n```\n\n## 7. Navigating Obfuscated Code\n\nWhen code is obfuscated (ProGuard/R8):\n\n### What gets obfuscated\n- Class names → `a`, `b`, `c`\n- Method names → `a()`, `b()`, `c()`\n- Field names → `f1234a`, `f1235b`\n\n### What does NOT get obfuscated\n- **String literals** — URLs, keys, error messages remain readable\n- **Android framework classes** — `Activity`, `Fragment`, `Intent` keep their names\n- **Library public APIs** — Retrofit annotations, OkHttp builders retain names\n- **AndroidManifest entries** — Activity/Service names must be real\n\n### Strategy for obfuscated code\n\n1. **Start from strings**: Search for URLs, error messages, and known constants\n2. **Start from framework classes**: Activities and Fragments are named in the manifest\n3. **Follow library calls**: Retrofit `@GET`/`@POST` annotations are readable even when the interface class name is obfuscated\n4. **Recover original Kotlin names from metadata**: `@DebugMetadata` and `@Metadata.d2` strings preserve the original FQNs even after R8 obfuscation. Run `scripts/recover-kotlin-names.sh` to build an `obf -> real` map (typically recovers 30-50% of classes — and almost 100% of `*Repository` / `*ViewModel` / `*Impl`). See [`kotlin-name-recovery.md`](./kotlin-name-recovery.md). This is the single highest-leverage step on any Kotlin app.\n5. **Cross-reference**: If `class a` calls `Retrofit.create(b.class)`, then `b` is a Retrofit service interface\n6. **`--deobf` is rarely enough on its own**: jadx's `--deobf` renames obfuscated symbols with synthetic placeholders (`p001a`, `C0123Foo`) — useful for disambiguation but it does **not** recover original names. Pair it with the metadata recovery above.\n\n## 8. Tracing a Complete Call Flow: Example\n\nGoal: Find how login works in an obfuscated app.\n\n```\n1. grep for \"login\" in strings → find \"auth/login\" URL in class `c.a.b.d`\n2. Class `c.a.b.d` has @POST(\"auth/login\") → it's a Retrofit interface\n3. grep for `c.a.b.d` usage → class `c.a.b.f` calls it (the repository)\n4. grep for `c.a.b.f` usage → class `c.a.a.g` calls it (the ViewModel)\n5. grep for `c.a.a.g` usage → `LoginActivity` has a field of this type\n6. Read LoginActivity.onCreate() → sets click listener → calls ViewModel method\n```\n\nResult: `LoginActivity → ViewModel → Repository → Retrofit @POST(\"auth/login\")`\n\n## 9. Tools and Commands Summary\n\n| Goal | Command |\n|---|---|\n| Find entry points | `grep 'android:name' resources/AndroidManifest.xml` |\n| Find lifecycle methods | `grep -rn 'onCreate\\|onResume' sources/` |\n| Find click handlers | `grep -rn 'setOnClickListener\\|onClick' sources/` |\n| Find DI bindings | `grep -rn '@Provides\\|@Binds\\|@Inject' sources/` |\n| Find constants | `grep -rni 'BASE_URL\\|API_KEY' sources/` |\n| Find usages of a class | `grep -rn 'ClassName' sources/` |\n| Follow a string | `grep -rn '\"some text\"' sources/` |\n","isInternal":false,"tokens":1833,"sizeBytes":6988},{"name":"fernflower-usage.md","path":"plugins/android-reverse-engineering/skills/android-reverse-engineering/references/fernflower-usage.md","rawUrl":"https://raw.githubusercontent.com/SimoneAvogadro/android-reverse-engineering-skill/HEAD/plugins/android-reverse-engineering/skills/android-reverse-engineering/references/fernflower-usage.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Fernflower / Vineflower CLI Reference\n\nFernflower is the JetBrains analytical Java decompiler. [Vineflower](https://github.com/Vineflower/vineflower) is the actively maintained community fork with better output quality and published releases. They share the same CLI interface.\n\n## When to Use Fernflower vs jadx\n\n| Scenario | Recommended |\n|---|---|\n| APK with resources needed | jadx |\n| Standard Java JAR/library | Fernflower |\n| jadx output has warnings/errors on specific classes | Fernflower on those classes |\n| Complex lambdas, generics, streams | Fernflower |\n| Large APK (>50MB), quick overview | jadx |\n| Obfuscated Android app | jadx first, Fernflower on problem areas |\n| Both decompilers available | Use `--engine both` and compare |\n\n## Basic Usage\n\n```bash\njava -jar fernflower.jar [options] <source>... <destination>\n```\n\n- `<source>` — JAR file, class file, or directory containing class files\n- `<destination>` — output directory\n\nFor a JAR input, Fernflower produces a JAR in the destination containing `.java` source files. Extract it with `unzip` to browse the sources.\n\n## Key Options\n\nOptions use the format `-<key>=<value>`. Boolean options: `1` = enabled, `0` = disabled.\n\n| Option | Default | Description |\n|---|---|---|\n| `-dgs=1` | 0 | Decompile generic signatures (recommended) |\n| `-ren=1` | 0 | Rename obfuscated identifiers |\n| `-mpm=60` | 0 | Max seconds per method — prevents hangs (recommended) |\n| `-hes=0` | 1 | Show empty super() calls |\n| `-hdc=0` | 1 | Show empty default constructors |\n| `-udv=1` | 1 | Use debug variable names if available |\n| `-ump=1` | 1 | Use debug parameter names if available |\n| `-lit=1` | 0 | Output numeric literals as-is |\n| `-asc=1` | 0 | Encode non-ASCII as unicode escapes |\n| `-lac=1` | 0 | Decompile lambdas as anonymous classes |\n| `-log=WARN` | INFO | Reduce output verbosity |\n| `-e=<lib>` | — | Add library for context (not decompiled, improves type resolution) |\n\n## Recommended Presets\n\n### General use\n\n```bash\njava -jar fernflower.jar -dgs=1 -mpm=60 input.jar output/\n```\n\n### Obfuscated code\n\n```bash\njava -jar fernflower.jar -dgs=1 -ren=1 -mpm=60 input.jar output/\n```\n\n### Maximum detail\n\n```bash\njava -jar fernflower.jar -dgs=1 -hes=0 -hdc=0 -mpm=60 input.jar output/\n```\n\n### With Android SDK context (better type resolution)\n\n```bash\njava -jar fernflower.jar -dgs=1 -mpm=60 -e=$ANDROID_HOME/platforms/android-34/android.jar input.jar output/\n```\n\n## Working with APK Files\n\nFernflower cannot read APK/DEX files directly. Use dex2jar first:\n\n```bash\n# Step 1: Convert DEX to JAR\nd2j-dex2jar -f -o app-converted.jar app.apk\n\n# Step 2: Decompile with Fernflower\njava -jar fernflower.jar -dgs=1 -mpm=60 app-converted.jar output/\n\n# Step 3: Extract the resulting source JAR\nunzip -o output/app-converted.jar -d output/sources/\n```\n\nThe `decompile.sh --engine fernflower` script automates these steps.\n\n## Supported Input Formats\n\n| Format | Direct support | Via dex2jar |\n|---|---|---|\n| `.jar` | Yes | — |\n| `.class` | Yes | — |\n| `.zip` (with classes) | Yes | — |\n| `.apk` | No | Yes |\n| `.dex` | No | Yes |\n| `.aar` | No | Yes |\n\n## Output Format\n\n- **JAR input** → Produces `<destination>/<input-name>.jar` containing `.java` files\n- **Class file input** → Produces `.java` files directly in the destination\n- **No resource decoding** — Fernflower only produces Java source, never XML/resources\n\n## Fernflower vs Vineflower\n\nVineflower is the recommended fork. Improvements over upstream Fernflower:\n\n- Published releases on GitHub and Maven Central\n- Better handling of modern Java (records, sealed classes, pattern matching)\n- More accurate lambda and switch expression decompilation\n- Active bug fixes and community maintenance\n- Same CLI interface — drop-in replacement\n","isInternal":false,"tokens":1011,"sizeBytes":3785},{"name":"jadx-usage.md","path":"plugins/android-reverse-engineering/skills/android-reverse-engineering/references/jadx-usage.md","rawUrl":"https://raw.githubusercontent.com/SimoneAvogadro/android-reverse-engineering-skill/HEAD/plugins/android-reverse-engineering/skills/android-reverse-engineering/references/jadx-usage.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# jadx CLI Reference\n\n## Basic Usage\n\n```bash\njadx [options] <input-file>\n```\n\nInput can be an `.apk`, `.jar`, `.aar`, `.dex`, or `.zip` file.\n\n## Key Options\n\n| Option | Description |\n|---|---|\n| `-d <dir>` | Output directory for decompiled sources |\n| `--deobf` | Enable deobfuscation — renames obfuscated classes/methods to readable names |\n| `--show-bad-code` | Show partially decompiled code instead of error comments |\n| `--no-res` | Skip resource decoding — faster when you only need code |\n| `--no-src` | Skip source decompilation — only decode resources |\n| `--export-gradle` | Generate a Gradle project structure (useful for importing into IDE) |\n| `-e` | Same as `--export-gradle` |\n| `--threads-count <N>` | Number of processing threads (default: CPU count) |\n| `-Xmx<size>` | Set maximum Java heap (e.g., `-Xmx4g` for large APKs) |\n\n## Decompiling Different File Types\n\n### APK (Android Application Package)\n\n```bash\njadx -d output-dir app.apk\n```\n\nProduces:\n- `output-dir/sources/` — Decompiled Java source files\n- `output-dir/resources/` — Decoded resources (AndroidManifest.xml, layouts, drawables, etc.)\n\n### JAR (Java Archive)\n\n```bash\njadx -d output-dir library.jar\n```\n\nUseful for analyzing third-party libraries bundled within an APK.\n\n### AAR (Android Archive)\n\n```bash\njadx -d output-dir library.aar\n```\n\nAAR files contain both compiled code and Android resources. jadx handles them directly.\n\n## Handling Obfuscated Code\n\nApps built with ProGuard or R8 produce obfuscated bytecode with single-letter class and method names.\n\n### Strategies\n\n1. **Use `--deobf`** to generate readable replacement names:\n   ```bash\n   jadx --deobf -d output-dir app.apk\n   ```\n   jadx creates a mapping file at `output-dir/deobf-mapping.txt` that maps original obfuscated names to generated names.\n\n2. **Use the ProGuard mapping file** if available (sometimes shipped in the APK under `assets/` or obtainable from build artifacts):\n   ```bash\n   jadx --deobf-map mapping.txt -d output-dir app.apk\n   ```\n\n3. **Focus on string constants and API calls** rather than class names when navigating obfuscated code. URL strings, annotation values, and library classes are not obfuscated.\n\n## jadx-gui\n\nFor interactive exploration, use the GUI version:\n\n```bash\njadx-gui app.apk\n```\n\nFeatures:\n- Full-text search across all decompiled sources\n- Click-through navigation (jump to definition)\n- Deobfuscation with live renaming\n- Smali view alongside Java\n\njadx-gui is included in the same distribution as the CLI tool.\n\n## Common Workflows\n\n### Code-only decompilation (fastest)\n\n```bash\njadx --no-res --show-bad-code -d output app.apk\n```\n\n### Full decompilation with deobfuscation\n\n```bash\njadx --deobf --show-bad-code -d output app.apk\n```\n\n### Export as Gradle project for IDE import\n\n```bash\njadx -e -d output app.apk\n# Then open output/ in Android Studio or IntelliJ\n```\n\n### Decompile a specific DEX from a multi-dex APK\n\nExtract the APK (it's a ZIP), then target individual DEX files:\n\n```bash\nunzip app.apk -d extracted/\njadx -d output extracted/classes2.dex\n```\n","isInternal":false,"tokens":799,"sizeBytes":3078},{"name":"kotlin-name-recovery.md","path":"plugins/android-reverse-engineering/skills/android-reverse-engineering/references/kotlin-name-recovery.md","rawUrl":"https://raw.githubusercontent.com/SimoneAvogadro/android-reverse-engineering-skill/HEAD/plugins/android-reverse-engineering/skills/android-reverse-engineering/references/kotlin-name-recovery.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Recovering Original Class Names from Kotlin Metadata\n\nWhen R8/ProGuard obfuscates a Kotlin app, JVM symbols are renamed but the\n**Kotlin metadata strings cannot be stripped** — the Kotlin runtime depends\non them at runtime for reflection, coroutines, and `data class` features.\n\nTwo annotations leak the original fully-qualified names:\n\n## `@DebugMetadata`\n\nGenerated for nearly every Kotlin coroutine `SuspendLambda` (i.e. almost\nevery `suspend` function in a modern app):\n\n```java\n@DebugMetadata(\n    c  = \"com.example.feature.account.AccountRepositoryImpl$fetch$1\",\n    f  = \"AccountRepositoryImpl.kt\",\n    l  = {42, 51},\n    m  = \"invokeSuspend\"\n)\npublic final class a extends SuspendLambda implements Function2<...> { ... }\n```\n\nThe `c =` field carries the original outer class FQN (with a `$` suffix\nfor inner / lambda scopes — strip everything after the first `$` to get the\ndeclaring class).\n\n## `@Metadata.d2`\n\nEvery Kotlin class carries a top-level `@Metadata` annotation. The `d2`\narray lists internal class refs in JVM type-descriptor format\n(`Lcom/example/Foo;`):\n\n```java\n@Metadata(d1 = {\"...\"},\n          d2 = {\"...\",\"Lcom/example/feature/account/AccountRepositoryImpl;\",\"...\"})\npublic final class b implements ... { ... }\n```\n\nThe first non-stdlib descriptor in `d2` is usually the file's primary\nclass.\n\n## How to mine them\n\nThe skill ships two scripts:\n\n```bash\n# Build a mapping from a decompiled sources directory:\nbash scripts/recover-kotlin-names.sh <output>/sources [mapping-dir]\n\n# Outputs:\n#   <mapping-dir>/mapping.tsv        obf_fqn  real_fqn  file\n#   <mapping-dir>/mapping.json       same data, JSON\n#   <mapping-dir>/by_package/        per-real-package index files\n\n# Query the mapping:\nbash scripts/lookup-name.sh <mapping-dir> Repository                 # search\nbash scripts/lookup-name.sh <mapping-dir> -o ab.cd                   # obf -> real\nbash scripts/lookup-name.sh <mapping-dir> -p com.example.feature     # list package\nbash scripts/lookup-name.sh <mapping-dir> --grep '\"api/' <output>/sources\n   # ^ greps decompiled code and appends '// real.fqn' to each hit\n```\n\n## What you typically recover\n\nOn a real-world obfuscated Kotlin app the script recovers **30 – 50 % of\nclasses** — but more importantly, **almost 100 % of the classes you\nactually want to read**:\n\n| Class kind                | Recovery rate |\n|---------------------------|---------------|\n| `*Repository` / `*Impl`   | ~100 %        |\n| `*ViewModel`              | ~100 %        |\n| `*UseCase` / `*Interactor`| ~100 %        |\n| Plain `data class` DTOs   | ~80 %         |\n| Pure-Java helper classes  | low (no Kotlin metadata) |\n| Anonymous inner classes   | sometimes recovered as the parent FQN |\n\n## Why `jadx --deobf` is not enough\n\n`--deobf` renames obfuscated identifiers using internal heuristics, but the\noutput is still synthetic (`p001a`, `C0123Foo`). It does **not** recover\nthe *original* names. Kotlin metadata recovery is the only reliable way to\nmap back to the names the developer actually wrote, and it costs essentially\nnothing — just a regex pass over the decompiled sources.\n\nRun both: `--deobf` for fields/methods that have no metadata source, plus\nthe recovery script for class names.\n\n## Limitations\n\n- **Method names and field names** are not recovered. Kotlin metadata only\n  preserves class-level FQNs and a few signatures. For method names you\n  still need jadx-gui's interactive rename or pattern inference.\n- **Pure-Java classes** carry no `@Metadata`, so they remain obfuscated.\n- **Heavily inlined classes** (`@JvmInline value class`, top-level fun\n  files compiled into shared `*Kt.class` synthetic classes) sometimes show\n  up under the wrong filename — treat results as a strong hint, not gospel.\n\n## Reading flow with the mapping\n\n1. Run `recover-kotlin-names.sh` once after decompiling.\n2. Use `lookup-name.sh --grep '<pattern>' <sources>` instead of plain `grep`\n   so every hit comes annotated with the real owning class.\n3. When you hit an obfuscated FQN in code (e.g. `nq.e`), resolve it with\n   `lookup-name.sh <mapping-dir> -o nq.e` — you will often see siblings\n   (`nq.d`, `nq.f`, ...) that are the same class's split lambdas/inner\n   classes, which is useful context.\n","isInternal":false,"tokens":1066,"sizeBytes":4239},{"name":"setup-guide.md","path":"plugins/android-reverse-engineering/skills/android-reverse-engineering/references/setup-guide.md","rawUrl":"https://raw.githubusercontent.com/SimoneAvogadro/android-reverse-engineering-skill/HEAD/plugins/android-reverse-engineering/skills/android-reverse-engineering/references/setup-guide.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Setup Guide: Dependencies for Android Reverse Engineering\n\n## Java JDK 17+\n\njadx requires Java 17 or later.\n\n### Ubuntu / Debian\n\n```bash\nsudo apt update\nsudo apt install openjdk-17-jdk\n```\n\n### Fedora\n\n```bash\nsudo dnf install java-17-openjdk-devel\n```\n\n### Arch Linux\n\n```bash\nsudo pacman -S jdk17-openjdk\n```\n\n### macOS (Homebrew)\n\n```bash\nbrew install openjdk@17\n```\n\nAfter installation on macOS, follow the symlink instructions printed by Homebrew, or add to your shell profile:\n\n```bash\nexport PATH=\"/opt/homebrew/opt/openjdk@17/bin:$PATH\"\n```\n\n### Verify\n\n```bash\njava -version\n# Should show version 17.x or higher\n```\n\n---\n\n## jadx\n\njadx is the Java decompiler used to convert APK/JAR/AAR files to readable Java source.\n\n### Option 1: GitHub Releases (recommended)\n\n1. Go to <https://github.com/skylot/jadx/releases/latest>\n2. Download the `jadx-<version>.zip` file (not the source archive)\n3. Extract and add to PATH:\n\n```bash\nunzip jadx-*.zip -d ~/jadx\nexport PATH=\"$HOME/jadx/bin:$PATH\"\n# Add the export line to your ~/.bashrc or ~/.zshrc for persistence\n```\n\n### Option 2: Homebrew (macOS / Linux)\n\n```bash\nbrew install jadx\n```\n\n### Option 3: Build from source\n\n```bash\ngit clone https://github.com/skylot/jadx.git\ncd jadx\n./gradlew dist\n# Binaries will be in build/jadx/bin/\nexport PATH=\"$(pwd)/build/jadx/bin:$PATH\"\n```\n\n### Verify\n\n```bash\njadx --version\n```\n\n---\n\n## Fernflower / Vineflower (optional, recommended)\n\nFernflower is the JetBrains Java decompiler. It produces better output than jadx on complex Java constructs, lambdas, and generics. [Vineflower](https://github.com/Vineflower/vineflower) is the actively maintained community fork with published releases — prefer it over upstream Fernflower.\n\n### Option 1: Vineflower from GitHub Releases (recommended)\n\n1. Go to <https://github.com/Vineflower/vineflower/releases/latest>\n2. Download `vineflower-<version>.jar`\n3. Place it and set the environment variable:\n\n```bash\nmkdir -p ~/vineflower\nmv vineflower-*.jar ~/vineflower/vineflower.jar\nexport FERNFLOWER_JAR_PATH=\"$HOME/vineflower/vineflower.jar\"\n# Add the export to ~/.bashrc or ~/.zshrc for persistence\n```\n\n### Option 2: Build Fernflower from source\n\n```bash\ngit clone https://github.com/JetBrains/fernflower.git\ncd fernflower\n./gradlew jar\n# Produces: build/libs/fernflower.jar\nexport FERNFLOWER_JAR_PATH=\"$(pwd)/build/libs/fernflower.jar\"\n```\n\n### Option 3: Homebrew (Vineflower)\n\n```bash\nbrew install vineflower\n```\n\n### Verify\n\n```bash\njava -jar \"$FERNFLOWER_JAR_PATH\" --version\n```\n\n> **Note**: Fernflower only works on JVM bytecode (JAR, class files). For APK/DEX files, you also need **dex2jar** (see below) as an intermediate conversion step.\n\n---\n\n## dex2jar (optional, needed for Fernflower on APK files)\n\nConverts Android DEX bytecode to standard Java JAR files.\n\n### GitHub Releases\n\n1. Go to <https://github.com/ThexXTURBOXx/dex2jar/releases/latest>\n2. Download and extract:\n\n```bash\nunzip dex-tools-*.zip -d ~/dex2jar\nexport PATH=\"$HOME/dex2jar:$PATH\"\n```\n\n### Homebrew\n\n```bash\nbrew install dex2jar\n```\n\n### Verify\n\n```bash\nd2j-dex2jar --help\n```\n\n### Usage\n\n```bash\n# Convert APK (or DEX) to JAR\nd2j-dex2jar -f -o output.jar app.apk\n\n# Then decompile with Fernflower\njava -jar vineflower.jar output.jar decompiled/\n```\n\n---\n\n## Optional Tools\n\n### apktool\n\nUseful for decoding resources (XML layouts, drawables) that jadx sometimes handles poorly.\n\n```bash\n# Ubuntu/Debian\nsudo apt install apktool\n\n# macOS\nbrew install apktool\n\n# Manual: https://apktool.org/docs/install\n```\n\n### adb (Android Debug Bridge)\n\nUseful for pulling APKs directly from a connected Android device.\n\n```bash\n# Ubuntu/Debian\nsudo apt install adb\n\n# macOS\nbrew install android-platform-tools\n```\n\nPull an APK from a device:\n\n```bash\n# List installed packages\nadb shell pm list packages | grep <keyword>\n\n# Get APK path\nadb shell pm path com.example.app\n\n# Pull the APK\nadb pull /data/app/com.example.app-xxxx/base.apk ./app.apk\n```\n\n---\n\n## Troubleshooting\n\n| Problem | Solution |\n|---|---|\n| `jadx: command not found` | Ensure the jadx `bin/` directory is in your `$PATH` |\n| `Error: Could not find or load main class` | Java is missing or wrong version — verify with `java -version` |\n| jadx runs out of memory on large APKs | Increase heap: `jadx -Xmx4g -d output app.apk` or set `JAVA_OPTS=\"-Xmx4g\"` |\n| Decompiled code has many `// Error` comments | Try `--show-bad-code` to see partial output, or use `--deobf` for obfuscated apps |\n| Fernflower hangs on a method | Use `-mpm=60` to set a 60-second timeout per method |\n| Fernflower JAR not found | Set `FERNFLOWER_JAR_PATH` env variable to the full path of the JAR |\n| dex2jar fails with `ZipException` | The APK may have a non-standard ZIP structure — try `jadx` instead |\n","isInternal":false,"tokens":1309,"sizeBytes":4764},{"name":"SKILL.md","path":"plugins/android-reverse-engineering/skills/android-reverse-engineering/SKILL.md","rawUrl":"https://raw.githubusercontent.com/SimoneAvogadro/android-reverse-engineering-skill/HEAD/plugins/android-reverse-engineering/skills/android-reverse-engineering/SKILL.md","title":"android-reverse-engineering","category":"anthropic-skill","format":"markdown","content":"---\nname: android-reverse-engineering\ndescription: Decompile Android APK, XAPK, JAR, and AAR files using jadx or Fernflower/Vineflower. Reverse engineer Android apps, extract HTTP API endpoints (Retrofit, OkHttp, Volley), and trace call flows from UI to network layer. Use when the user wants to decompile, analyze, or reverse engineer Android packages, find API endpoints, or follow call flows. 中文触发词：反编译APK、安卓逆向、提取API、分析安卓应用、反编译安卓、逆向工程、追踪调用链、提取接口\ntrigger: decompile APK|decompile XAPK|reverse engineer Android|extract API|analyze Android|jadx|fernflower|vineflower|follow call flow|decompile JAR|decompile AAR|Android reverse engineering|find API endpoints|反编译APK|安卓逆向|提取API|分析安卓应用\n---\n\n# Android Reverse Engineering\n\nDecompile Android APK, XAPK, JAR, and AAR files using jadx and Fernflower/Vineflower, trace call flows through application code and libraries, and produce structured documentation of extracted APIs. Two decompiler engines are supported — jadx for broad Android coverage and Fernflower for higher-quality output on complex Java code — and can be used together for comparison.\n\n## Prerequisites\n\nThis skill requires **Java JDK 17+** and **jadx** to be installed. **Fernflower/Vineflower** and **dex2jar** are optional but recommended for better decompilation quality. Run the dependency checker to verify:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.ps1\"\n```\n\nIf anything is missing, follow the installation instructions in `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/setup-guide.md`.\n\n## Workflow\n\n### Phase 0: Fingerprint the App (recommended before anything else)\n\nBefore installing tools or decompiling, run a fast triage to determine what\nkind of app you are looking at. **Decompiling Java is mostly useless for\nFlutter, React Native, Cordova/Capacitor, and Xamarin apps** — the real code\nlives elsewhere. The fingerprint script tells you which.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/fingerprint.sh <file.apk|file.xapk>\n```\n\nIt prints, in one screen:\n\n- **Mobile framework** (Flutter / React Native / Cordova / Xamarin / Native Kotlin / etc.) with the file marker that triggered the verdict.\n- **HTTP stack** (Retrofit, OkHttp, Ktor, Apollo, Volley) detected via DEX string scan — works even when class names are obfuscated.\n- **DI / serialization** signals (Hilt, Dagger, Koin, kotlinx.serialization, Moshi, Gson, Jackson).\n- **Obfuscation level** estimate based on root-level short-named packages.\n- **Notable third-party SDKs** (AppsFlyer, Datadog, Sentry, Firebase, payment SDKs, support/chat SDKs, etc.).\n- **Consolidated native libraries** across the base APK and all splits — XAPK split bundles often place `.so` files in `config.<abi>.apk`, not in `base.apk`.\n- **Recommended next step**, which differs by framework (e.g. for Flutter the script suggests `blutter` / `strings libapp.so` rather than jadx).\n\nIf the fingerprint says the app is Flutter / RN / Cordova / Xamarin, **stop**\nand switch to the framework-appropriate tooling. Phases 1–5 below assume a\nnative (Java/Kotlin) Android app.\n\n### Phase 1: Verify and Install Dependencies\n\nBefore decompiling, confirm that the required tools are available — and install any that are missing.\n\n**Action**: Run the dependency check script.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.ps1\"\n```\n\nThe output contains machine-readable lines:\n- `INSTALL_REQUIRED:<dep>` — must be installed before proceeding\n- `INSTALL_OPTIONAL:<dep>` — recommended but not blocking\n\n**If required dependencies are missing** (exit code 1), install them automatically:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/install-dep.sh <dep>\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/install-dep.ps1\" <dep>\n```\n\nThe install script detects the OS and package manager, then:\n- Installs without sudo when possible (downloads to `~/.local/share/`, symlinks in `~/.local/bin/`)\n- Uses sudo and the system package manager when necessary (apt, dnf, pacman)\n- If sudo is needed but unavailable or the user declines, it prints the exact manual command and exits with code 2 — show these instructions to the user\n\n**Windows notes**: The PowerShell install script uses `winget`, `scoop`, or `choco` (in that order). If none are available, it downloads directly to `%USERPROFILE%\\.local\\share\\` and adds the directory to the user's PATH. After running `install-dep.ps1`, the PATH is persisted but the current terminal session may not see it. The `check-deps.ps1` and `decompile.ps1` scripts automatically refresh PATH from the user environment, so re-running them will find newly installed tools without restarting the terminal.\n\n**For optional dependencies**, ask the user if they want to install them. Vineflower and dex2jar are recommended for best results.\n\nAfter installation, re-run `check-deps.sh` to confirm everything is in place. Do not proceed to Phase 2 until all required dependencies are OK.\n\n### Phase 2: Decompile\n\nUse the decompile wrapper script to process the target file. The script supports three engines: `jadx`, `fernflower`, and `both`.\n\n**Action**: Choose the engine and run the decompile script. The script handles APK, XAPK, JAR, and AAR files.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh [OPTIONS] <file>\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.ps1\" [OPTIONS] <file>\n```\n\nFor **XAPK** files (ZIP bundles containing multiple APKs, used by APKPure and similar stores): the script automatically extracts the archive, identifies all APK files inside (base + split APKs), and decompiles each one into a separate subdirectory. The XAPK manifest is copied to the output for reference.\n\n**Split/bundled APK detection**: Some APKs are actually bundle wrappers — the outer APK contains `base.apk` plus `split_config.*.apk` files inside its resources directory. When this happens, jadx will decompile the thin wrapper and produce very few Java files. The decompile scripts automatically detect this (≤10 Java files + inner APKs present) and re-decompile `base.apk` into an `<output>/base/` subdirectory. Config-only splits (ABI, language, density) are skipped. The main decompiled source will be in `<output>/base/sources/`.\n\nOptions:\n- `-o <dir>` — Custom output directory (default: `<filename>-decompiled`)\n- `--deobf` — Enable deobfuscation (recommended for obfuscated apps)\n- `--no-res` — Skip resources, decompile code only (faster)\n- `--engine ENGINE` — `jadx` (default), `fernflower`, or `both`\n\n**Engine selection strategy**:\n\n| Situation | Engine |\n|---|---|\n| First pass on any APK | `jadx` (fastest, handles resources) |\n| JAR/AAR library analysis | `fernflower` (better Java output) |\n| jadx output has warnings/broken code | `both` (compare and pick best per class) |\n| Complex lambdas, generics, streams | `fernflower` |\n| Quick overview of a large APK | `jadx --no-res` |\n\nWhen using `--engine both`, the outputs go into `<output>/jadx/` and `<output>/fernflower/` respectively, with a comparison summary at the end showing file counts and jadx warning counts. Review classes with jadx warnings in the Fernflower output for better code.\n\nFor APK files with Fernflower, the script automatically uses dex2jar as an intermediate step. dex2jar must be installed for this to work.\n\nSee `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/jadx-usage.md` and `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/fernflower-usage.md` for the full CLI references.\n\n### Phase 3: Analyze Structure\n\nNavigate the decompiled output to understand the app's architecture.\n\n**Actions**:\n\n1. **Read AndroidManifest.xml** from `<output>/resources/AndroidManifest.xml`:\n   - Identify the main launcher Activity\n   - List all Activities, Services, BroadcastReceivers, ContentProviders\n   - Note permissions (especially `INTERNET`, `ACCESS_NETWORK_STATE`)\n   - Find the application class (`android:name` on `<application>`)\n\n2. **Survey the package structure** under `<output>/sources/`:\n   - Identify the main app package and sub-packages\n   - Distinguish app code from third-party libraries\n   - Look for packages named `api`, `network`, `data`, `repository`, `service`, `retrofit`, `http` — these are where API calls live\n\n3. **Read every `BuildConfig.java`** — these are almost never obfuscated and frequently leak the highest-signal constants in the entire APK (base URLs, flavor names, build type, third-party API keys, feature flags):\n   ```bash\n   find <output>/sources -name BuildConfig.java -exec grep -H '=' {} \\;\n   ```\n   Each Gradle module emits its own `BuildConfig`, so expect 1–N hits. Read all of them.\n\n4. **Identify the architecture pattern**:\n   - MVP: look for `Presenter` classes\n   - MVVM: look for `ViewModel` classes and `LiveData`/`StateFlow`\n   - Clean Architecture: look for `domain`, `data`, `presentation` packages\n   - This informs where to look for network calls in the next phases\n\n### Phase 3.5: Recover Kotlin Class Names (only for obfuscated Kotlin apps)\n\nIf Phase 0 reported moderate / high obfuscation **and** the app is Kotlin\n(Compose / kotlin_module markers detected), run the metadata recovery\nscript before tracing call flows. R8 obfuscates JVM symbols but cannot\nstrip Kotlin metadata strings, so original FQNs leak through\n`@DebugMetadata` and `@Metadata.d2`.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/recover-kotlin-names.sh \\\n    <output>/sources <output>/mapping\n```\n\nThen use the lookup helper instead of plain grep — every hit comes\nannotated with the owning class's real name:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/lookup-name.sh \\\n    <output>/mapping --grep '\"/api/' <output>/sources\n```\n\nTypical recovery on a real-world Kotlin app: ~100% of `*Repository` /\n`*ViewModel` / `*UseCase` / `*Impl` classes, ~80% of DTOs.\n\nSee `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/kotlin-name-recovery.md`\nfor the full technique and limitations.\n\n### Phase 4: Trace Call Flows\n\nFollow execution paths from user-facing entry points down to network calls.\n\n**Actions**:\n\n1. **Start from entry points**: Read the main Activity or Application class identified in Phase 3.\n\n2. **Follow the initialization chain**: Application.onCreate() often sets up the HTTP client, base URL, and DI framework. Read this first.\n\n3. **Trace user actions**: From an Activity, follow:\n   - `onCreate()` → view setup → click listeners\n   - Click handler → ViewModel/Presenter method\n   - ViewModel → Repository → API service interface\n   - API service → actual HTTP call\n\n4. **Map DI bindings** (if Dagger/Hilt is used): Find `@Module` classes to understand which implementations are provided for which interfaces.\n\n5. **Handle obfuscated code**: When class names are mangled, use string literals and library API calls as anchors. Retrofit annotations and URL strings are never obfuscated.\n\nSee `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/call-flow-analysis.md` for detailed techniques and grep commands.\n\n### Phase 5: Extract and Document APIs\n\nFind all API endpoints and produce structured documentation.\n\n**Action**: Run the API search script for a broad sweep.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.sh <output>/sources/\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.ps1\" <output>/sources/\n```\n\nTargeted searches:\n```bash\n# Only Retrofit\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.sh <output>/sources/ --retrofit\n\n# Only hardcoded URLs\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.sh <output>/sources/ --urls\n\n# Only auth patterns\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.sh <output>/sources/ --auth\n```\n\nOn Windows (PowerShell):\n```powershell\n# Only Retrofit\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.ps1\" <output>/sources/ -Retrofit\n\n# Only hardcoded URLs\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.ps1\" <output>/sources/ -Urls\n\n# Only auth patterns\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.ps1\" <output>/sources/ -AuthPatterns\n```\n\nDocument the endpoints in **two tiers** — going deep on every endpoint is\nprohibitively expensive on apps with 100+ paths, and most of them do not\nwarrant it. Always produce Tier 1; expand Tier 2 only for the endpoints\nthat matter.\n\n#### Tier 1 — flat inventory (always)\n\nA single table covering every discovered endpoint. Aim for one line each;\nif you cannot determine a column, write `?`.\n\n| Host | Method | Path | Auth | Source file |\n|------|--------|------|------|-------------|\n| `api.example.com` | GET | `/v1/users/profile` | Bearer | `com/example/api/UserApi.java` |\n| `api.example.com` | POST | `/v1/auth/login` | none | `com/example/api/AuthApi.java` |\n\nThis table answers \"what does the backend look like\" in one screen and\ntakes ~5 minutes to produce from the `--paths` output even on a large app.\n\n#### Tier 2 — per-endpoint detail (only for high-value endpoints)\n\nReserve the detailed format for the few endpoints that actually need it:\n\n- the entire authentication flow (login, refresh, logout, OTP/SMS, anonymous, registration)\n- payment / checkout / order-creation endpoints\n- anything the user explicitly asked about\n- anything that looked unusual during the scan (custom signing, undocumented headers, etc.)\n\n```markdown\n### `METHOD /path`\n\n- **Source**: `com.example.api.ApiService` (ApiService.java:42)\n- **Base URL**: `https://api.example.com/v1`\n- **Path params**: `id` (String)\n- **Query params**: `page` (int), `limit` (int)\n- **Headers**: `Authorization: Bearer <token>`\n- **Request body**: `{ \"email\": \"string\", \"password\": \"string\" }`\n- **Response**: `ApiResponse<User>`\n- **Called from**: `LoginActivity → LoginViewModel → UserRepository → ApiService`\n```\n\nAs a default, do not produce Tier 2 entries for more than ~10 endpoints\nunless the user explicitly asks for more — Tier 1 plus a Tier 2 deep dive\non auth + 1-2 key flows is what most consumers of this work actually want.\n\nSee `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/api-extraction-patterns.md` for library-specific search patterns and the full documentation template.\n\n## Output\n\nAt the end of the workflow, deliver:\n\n1. **Decompiled source** in the output directory\n2. **Architecture summary** — app structure, main packages, pattern used\n3. **API documentation** — all discovered endpoints in the format above\n4. **Call flow map** — key paths from UI to network (especially authentication and main features)\n\n## References\n\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/setup-guide.md` — Installing Java, jadx, Fernflower/Vineflower, dex2jar, and optional tools\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/jadx-usage.md` — jadx CLI options and workflows\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/fernflower-usage.md` — Fernflower/Vineflower CLI options, when to use, APK workflow\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/api-extraction-patterns.md` — Library-specific search patterns and documentation template\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/call-flow-analysis.md` — Techniques for tracing call flows in decompiled code\n","frontmatter":{"name":"android-reverse-engineering","description":"Decompile Android APK, XAPK, JAR, and AAR files using jadx or Fernflower/Vineflower. Reverse engineer Android apps, extract HTTP API endpoints (Retrofit, OkHttp, Volley), and trace call flows from UI to network layer. Use when the user wants to decompile, analyze, or reverse engineer Android packages, find API endpoints, or follow call flows. 中文触发词：反编译APK、安卓逆向、提取API、分析安卓应用、反编译安卓、逆向工程、追踪调用链、提取接口","trigger":"decompile APK|decompile XAPK|reverse engineer Android|extract API|analyze Android|jadx|fernflower|vineflower|follow call flow|decompile JAR|decompile AAR|Android reverse engineering|find API endpoints|反编译APK|安卓逆向|提取API|分析安卓应用"},"isInternal":false,"tokens":3899,"sizeBytes":16286},{"name":"marketplace.json","path":".claude-plugin/marketplace.json","rawUrl":"https://raw.githubusercontent.com/SimoneAvogadro/android-reverse-engineering-skill/HEAD/.claude-plugin/marketplace.json","title":"android-reverse-engineering-skill","category":"marketplace","format":"json","content":"{\n  \"$schema\": \"https://anthropic.com/claude-code/marketplace.schema.json\",\n  \"name\": \"android-reverse-engineering-skill\",\n  \"description\": \"Claude Code plugins for Android reverse engineering\",\n  \"owner\": {\n    \"name\": \"Simone Avogadro\"\n  },\n  \"metadata\": {\n    \"description\": \"Claude Code plugins for Android reverse engineering\",\n    \"version\": \"1.5.0\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"android-reverse-engineering\",\n      \"source\": \"./plugins/android-reverse-engineering\",\n      \"description\": \"Decompile Android APK/JAR/AAR with jadx, trace call flows through libraries, and document extracted APIs.\",\n      \"version\": \"1.5.0\",\n      \"author\": {\n        \"name\": \"Simone Avogadro\"\n      },\n      \"repository\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill\",\n      \"license\": \"Apache-2.0\",\n      \"keywords\": [\"android\", \"reverse-engineering\", \"apk\", \"jadx\", \"decompile\", \"api-extraction\"],\n      \"category\": \"security\"\n    }\n  ]\n}\n","frontmatter":{"$schema":"https://anthropic.com/claude-code/marketplace.schema.json","name":"android-reverse-engineering-skill","description":"Claude Code plugins for Android reverse engineering","owner":{"name":"Simone Avogadro"},"metadata":{"description":"Claude Code plugins for Android reverse engineering","version":"1.5.0"},"plugins":[{"name":"android-reverse-engineering","source":"./plugins/android-reverse-engineering","description":"Decompile Android APK/JAR/AAR with jadx, trace call flows through libraries, and document extracted APIs.","version":"1.5.0","author":{"name":"Simone Avogadro"},"repository":"https://github.com/SimoneAvogadro/android-reverse-engineering-skill","license":"Apache-2.0","keywords":["android","reverse-engineering","apk","jadx","decompile","api-extraction"],"category":"security"}]},"isInternal":false,"tokens":259,"sizeBytes":964},{"name":"plugin.json","path":"plugins/android-reverse-engineering/.claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/SimoneAvogadro/android-reverse-engineering-skill/HEAD/plugins/android-reverse-engineering/.claude-plugin/plugin.json","title":"android-reverse-engineering","category":"plugin-manifest","format":"json","content":"{\n  \"name\": \"android-reverse-engineering\",\n  \"version\": \"1.5.0\",\n  \"description\": \"Decompile Android APK/JAR/AAR with jadx, trace call flows through libraries, and document extracted APIs.\",\n  \"author\": {\n    \"name\": \"Simone Avogadro\"\n  },\n  \"homepage\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill\",\n  \"repository\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill\",\n  \"documentationUrl\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill#readme\",\n  \"license\": \"Apache-2.0\",\n  \"supportUrl\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill/issues/new\",\n  \"termsOfServiceUrl\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/master/LICENSE\",\n  \"privacyPolicyUrl\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/master/PRIVACY.md\",\n  \"keywords\": [\"android\", \"reverse-engineering\", \"apk\", \"jadx\", \"decompile\", \"api-extraction\"],\n  \"skills\": \"./skills/\",\n  \"commands\": \"./commands/\"\n}\n","frontmatter":{"name":"android-reverse-engineering","version":"1.5.0","description":"Decompile Android APK/JAR/AAR with jadx, trace call flows through libraries, and document extracted APIs.","author":{"name":"Simone Avogadro"},"homepage":"https://github.com/SimoneAvogadro/android-reverse-engineering-skill","repository":"https://github.com/SimoneAvogadro/android-reverse-engineering-skill","documentationUrl":"https://github.com/SimoneAvogadro/android-reverse-engineering-skill#readme","license":"Apache-2.0","supportUrl":"https://github.com/SimoneAvogadro/android-reverse-engineering-skill/issues/new","termsOfServiceUrl":"https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/master/LICENSE","privacyPolicyUrl":"https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/master/PRIVACY.md","keywords":["android","reverse-engineering","apk","jadx","decompile","api-extraction"],"skills":"./skills/","commands":"./commands/"},"isInternal":false,"tokens":283,"sizeBytes":1018},{"name":"decompile.md","path":"plugins/android-reverse-engineering/commands/decompile.md","rawUrl":"https://raw.githubusercontent.com/SimoneAvogadro/android-reverse-engineering-skill/HEAD/plugins/android-reverse-engineering/commands/decompile.md","title":"Command: /decompile","category":"command-prompt","format":"markdown","content":"---\nallowed-tools: Bash(bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh), Bash(bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh *), Read, Glob, Grep\ndescription: Decompile an Android APK/XAPK/JAR/AAR and analyze its structure\nuser-invocable: true\nargument-hint: <path to APK, XAPK, JAR, or AAR file>\nargument: path to APK, XAPK, JAR, or AAR file (optional)\n---\n\n# /decompile\n\nDecompile an Android application and perform initial structure analysis.\n\n## Instructions\n\nYou are starting the Android reverse engineering workflow. Follow these steps:\n\n### Step 1: Get the target file\n\nIf the user provided a file path as an argument, use that. Otherwise, ask the user for the path to the APK, XAPK, JAR, or AAR file they want to decompile.\n\n### Step 2: Check and install dependencies\n\nRun the dependency check:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh\n```\n\nParse the output looking for `INSTALL_REQUIRED:` and `INSTALL_OPTIONAL:` lines.\n\n**If required dependencies are missing**, install them one by one:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/install-dep.sh java\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/install-dep.sh jadx\n```\n\nThe install script auto-detects the OS and installs without sudo when possible (user-local install to `~/.local/`). If sudo is needed, it will prompt — if the user declines or sudo is unavailable, the script prints exact manual instructions (exit code 2). Show those instructions to the user and stop.\n\n**For optional dependencies** (`INSTALL_OPTIONAL:vineflower`, `INSTALL_OPTIONAL:dex2jar`, etc.), ask the user if they want to install them. Recommend vineflower and dex2jar for better results.\n\nAfter any installations, re-run `check-deps.sh` to verify. Do not proceed until all required dependencies pass.\n\n### Step 3: Decompile\n\nRun the decompile script on the target file. Choose the engine based on the input:\n\n- **APK or XAPK** → use jadx first (handles resources natively; XAPK is auto-extracted):\n\n  ```bash\n  bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh <file>\n  ```\n\n- **JAR/AAR** and Fernflower is available → prefer fernflower for better Java output:\n\n  ```bash\n  bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh --engine fernflower <file>\n  ```\n\n- **If jadx output has warnings** or the user wants the best quality → run both and compare:\n\n  ```bash\n  bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh --engine both <file>\n  ```\n\nFor obfuscated apps (if the user mentions it or you detect single-letter package names), add `--deobf`:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh --deobf <file>\n```\n\n### Step 4: Analyze structure\n\nAfter decompilation completes:\n\n1. Read `AndroidManifest.xml` from the resources directory. For XAPK, check the base APK's output first.\n2. If XAPK, review `xapk-manifest.json` in the output directory to understand the split structure.\n3. List the top-level package structure\n4. Identify the app's main Activity, Application class, and architecture pattern\n5. Report a summary to the user\n\n### Step 5: Offer next steps\n\nTell the user what they can do next:\n\n- **Trace call flows**: \"I can follow the execution flow from any Activity to its API calls\"\n- **Extract APIs**: \"I can search for all HTTP endpoints and document them\"\n- **Analyze specific classes**: \"Point me to a specific class or feature to analyze\"\n- **Re-decompile with Fernflower**: If jadx output has warnings, offer to re-run with `--engine both` for comparison\n\nRefer to the full skill documentation in `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/SKILL.md` for the complete workflow.\n","frontmatter":{"allowed-tools":"Bash(bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh), Bash(bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh *), Read, Glob, Grep","description":"Decompile an Android APK/XAPK/JAR/AAR and analyze its structure","user-invocable":true,"argument-hint":"<path to APK, XAPK, JAR, or AAR file>","argument":"path to APK, XAPK, JAR, or AAR file (optional)","allowedTools":["Bash(bash","${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh),","Bash(bash","${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh","*),","Read,","Glob,","Grep"]},"allowedTools":["Bash(bash","${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh),","Bash(bash","${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh","*),","Read,","Glob,","Grep"],"isInternal":false,"tokens":938,"sizeBytes":3886}],"systemPromptSnippet":"<yakaai_skills repo=\"SimoneAvogadro/android-reverse-engineering-skill\">\n<!-- File: plugins/android-reverse-engineering/skills/android-reverse-engineering/references/api-extraction-patterns.md (Tokens: ~1846 | Category: anthropic-skill) -->\n# API Extraction Patterns\n\nPatterns and grep commands for finding HTTP API calls in decompiled Android source code.\n\n## Retrofit\n\nRetrofit is the most common HTTP client in Android apps. API endpoints are declared as annotated interface methods.\n\n### Annotations to search for\n\n```bash\n# HTTP method annotations\ngrep -rn '@GET\\|@POST\\|@PUT\\|@DELETE\\|@PATCH\\|@HEAD' sources/\n\n# Parameter annotations\ngrep -rn '@Query\\|@QueryMap\\|@Path\\|@Body\\|@Field\\|@FieldMap\\|@Part\\|@Header\\|@HeaderMap' sources/\n\n# Headers annotation (static headers)\ngrep -rn '@Headers' sources/\n\n# Base URL configuration\ngrep -rn 'baseUrl\\|\\.baseUrl(' sources/\n```\n\n### Typical Retrofit interface\n\n```java\npublic interface ApiService {\n    @GET(\"users/{id}\")\n    Call<User> getUser(@Path(\"id\") String userId);\n\n    @POST(\"auth/login\")\n    @Headers({\"Content-Type: application/json\"})\n    Call<LoginResponse> login(@Body LoginRequest request);\n}\n```\n\nWhen documenting, capture: HTTP method, path, path parameters, query parameters, request body type, response type, and any static headers.\n\n## OkHttp\n\nOkHttp is often used directly or as the transport layer for Retrofit.\n\n```bash\n# Request building\ngrep -rn 'Request\\.Builder\\|Request.Builder\\|\\.url(\\|\\.post(\\|\\.put(\\|\\.delete(\\|\\.patch(' sources/\n\n# URL construction\ngrep -rn 'HttpUrl\\|\\.addQueryParameter\\|\\.addPathSegment' sources/\n\n# Interceptors (often add auth headers)\ngrep -rn 'Interceptor\\|addInterceptor\\|addNetworkInterceptor\\|intercept(' sources/\n\n# Response handling\ngrep -rn '\\.execute()\\|\\.enqueue(' sources/\n```\n\n## Ktor (Kotlin)\n\nKtor is the dominant HTTP client in Kotlin Multiplatform and modern\nKotlin-only Android apps. Unlike Retrofit, Ktor does **not** use annotations\nto declare endpoints — paths appear as plain string arguments to\n`client.get(...)` / `client.post(...)`, often inside an extension function.\n\n```bash\n# Calls\ngrep -rn '\\b\\(client\\|httpClient\\|HttpClient\\)\\.\\(get\\|post\\|put\\|delete\\|patch\\|head\\|request\\)\\s*[<(]' sources/\n\n# Default request / base URL configuration\ngrep -rn 'HttpRequestBuilder\\|defaultRequest\\s*{\\|\\burl\\s*(\\s*\"\\|URLBuilder' sources/\n\n# Auth plugin (bearer / refresh)\ngrep -rn '\\bbearer\\s*{\\|BearerTokens\\s*(\\|loadTokens\\s*{\\|refreshTokens\\s*{' sources/\n```\n\nTypical Ktor call (after decompile):\n\n```java\nclient.get(\"api/v1/users/profile\") {\n    parameter(\"locale\", \"en-US\");\n}\n```\n\nThe base URL is usually applied via `defaultRequest { url { host = \"...\" } }`\nin the client builder. Search for `host =` and `URLProtocol.HTTPS` references\nto pin it down.\n\n**Note on obfuscation:** in heavily R8-shrunk apps the call site\n`client.get(\"path\")` is inlined to something like `aVar.a(dVar, \"path\")`\nand the `client.<verb>(` regex misses it. The path string itself is **not**\nobfuscated, however — fall back to the generic path-literal search\n(`--paths`) for the endpoint inventory in those cases. Ktor library\ninternals (`BearerTokens`, `loadTokens`, `refreshTokens`, `URLProtocol`)\nremain searchable because Ktor keeps these on its public API.\n\nKtor's authentication plugin uses the\n[`Auth { bearer { loadTokens { ... }; refreshTokens { ... } } }`](https://ktor.io/docs/auth.html)\nDSL — bearer access tokens with automatic refresh. After R8, the DSL\nlambdas appear as `Function2`/`Function3` impls referencing\n`BearerTokens(...)` calls.\n\n## Apollo Kotlin (GraphQL)\n\n```bash\n# Client setup\ngrep -rn 'ApolloClient\\|\\.serverUrl(\\|HttpNetworkTransport' sources/\n\n# Operations (queries / mutations / subscriptions)\ngrep -rn '\\.query(\\s*[A-Z]\\|\\.mutation(\\s*[A-Z]\\|\\.subscription(\\s*[A-Z]' sources/\n```\n\nApollo generates one class per operation under a generated package; once you\nfind the GraphQL endpoint URL via `ApolloClient.serverUrl(\"...\")`, use the\noperation classes themselves as the API documentation — each carries its\nGraphQL document text in `OPERATION_DOCUMENT`.\n\n## Volley\n\n```bash\ngrep -rn 'StringRequest\\|JsonObjectRequest\\|JsonArrayRequest\\|Volley\\.newRequestQueue\\|RequestQueue' sources/\n```\n\nVolley requests typically pass the URL as a constructor argument and override `getHeaders()` or `getParams()` for custom headers/parameters.\n\n## HttpURLConnection (legacy)\n\n```bash\ngrep -rn 'HttpURLConnection\\|HttpsURLConnection\\|openConnection\\|setRequestMethod\\|setRequestProperty' sources/\n```\n\n## WebView\n\n```bash\ngrep -rn 'loadUrl\\|evaluateJavascript\\|addJavascriptInterface\\|WebViewClient\\|shouldOverrideUrlLoading' sources/\n```\n\nWebView-based apps may load API endpoints via JavaScript bridges. Look for `@JavascriptInterface` annotated methods.\n\n## Endpoint-Shaped Path Literals (obfuscation-resistant)\n\nWhen the HTTP client cannot be identified (custom abstraction, heavy\ninlining, KMP shared module), or the call sites are obfuscated to\n`a.b(c, \"path\")`, fall back to extracting the path string literals\nthemselves. R8 does not obfuscate string contents, so paths leak through.\n\n```bash\n# All quoted strings shaped like an API path, deduplicated\ngrep -rhoE '\"(/[A-Za-z0-9_{}.\\-]+(/[A-Za-z0-9_{}.\\-]+)+/?|(api|v[0-9]+|graphql|users?|account|auth|sso|oauth|profile|cart|basket|order|product|inventory|search|category|address|location|delivery|payment|invoice|favo[u]?rites?)(/[A-Za-z0-9_{}.\\-]+)+/?)\"' sources/ \\\n    | grep -Ev '^\"(image|video|audio|text|application|content)/|^\"/(proc|sys|dev|tmp|etc)/' \\\n    | sort -u\n```\n\nThe skill ships this as `find-api-calls.sh --paths`, which prints both a\ndeduplicated inventory and the full list of call sites. On real-world\nKotlin apps this single command typically produces 100–300 distinct\nendpoint paths, which is the most useful first artifact for documentation.\n\n## Hardcoded URLs and Secrets\n\n```bash\n# HTTP/HTTPS URLs\ngrep -rn '\"https\\?://[^\"]*\"' sources/\n\n# API keys and tokens\ngrep -rni 'api[_-]\\?key\\|api[_-]\\?secret\\|auth[_-]\\?token\\|bearer\\|access[_-]\\?token\\|client[_-]\\?secret' sources/\n\n# Base URL constants\ngrep -rni 'BASE_URL\\|API_URL\\|SERVER_URL\\|ENDPOINT\\|API_BASE' sources/\n```\n\n## Documentation Template\n\nFor each discovered API endpoint, document it using this template:\n\n```markdown\n### `METHOD /path/to/endpoint`\n\n- **Source**: `com.example.app.api.ApiService` (file:line)\n- **Base URL**: `https://api.example.com/v1`\n- **Full URL**: `https://api.example.com/v1/path/to/endpoint`\n- **Path parameters**: `id` (String)\n- **Query parameters**: `page` (int), `limit` (int)\n- **Headers**:\n  - `Authorization: Bearer <token>`\n  - `Content-Type: application/json`\n- **Request body**: `LoginRequest { email: String, password: String }`\n- **Response type**: `ApiResponse<User>`\n- **Notes**: Called from `LoginActivity.onLoginClicked()`\n```\n\n## Search Strategy\n\n1. Start with **base URL constants** — find where the API root is configured\n2. Search for **Retrofit interfaces** — they give the clearest picture of all endpoints\n3. Check **interceptors** — they reveal auth schemes and common headers\n4. Search for **hardcoded URLs** — catch any one-off API calls outside the main client\n5. Look for **WebView URLs** — some apps use hybrid web/native approaches\n\n<!-- File: plugins/android-reverse-engineering/skills/android-reverse-engineering/references/call-flow-analysis.md (Tokens: ~1833 | Category: anthropic-skill) -->\n# Call Flow Analysis\n\nTechniques for tracing execution flows in decompiled Android applications, from entry points down to network calls.\n\n## 1. Start from AndroidManifest.xml\n\nThe manifest declares all entry points. After decompilation, find it at:\n\n```\n<output-dir>/resources/AndroidManifest.xml\n```\n\nKey elements to look for:\n\n```bash\n# Activities (UI screens)\ngrep -n 'android:name=.*Activity' resources/AndroidManifest.xml\n\n# Services (background work)\ngrep -n 'android:name=.*Service' resources/AndroidManifest.xml\n\n# BroadcastReceivers\ngrep -n '<receiver' resources/AndroidManifest.xml\n\n# ContentProviders\ngrep -n '<provider' resources/AndroidManifest.xml\n\n# Launcher activity (main entry point)\ngrep -A5 'MAIN' resources/AndroidManifest.xml | grep 'android:name'\n```\n\n## 2. Follow the Android Lifecycle\n\nTypical call chain from UI to network:\n\n```\nActivity.onCreate()\n  → setContentView(R.layout.activity_main)\n  → findViewById() / View Binding\n  → button.setOnClickListener()\n    → onClick()\n      → viewModel.doSomething()\n        → repository.fetchData()\n          → apiService.getEndpoint()\n            → HTTP request\n```\n\nKey lifecycle methods to search:\n\n```bash\ngrep -rn 'onCreate\\|onResume\\|onStart\\|onViewCreated' sources/\n```\n\n## 3. Identify Click Handlers\n\nUser interactions trigger API calls. Common patterns:\n\n```bash\n# XML onClick\ngrep -rn 'setOnClickListener\\|onClick\\|OnClickListener' sources/\n\n# Data Binding\ngrep -rn '@BindingAdapter\\|android:onClick' sources/ resources/\n\n# Navigation actions\ngrep -rn 'findNavController\\|NavController\\|navigate(' sources/\n```\n\n## 4. Application Class Initialization\n\nThe `Application` subclass initializes global singletons (HTTP clients, DI frameworks, analytics):\n\n```bash\n# Find Application subclass\ngrep -rn 'extends Application\\|: Application()' sources/\n\n# Check onCreate for initialization\n# Then read the class to see what gets configured at startup\n```\n\nLook for:\n- Retrofit/OkHttp client setup\n- Dagger/Hilt component initialization\n- Firebase/analytics initialization\n- Base URL configuration\n\n## 5. Dependency Injection\n\n### Dagger / Hilt\n\n```bash\n# Hilt modules\ngrep -rn '@Module\\|@InstallIn\\|@Provides\\|@Binds' sources/\n\n# Hilt entry points\ngrep -rn '@HiltAndroidApp\\|@AndroidEntryPoint\\|@HiltViewModel' sources/\n\n# Dagger components\ngrep -rn '@Component\\|@Subcomponent' sources/\n\n# Injected fields\ngrep -rn '@Inject' sources/\n```\n\n### Koin\n\nKoin is the dominant DI framework in Kotlin Multiplatform and a large\nshare of Kotlin-only Android apps. It uses a runtime DSL rather than\ncompile-time generated factories, so the search patterns are different:\n\n```bash\n# Confirm Koin is actually wired up\ngrep -rn 'org\\.koin\\.' sources/\n\n# DI module declarations\ngrep -rn 'fun [A-Za-z]\\+Module\\|module\\s*{\\|module(' sources/\n\n# Bindings inside a module DSL\ngrep -rn 'single\\s*[<{(]\\|factory\\s*[<{(]\\|viewModel\\s*[<{(]\\|scoped\\s*[<{(]\\|singleOf\\|factoryOf' sources/\n\n# Resolution call-sites (where a binding is consumed)\ngrep -rn '\\bget\\s*<\\|\\binject\\s*<\\|by\\s\\+inject\\b\\|by\\s\\+viewModel\\b\\|getKoin' sources/\n```\n\nAfter R8, every binding lambda becomes an anonymous\n`Function2<Scope, ParametersHolder, T>` impl. To find the binding for an\ninterface `Foo`, look for files that contain both a Koin import / module\nDSL marker and a reference to `Foo`:\n\n```bash\ngrep -rln 'org\\.koin\\.core\\.module' sources/ | xargs grep -l 'Foo'\n```\n\n### Trace through DI\n\n1. Find where an interface is used (e.g. `ApiService` injected into a\n   repository).\n2. Find the `@Provides` / `@Binds` method (Hilt) **or** the\n   `single { ... }` / `factory { ... }` block (Koin) that creates the\n   implementation.\n3. Follow the implementation to the actual HTTP call.\n\n## 6. Find Constants and Configuration\n\nHardcoded values are rarely obfuscated:\n\n```bash\n# Base URLs\ngrep -rni 'BASE_URL\\|API_URL\\|SERVER_URL\\|HOST' sources/\n\n# API keys\ngrep -rni 'API_KEY\\|CLIENT_ID\\|APP_KEY\\|SECRET' sources/\n\n# BuildConfig values\ngrep -rn 'BuildConfig\\.' sources/\n\n# SharedPreferences keys (runtime config)\ngrep -rn 'getSharedPreferences\\|getString(\\|putString(' sources/\n```\n\n## 7. Navigating Obfuscated Code\n\nWhen code is obfuscated (ProGuard/R8):\n\n### What gets obfuscated\n- Class names → `a`, `b`, `c`\n- Method names → `a()`, `b()`, `c()`\n- Field names → `f1234a`, `f1235b`\n\n### What does NOT get obfuscated\n- **String literals** — URLs, keys, error messages remain readable\n- **Android framework classes** — `Activity`, `Fragment`, `Intent` keep their names\n- **Library public APIs** — Retrofit annotations, OkHttp builders retain names\n- **AndroidManifest entries** — Activity/Service names must be real\n\n### Strategy for obfuscated code\n\n1. **Start from strings**: Search for URLs, error messages, and known constants\n2. **Start from framework classes**: Activities and Fragments are named in the manifest\n3. **Follow library calls**: Retrofit `@GET`/`@POST` annotations are readable even when the interface class name is obfuscated\n4. **Recover original Kotlin names from metadata**: `@DebugMetadata` and `@Metadata.d2` strings preserve the original FQNs even after R8 obfuscation. Run `scripts/recover-kotlin-names.sh` to build an `obf -> real` map (typically recovers 30-50% of classes — and almost 100% of `*Repository` / `*ViewModel` / `*Impl`). See [`kotlin-name-recovery.md`](./kotlin-name-recovery.md). This is the single highest-leverage step on any Kotlin app.\n5. **Cross-reference**: If `class a` calls `Retrofit.create(b.class)`, then `b` is a Retrofit service interface\n6. **`--deobf` is rarely enough on its own**: jadx's `--deobf` renames obfuscated symbols with synthetic placeholders (`p001a`, `C0123Foo`) — useful for disambiguation but it does **not** recover original names. Pair it with the metadata recovery above.\n\n## 8. Tracing a Complete Call Flow: Example\n\nGoal: Find how login works in an obfuscated app.\n\n```\n1. grep for \"login\" in strings → find \"auth/login\" URL in class `c.a.b.d`\n2. Class `c.a.b.d` has @POST(\"auth/login\") → it's a Retrofit interface\n3. grep for `c.a.b.d` usage → class `c.a.b.f` calls it (the repository)\n4. grep for `c.a.b.f` usage → class `c.a.a.g` calls it (the ViewModel)\n5. grep for `c.a.a.g` usage → `LoginActivity` has a field of this type\n6. Read LoginActivity.onCreate() → sets click listener → calls ViewModel method\n```\n\nResult: `LoginActivity → ViewModel → Repository → Retrofit @POST(\"auth/login\")`\n\n## 9. Tools and Commands Summary\n\n| Goal | Command |\n|---|---|\n| Find entry points | `grep 'android:name' resources/AndroidManifest.xml` |\n| Find lifecycle methods | `grep -rn 'onCreate\\|onResume' sources/` |\n| Find click handlers | `grep -rn 'setOnClickListener\\|onClick' sources/` |\n| Find DI bindings | `grep -rn '@Provides\\|@Binds\\|@Inject' sources/` |\n| Find constants | `grep -rni 'BASE_URL\\|API_KEY' sources/` |\n| Find usages of a class | `grep -rn 'ClassName' sources/` |\n| Follow a string | `grep -rn '\"some text\"' sources/` |\n\n<!-- File: plugins/android-reverse-engineering/skills/android-reverse-engineering/references/fernflower-usage.md (Tokens: ~1011 | Category: anthropic-skill) -->\n# Fernflower / Vineflower CLI Reference\n\nFernflower is the JetBrains analytical Java decompiler. [Vineflower](https://github.com/Vineflower/vineflower) is the actively maintained community fork with better output quality and published releases. They share the same CLI interface.\n\n## When to Use Fernflower vs jadx\n\n| Scenario | Recommended |\n|---|---|\n| APK with resources needed | jadx |\n| Standard Java JAR/library | Fernflower |\n| jadx output has warnings/errors on specific classes | Fernflower on those classes |\n| Complex lambdas, generics, streams | Fernflower |\n| Large APK (>50MB), quick overview | jadx |\n| Obfuscated Android app | jadx first, Fernflower on problem areas |\n| Both decompilers available | Use `--engine both` and compare |\n\n## Basic Usage\n\n```bash\njava -jar fernflower.jar [options] <source>... <destination>\n```\n\n- `<source>` — JAR file, class file, or directory containing class files\n- `<destination>` — output directory\n\nFor a JAR input, Fernflower produces a JAR in the destination containing `.java` source files. Extract it with `unzip` to browse the sources.\n\n## Key Options\n\nOptions use the format `-<key>=<value>`. Boolean options: `1` = enabled, `0` = disabled.\n\n| Option | Default | Description |\n|---|---|---|\n| `-dgs=1` | 0 | Decompile generic signatures (recommended) |\n| `-ren=1` | 0 | Rename obfuscated identifiers |\n| `-mpm=60` | 0 | Max seconds per method — prevents hangs (recommended) |\n| `-hes=0` | 1 | Show empty super() calls |\n| `-hdc=0` | 1 | Show empty default constructors |\n| `-udv=1` | 1 | Use debug variable names if available |\n| `-ump=1` | 1 | Use debug parameter names if available |\n| `-lit=1` | 0 | Output numeric literals as-is |\n| `-asc=1` | 0 | Encode non-ASCII as unicode escapes |\n| `-lac=1` | 0 | Decompile lambdas as anonymous classes |\n| `-log=WARN` | INFO | Reduce output verbosity |\n| `-e=<lib>` | — | Add library for context (not decompiled, improves type resolution) |\n\n## Recommended Presets\n\n### General use\n\n```bash\njava -jar fernflower.jar -dgs=1 -mpm=60 input.jar output/\n```\n\n### Obfuscated code\n\n```bash\njava -jar fernflower.jar -dgs=1 -ren=1 -mpm=60 input.jar output/\n```\n\n### Maximum detail\n\n```bash\njava -jar fernflower.jar -dgs=1 -hes=0 -hdc=0 -mpm=60 input.jar output/\n```\n\n### With Android SDK context (better type resolution)\n\n```bash\njava -jar fernflower.jar -dgs=1 -mpm=60 -e=$ANDROID_HOME/platforms/android-34/android.jar input.jar output/\n```\n\n## Working with APK Files\n\nFernflower cannot read APK/DEX files directly. Use dex2jar first:\n\n```bash\n# Step 1: Convert DEX to JAR\nd2j-dex2jar -f -o app-converted.jar app.apk\n\n# Step 2: Decompile with Fernflower\njava -jar fernflower.jar -dgs=1 -mpm=60 app-converted.jar output/\n\n# Step 3: Extract the resulting source JAR\nunzip -o output/app-converted.jar -d output/sources/\n```\n\nThe `decompile.sh --engine fernflower` script automates these steps.\n\n## Supported Input Formats\n\n| Format | Direct support | Via dex2jar |\n|---|---|---|\n| `.jar` | Yes | — |\n| `.class` | Yes | — |\n| `.zip` (with classes) | Yes | — |\n| `.apk` | No | Yes |\n| `.dex` | No | Yes |\n| `.aar` | No | Yes |\n\n## Output Format\n\n- **JAR input** → Produces `<destination>/<input-name>.jar` containing `.java` files\n- **Class file input** → Produces `.java` files directly in the destination\n- **No resource decoding** — Fernflower only produces Java source, never XML/resources\n\n## Fernflower vs Vineflower\n\nVineflower is the recommended fork. Improvements over upstream Fernflower:\n\n- Published releases on GitHub and Maven Central\n- Better handling of modern Java (records, sealed classes, pattern matching)\n- More accurate lambda and switch expression decompilation\n- Active bug fixes and community maintenance\n- Same CLI interface — drop-in replacement\n\n<!-- File: plugins/android-reverse-engineering/skills/android-reverse-engineering/references/jadx-usage.md (Tokens: ~799 | Category: anthropic-skill) -->\n# jadx CLI Reference\n\n## Basic Usage\n\n```bash\njadx [options] <input-file>\n```\n\nInput can be an `.apk`, `.jar`, `.aar`, `.dex`, or `.zip` file.\n\n## Key Options\n\n| Option | Description |\n|---|---|\n| `-d <dir>` | Output directory for decompiled sources |\n| `--deobf` | Enable deobfuscation — renames obfuscated classes/methods to readable names |\n| `--show-bad-code` | Show partially decompiled code instead of error comments |\n| `--no-res` | Skip resource decoding — faster when you only need code |\n| `--no-src` | Skip source decompilation — only decode resources |\n| `--export-gradle` | Generate a Gradle project structure (useful for importing into IDE) |\n| `-e` | Same as `--export-gradle` |\n| `--threads-count <N>` | Number of processing threads (default: CPU count) |\n| `-Xmx<size>` | Set maximum Java heap (e.g., `-Xmx4g` for large APKs) |\n\n## Decompiling Different File Types\n\n### APK (Android Application Package)\n\n```bash\njadx -d output-dir app.apk\n```\n\nProduces:\n- `output-dir/sources/` — Decompiled Java source files\n- `output-dir/resources/` — Decoded resources (AndroidManifest.xml, layouts, drawables, etc.)\n\n### JAR (Java Archive)\n\n```bash\njadx -d output-dir library.jar\n```\n\nUseful for analyzing third-party libraries bundled within an APK.\n\n### AAR (Android Archive)\n\n```bash\njadx -d output-dir library.aar\n```\n\nAAR files contain both compiled code and Android resources. jadx handles them directly.\n\n## Handling Obfuscated Code\n\nApps built with ProGuard or R8 produce obfuscated bytecode with single-letter class and method names.\n\n### Strategies\n\n1. **Use `--deobf`** to generate readable replacement names:\n   ```bash\n   jadx --deobf -d output-dir app.apk\n   ```\n   jadx creates a mapping file at `output-dir/deobf-mapping.txt` that maps original obfuscated names to generated names.\n\n2. **Use the ProGuard mapping file** if available (sometimes shipped in the APK under `assets/` or obtainable from build artifacts):\n   ```bash\n   jadx --deobf-map mapping.txt -d output-dir app.apk\n   ```\n\n3. **Focus on string constants and API calls** rather than class names when navigating obfuscated code. URL strings, annotation values, and library classes are not obfuscated.\n\n## jadx-gui\n\nFor interactive exploration, use the GUI version:\n\n```bash\njadx-gui app.apk\n```\n\nFeatures:\n- Full-text search across all decompiled sources\n- Click-through navigation (jump to definition)\n- Deobfuscation with live renaming\n- Smali view alongside Java\n\njadx-gui is included in the same distribution as the CLI tool.\n\n## Common Workflows\n\n### Code-only decompilation (fastest)\n\n```bash\njadx --no-res --show-bad-code -d output app.apk\n```\n\n### Full decompilation with deobfuscation\n\n```bash\njadx --deobf --show-bad-code -d output app.apk\n```\n\n### Export as Gradle project for IDE import\n\n```bash\njadx -e -d output app.apk\n# Then open output/ in Android Studio or IntelliJ\n```\n\n### Decompile a specific DEX from a multi-dex APK\n\nExtract the APK (it's a ZIP), then target individual DEX files:\n\n```bash\nunzip app.apk -d extracted/\njadx -d output extracted/classes2.dex\n```\n\n<!-- File: plugins/android-reverse-engineering/skills/android-reverse-engineering/references/kotlin-name-recovery.md (Tokens: ~1066 | Category: anthropic-skill) -->\n# Recovering Original Class Names from Kotlin Metadata\n\nWhen R8/ProGuard obfuscates a Kotlin app, JVM symbols are renamed but the\n**Kotlin metadata strings cannot be stripped** — the Kotlin runtime depends\non them at runtime for reflection, coroutines, and `data class` features.\n\nTwo annotations leak the original fully-qualified names:\n\n## `@DebugMetadata`\n\nGenerated for nearly every Kotlin coroutine `SuspendLambda` (i.e. almost\nevery `suspend` function in a modern app):\n\n```java\n@DebugMetadata(\n    c  = \"com.example.feature.account.AccountRepositoryImpl$fetch$1\",\n    f  = \"AccountRepositoryImpl.kt\",\n    l  = {42, 51},\n    m  = \"invokeSuspend\"\n)\npublic final class a extends SuspendLambda implements Function2<...> { ... }\n```\n\nThe `c =` field carries the original outer class FQN (with a `$` suffix\nfor inner / lambda scopes — strip everything after the first `$` to get the\ndeclaring class).\n\n## `@Metadata.d2`\n\nEvery Kotlin class carries a top-level `@Metadata` annotation. The `d2`\narray lists internal class refs in JVM type-descriptor format\n(`Lcom/example/Foo;`):\n\n```java\n@Metadata(d1 = {\"...\"},\n          d2 = {\"...\",\"Lcom/example/feature/account/AccountRepositoryImpl;\",\"...\"})\npublic final class b implements ... { ... }\n```\n\nThe first non-stdlib descriptor in `d2` is usually the file's primary\nclass.\n\n## How to mine them\n\nThe skill ships two scripts:\n\n```bash\n# Build a mapping from a decompiled sources directory:\nbash scripts/recover-kotlin-names.sh <output>/sources [mapping-dir]\n\n# Outputs:\n#   <mapping-dir>/mapping.tsv        obf_fqn  real_fqn  file\n#   <mapping-dir>/mapping.json       same data, JSON\n#   <mapping-dir>/by_package/        per-real-package index files\n\n# Query the mapping:\nbash scripts/lookup-name.sh <mapping-dir> Repository                 # search\nbash scripts/lookup-name.sh <mapping-dir> -o ab.cd                   # obf -> real\nbash scripts/lookup-name.sh <mapping-dir> -p com.example.feature     # list package\nbash scripts/lookup-name.sh <mapping-dir> --grep '\"api/' <output>/sources\n   # ^ greps decompiled code and appends '// real.fqn' to each hit\n```\n\n## What you typically recover\n\nOn a real-world obfuscated Kotlin app the script recovers **30 – 50 % of\nclasses** — but more importantly, **almost 100 % of the classes you\nactually want to read**:\n\n| Class kind                | Recovery rate |\n|---------------------------|---------------|\n| `*Repository` / `*Impl`   | ~100 %        |\n| `*ViewModel`              | ~100 %        |\n| `*UseCase` / `*Interactor`| ~100 %        |\n| Plain `data class` DTOs   | ~80 %         |\n| Pure-Java helper classes  | low (no Kotlin metadata) |\n| Anonymous inner classes   | sometimes recovered as the parent FQN |\n\n## Why `jadx --deobf` is not enough\n\n`--deobf` renames obfuscated identifiers using internal heuristics, but the\noutput is still synthetic (`p001a`, `C0123Foo`). It does **not** recover\nthe *original* names. Kotlin metadata recovery is the only reliable way to\nmap back to the names the developer actually wrote, and it costs essentially\nnothing — just a regex pass over the decompiled sources.\n\nRun both: `--deobf` for fields/methods that have no metadata source, plus\nthe recovery script for class names.\n\n## Limitations\n\n- **Method names and field names** are not recovered. Kotlin metadata only\n  preserves class-level FQNs and a few signatures. For method names you\n  still need jadx-gui's interactive rename or pattern inference.\n- **Pure-Java classes** carry no `@Metadata`, so they remain obfuscated.\n- **Heavily inlined classes** (`@JvmInline value class`, top-level fun\n  files compiled into shared `*Kt.class` synthetic classes) sometimes show\n  up under the wrong filename — treat results as a strong hint, not gospel.\n\n## Reading flow with the mapping\n\n1. Run `recover-kotlin-names.sh` once after decompiling.\n2. Use `lookup-name.sh --grep '<pattern>' <sources>` instead of plain `grep`\n   so every hit comes annotated with the real owning class.\n3. When you hit an obfuscated FQN in code (e.g. `nq.e`), resolve it with\n   `lookup-name.sh <mapping-dir> -o nq.e` — you will often see siblings\n   (`nq.d`, `nq.f`, ...) that are the same class's split lambdas/inner\n   classes, which is useful context.\n\n<!-- File: plugins/android-reverse-engineering/skills/android-reverse-engineering/references/setup-guide.md (Tokens: ~1309 | Category: anthropic-skill) -->\n# Setup Guide: Dependencies for Android Reverse Engineering\n\n## Java JDK 17+\n\njadx requires Java 17 or later.\n\n### Ubuntu / Debian\n\n```bash\nsudo apt update\nsudo apt install openjdk-17-jdk\n```\n\n### Fedora\n\n```bash\nsudo dnf install java-17-openjdk-devel\n```\n\n### Arch Linux\n\n```bash\nsudo pacman -S jdk17-openjdk\n```\n\n### macOS (Homebrew)\n\n```bash\nbrew install openjdk@17\n```\n\nAfter installation on macOS, follow the symlink instructions printed by Homebrew, or add to your shell profile:\n\n```bash\nexport PATH=\"/opt/homebrew/opt/openjdk@17/bin:$PATH\"\n```\n\n### Verify\n\n```bash\njava -version\n# Should show version 17.x or higher\n```\n\n---\n\n## jadx\n\njadx is the Java decompiler used to convert APK/JAR/AAR files to readable Java source.\n\n### Option 1: GitHub Releases (recommended)\n\n1. Go to <https://github.com/skylot/jadx/releases/latest>\n2. Download the `jadx-<version>.zip` file (not the source archive)\n3. Extract and add to PATH:\n\n```bash\nunzip jadx-*.zip -d ~/jadx\nexport PATH=\"$HOME/jadx/bin:$PATH\"\n# Add the export line to your ~/.bashrc or ~/.zshrc for persistence\n```\n\n### Option 2: Homebrew (macOS / Linux)\n\n```bash\nbrew install jadx\n```\n\n### Option 3: Build from source\n\n```bash\ngit clone https://github.com/skylot/jadx.git\ncd jadx\n./gradlew dist\n# Binaries will be in build/jadx/bin/\nexport PATH=\"$(pwd)/build/jadx/bin:$PATH\"\n```\n\n### Verify\n\n```bash\njadx --version\n```\n\n---\n\n## Fernflower / Vineflower (optional, recommended)\n\nFernflower is the JetBrains Java decompiler. It produces better output than jadx on complex Java constructs, lambdas, and generics. [Vineflower](https://github.com/Vineflower/vineflower) is the actively maintained community fork with published releases — prefer it over upstream Fernflower.\n\n### Option 1: Vineflower from GitHub Releases (recommended)\n\n1. Go to <https://github.com/Vineflower/vineflower/releases/latest>\n2. Download `vineflower-<version>.jar`\n3. Place it and set the environment variable:\n\n```bash\nmkdir -p ~/vineflower\nmv vineflower-*.jar ~/vineflower/vineflower.jar\nexport FERNFLOWER_JAR_PATH=\"$HOME/vineflower/vineflower.jar\"\n# Add the export to ~/.bashrc or ~/.zshrc for persistence\n```\n\n### Option 2: Build Fernflower from source\n\n```bash\ngit clone https://github.com/JetBrains/fernflower.git\ncd fernflower\n./gradlew jar\n# Produces: build/libs/fernflower.jar\nexport FERNFLOWER_JAR_PATH=\"$(pwd)/build/libs/fernflower.jar\"\n```\n\n### Option 3: Homebrew (Vineflower)\n\n```bash\nbrew install vineflower\n```\n\n### Verify\n\n```bash\njava -jar \"$FERNFLOWER_JAR_PATH\" --version\n```\n\n> **Note**: Fernflower only works on JVM bytecode (JAR, class files). For APK/DEX files, you also need **dex2jar** (see below) as an intermediate conversion step.\n\n---\n\n## dex2jar (optional, needed for Fernflower on APK files)\n\nConverts Android DEX bytecode to standard Java JAR files.\n\n### GitHub Releases\n\n1. Go to <https://github.com/ThexXTURBOXx/dex2jar/releases/latest>\n2. Download and extract:\n\n```bash\nunzip dex-tools-*.zip -d ~/dex2jar\nexport PATH=\"$HOME/dex2jar:$PATH\"\n```\n\n### Homebrew\n\n```bash\nbrew install dex2jar\n```\n\n### Verify\n\n```bash\nd2j-dex2jar --help\n```\n\n### Usage\n\n```bash\n# Convert APK (or DEX) to JAR\nd2j-dex2jar -f -o output.jar app.apk\n\n# Then decompile with Fernflower\njava -jar vineflower.jar output.jar decompiled/\n```\n\n---\n\n## Optional Tools\n\n### apktool\n\nUseful for decoding resources (XML layouts, drawables) that jadx sometimes handles poorly.\n\n```bash\n# Ubuntu/Debian\nsudo apt install apktool\n\n# macOS\nbrew install apktool\n\n# Manual: https://apktool.org/docs/install\n```\n\n### adb (Android Debug Bridge)\n\nUseful for pulling APKs directly from a connected Android device.\n\n```bash\n# Ubuntu/Debian\nsudo apt install adb\n\n# macOS\nbrew install android-platform-tools\n```\n\nPull an APK from a device:\n\n```bash\n# List installed packages\nadb shell pm list packages | grep <keyword>\n\n# Get APK path\nadb shell pm path com.example.app\n\n# Pull the APK\nadb pull /data/app/com.example.app-xxxx/base.apk ./app.apk\n```\n\n---\n\n## Troubleshooting\n\n| Problem | Solution |\n|---|---|\n| `jadx: command not found` | Ensure the jadx `bin/` directory is in your `$PATH` |\n| `Error: Could not find or load main class` | Java is missing or wrong version — verify with `java -version` |\n| jadx runs out of memory on large APKs | Increase heap: `jadx -Xmx4g -d output app.apk` or set `JAVA_OPTS=\"-Xmx4g\"` |\n| Decompiled code has many `// Error` comments | Try `--show-bad-code` to see partial output, or use `--deobf` for obfuscated apps |\n| Fernflower hangs on a method | Use `-mpm=60` to set a 60-second timeout per method |\n| Fernflower JAR not found | Set `FERNFLOWER_JAR_PATH` env variable to the full path of the JAR |\n| dex2jar fails with `ZipException` | The APK may have a non-standard ZIP structure — try `jadx` instead |\n\n<!-- File: plugins/android-reverse-engineering/skills/android-reverse-engineering/SKILL.md (Tokens: ~3899 | Category: anthropic-skill) -->\n---\nname: android-reverse-engineering\ndescription: Decompile Android APK, XAPK, JAR, and AAR files using jadx or Fernflower/Vineflower. Reverse engineer Android apps, extract HTTP API endpoints (Retrofit, OkHttp, Volley), and trace call flows from UI to network layer. Use when the user wants to decompile, analyze, or reverse engineer Android packages, find API endpoints, or follow call flows. 中文触发词：反编译APK、安卓逆向、提取API、分析安卓应用、反编译安卓、逆向工程、追踪调用链、提取接口\ntrigger: decompile APK|decompile XAPK|reverse engineer Android|extract API|analyze Android|jadx|fernflower|vineflower|follow call flow|decompile JAR|decompile AAR|Android reverse engineering|find API endpoints|反编译APK|安卓逆向|提取API|分析安卓应用\n---\n\n# Android Reverse Engineering\n\nDecompile Android APK, XAPK, JAR, and AAR files using jadx and Fernflower/Vineflower, trace call flows through application code and libraries, and produce structured documentation of extracted APIs. Two decompiler engines are supported — jadx for broad Android coverage and Fernflower for higher-quality output on complex Java code — and can be used together for comparison.\n\n## Prerequisites\n\nThis skill requires **Java JDK 17+** and **jadx** to be installed. **Fernflower/Vineflower** and **dex2jar** are optional but recommended for better decompilation quality. Run the dependency checker to verify:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.ps1\"\n```\n\nIf anything is missing, follow the installation instructions in `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/setup-guide.md`.\n\n## Workflow\n\n### Phase 0: Fingerprint the App (recommended before anything else)\n\nBefore installing tools or decompiling, run a fast triage to determine what\nkind of app you are looking at. **Decompiling Java is mostly useless for\nFlutter, React Native, Cordova/Capacitor, and Xamarin apps** — the real code\nlives elsewhere. The fingerprint script tells you which.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/fingerprint.sh <file.apk|file.xapk>\n```\n\nIt prints, in one screen:\n\n- **Mobile framework** (Flutter / React Native / Cordova / Xamarin / Native Kotlin / etc.) with the file marker that triggered the verdict.\n- **HTTP stack** (Retrofit, OkHttp, Ktor, Apollo, Volley) detected via DEX string scan — works even when class names are obfuscated.\n- **DI / serialization** signals (Hilt, Dagger, Koin, kotlinx.serialization, Moshi, Gson, Jackson).\n- **Obfuscation level** estimate based on root-level short-named packages.\n- **Notable third-party SDKs** (AppsFlyer, Datadog, Sentry, Firebase, payment SDKs, support/chat SDKs, etc.).\n- **Consolidated native libraries** across the base APK and all splits — XAPK split bundles often place `.so` files in `config.<abi>.apk`, not in `base.apk`.\n- **Recommended next step**, which differs by framework (e.g. for Flutter the script suggests `blutter` / `strings libapp.so` rather than jadx).\n\nIf the fingerprint says the app is Flutter / RN / Cordova / Xamarin, **stop**\nand switch to the framework-appropriate tooling. Phases 1–5 below assume a\nnative (Java/Kotlin) Android app.\n\n### Phase 1: Verify and Install Dependencies\n\nBefore decompiling, confirm that the required tools are available — and install any that are missing.\n\n**Action**: Run the dependency check script.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.ps1\"\n```\n\nThe output contains machine-readable lines:\n- `INSTALL_REQUIRED:<dep>` — must be installed before proceeding\n- `INSTALL_OPTIONAL:<dep>` — recommended but not blocking\n\n**If required dependencies are missing** (exit code 1), install them automatically:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/install-dep.sh <dep>\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/install-dep.ps1\" <dep>\n```\n\nThe install script detects the OS and package manager, then:\n- Installs without sudo when possible (downloads to `~/.local/share/`, symlinks in `~/.local/bin/`)\n- Uses sudo and the system package manager when necessary (apt, dnf, pacman)\n- If sudo is needed but unavailable or the user declines, it prints the exact manual command and exits with code 2 — show these instructions to the user\n\n**Windows notes**: The PowerShell install script uses `winget`, `scoop`, or `choco` (in that order). If none are available, it downloads directly to `%USERPROFILE%\\.local\\share\\` and adds the directory to the user's PATH. After running `install-dep.ps1`, the PATH is persisted but the current terminal session may not see it. The `check-deps.ps1` and `decompile.ps1` scripts automatically refresh PATH from the user environment, so re-running them will find newly installed tools without restarting the terminal.\n\n**For optional dependencies**, ask the user if they want to install them. Vineflower and dex2jar are recommended for best results.\n\nAfter installation, re-run `check-deps.sh` to confirm everything is in place. Do not proceed to Phase 2 until all required dependencies are OK.\n\n### Phase 2: Decompile\n\nUse the decompile wrapper script to process the target file. The script supports three engines: `jadx`, `fernflower`, and `both`.\n\n**Action**: Choose the engine and run the decompile script. The script handles APK, XAPK, JAR, and AAR files.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh [OPTIONS] <file>\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.ps1\" [OPTIONS] <file>\n```\n\nFor **XAPK** files (ZIP bundles containing multiple APKs, used by APKPure and similar stores): the script automatically extracts the archive, identifies all APK files inside (base + split APKs), and decompiles each one into a separate subdirectory. The XAPK manifest is copied to the output for reference.\n\n**Split/bundled APK detection**: Some APKs are actually bundle wrappers — the outer APK contains `base.apk` plus `split_config.*.apk` files inside its resources directory. When this happens, jadx will decompile the thin wrapper and produce very few Java files. The decompile scripts automatically detect this (≤10 Java files + inner APKs present) and re-decompile `base.apk` into an `<output>/base/` subdirectory. Config-only splits (ABI, language, density) are skipped. The main decompiled source will be in `<output>/base/sources/`.\n\nOptions:\n- `-o <dir>` — Custom output directory (default: `<filename>-decompiled`)\n- `--deobf` — Enable deobfuscation (recommended for obfuscated apps)\n- `--no-res` — Skip resources, decompile code only (faster)\n- `--engine ENGINE` — `jadx` (default), `fernflower`, or `both`\n\n**Engine selection strategy**:\n\n| Situation | Engine |\n|---|---|\n| First pass on any APK | `jadx` (fastest, handles resources) |\n| JAR/AAR library analysis | `fernflower` (better Java output) |\n| jadx output has warnings/broken code | `both` (compare and pick best per class) |\n| Complex lambdas, generics, streams | `fernflower` |\n| Quick overview of a large APK | `jadx --no-res` |\n\nWhen using `--engine both`, the outputs go into `<output>/jadx/` and `<output>/fernflower/` respectively, with a comparison summary at the end showing file counts and jadx warning counts. Review classes with jadx warnings in the Fernflower output for better code.\n\nFor APK files with Fernflower, the script automatically uses dex2jar as an intermediate step. dex2jar must be installed for this to work.\n\nSee `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/jadx-usage.md` and `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/fernflower-usage.md` for the full CLI references.\n\n### Phase 3: Analyze Structure\n\nNavigate the decompiled output to understand the app's architecture.\n\n**Actions**:\n\n1. **Read AndroidManifest.xml** from `<output>/resources/AndroidManifest.xml`:\n   - Identify the main launcher Activity\n   - List all Activities, Services, BroadcastReceivers, ContentProviders\n   - Note permissions (especially `INTERNET`, `ACCESS_NETWORK_STATE`)\n   - Find the application class (`android:name` on `<application>`)\n\n2. **Survey the package structure** under `<output>/sources/`:\n   - Identify the main app package and sub-packages\n   - Distinguish app code from third-party libraries\n   - Look for packages named `api`, `network`, `data`, `repository`, `service`, `retrofit`, `http` — these are where API calls live\n\n3. **Read every `BuildConfig.java`** — these are almost never obfuscated and frequently leak the highest-signal constants in the entire APK (base URLs, flavor names, build type, third-party API keys, feature flags):\n   ```bash\n   find <output>/sources -name BuildConfig.java -exec grep -H '=' {} \\;\n   ```\n   Each Gradle module emits its own `BuildConfig`, so expect 1–N hits. Read all of them.\n\n4. **Identify the architecture pattern**:\n   - MVP: look for `Presenter` classes\n   - MVVM: look for `ViewModel` classes and `LiveData`/`StateFlow`\n   - Clean Architecture: look for `domain`, `data`, `presentation` packages\n   - This informs where to look for network calls in the next phases\n\n### Phase 3.5: Recover Kotlin Class Names (only for obfuscated Kotlin apps)\n\nIf Phase 0 reported moderate / high obfuscation **and** the app is Kotlin\n(Compose / kotlin_module markers detected), run the metadata recovery\nscript before tracing call flows. R8 obfuscates JVM symbols but cannot\nstrip Kotlin metadata strings, so original FQNs leak through\n`@DebugMetadata` and `@Metadata.d2`.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/recover-kotlin-names.sh \\\n    <output>/sources <output>/mapping\n```\n\nThen use the lookup helper instead of plain grep — every hit comes\nannotated with the owning class's real name:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/lookup-name.sh \\\n    <output>/mapping --grep '\"/api/' <output>/sources\n```\n\nTypical recovery on a real-world Kotlin app: ~100% of `*Repository` /\n`*ViewModel` / `*UseCase` / `*Impl` classes, ~80% of DTOs.\n\nSee `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/kotlin-name-recovery.md`\nfor the full technique and limitations.\n\n### Phase 4: Trace Call Flows\n\nFollow execution paths from user-facing entry points down to network calls.\n\n**Actions**:\n\n1. **Start from entry points**: Read the main Activity or Application class identified in Phase 3.\n\n2. **Follow the initialization chain**: Application.onCreate() often sets up the HTTP client, base URL, and DI framework. Read this first.\n\n3. **Trace user actions**: From an Activity, follow:\n   - `onCreate()` → view setup → click listeners\n   - Click handler → ViewModel/Presenter method\n   - ViewModel → Repository → API service interface\n   - API service → actual HTTP call\n\n4. **Map DI bindings** (if Dagger/Hilt is used): Find `@Module` classes to understand which implementations are provided for which interfaces.\n\n5. **Handle obfuscated code**: When class names are mangled, use string literals and library API calls as anchors. Retrofit annotations and URL strings are never obfuscated.\n\nSee `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/call-flow-analysis.md` for detailed techniques and grep commands.\n\n### Phase 5: Extract and Document APIs\n\nFind all API endpoints and produce structured documentation.\n\n**Action**: Run the API search script for a broad sweep.\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.sh <output>/sources/\n```\n\nOn Windows (PowerShell):\n```powershell\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.ps1\" <output>/sources/\n```\n\nTargeted searches:\n```bash\n# Only Retrofit\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.sh <output>/sources/ --retrofit\n\n# Only hardcoded URLs\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.sh <output>/sources/ --urls\n\n# Only auth patterns\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.sh <output>/sources/ --auth\n```\n\nOn Windows (PowerShell):\n```powershell\n# Only Retrofit\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.ps1\" <output>/sources/ -Retrofit\n\n# Only hardcoded URLs\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.ps1\" <output>/sources/ -Urls\n\n# Only auth patterns\n& \"${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/find-api-calls.ps1\" <output>/sources/ -AuthPatterns\n```\n\nDocument the endpoints in **two tiers** — going deep on every endpoint is\nprohibitively expensive on apps with 100+ paths, and most of them do not\nwarrant it. Always produce Tier 1; expand Tier 2 only for the endpoints\nthat matter.\n\n#### Tier 1 — flat inventory (always)\n\nA single table covering every discovered endpoint. Aim for one line each;\nif you cannot determine a column, write `?`.\n\n| Host | Method | Path | Auth | Source file |\n|------|--------|------|------|-------------|\n| `api.example.com` | GET | `/v1/users/profile` | Bearer | `com/example/api/UserApi.java` |\n| `api.example.com` | POST | `/v1/auth/login` | none | `com/example/api/AuthApi.java` |\n\nThis table answers \"what does the backend look like\" in one screen and\ntakes ~5 minutes to produce from the `--paths` output even on a large app.\n\n#### Tier 2 — per-endpoint detail (only for high-value endpoints)\n\nReserve the detailed format for the few endpoints that actually need it:\n\n- the entire authentication flow (login, refresh, logout, OTP/SMS, anonymous, registration)\n- payment / checkout / order-creation endpoints\n- anything the user explicitly asked about\n- anything that looked unusual during the scan (custom signing, undocumented headers, etc.)\n\n```markdown\n### `METHOD /path`\n\n- **Source**: `com.example.api.ApiService` (ApiService.java:42)\n- **Base URL**: `https://api.example.com/v1`\n- **Path params**: `id` (String)\n- **Query params**: `page` (int), `limit` (int)\n- **Headers**: `Authorization: Bearer <token>`\n- **Request body**: `{ \"email\": \"string\", \"password\": \"string\" }`\n- **Response**: `ApiResponse<User>`\n- **Called from**: `LoginActivity → LoginViewModel → UserRepository → ApiService`\n```\n\nAs a default, do not produce Tier 2 entries for more than ~10 endpoints\nunless the user explicitly asks for more — Tier 1 plus a Tier 2 deep dive\non auth + 1-2 key flows is what most consumers of this work actually want.\n\nSee `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/api-extraction-patterns.md` for library-specific search patterns and the full documentation template.\n\n## Output\n\nAt the end of the workflow, deliver:\n\n1. **Decompiled source** in the output directory\n2. **Architecture summary** — app structure, main packages, pattern used\n3. **API documentation** — all discovered endpoints in the format above\n4. **Call flow map** — key paths from UI to network (especially authentication and main features)\n\n## References\n\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/setup-guide.md` — Installing Java, jadx, Fernflower/Vineflower, dex2jar, and optional tools\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/jadx-usage.md` — jadx CLI options and workflows\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/fernflower-usage.md` — Fernflower/Vineflower CLI options, when to use, APK workflow\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/api-extraction-patterns.md` — Library-specific search patterns and documentation template\n- `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/references/call-flow-analysis.md` — Techniques for tracing call flows in decompiled code\n\n<!-- File: .claude-plugin/marketplace.json (Tokens: ~259 | Category: marketplace) -->\n{\n  \"$schema\": \"https://anthropic.com/claude-code/marketplace.schema.json\",\n  \"name\": \"android-reverse-engineering-skill\",\n  \"description\": \"Claude Code plugins for Android reverse engineering\",\n  \"owner\": {\n    \"name\": \"Simone Avogadro\"\n  },\n  \"metadata\": {\n    \"description\": \"Claude Code plugins for Android reverse engineering\",\n    \"version\": \"1.5.0\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"android-reverse-engineering\",\n      \"source\": \"./plugins/android-reverse-engineering\",\n      \"description\": \"Decompile Android APK/JAR/AAR with jadx, trace call flows through libraries, and document extracted APIs.\",\n      \"version\": \"1.5.0\",\n      \"author\": {\n        \"name\": \"Simone Avogadro\"\n      },\n      \"repository\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill\",\n      \"license\": \"Apache-2.0\",\n      \"keywords\": [\"android\", \"reverse-engineering\", \"apk\", \"jadx\", \"decompile\", \"api-extraction\"],\n      \"category\": \"security\"\n    }\n  ]\n}\n\n<!-- File: plugins/android-reverse-engineering/.claude-plugin/plugin.json (Tokens: ~283 | Category: plugin-manifest) -->\n{\n  \"name\": \"android-reverse-engineering\",\n  \"version\": \"1.5.0\",\n  \"description\": \"Decompile Android APK/JAR/AAR with jadx, trace call flows through libraries, and document extracted APIs.\",\n  \"author\": {\n    \"name\": \"Simone Avogadro\"\n  },\n  \"homepage\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill\",\n  \"repository\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill\",\n  \"documentationUrl\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill#readme\",\n  \"license\": \"Apache-2.0\",\n  \"supportUrl\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill/issues/new\",\n  \"termsOfServiceUrl\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/master/LICENSE\",\n  \"privacyPolicyUrl\": \"https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/master/PRIVACY.md\",\n  \"keywords\": [\"android\", \"reverse-engineering\", \"apk\", \"jadx\", \"decompile\", \"api-extraction\"],\n  \"skills\": \"./skills/\",\n  \"commands\": \"./commands/\"\n}\n\n<!-- File: plugins/android-reverse-engineering/commands/decompile.md (Tokens: ~938 | Category: command-prompt) -->\n---\nallowed-tools: Bash(bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh), Bash(bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh *), Read, Glob, Grep\ndescription: Decompile an Android APK/XAPK/JAR/AAR and analyze its structure\nuser-invocable: true\nargument-hint: <path to APK, XAPK, JAR, or AAR file>\nargument: path to APK, XAPK, JAR, or AAR file (optional)\n---\n\n# /decompile\n\nDecompile an Android application and perform initial structure analysis.\n\n## Instructions\n\nYou are starting the Android reverse engineering workflow. Follow these steps:\n\n### Step 1: Get the target file\n\nIf the user provided a file path as an argument, use that. Otherwise, ask the user for the path to the APK, XAPK, JAR, or AAR file they want to decompile.\n\n### Step 2: Check and install dependencies\n\nRun the dependency check:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/check-deps.sh\n```\n\nParse the output looking for `INSTALL_REQUIRED:` and `INSTALL_OPTIONAL:` lines.\n\n**If required dependencies are missing**, install them one by one:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/install-dep.sh java\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/install-dep.sh jadx\n```\n\nThe install script auto-detects the OS and installs without sudo when possible (user-local install to `~/.local/`). If sudo is needed, it will prompt — if the user declines or sudo is unavailable, the script prints exact manual instructions (exit code 2). Show those instructions to the user and stop.\n\n**For optional dependencies** (`INSTALL_OPTIONAL:vineflower`, `INSTALL_OPTIONAL:dex2jar`, etc.), ask the user if they want to install them. Recommend vineflower and dex2jar for better results.\n\nAfter any installations, re-run `check-deps.sh` to verify. Do not proceed until all required dependencies pass.\n\n### Step 3: Decompile\n\nRun the decompile script on the target file. Choose the engine based on the input:\n\n- **APK or XAPK** → use jadx first (handles resources natively; XAPK is auto-extracted):\n\n  ```bash\n  bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh <file>\n  ```\n\n- **JAR/AAR** and Fernflower is available → prefer fernflower for better Java output:\n\n  ```bash\n  bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh --engine fernflower <file>\n  ```\n\n- **If jadx output has warnings** or the user wants the best quality → run both and compare:\n\n  ```bash\n  bash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh --engine both <file>\n  ```\n\nFor obfuscated apps (if the user mentions it or you detect single-letter package names), add `--deobf`:\n\n```bash\nbash ${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/scripts/decompile.sh --deobf <file>\n```\n\n### Step 4: Analyze structure\n\nAfter decompilation completes:\n\n1. Read `AndroidManifest.xml` from the resources directory. For XAPK, check the base APK's output first.\n2. If XAPK, review `xapk-manifest.json` in the output directory to understand the split structure.\n3. List the top-level package structure\n4. Identify the app's main Activity, Application class, and architecture pattern\n5. Report a summary to the user\n\n### Step 5: Offer next steps\n\nTell the user what they can do next:\n\n- **Trace call flows**: \"I can follow the execution flow from any Activity to its API calls\"\n- **Extract APIs**: \"I can search for all HTTP endpoints and document them\"\n- **Analyze specific classes**: \"Point me to a specific class or feature to analyze\"\n- **Re-decompile with Fernflower**: If jadx output has warnings, offer to re-run with `--engine both` for comparison\n\nRefer to the full skill documentation in `${CLAUDE_PLUGIN_ROOT}/skills/android-reverse-engineering/SKILL.md` for the complete workflow.\n</yakaai_skills>"}