RepoPilotOpen in app →

Col-E/Recaf

The modern Java bytecode editor

Healthy

Healthy across all four use cases

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 1w ago
  • 4 active contributors
  • MIT licensed
Show all 7 evidence items →
  • CI configured
  • Tests present
  • Small team — 4 contributors active in recent commits
  • Single-maintainer risk — top contributor 93% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/col-e/recaf)](https://repopilot.app/r/col-e/recaf)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/col-e/recaf on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: Col-E/Recaf

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/Col-E/Recaf shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across all four use cases

  • Last commit 1w ago
  • 4 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Small team — 4 contributors active in recent commits
  • ⚠ Single-maintainer risk — top contributor 93% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live Col-E/Recaf repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/Col-E/Recaf.

What it runs against: a local clone of Col-E/Recaf — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in Col-E/Recaf | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 39 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>Col-E/Recaf</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of Col-E/Recaf. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/Col-E/Recaf.git
#   cd Recaf
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of Col-E/Recaf and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "Col-E/Recaf(\\.git)?\\b" \\
  && ok "origin remote is Col-E/Recaf" \\
  || miss "origin remote is not Col-E/Recaf (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "recaf-core/src/main/java/software/coley/recaf/Recaf.java" \\
  && ok "recaf-core/src/main/java/software/coley/recaf/Recaf.java" \\
  || miss "missing critical file: recaf-core/src/main/java/software/coley/recaf/Recaf.java"
test -f "recaf-core/src/main/java/software/coley/recaf/Bootstrap.java" \\
  && ok "recaf-core/src/main/java/software/coley/recaf/Bootstrap.java" \\
  || miss "missing critical file: recaf-core/src/main/java/software/coley/recaf/Bootstrap.java"
test -f "recaf-core/src/main/java/software/coley/recaf/info/ClassInfo.java" \\
  && ok "recaf-core/src/main/java/software/coley/recaf/info/ClassInfo.java" \\
  || miss "missing critical file: recaf-core/src/main/java/software/coley/recaf/info/ClassInfo.java"
test -f "recaf-core/src/main/java/software/coley/recaf/cdi/EagerInitializationExtension.java" \\
  && ok "recaf-core/src/main/java/software/coley/recaf/cdi/EagerInitializationExtension.java" \\
  || miss "missing critical file: recaf-core/src/main/java/software/coley/recaf/cdi/EagerInitializationExtension.java"
test -f "recaf-core/src/main/java/software/coley/recaf/config/ConfigPersistence.java" \\
  && ok "recaf-core/src/main/java/software/coley/recaf/config/ConfigPersistence.java" \\
  || miss "missing critical file: recaf-core/src/main/java/software/coley/recaf/config/ConfigPersistence.java"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 39 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~9d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/Col-E/Recaf"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Recaf is a modern Java bytecode editor that lets users visually edit compiled Java classes without manually managing the constant pool, stack frames, or instruction selection. It abstracts away the complexity of bytecode manipulation while supporting both standard Java and Android applications, and includes integrated decompilers, a bytecode assembler, a built-in compiler, and deobfuscation tools. Multi-module Gradle project: recaf-core is the main library module under recaf-core/src/main/java/software/coley/recaf/, organized by feature domains (analytics, cdi, behavior, logging). Bootstrap.java is the entry point. CDI (Contexts and Dependency Injection via Jakarta) handles initialization through EagerInitializationExtension. UI is separate (not shown in top 60 files but mentioned as JavaFX-based in v4).

👥Who it's for

Reverse engineers, security researchers, and developers who need to analyze or modify Java/Android applications at the bytecode level without writing raw assembly-like code. Users want to rename obfuscated symbols, patch code, or inspect compiled internals without deep JVM knowledge.

🌱Maturity & risk

Actively developed and production-ready. The project is at v4.0.0-SNAPSHOT with a modern Java toolchain setup, CI/CD via GitHub Actions (build.yml), JaCoCo code coverage, and integration with codecov. The codebase is substantial (~5.7M lines of Java) and has an active Discord community, indicating maturity and active maintenance.

Single-maintainer project (Col-E) increases bus-factor risk. No independent releases yet for v4.x (only snapshots via launcher or CI artifacts), suggesting the 4.x rewrite is still stabilizing. Dependency exclusions in build.gradle (checkerframework, findbugs, IBM ICU) indicate careful curation but the full dependency tree isn't visible from the snippet provided.

Active areas of work

Version 4.0.0-SNAPSHOT is under active development with a rewrite indicated by snapshot versioning. Recent work includes CDI integration for dependency injection (EagerInitialization* classes), structured logging (InterceptingLogger, DebuggingLogger), and system analytics. No specific milestone or open PR data is visible, but the 4.x branch represents a major modernization.

🚀Get running

Check README for instructions.

Daily commands:

./gradlew build

For UI: use the Launcher (separate repo) or snapshot artifacts. The core library can be consumed as a dependency; running the full editor requires the UI module (not shown in file list, likely in a separate module or branch).

🗺️Map of the codebase

  • recaf-core/src/main/java/software/coley/recaf/Recaf.java — Main entry point for the Recaf application; all contributors must understand the application lifecycle and initialization flow
  • recaf-core/src/main/java/software/coley/recaf/Bootstrap.java — Bootstrap initialization sequence that sets up CDI, logging, and system resources before Recaf starts
  • recaf-core/src/main/java/software/coley/recaf/info/ClassInfo.java — Core abstraction for Java class metadata; fundamental to bytecode editing operations throughout the codebase
  • recaf-core/src/main/java/software/coley/recaf/cdi/EagerInitializationExtension.java — CDI extension managing dependency injection and bean lifecycle; essential for understanding how services are wired
  • recaf-core/src/main/java/software/coley/recaf/config/ConfigPersistence.java — Configuration persistence layer that manages user settings and state; critical for data durability
  • recaf-core/src/main/java/software/coley/recaf/RecafConstants.java — Central constants and configuration values used throughout the application for consistency
  • build.gradle — Root build configuration with dependency management; required reading for setting up development environment

🛠️How to make changes

Add Support for a New Class Information Type

  1. Create a new interface extending ClassInfo in recaf-core/src/main/java/software/coley/recaf/info/ (recaf-core/src/main/java/software/coley/recaf/info/ClassInfo.java)
  2. Create a Basic* implementation class following the pattern of BasicJvmClassInfo or BasicAndroidClassInfo (recaf-core/src/main/java/software/coley/recaf/info/BasicJvmClassInfo.java)
  3. Register the new type in the info package alongside other ClassInfo implementations (recaf-core/src/main/java/software/coley/recaf/info/)

Add a New File Archive Type

  1. Create interface extending FileInfo for the archive type in recaf-core/src/main/java/software/coley/recaf/info/ (recaf-core/src/main/java/software/coley/recaf/info/FileInfo.java)
  2. Create Basic* implementation following patterns from BasicJarFileInfo, BasicApkFileInfo, or BasicWarFileInfo (recaf-core/src/main/java/software/coley/recaf/info/BasicJarFileInfo.java)
  3. Implement file parsing logic and class extraction in the Basic* implementation (recaf-core/src/main/java/software/coley/recaf/info/)

Add a New Configuration Option

  1. Create a ConfigContainer subclass or add a ConfigValue field to an existing container (recaf-core/src/main/java/software/coley/recaf/config/BasicConfigContainer.java)
  2. Use BasicConfigValue or BasicMapConfigValue wrappers depending on the data type (recaf-core/src/main/java/software/coley/recaf/config/BasicConfigValue.java)
  3. Annotate with @EagerInitialization if the config should load immediately on startup (recaf-core/src/main/java/software/coley/recaf/cdi/EagerInitialization.java)

Add a New Logging Consumer or Handler

  1. Create a class implementing LogConsumer interface with custom message handling logic (recaf-core/src/main/java/software/coley/recaf/analytics/logging/LogConsumer.java)
  2. Register the consumer in Logging facade via addConsumer() method (recaf-core/src/main/java/software/coley/recaf/analytics/logging/Logging.java)
  3. Optionally extend InterceptingLogger for more sophisticated log filtering/transformation (recaf-core/src/main/java/software/coley/recaf/analytics/logging/InterceptingLogger.java)

🔧Why these technologies

  • Jakarta EE / CDI (Contexts and Dependency Injection) — Provides inversion-of-control and lazy/eager initialization patterns for managing complex service dependencies without manual wiring
  • Gradle with multi-module layout (recaf-core as primary module) — Enables separation of concerns and modular builds; allows core bytecode editing logic to be isolated from UI layers
  • JaCoCo for code coverage — Ensures quality and maintainability of complex bytecode manipulation logic through automated coverage tracking
  • Abstract ClassInfo and FileInfo hierarchies — Decouples bytecode editing logic from specific class file formats (JVM, Android DEX, etc.), enabling support for multiple platforms

⚖️Trade-offs already made

  • Use abstract FileInfo and ClassInfo interfaces with multiple implementations

    • Why: Support diverse formats (JAR, APK, WAR, DEX, etc.) without duplicating bytecode logic
    • Consequence: Increased number of classes and interfaces; higher complexity in type checking and factory methods
  • Eager initialization of @EagerInitialization-annotated beans via CDI extension

    • Why: Ensures critical services are ready before
    • Consequence: undefined

🪤Traps & gotchas

  1. No UI module in provided file list: The UI is likely in a separate submodule or branch not shown; just building recaf-core produces a library, not a runnable editor.
  2. Snapshot-only builds: v4.0.0-SNAPSHOT has no stable release artifacts yet; snapshot behavior and breaking changes possible.
  3. CDI initialization order: EagerInitialization and InitializationEvent require understanding of CDI lifecycle; beans marked eager must be declared properly.
  4. Dependency exclusions are strict: Many libraries are explicitly excluded (checkerframework, IBM ICU, findbugs) to reduce transitive bloat; re-adding them may cause unexpected behavior.
  5. Java toolchain requirement: Uses Gradle toolchain, not system Java; ensure your JDK version matches gradle.properties languageVersion.

🏗️Architecture

💡Concepts to learn

  • Constant Pool Management — Recaf's core value is abstracting the JVM constant pool from users; understanding how it works (CONSTANT_Utf8, CONSTANT_Class, CONSTANT_NameAndType entries) explains why the editor is needed
  • Stack Frame Calculation — Recaf automatically computes max_stack and max_locals; without understanding frame semantics, edits can produce unpredictable runtime errors
  • Java Bytecode (Dalvik for Android) — Recaf's entire purpose is manipulating compiled bytecode; familiarity with opcodes (ALOAD, INVOKEVIRTUAL, etc.) and class file format is essential
  • Contexts and Dependency Injection (CDI) — Recaf 4.x uses Jakarta CDI for component lifecycle management via EagerInitializationExtension; understanding scopes and bean discovery is required for adding new services
  • Code Deobfuscation Patterns — Recaf includes automated deobfuscation tools that detect and reverse common obfuscation strategies (string encryption, control flow flattening); understanding these patterns informs feature development
  • Bytecode Assembler & Syntactic Sugar — Recaf's assembler with variable names and stack visualization is a Domain-Specific Language (DSL) that trades fidelity for usability; this design choice underlies the entire editor paradigm
  • Ahead-of-Time (AOT) vs. Just-in-Time (JIT) Compilation — Recaf's built-in compiler must handle missing dependencies and produce bytecode that the JVM can verify; understanding JIT pitfalls explains why certain transformations are risky
  • Col-E/Recaf-Launcher — Official launcher for Recaf 4.x; manages snapshots and bundled distribution since no stable releases exist yet
  • leibnitz137/MappingGenerator — Generates obfuscation mappings compatible with Recaf's deobfuscation tools for automated class/member renaming
  • Konloch/bytecode-viewer — Alternative Java bytecode editor with similar decompiler/disassembler capabilities; useful for comparing UX and architecture choices
  • JetBrains/intellij-community — IntelliJ's bytecode viewer is a lighter-weight alternative for inspection-only use; Recaf targets deeper manipulation
  • crash-and-compile/tools — Collection of Java reverse engineering tools that often integrate with or complement Recaf for larger workflows

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive unit tests for config system (recaf-core/src/main/java/software/coley/recaf/config/)

The config module has multiple implementations (BasicConfigValue, BasicConfigContainer, BasicMapConfigValue, etc.) but the file structure shows no corresponding test directory. Given that ConfigPersistence is critical for saving user preferences and RecafConstants depends on it, adding thorough unit tests would improve reliability and catch regressions early. This is especially important for a tool that modifies bytecode where configuration correctness is crucial.

  • [ ] Create recaf-core/src/test/java/software/coley/recaf/config/ directory structure
  • [ ] Add tests for BasicConfigValue covering getters, setters, and observers
  • [ ] Add tests for BasicConfigContainer covering nested container behavior and persistence
  • [ ] Add tests for BasicMapConfigValue and BasicCollectionConfigValue with edge cases
  • [ ] Add integration tests for ConfigPersistence round-trip serialization

Add unit tests for info module classes (recaf-core/src/main/java/software/coley/recaf/info/)

The info module contains multiple file type classes (AndroidChunkFileInfo, AndroidClassInfo, ApkFileInfo, ArscFileInfo, etc.) that handle parsing and representing different bytecode/archive formats. These are core abstractions for the editor's functionality, yet no test files are visible in the provided structure. Testing these classes ensures correct parsing of various Android/Java formats and prevents regressions in the core model layer.

  • [ ] Create recaf-core/src/test/java/software/coley/recaf/info/ directory
  • [ ] Add tests for AndroidChunkFileInfo with sample chunk data
  • [ ] Add tests for ApkFileInfo covering APK structure validation
  • [ ] Add tests for ArscFileInfo covering resource bundle parsing
  • [ ] Add tests for the Accessed interface implementation across file info classes

Add missing unit tests for CDI/initialization system (recaf-core/src/main/java/software/coley/recaf/cdi/)

The CDI extension system (EagerInitializationExtension, InitializationEvent, InitializationStage, UiInitializationEvent) is responsible for application startup sequencing and dependency injection. This is a critical system for Recaf's initialization, and testing it ensures proper startup order and that components initialize correctly. Given the complexity of CDI extensions, comprehensive tests would prevent hard-to-debug initialization issues.

  • [ ] Create recaf-core/src/test/java/software/coley/recaf/cdi/ directory
  • [ ] Add tests for EagerInitializationExtension verifying correct bean discovery
  • [ ] Add tests for InitializationStage ordering and event firing
  • [ ] Add tests for UiInitializationEvent that verify UI-specific initialization happens after core init
  • [ ] Add integration tests for complete initialization lifecycle with multiple stages

🌿Good first issues

  • Add unit tests for recaf-core/src/main/java/software/coley/recaf/analytics/SystemInformation.java; currently no test files visible for analytics modules and system info gathering is critical for multi-platform support (Windows/Linux/macOS).
  • Document the CDI initialization flow with inline JavaDoc examples in EagerInitializationExtension and InitializationEvent; new contributors struggle to understand why components aren't injected without this.
  • Create a gradle/DEVELOPMENT.md guide explaining how to build recaf-core standalone, run tests, and connect to the UI module; the repo references a separate Launcher but provides no developer instructions.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 3480296 — Move script run clearing earlier (Col-E)
  • 3ed4253 — I guess the CI is trying to run this test parallel (Col-E)
  • f5e1699 — Disable heap space test since CI isn't configured for this under regular builds (Col-E)
  • 09e3d22 — Fix mapping not effectively traversing up inheritance trees (Col-E)
  • 9e1dd9b — Update vineflower (Col-E)
  • c24480c — Bump extra-collections (Col-E)
  • b846f72 — Fix memory leak from explorer pane being kept around in docking manager (Col-E)
  • 237d609 — Major inheritance graph optimizations (Col-E)
  • fa13e3d — Add similar method + class search (Col-E)
  • ecb4017 — Fix NPE when navigating to methods in some cases (Col-E)

🔒Security observations

The Recaf codebase shows generally good security practices with proper use of Jakarta annotations and exclusion of problematic dependencies. However, the main concerns are: (1) an incomplete gradle configuration that needs verification, (2) reliance on local JAR files without version tracking, and (3) inclusion of JitPack which lacks artifact signing guarantees. The project would benefit from fully migrating to dependency management through standard repositories and ensuring all build configurations are complete. No hardcoded credentials or obvious injection vulnerabilities were detected in the provided file structure.

  • Medium · Incomplete Gradle Configuration — build.gradle - Java toolchain configuration. The build.gradle file appears to be truncated at the Java toolchain configuration section (line ends with 'JavaLangua'). This incomplete configuration could lead to unpredictable build behavior and potential security issues if toolchain requirements are not properly specified. Fix: Complete the Java toolchain configuration by specifying the full languageVersion (e.g., 'JavaLanguage.of(21)'). Ensure the gradle.properties file specifies a minimum Java version compatible with security requirements.
  • Low · Local JAR Files Without Version Control — libs/kotlin-metadata.jar. The project includes local JAR files in the 'libs' directory (libs/kotlin-metadata.jar) that are committed to the repository. These files lack version tracking and source verification, making it difficult to audit dependencies and detect compromised libraries. Fix: Migrate local JAR dependencies to a proper dependency management system (Maven Central, JCenter, or custom Maven repository). Remove pre-built JARs from version control and manage versions through gradle dependencies instead.
  • Low · JitPack Repository Usage — build.gradle - repositories section. The build configuration includes JitPack (https://jitpack.io) as a Maven repository. While JitPack is useful for GitHub-based dependencies, it builds code on-demand without guaranteed security scanning or artifact verification, increasing supply chain risk. Fix: For critical dependencies, prefer verified sources like Maven Central. If using JitPack, verify the source repository is trustworthy and consider pinning specific commit hashes rather than tags for dependencies from JitPack.
  • Low · Overly Broad Artifact Exclusions — build.gradle - configurations.configureEach block. The configuration excludes 'com.ibm.icu' globally based on the assumption that it's unused. While reasonable, blanket exclusions can mask transitive dependency issues and should be replaced with explicit version management where possible. Fix: Replace global exclusions with explicit dependency constraints using gradle's dependency management. Document why each exclusion is necessary and monitor for transitive dependency updates.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · Col-E/Recaf — RepoPilot