deathmarine/Luyten
An Open Source Java Decompiler Gui for Procyon
Stale — last commit 2y ago
weakest axisnon-standard license (Other); last commit was 2y ago…
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
last commit was 2y ago; no CI workflows detected
- ✓18 active contributors
- ✓Other licensed
- ⚠Stale — last commit 2y ago
Show all 7 evidence items →Show less
- ⚠Concentrated ownership — top contributor handles 61% of recent commits
- ⚠Non-standard license (Other) — review terms
- ⚠No CI workflows detected
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Concerns → Mixed if: clarify license terms
- →Deploy as-is Mixed → Healthy if: 1 commit in the last 180 days
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 "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/deathmarine/luyten)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/deathmarine/luyten on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: deathmarine/Luyten
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:
- 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. - 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.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/deathmarine/Luyten 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
WAIT — Stale — last commit 2y ago
- 18 active contributors
- Other licensed
- ⚠ Stale — last commit 2y ago
- ⚠ Concentrated ownership — top contributor handles 61% of recent commits
- ⚠ Non-standard license (Other) — review terms
- ⚠ No CI workflows detected
- ⚠ No test directory detected
<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 deathmarine/Luyten
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/deathmarine/Luyten.
What it runs against: a local clone of deathmarine/Luyten — 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 deathmarine/Luyten | Confirms the artifact applies here, not a fork |
| 2 | License is still Other | 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 ≤ 696 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of deathmarine/Luyten. If you don't
# have one yet, run these first:
#
# git clone https://github.com/deathmarine/Luyten.git
# cd Luyten
#
# 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 deathmarine/Luyten and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "deathmarine/Luyten(\\.git)?\\b" \\
&& ok "origin remote is deathmarine/Luyten" \\
|| miss "origin remote is not deathmarine/Luyten (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Other)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Other\"" package.json 2>/dev/null) \\
&& ok "license is Other" \\
|| miss "license drift — was Other 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 "src/us/deathmarine/luyten/Luyten.java" \\
&& ok "src/us/deathmarine/luyten/Luyten.java" \\
|| miss "missing critical file: src/us/deathmarine/luyten/Luyten.java"
test -f "src/us/deathmarine/luyten/MainWindow.java" \\
&& ok "src/us/deathmarine/luyten/MainWindow.java" \\
|| miss "missing critical file: src/us/deathmarine/luyten/MainWindow.java"
test -f "src/us/deathmarine/luyten/Model.java" \\
&& ok "src/us/deathmarine/luyten/Model.java" \\
|| miss "missing critical file: src/us/deathmarine/luyten/Model.java"
test -f "src/us/deathmarine/luyten/LuytenTypeLoader.java" \\
&& ok "src/us/deathmarine/luyten/LuytenTypeLoader.java" \\
|| miss "missing critical file: src/us/deathmarine/luyten/LuytenTypeLoader.java"
test -f "src/us/deathmarine/luyten/OpenFile.java" \\
&& ok "src/us/deathmarine/luyten/OpenFile.java" \\
|| miss "missing critical file: src/us/deathmarine/luyten/OpenFile.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 696 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~666d)"
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/deathmarine/Luyten"
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).
⚡TL;DR
Luyten is a standalone GUI wrapper around Procyon, a Java decompiler, that lets users graphically explore and decompile JAR/class files into readable Java source code. It provides a tree-based file browser, syntax-highlighted source viewer, and search capabilities for reverse-engineering compiled Java binaries without touching the command line. Monolithic single-module Maven project under src/us/deathmarine/luyten/ with ~40 Java classes handling distinct concerns: Luyten.java is the entry point, MainWindow.java builds the UI frame, Model.java manages decompiler state, OpenFile.java handles JAR loading, and specialized classes like FindBox.java, FileSaver.java, TreeUtil.java provide search, export, and tree navigation. Resources (icons, licenses) live in src/resources/ and src/distfiles/.
👥Who it's for
Java developers, security researchers, and reverse engineers who need to inspect compiled Java libraries or applications; they use Luyten to quickly browse JAR internals and read decompiled source code instead of wrestling with hex editors or command-line decompiler CLIs.
🌱Maturity & risk
Moderately mature but inactive: version 0.7.0 is stable and the project has accumulated 212K lines of Java code across a monolithic structure. No evidence of recent commits, CI/CD pipeline, or test suite is visible in the file list. Suitable for production use if you accept no active maintenance; not a bleeding-edge project.
Low to moderate risk for production use: depends entirely on outdated Procyon 0.5.36 (released ~2015) which has not tracked Java language evolution past Java 8–9 era, so modern language features (records, sealed classes, pattern matching) will decompile poorly or fail. Single maintainer (deathmarine) with no visible CI or test automation means bugs could linger. RSyntaxTextArea 3.0.2 is reasonably maintained but Procyon is a stale dependency.
Active areas of work
No active development visible; the codebase appears dormant. Version 0.7.0 is the current release with no pending milestones or visible recent pull requests in the file manifest. The project likely receives only occasional bug-fix PRs or security updates.
🚀Get running
Clone and build with Maven: git clone https://github.com/deathmarine/Luyten.git && cd Luyten && mvn clean install. Then run the compiled JAR (created as target/luyten-0.7.0-lib.jar). Maven 3+ and Java 8+ are required.
Daily commands:
mvn clean install builds the JAR. Execute via java -jar target/luyten-0.7.0-lib.jar or your platform's JAR launcher. On macOS, LuytenOsx.java provides OS integration hooks (menu bar, etc.) but the standard launcher works on all platforms.
🗺️Map of the codebase
src/us/deathmarine/luyten/Luyten.java— Application entry point and main initialization; all contributors must understand the startup sequence and window lifecyclesrc/us/deathmarine/luyten/MainWindow.java— Core UI container and orchestrator; defines the primary window structure, tab management, and event delegationsrc/us/deathmarine/luyten/Model.java— Central state model managing opened files, decompilation results, and model-view synchronizationsrc/us/deathmarine/luyten/LuytenTypeLoader.java— Bridge to Procyon decompiler; handles type resolution and class loading from JAR/binary filessrc/us/deathmarine/luyten/OpenFile.java— Manages individual file tabs and decompilation output rendering; critical for understanding decompiled code displaypom.xml— Maven build configuration defining Procyon and RSyntaxTextArea dependencies; essential for understanding the decompilation and editor stack
🛠️How to make changes
Add a new menu action to the main menu
- Define the action handler in MainWindow.java, implementing logic to interact with Model or OpenFile state (
src/us/deathmarine/luyten/MainWindow.java) - Register the action in MainMenuBar.java, binding it to a menu item and keyboard shortcut (
src/us/deathmarine/luyten/MainMenuBar.java) - If the action requires a new preference, add it to LuytenPreferences.java for persistence (
src/us/deathmarine/luyten/LuytenPreferences.java)
Add support for a new file type or filter
- Extend JarEntryFilter.java to recognize and filter the new file extension (
src/us/deathmarine/luyten/JarEntryFilter.java) - Update LuytenTypeLoader.java if type resolution differs from standard Java classes (
src/us/deathmarine/luyten/LuytenTypeLoader.java) - Add corresponding icon to src/resources/ and register in CellRenderer.java for tree display (
src/us/deathmarine/luyten/CellRenderer.java) - Handle display in OpenFile.java if special syntax highlighting or rendering is needed (
src/us/deathmarine/luyten/OpenFile.java)
Add a new search or navigation feature
- Create a new UI component class (similar to FindBox.java) in src/us/deathmarine/luyten/ (
src/us/deathmarine/luyten/FindBox.java) - Integrate the component into MainWindow.java, adding toolbar or panel support (
src/us/deathmarine/luyten/MainWindow.java) - Use Model.java to query opened files or leverage OpenFile.java for content search (
src/us/deathmarine/luyten/Model.java) - Bind actions to MainMenuBar.java and optionally save search preferences (
src/us/deathmarine/luyten/MainMenuBar.java)
Customize the decompiler output or code formatting
- Modify LuytenTypeLoader.java to adjust Procyon settings or pass custom configuration (
src/us/deathmarine/luyten/LuytenTypeLoader.java) - Post-process decompiled output in OpenFile.java before rendering in the editor (
src/us/deathmarine/luyten/OpenFile.java) - Add corresponding user preferences to LuytenPreferences.java for end-user control (
src/us/deathmarine/luyten/LuytenPreferences.java) - Expose preference UI in a settings dialog, linking back to MainWindow.java (
src/us/deathmarine/luyten/MainWindow.java)
🔧Why these technologies
- Procyon Decompiler (procyon-core 0.5. — undefined
🪤Traps & gotchas
Procyon version lock: Procyon 0.5.36 is hardcoded in pom.xml and will not decompile Java 9+ features correctly. Upgrading risks API breaks in OpenFile.java and LuytenTypeLoader.java. Swing threading: UI operations must run on the EDT (Event Dispatch Thread); look for SwingUtilities.invokeLater() patterns in OpenFile.java when decompiling large JARs to avoid freezes. Classpath hell: LuytenTypeLoader must see all transitive JAR dependencies at runtime or Procyon will fail to resolve inner/nested types; users must manually manage import JARs (see DirPreferences.java). No logging: errors are silently swallowed in many places (e.g., OpenFile.java) — add println() or log4j if debugging failed decompilations. macOS-specific code: LuytenOsx.java will fail silently on non-macOS platforms; menu bar integration is platform-conditional.
🏗️Architecture
💡Concepts to learn
- Java Bytecode Decompilation — Understanding how Procyon reverses JVM bytecode back to source is critical for diagnosing decompilation failures and knowing what language features Luyten can handle; Procyon's 2015 feature set only covers up to Java 8.
- Type Resolution & Classpaths in JVM Tools — Luyten's LuytenTypeLoader must resolve class references when decompiling; understanding how Procyon's reflection API hooks into JAR classpaths explains why DirPreferences and manual JAR imports exist.
- Swing Event-Driven Architecture — All of Luyten's UI (MainWindow.java, MainMenuBar.java, FindBox.java) uses Swing listeners and the Event Dispatch Thread; incorrect threading (e.g., blocking EDT during decompilation) causes UI freezes.
- JAR File Structure & ZIP Format — OpenFile.java reads JARs as ZIP archives and extracts .class bytecode; understanding how TreeUtil.java maps ZIP entries to a Swing JTree hierarchy is key to extending the file browser.
- Maven Build Lifecycle & Resource Bundling — The pom.xml configuration determines how resources (icons in src/resources/, license files in src/distfiles/) are packaged into the final JAR; Maven's resource plugin excludes .java files from output.
- Syntax Highlighting & Lexer-based Editors — RSyntaxTextArea (used in MainWindow's source viewer) uses lexers to tokenize Java code for color and styling; understanding its API is needed to customize syntax themes or add language support.
- Cross-Platform GUI Abstraction (Swing vs Platform-Specific Code) — LuytenOsx.java shows how Luyten handles macOS-specific integrations (menu bar, dock) while keeping the core cross-platform; understanding this pattern helps when adding Windows or Linux-specific features.
🔗Related repos
konloch/bytecode-viewer— Similar Java decompiler GUI (more actively maintained) supporting multiple decompilers (Procyon, CFR, Fernflower) with a comparable tree+editor layout.leibnitz60/MachineCode— Another Java decompiler GUI focused on bytecode inspection; smaller project but shows alternative approach to Swing-based JAR browsing.mstrobel/procyon— The upstream Procyon decompiler engine that Luyten wraps; understanding Procyon's DecompilerContext and type-loader is essential to extending Luyten's capabilities.bobbylight/RSyntaxTextArea— The syntax-highlighting editor library Luyten uses for source code display; upstream for bug fixes and feature additions to editor behavior.cfr-dev/cfr— Modern alternative decompiler (supports Java 8–21 features) that could replace Procyon if maintainers wanted to update Luyten's backend to handle contemporary Java code.
🪄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 GitHub Actions CI/CD workflow for Maven builds and cross-platform testing
The repo has a Maven-based build system but no CI/CD pipeline. This is critical for a GUI application that targets multiple platforms (Windows, macOS, Linux) given the presence of LuytenOsx.java and platform-specific resources (Luyten.icns). A workflow would catch build failures early, verify Procyon decompilation works correctly, and ensure the final artifact builds on each platform.
- [ ] Create .github/workflows/maven-build.yml with jobs for Ubuntu, Windows, and macOS
- [ ] Configure matrix build testing against Java 8+ versions (Procyon supports older Java bytecode)
- [ ] Add step to verify JAR artifact generation and basic decompilation smoke test
- [ ] Test that resources (src/resources/.png, src/distfiles/.txt) are correctly bundled
- [ ] Add badge to README.md linking to workflow status
Extract and test decompilation logic from MainWindow.java into a dedicated DecompilationService class
MainWindow.java likely contains mixed concerns (UI rendering + decompilation orchestration). Given that Procyon decompilation is the core value proposition, separating decompilation logic into a testable service class would enable unit testing of edge cases (TooLargeFileException, FileIsBinaryException, FileEntryNotFoundException, binary files in JARs). This improves code reusability and makes the codebase more maintainable.
- [ ] Analyze MainWindow.java to identify decompilation orchestration code (JAR parsing, type loading via LuytenTypeLoader.java, Procyon API calls)
- [ ] Create src/us/deathmarine/luyten/DecompilationService.java to encapsulate decompilation logic
- [ ] Move exception handling (custom exceptions already exist: FileIsBinaryException, TooLargeFileException, FileEntryNotFoundException) into the service
- [ ] Create src/us/deathmarine/luyten/DecompilationServiceTest.java with tests for binary files, oversized files, missing entries, and nested JARs
- [ ] Update MainWindow.java to delegate to DecompilationService
Add structured logging and error reporting via SLF4J/Logback instead of silent failures
The codebase has custom exception classes (FileIsBinaryException, TooLargeFileException, etc.) but no visible logging framework. This makes debugging user issues and decompilation failures difficult. Adding SLF4J with a bundled Logback config would help users and maintainers troubleshoot issues with Procyon decompilation, JAR loading, and UI interactions without modifying code.
- [ ] Add SLF4J API and Logback implementation dependencies to pom.xml
- [ ] Create src/resources/logback.xml with INFO level console output and DEBUG-level file output to user home directory
- [ ] Add logging statements to key classes: OpenFile.java (file loading), Model.java (decompilation state), LuytenTypeLoader.java (classpath resolution)
- [ ] Log exception stack traces when custom exceptions are caught in MainWindow.java and FileDialog.java
- [ ] Document log file location in README.md and update error dialogs to reference log file for troubleshooting
🌿Good first issues
- Add JUnit tests for TreeUtil.java and FileSaver.java: these file/tree utilities have no test coverage visible in the file list; write unit tests that verify JAR tree population and source file export under
src/test/to catch regressions early. - Document Procyon decompilation options in README: OpenFile.java instantiates DecompilerContext with hardcoded settings but no docs explain what settings are available or how to expose them in Preferences; add a section to README.md with examples and add a 'Decompiler Settings' dialog in MainWindow.java.
- Fix or remove dead code in FindAllBox.java and FindBox.java: the file list suggests search features exist but no search UI is visible in MainWindow.java; either wire these up with keyboard shortcuts and a Find toolbar, or document why they're unused.
⭐Top contributors
Click to expand
Top contributors
- @deathmarine — 61 commits
- @FisheyLP — 9 commits
- @atnayan — 5 commits
- @Deathmarine — 4 commits
- @toonetown — 4 commits
📝Recent commits
Click to expand
Recent commits
64af8d1— Merge pull request #220 from psytester/patch-2 (deathmarine)6558b5d— Merge pull request #242 from atnayan/Single-Instance (deathmarine)b036b13— [Single-Instance] Opening a jar from OS opens a tab in currently opened instance (atnayan)ad47a93— Force refresh & Bug Fix (atnayan)f2288ce— Bug fix (atnayan)0b3339a— Make tab appear for single jar when opened from OS (atnayan)1c64417— Add ability to open multiple jars in same window (atnayan)7e63d5a— Merge pull request #240 from berryh/feature/LT-238-maven-https-adresses (deathmarine)0d89554— Change Maven address to HTTPS. (Berry Holtrust)a862223— Merge pull request #226 from Phoenix616/pr/fix-duplicate-tab-names (deathmarine)
🔒Security observations
The Luyten Java decompiler project has moderate security concerns primarily related to outdated dependencies (Procyon 0.5.36 from 2015, AppleJavaExtensions 1.4 from 2013). The incomplete pom.xml file and lack of dependency management strategy pose additional risks. As a tool that processes untrusted bytecode
- High · Outdated Procyon Dependency —
pom.xml - procyon-core, procyon-expressions, procyon-reflection, procyon-compilertools dependencies. The project uses Procyon version 0.5.36, which is significantly outdated (released in 2015). This decompiler library may contain unpatched security vulnerabilities and bugs. The last known stable version of Procyon is from 2015, and no active maintenance is evident. Fix: Check if newer versions of Procyon are available or consider switching to an actively maintained Java decompiler library. If 0.5.36 is the latest available, ensure the dependency source is trusted and review the Procyon project status. - High · Outdated RSyntaxTextArea Dependency —
pom.xml - rsyntaxtextarea dependency. RSyntaxTextArea version 3.0.2 is being used. While this is relatively recent, ensure it's the latest available version to receive security patches and bug fixes. Fix: Update to the latest stable version of RSyntaxTextArea. Check the project's GitHub releases page for the most current version and security advisories. - Medium · Outdated AppleJavaExtensions Dependency —
pom.xml - AppleJavaExtensions dependency. AppleJavaExtensions version 1.4 from 2013 is significantly outdated and no longer actively maintained by Apple. This Mac-specific extension may have unpatched vulnerabilities. Fix: Review if this dependency is still necessary for modern macOS support. Consider removing it if functionality has been replaced by modern Java APIs, or find an actively maintained alternative. - Medium · No Dependency Version Pinning Strategy —
pom.xml - entire dependencies section. The pom.xml lacks explicit version constraints for transitive dependencies. This could lead to unexpected version updates of indirect dependencies that may introduce vulnerabilities or breaking changes. Fix: Implement a dependency management strategy using Maven's <dependencyManagement> section to lock transitive dependency versions and ensure reproducible builds. - Medium · Incomplete pom.xml File —
pom.xml - end of file. The provided pom.xml appears truncated (ends with incomplete<exclude>tag), suggesting the file may be corrupted or incomplete. This could hide additional configuration issues or missing security settings. Fix: Verify the complete pom.xml file is valid and properly formatted. Runmvn validateto ensure Maven can parse it correctly. - Low · No Security Manager Configuration —
Luyten.java and related entry points. As a decompiler GUI application that processes untrusted JAR/class files, there is no evidence of a security manager being configured to restrict potentially dangerous operations. Fix: Consider implementing a Java SecurityManager to restrict file system access, network operations, and reflection capabilities when processing untrusted bytecode files. - Low · Missing Dependency Integrity Verification —
pom.xml - repository configuration. No evidence of dependency checksum verification (e.g., checksums, signature validation) in the Maven configuration. Fix: Enable Maven's checksum verification and consider using trusted repository mirrors with signed artifacts. Usemvn -DgeneratePom=trueand verify all downloaded JARs. - Low · Potential File Handling Vulnerabilities —
src/us/deathmarine/luyten/ - FileSaver.java, FileDialog.java, DropListener.java. Files like FileSaver.java, FileDialog.java, and DropListener.java suggest file I/O operations. Without code review, path traversal or insecure deserialization risks cannot be ruled out. Fix: Perform code review of file handling operations to ensure proper input validation, path canonicalization, and prevention of path traversal attacks. Use Java NIO APIs with secure file operations.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.