We present WinRA, a lightweight archive manager designed exclusively for macOS that brings WinRAR-style functionality to the Apple ecosystem with a modern, native-feeling interface. Built with Python 3.13 and CustomTkinter, WinRA provides three core operations—extract, compress, and convert—for ZIP and RAR archive formats through a sidebar-navigated GUI that follows Apple's Human Interface Guidelines. The application features automatic dark/light mode detection via the darkdetect library, a comprehensive macOS color system with full light and dark palettes, real-time progress tracking with file-level granularity, a Treeview-based archive content inspector, and Finder integration for output navigation. WinRA leverages Python's built-in zipfile module for ZIP operations and the unar/lsar command-line tools for RAR support, enabling format conversion between RAR and ZIP through a temporary extraction pipeline. The application is distributed as a native macOS .app bundle via PyInstaller, with both DMG (drag-and-drop) and PKG (installer) distribution formats generated by a single build script. All archive operations run in background threads to maintain UI responsiveness, and the entire codebase follows a clean MVC separation with dedicated modules for GUI, archive operations, and utility functions.
Archive management on macOS has historically been limited compared to the Windows ecosystem. While Windows users have long relied on tools like WinRAR, 7-Zip, and WinZip for comprehensive archive handling, macOS provides only basic ZIP extraction through the built-in Archive Utility. Users who need RAR support, format conversion, or detailed archive inspection must resort to command-line tools or third-party applications that often feel foreign to the macOS environment.
WinRA addresses this gap by providing a native-feeling macOS application that combines the core functionality of WinRAR—extraction, compression, and format conversion—with a modern GUI that respects Apple's design language. The application is built entirely in Python using CustomTkinter, a modern widget library that extends Tkinter with contemporary styling capabilities including rounded corners, smooth transitions, and system-aware theming.
The key contributions of this work are:
.app, .dmg, and .pkg distribution artifacts from a single script.
The archive management landscape on macOS is dominated by a handful of tools. The built-in Archive Utility handles ZIP creation and extraction but offers no GUI for archive inspection, no RAR support, and no format conversion. The Unarchiver (codename: unar) provides broad format support via command-line tools but lacks a modern GUI. Keka offers a native macOS interface but is primarily focused on compression rather than archive inspection or conversion.
On the GUI framework side, CustomTkinter (Schimansky, 2022) has emerged as a popular choice for building modern-looking desktop applications in Python. Unlike traditional Tkinter, which produces dated-looking interfaces, CustomTkinter provides rounded widgets, system-aware theming, and a flat design aesthetic that aligns with contemporary macOS design. Alternative frameworks like PyQt and wxPython offer more comprehensive widget sets but introduce significant dependency overhead and licensing considerations.
WinRA combines the format breadth of unar with the modern GUI capabilities of CustomTkinter, resulting in an application that feels native to macOS while providing the comprehensive archive management functionality previously available only on Windows through tools like WinRAR.
WinRA follows a clean Model-View-Controller architecture with three dedicated Python modules: gui.py for the user interface, archive_ops.py for archive operations, and utils.py for utility functions. This separation ensures that archive logic remains independent of the GUI layer, facilitating testing and maintenance.
WinRA/
main.py # Application entry point
requirements.txt # Python dependencies
build.sh # Build script (.app, .dmg, .pkg)
build_pkg.sh # PKG installer builder
app/
__init__.py
gui.py # Main GUI (CustomTkinter) — 1,141 lines
archive_ops.py # Archive operations (extract, compress, convert)
utils.py # Utility functions (path handling, format detection)
All three core operations follow a consistent pattern:
self.after() → Completion/Error Dialog
The critical design decision is the use of threading.Thread with daemon=True for all archive operations. This ensures the GUI remains responsive during long-running extractions or compressions. Progress updates are marshaled back to the main thread using Tkinter's self.after(0, callback) mechanism, which schedules UI updates on the next event loop iteration.
WinRA's interface is designed to feel native to macOS, drawing from Apple's Human Interface Guidelines while adapting them to CustomTkinter's widget capabilities.
The application implements a comprehensive dual-mode color system through the MacColors class, which defines both system accent colors (Blue #007AFF, Green #34C759, Purple #AF52DE, Red #FF3B30) and complete light/dark palettes covering backgrounds, text hierarchy, separators, cards, toolbar, inputs, and tags. The initial mode is detected at startup using the darkdetect library, which reads macOS system preferences.
| Token | Light Mode | Dark Mode | Purpose |
|---|---|---|---|
| BG | #F5F5F7 | #1D1D1F | Primary background |
| BG_SECONDARY | #FFFFFF | #2C2C2E | Card backgrounds |
| TEXT_PRIMARY | #1D1D1F | #F5F5F7 | Main text |
| TEXT_SECONDARY | #6E6E73 | #A1A1A6 | Descriptions |
| SIDEBAR_BG | #F0F0F2 | #252528 | Navigation sidebar |
| CARD_BORDER | #E5E5EA | #3A3A3C | Card edges |
The main window (1060×680px, minimum 900×580px) uses a two-column grid layout:
The three operational modes are implemented as soft tabs controlled by sidebar buttons. Each tab configures the UI with mode-specific labels, button colors, toolbar actions, and empty-state messages. The active tab receives a blue highlight (#007AFF) while inactive tabs use transparent backgrounds with hover effects:
| Tab | Primary Action | Button Color | Toolbar Actions |
|---|---|---|---|
| Extract | Extract | Blue (#007AFF) | Open, Extract Here, Info |
| Compress | Create ZIP | Green (#34C759) | Add Files, Add Folder, Clear |
| Convert | Convert | Purple (#AF52DE) | Open Archive, RAR→ZIP, ZIP→RAR |
The dark/light mode switch triggers a comprehensive theme update that refreshes over 25 UI elements including the sidebar, navigation buttons, toolbar, action cards, drop zone, file info labels, output bar, tree card, progress bar, and ttk Treeview styles. This is necessary because CustomTkinter's set_appearance_mode() does not automatically propagate to all custom-configured widgets.
ZIP operations use Python's built-in zipfile module with ZIP_DEFLATED compression. Extraction iterates over archive members with per-file progress callbacks, while compression supports both individual files and recursive directory walking with relative path preservation. The get_archive_info() function parses ZIP metadata including per-file sizes, compressed sizes, and directory flags.
RAR operations delegate to the unar and lsar command-line tools from The Unarchiver project (installable via brew install unar). The lsar -j command provides JSON-formatted archive listings for the content inspector, while unar -o <dest> -f performs extraction. A file-snapshotting approach is used for progress tracking: the destination directory is scanned before and after extraction, with only newly created files counted as extracted.
Tool discovery uses a cascading search strategy: shutil.which() for PATH-based lookup, followed by checks at /opt/homebrew/bin/ (Apple Silicon), /usr/local/bin/ (Intel Homebrew), and /usr/bin/ (system).
Conversion between RAR and ZIP formats is implemented as a two-phase pipeline using a temporary directory:
RAR-to-ZIP conversion extracts via unar and re-compresses with zipfile. ZIP-to-RAR conversion requires the rar command-line tool, which is noted as optional since WinRAR CLI is a proprietary tool. Progress callbacks report approximate percentages (0–50% for extraction, 50–100% for re-compression).
The Treeview-based content inspector displays four columns: Name (with file-type emoji icons), Size (human-readable), Packed (compressed size), and Kind (file extension). The icon mapping covers 30+ file types including documents, images, audio, video, code files, and archives. The inspector uses ttk Treeview with custom styling to match the macOS aesthetic, including selection highlighting in system blue and header styling consistent with the application's color system.
| Extensions | Icon | Category |
|---|---|---|
| 📕 | Document | |
| .jpg, .png, .svg, .webp | 🖼 | Image |
| .py | 🐍 | Python |
| .js | 🟡 | JavaScript |
| .zip, .rar, .gz | 📦 | Archive |
| .dmg | 💿 | Disk Image |
The build.sh script produces three distribution artifacts from a single invocation:
--windowed --onedir) → DMG (hdiutil create) → Code Sign (codesign -s -) → PKG (pkgbuild)
PyInstaller bundles the application with --windowed (no terminal window) and --onedir (directory bundle), collecting all CustomTkinter resources and hidden imports (PIL, rarfile, darkdetect). The DMG is created using macOS's native hdiutil with UDZO compression and includes a symbolic link to /Applications for drag-and-drop installation. Ad-hoc code signing with codesign -s - removes quarantine attributes that would otherwise trigger Gatekeeper warnings.
| Format | File | Installation Method |
|---|---|---|
| .app | dist/WinRA.app | Direct execution |
| .dmg | WinRA.dmg | Drag to Applications |
| .pkg | WinRA.pkg | macOS Installer wizard |
| Package | Version | Purpose |
|---|---|---|
| customtkinter | ≥5.2.0 | Modern Tkinter GUI widgets |
| rarfile | ≥4.0 | RAR archive metadata reading |
| Pillow | ≥10.0 | Image handling for GUI |
| pyinstaller | ≥6.0 | Application bundling |
| darkdetect | (bundled) | System theme detection |
| Requirement | Specification |
|---|---|
| Operating System | macOS 12.0 Monterey or later |
| Architecture | Apple Silicon (M1/M2/M3/M4) and Intel x86_64 |
| Python (development) | 3.13+ |
| RAR support | unar via Homebrew (brew install unar) |
| ZIP support | Built-in (Python zipfile stdlib) |
WinRA demonstrates that Python with CustomTkinter is a viable platform for building native-feeling macOS desktop applications. The combination of CustomTkinter's modern widget styling, darkdetect's system theme integration, and SF Pro typography produces an interface that is visually consistent with native macOS applications while maintaining the rapid development velocity that Python provides.
The threaded architecture ensures UI responsiveness during resource-intensive archive operations, and the clean MVC separation between GUI, operations, and utilities facilitates maintainability. The single-script build pipeline producing .app, .dmg, and .pkg artifacts simplifies distribution to end users.
Future directions include:
py7zr and Python's tarfile module.The complete source code is available at https://github.com/romizone/WinRA under the MIT license.