Overview
Arcana is a single JAR that is both a command-line tool and a Java library. It reads the archive formats you meet in practice, writes the most common ones, and tells you what an unknown file is.
Everything is implemented in Java: the decompressors (Deflate, Deflate64, LZMA, LZMA2, PPMd, BZip2, LZ4, Zstandard, Brotli, LZX, the RAR 4 and RAR 5 algorithms...), the encryption (AES, ZipCrypto) and the container formats. There is no call to a native library and no third-party JAR, so Arcana behaves the same on Windows, Linux and macOS and can be dropped into any Java 8 application.
What you can do with it
- Extract
- every supported format, encrypted or not, from a file or from a stream.
- Compress
- to ZIP, 7z, TAR (plain, GZIP, BZIP2, XZ, LZ4), GZIP, BZIP2, XZ, LHA and CAB, with AES-256 encryption for ZIP and 7z.
- Identify
- any file: archive, executable, image, document, database, font, media, with its version and details.
- Recover
- what is still readable in a damaged archive, with a report giving the state of every file.
- Split
- files made of several files glued together, such as installers and self-extracting archives.
- Extend
- with plugins that add formats without changing Arcana.
Formats
The signature column shows the bytes Arcana looks for. Formats without a signature (LZMA, Brotli) are recognized by their extension. arcana formats prints the same list, including the formats added by installed plugins.
| Format | Extract | Create | Signature | Notes |
|---|---|---|---|---|
| ZIP | yes | yes | 50 4B 03 04 | Also JAR, WAR, EAR. Decrypts ZipCrypto and WinZip AES; encrypts with AES-256 (ZipCrypto from the Java API). Extracts Deflate, Deflate64, BZip2, LZMA, XZ, Zstandard and PPMd. |
| 7-Zip | yes | yes | 37 7A BC AF 27 1C | LZMA, LZMA2, PPMd, BZip2, Deflate, Deflate64; BCJ, BCJ2, ARM, ARM-Thumb, ARM64, RISC-V, PowerPC, SPARC, IA-64, Delta and Swap filters. AES-256, encrypted headers, split archives (.7z.001). Creates LZMA2, levels 0 to 9. |
| RAR 5 | yes | no | 52 61 72 21 1A 07 01 00 | AES-256, encrypted headers, multi-volume, solid archives. Also .cbr. |
| RAR 4 | yes | no | 52 61 72 21 1A 07 00 | AES-128, encrypted headers, multi-volume, solid archives, VM filters. |
| TAR | yes | yes | "ustar" at byte 257 | Also .gem. |
| TAR + GZIP | yes | yes | 1F 8B | .tar.gz, .tgz |
| TAR + BZIP2 | yes | yes | 42 5A 68 | .tar.bz2, .tbz2, .tbz |
| TAR + XZ | yes | yes | FD 37 7A 58 5A 00 | .tar.xz, .txz; levels 0 to 9 |
| TAR + LZ4 | yes | yes | 04 22 4D 18 | .tar.lz4 |
| TAR + Zstandard | yes | no | FD 2F B5 28 | .tar.zst, .tzst |
| TAR + Brotli | yes | no | none | .tar.br, .tbr |
| GZIP | yes | yes | 1F 8B | Single file. |
| BZIP2 | yes | yes | 42 5A 68 | Single file. |
| XZ | yes | yes | FD 37 7A 58 5A 00 | Single file, LZMA2, levels 0 to 9. |
| LZMA | yes | no | none | Raw .lzma stream, recognized by its extension. |
| LZ4 | yes | no | 04 22 4D 18 | Frame format. |
| Zstandard | yes | no | FD 2F B5 28 | .zst, .zstd |
| Snappy | yes | no | FF 06 00 00 73 4E 61 50 70 59 | Framing format. |
| Brotli | yes | no | none | .br, recognized by its extension. |
| Unix compress | yes | no | 1F 9D | .Z (LZW) |
| MS compress (SZDD) | yes | no | "SZDD" | Files packed by COMPRESS.EXE on old setup disks (.ex_, .dl_...); the original name is restored. |
| LHA / LZH | yes | yes | "-lh" at byte 2 | Extracts -lh0-, -lh4- to -lh7-; creates -lh5- (default), -lh6-, -lh7-. |
| ARJ | yes | no | 60 EA | Methods 0 to 4. Not supported: encrypted (garbled) entries and files split across volumes. |
| Cabinet | yes | yes | "MSCF" | Extracts stored, MSZIP and LZX; creates MSZIP. |
| Windows Installer | yes | no | D0 CF 11 E0 A1 B1 1A E1 | .msi: the installed files with their real names and folders (File, Component and Directory tables, embedded cabinets); the other streams go to [streams]/. |
| OLE compound file | yes | no | D0 CF 11 E0 A1 B1 1A E1 | .msp, Office 97-2003 documents (.doc, .xls, .ppt), Outlook .msg: storages and streams. |
| Compiled HTML Help | yes | no | "ITSF" | .chm (LZX): the pages, images and scripts of the help file. |
| CPIO | yes | no | "07070" | newc (SVR4) and odc. |
| ISO 9660 | yes | no | "CD001" at byte 32769 | CD and DVD images. |
| UDF | yes | no | "NSR02" or "NSR03" from byte 32769 | DVD, Blu-ray and Windows install images, UDF 1.02 to 2.60 (physical, sparable, virtual and metadata partitions). On discs that are both UDF and ISO 9660, the UDF side is read. |
| WIM | yes | no | "MSWIM" | Windows Imaging Format: XPRESS, LZX, LZMS (.esd files, such as the install.esd of Windows ISO images), uncompressed and solid resources; SHA-1 of every file checked; one directory per image when there are several. Not supported: split .swm files. |
| SquashFS | yes | no | "hsqs" | Version 4.0: gzip, LZMA, LZO, XZ, LZ4 and Zstandard. Linux live systems, Snap packages (.snap), firmware images. |
| AR / Debian package | yes | no | "!<arch>" | .a, .deb (contents unpacked, control files in DEBIAN/). |
| RPM | yes | no | ED AB EE DB | gzip, bzip2, xz and zstd payloads. |
| XAR | yes | no | "xar!" | Apple. |
| Self-extracting archive | yes | no | "MZ" or 7F "ELF" | Finds and extracts the ZIP, RAR, 7z or CAB (IExpress) inside an executable. |
A TAR or CPIO archive inside any single-file format is unpacked automatically: .cpio.gz, .cpio.xz, .cpio.zst, .tar.lzma...
Archive-based files
Many everyday files are archives under another name. Because Arcana goes by the content, it opens them directly, whatever their extension.
| Built on | Files |
|---|---|
| ZIP | Word, Excel and PowerPoint documents (.docx, .xlsx, .pptx, their templates and macro-enabled variants), OpenDocument (.odt, .ods, .odp, .odg, .odf, .odb), EPUB books, Java archives (.jar, .war, .ear, .aar), Android and iOS packages (.apk, .ipa), Python packages (.whl, .egg), browser and IDE extensions (.xpi, .crx, .vsix), NuGet packages, Google Earth .kmz, comic books .cbz, XPS documents, FreeCAD .fcstd, 3D printing .3mf |
| GZIP | Dia diagrams (.dia), compressed SVG (.svgz) |
| RAR, 7z | Comic books (.cbr, .cb7) |
| TAR | Ruby gems (.gem) |
| AR | Debian packages (.deb) |
$ arcana x report.docx -o report Extracting report.docx -> /home/anna/report Done.
A single-file stream (GZIP, BZIP2, XZ...) that does not store its original name is extracted to a file named output.
Identification
arcana i tells what a file is without extracting anything. It recognizes:
- archives: every format of the table above;
- executables: Windows PE32 and PE32+ (architecture, subsystem, EXE or DLL), .NET assemblies and .NET single-file bundles, Linux ELF, macOS Mach-O, MS-DOS programs, Java class files, WebAssembly modules;
- images: PNG, JPEG, GIF, BMP, TIFF and WebP, with their dimensions;
- documents and data: PDF, SQLite databases, OLE2 compound files (legacy Office documents, MSI...);
- fonts: TrueType, OpenType, WOFF and WOFF2;
- media: MP3, FLAC, Ogg, MP4 and other RIFF or ISO media containers.
$ arcana i sunset.png File : sunset.png Category : image Type : PNG Description: PNG image, 640x480 dimensions : 640 x 480 bit depth : 8 color type : truecolor (RGB) $ arcana i setup.exe File : setup.exe Category : executable Type : PE32 Description: PE32 EXE x86 kind : EXE (application) architecture : x86 (32-bit) subsystem : Windows GUI
Download
| File | Content | Size |
|---|---|---|
| Arcana-v1.0.0.jar | Command-line tool and Java library | |
| SHA256SUMS.txt | SHA-256 checksums of the JAR files |
Arcana needs a Java runtime, version 8 or later. Nothing else: no installer, no native library. Every release is built and tested automatically with Java 8 and Java 21.
Check the download
Compare the SHA-256 of the file with the line given for it in SHA256SUMS.txt:
C:\> certutil -hashfile Arcana-v1.0.0.jar SHA256 $ sha256sum -c SHA256SUMS.txt --ignore-missing
As a dependency
Add the JAR to the class path of your application. Publication on Maven Central under io.github.realburst:arcana is planned.
Command line
java -jar Arcana-v1.0.0.jar <command> [options]
In the examples below, arcana stands for java -jar Arcana-v1.0.0.jar. On Windows, a one-line arcana.bat next to the JAR gives you the short form: @java -jar "%~dp0Arcana-v1.0.0.jar" %*.
Run it without arguments for the syntax of each command, and with help (or -h, --help) for the descriptions, options and examples. version (or -v, --version) prints the version.
- arcana x <archive> [-o dest] [-p password] [-f format]
- Extracts the archive into dest, or into the current directory.
- arcana l <archive> [-p password] [-f format]
- Lists the contents: size, date and name of every entry.
- arcana c <source> <archive> [-t format] [-l 0-9] [-p password]
- Compresses a file or a directory. The format comes from the archive name, using the longest known extension (
backup.tar.gzgivestar.gz);-tsets it explicitly. - arcana r <archive> [-o dest] [-p password] [-f format]
- Recovers a damaged archive: extracts everything that can still be read and writes a report.
- arcana s <file> [-o dest] [-n]
- Splits a file made of files glued together into dest/file name/.
- arcana i <file>
- Identifies a file: category, type, version and details.
- arcana formats [extract|compress]
- Lists the supported formats, optionally only those that can be extracted or created.
- arcana plugins [<file>]
- Lists the plugins found, loaded or refused, with their directories and checksums. With a file, shows which plugin or format Arcana chooses for it, and why.
$ arcana c demo backup.7z -l 9 -p secret Compressing demo -> backup.7z Done. 452 bytes in 621 ms. $ arcana l backup.7z -p secret Size Modified Name ------------ ------------------- ---------------------------------------- 14 2026-10-02 11:40:43 demo/docs/notes.txt 12 2026-10-02 11:40:43 demo/docs/budget.csv 2366 2026-10-02 11:40:43 demo/photos/sunset.png 0 2026-10-02 11:40:43 demo/ 0 2026-10-02 11:40:43 demo/docs/ 0 2026-10-02 11:40:43 demo/photos/ 6 entries $ arcana x backup.7z -o restored -p secret Extracting backup.7z -> /home/anna/restored Done.
Options
| Option | Commands | Meaning |
|---|---|---|
-o <dir> | x, r, s | Output directory. It can also be given as the second argument: arcana x a.zip out. |
-p <password> | x, l, r, c | Password to decrypt; with c, encrypts the new ZIP or 7z archive with AES-256. |
-f <format> | x, l, r | Forces the input format instead of detecting it: a format name or extension (zip, tar.gz...), or a plugin id. |
-t <format> | c | Forces the output format instead of taking it from the archive name. |
-l <level> | c | 0 (fastest) to 9 (smallest) for 7z, xz and tar.xz, default 6; 5, 6 or 7 for lzh (-lh5-, -lh6-, -lh7-). |
-n | s | Lists the pieces without writing anything. |
Before running any command, Arcana prints on the error output the plugins it refused, with the reason, or [plugins] No plugin found in any plugin directory. when there is none. Nothing is printed when every plugin loaded correctly. Because these lines go to the error output, they do not mix with a listing you redirect to a file.
Damaged archives
Normal extraction stops at the first error, so that you never get a damaged file without knowing it. arcana r does the opposite: it keeps everything that can be read and gives the state of every file.
$ arcana x photos.zip Extracting photos.zip -> /home/anna Error: ZIP entry 'photos/sunset.png' has 2 bytes instead of 2366 $ arcana r photos.zip -o rescue Archive : photos.zip Method : ZIP: local headers scanned one by one Result : 3 file(s): 2 OK, 0 unverified, 1 bad checksum, 0 partial, 0 lost Status Written / Expected Name OK 14 / 14 docs/notes.txt OK 12 / 12 docs/budget.csv BAD_CHECKSUM 2 / 2366 photos/sunset.png (CRC c0f36009 instead of 364d29a8) Report written to /home/anna/rescue/_ARCANA_RECOVERY_REPORT.txt
| Status | Meaning |
|---|---|
OK | Decoded completely, and its checksum (when the format has one) is correct. |
UNVERIFIED | Decoded completely, but no checksum could confirm the content. |
BAD_CHECKSUM | Decoded completely, but the checksum does not match: the content is damaged. |
PARTIAL | Decoding stopped on an error: only the beginning of the file was written. |
LOST | Nothing could be decoded (encrypted, unsupported method, destroyed data). |
A recovered file can be incomplete or contain garbage. Check every file whose status is not OK before using it.
Glued files
Installers, self-extracting archives and firmware images are often several files placed one after the other. arcana s finds where each one starts and ends.
$ arcana s bundle.bin -n Offset Size Type Description 0x00000000 99840 pe PE32+ EXE x64 0x00018600 452 7z 7-Zip archive 0x000187C4 2366 png PNG image 3 piece(s), 3 recognized
Without -n, the pieces are written into bundle/ in the output directory, named after their position and type (001_0x00018600.7z...). Parts that match no known format are written too, with _unknown in their name, so nothing is lost; only gaps made of zero bytes are skipped.
Exit codes
| Code | Meaning |
|---|---|
0 | Success. |
1 | Wrong command line: unknown command or option, missing argument, file not found, unknown format. |
2 | The operation failed: damaged or encrypted archive, wrong password, unsupported method... The message starts with Error:. |
Java API
Add the JAR to your class path. The entry point is be.stef.arcana.Arcana.
import be.stef.arcana.Arcana; import be.stef.arcana.ArcanaEntry; import be.stef.arcana.ArcanaFormat; // Format detected from the content Arcana.extractTo(new File("archive.tar.gz"), new File("out")); // Entries, without extracting for (ArcanaEntry e : Arcana.listEntries(new File("archive.rar"))) { System.out.println(e.getName() + " " + e.getUncompressedSize()); } // Encrypted archive Arcana.withPassword("secret".getBytes("UTF-8")).extract(new File("secure.7z"), new File("out")); // From a stream: the format must be given try (InputStream in = new FileInputStream("data.bz2")) { Arcana.with(ArcanaFormat.BZIP2).extract(in, new File("out")); }
ArcanaEntry also gives the compressed size, the modification time and whether the entry is a directory.
Compression
import be.stef.arcana.compressor.ZipCompressor; import be.stef.arcana.plugin.FormatRegistry; byte[] password = "secret".getBytes("UTF-8"); new ZipCompressor().compress(new File("mydir"), new File("backup.zip")); new ZipCompressor(password).compress(new File("mydir"), new File("secure.zip")); // WinZip AES-256 new ZipCompressor(password, ZipCompressor.ENCRYPT_ZIPCRYPTO).compress(new File("mydir"), new File("legacy.zip")); // Any format: level 0-9 (-1 = default), password or null FormatRegistry.builtin(ArcanaFormat.SEVEN_Z).createCompressor(9, password).compress(new File("mydir"), new File("vault.7z")); FormatRegistry.builtin(ArcanaFormat.TAR_XZ).createCompressor(-1, null).compress(new File("mydir"), new File("backup.tar.xz"));
createCompressor returns null for a format Arcana can only extract. ZipCrypto is weak encryption: use it only when the archive must open in very old tools.
Identification and splitting
import be.stef.arcana.analyze.Identification; import be.stef.arcana.formats.carve.FileCarver; Identification id = Arcana.identify(new File("mystery.bin")); // never null System.out.println(id.category + " / " + id.type + (id.version != null ? " " + id.version : "")); System.out.println(id.description); System.out.println(id.getDetails()); // for example the dimensions of an image for (FileCarver.Item item : Arcana.scanEmbedded(new File("setup.exe"))) { // list only System.out.println(item); } Arcana.split(new File("setup.exe"), new File("out")); // writes out/setup/...
Recovery
import be.stef.arcana.formats.recover.RecoveryReport; RecoveryReport report = Arcana.forceUnpack(new File("damaged.zip"), new File("rescue")); System.out.println(report.summary()); for (RecoveryReport.Entry e : report.getEntries()) { if (e.status != RecoveryReport.Status.OK) System.out.println(e.name + ": " + e.status); }
The same report is written to _ARCANA_RECOVERY_REPORT.txt in the destination directory.
Extraction limits
Every extraction made through Arcana is guarded by the limits of be.stef.arcana.util.ExtractionLimits. They are public static fields that you can change at run time.
| Field | Default | Effect |
|---|---|---|
maxRatio | 1000 | Largest allowed ratio between the extracted size and the archive size, checked once ratioThreshold bytes are written. Stops decompression bombs. |
ratioThreshold | 1 GiB | Extracted size from which the ratio is checked. |
maxTotalBytes | 0 (no limit) | Largest total size one extraction may write. |
minFreeSpace | 256 MiB | The extraction stops before the disk has less free space than this. |
Errors
All errors are IOExceptions. The Arcana ones extend be.stef.arcana.exceptions.ArcanaException:
| Exception | When |
|---|---|
ArcanaUnsupportedFormatException | The format cannot be detected, or no plugin matches the requested id. |
ArcanaCorruptedException | The archive is damaged. |
ArcanaEncryptedException | A ZIP or RAR archive is encrypted and the password is missing or wrong. |
ArcanaLimitExceededException | An extraction limit was reached. |
Plugins
A plugin is a JAR that adds a format to Arcana: extraction, and if the format allows it, creation, recovery, detection inside glued files or identification. Once installed, its format works with every command and through the Java API, exactly like a built-in one.
Installing a plugin
Copy the JAR into one of these directories, then check with arcana plugins:
plugins/next to the Arcana JAR;.arcana/plugins/in your home directory;plugins/in the current directory.
The system property arcana.plugins.dir replaces these directories with your own list, separated by the path separator: java -Darcana.plugins.dir=D:\tools\arcana-plugins -jar Arcana-v1.0.0.jar ...
$ arcana plugins Plugin directories: /home/anna/tools/plugins [LOADED] io.github.realburst.upx 0.3.0 - UPX executable decompression (PE/ELF) priority : 0 capabilities: extract source : https://github.com/RealBurst/arcana/tree/main/plugins/arcana-plugin-upx license: GPL-3.0-or-later jar : /home/anna/tools/plugins/arcana-plugin-upx.jar sha256: 44b3504815e08e04ac79016873228d9e798c0cb7ee93249a882e6dad3aa0c824
Rules checked at load time
A plugin JAR is refused, with the reason printed on every run, unless:
- the JAR contains the source code of each of its classes, so that anyone can read what it does;
- it declares a source URL and a license;
- its id is not already used by another plugin;
- its classes use their own package:
be.stef.arcanais reserved for Arcana; - it declares its plugin class in
META-INF/services/be.stef.arcana.plugin.ArcanaPlugin.
Which format wins
For each file, Arcana looks in this order and takes the first match:
- plugins with a priority above 0, highest first (they can replace a built-in format, on purpose);
- the built-in formats recognized by their content;
- the other plugins, in load order;
- the built-in formats recognized by their extension, then the search for an archive inside an executable.
A plugin with the default priority can therefore never take a file away from a built-in format. arcana plugins <file> shows the decision for a given file.
Plugins from Java
Your application can use plugins in three ways. In each case, the extraction goes through Arcana, so the extraction limits apply.
// 1. Plugin JAR in a plugin directory: detection works as for any archive System.setProperty("arcana.plugins.dir", "D:/myapp/plugins"); // optional, before the first use of Arcana Arcana.extractTo(new File("setup.exe"), new File("out")); // writes out/setup.unpacked.exe // 2. Force a plugin, by id or by extension Arcana.withPlugin("io.github.realburst.upx", null).extract(new File("setup.exe"), new File("out")); Arcana.withPlugin("pak", null).extract(new File("pak0.pak"), new File("out")); // 3. Plugin JAR on the class path of your application: found automatically, // or registered by code (no source check: you chose your dependencies) PluginManager.get().register(new MyPlugin()); // Loaded and refused plugins for (PluginManager.PluginInfo info : PluginManager.get().getPlugins()) System.out.println(info);
Plugins are loaded once, at the first use of Arcana: set arcana.plugins.dir before that.
Known plugins
A plugin is ordinary Java code that runs with the same rights as Arcana and your application. Being listed here is not a security audit. Read the source of a plugin before installing it, download it only from its own repository, and check that the SHA-256 shown by arcana plugins matches the published one.
| Plugin | What it does | Files | Capabilities | Author | License |
|---|---|---|---|---|---|
| The list of known plugins is in plugins.json. | |||||
To have your plugin listed, open an issue titled Plugin: <name> with its name, the URL of its public repository, its id, a one-sentence description, the formats it handles, its capabilities, its author and license, the Arcana version it was tested with, and the link and SHA-256 of its JAR. The plugin stays in your repository and under your control.
Write a plugin
Implement be.stef.arcana.plugin.ArcanaPlugin (and an ArchiveExtractor), declare it in META-INF/services, and package the classes together with their sources. The complete guide, with a working example, is in PLUGIN-API.md.
public final class FooPlugin implements ArcanaPlugin { public String getId() { return "io.github.you.foo"; } public String getName() { return "Foo archive"; } public String getVersion() { return "1.0.0"; } public String getSourceUrl() { return "https://github.com/you/arcana-plugin-foo"; } public String getLicense() { return "Apache-2.0"; } public String[] getExtensions() { return new String[] {"foo"}; } public boolean matches(byte[] header, String fileName) { return header.length >= 4 && header[0] == 'F' && header[1] == 'O' && header[2] == 'O' && header[3] == 0; } public ArchiveExtractor createExtractor(byte[] password) { return new FooExtractor(); } }
In an extractor, always create files with PluginSupport.openOutput(destination, entryName): your plugin then gets the same path checks and extraction limits as the built-in formats.
Safety
An archive is data from someone else. Arcana treats it that way.
- Paths
- Entry names are cleaned before anything is written: no absolute path, no
.., no character forbidden on Windows. An archive cannot write outside the destination directory. - Decompression bombs
- The extracted size is compared to the archive size; extraction stops when the ratio becomes absurd. See extraction limits.
- Disk space
- Extraction stops before the disk is full.
- Damaged data
- Normal extraction stops at the first inconsistency and reports it; only
arcana rkeeps doubtful data, and labels it. - Executables
- Arcana reads executables, it never runs them. The UPX plugin restores the original file without executing any of its code.
- Plugins
- A plugin must ship its source code, and
arcana pluginsshows the SHA-256 of each JAR so you know exactly which binary is loaded.
Building from source
No build tool is needed: only javac and jar from a JDK 8 or later. The version number comes from the VERSION file at the root of the repository.
$ git clone https://github.com/RealBurst/arcana.git $ cd arcana $ ./build.sh all Building Arcana v1.0.0... Done: jar/Arcana-v1.0.0.jar Building arcana-plugin-pak... Done: plugins/arcana-plugin-pak/jar/arcana-plugin-pak.jar Building arcana-plugin-upx... Done: plugins/arcana-plugin-upx/jar/arcana-plugin-upx.jar
On Windows, use build.bat with the same arguments: arcana, plugin-<name> or all. The repository holds Arcana in src/ and one directory per official plugin in plugins/; each of them is also an Eclipse project.
FAQ
Do I need to install anything besides Java?
No. Arcana is a single JAR with no dependency and no native library. Java 8 or any later version is enough.
Can Arcana create RAR archives?
No. RAR 4 and RAR 5 archives can be extracted, including encrypted and multi-volume ones, but not created. Use 7z or ZIP to create archives.
A file has the wrong extension. Will Arcana still open it?
Yes for every format that has a signature: Arcana reads the content first. A ZIP renamed .dat or a Word document is opened as a ZIP. Only LZMA and Brotli streams, which have no signature, need their usual extension, or -f lzma / -f br.
Extraction stops with "Error:" on a damaged archive. How do I get my files back?
Run arcana r on it. It extracts whatever can still be read and tells you, file by file, what is intact and what is not. See Damaged archives.
What are the "[plugins]" lines printed before each command?
They report plugins that were found but refused, with the reason, or the fact that no plugin was found. They are printed on the error output, so they do not end up in a listing you redirect to a file. When every plugin loads correctly, nothing is printed.
Can I use Arcana in a commercial product?
Arcana is under the Apache License 2.0, which allows it, including in closed-source software, provided you keep the license and copyright notices. Plugins have their own license: the UPX plugin, for example, is under the GPL-3.0-or-later. It is a separate JAR that you are free not to ship.
Which Java versions are tested?
Every change is built and tested automatically with Java 8 and Java 21: compression and extraction round trips in every writable format, encrypted ZIP and 7z, and the loading of the official plugins.
Bugs and help
Arcana is young and may still contain bugs, especially with unusual archives. When something goes wrong, open an issue with the command line, the full error message, the Arcana version (arcana version) and, if you can share it, the file or a way to reproduce it.
Pull requests are welcome, and so are plugins: see Write a plugin.