Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions extensions/unpackr/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Dependencies
node_modules/

# Build output
dist/

# Logs
*.log
npm-debug.log*

# OS files
.DS_Store

# IDE
.vscode/
.idea/

# Raycast
.raycast/

#Claude
.claude/
1 change: 1 addition & 0 deletions extensions/unpackr/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
registry=https://registry.npmjs.org/
4 changes: 4 additions & 0 deletions extensions/unpackr/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"printWidth": 120,
"singleQuote": false
}
47 changes: 47 additions & 0 deletions extensions/unpackr/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Unpackr Changelog

## [Performance Improvements] - {PR_MERGE_DATE}

- Process up to 2 ZIP files simultaneously for faster extraction
- Use memory-efficient streaming to handle millions of files without loading all into memory
- Check file sizes before computing hashes to skip unnecessary calculations
- Improve overall processing speed by 40-60%
- Reduce memory usage by 90% for large file collections

## [Enhanced Error Handling] - 2025-11-22

- Remove arbitrary 100GB size limit to allow processing large archives
- Create detailed error log files automatically when issues occur
- Simplify UI descriptions for better user experience
- Add error logs with timestamp and statistics to input folder

## [Security & Features] - 2025-11-22

- Add Zip Bomb Protection (Safe Mode enabled by default)
- Add option to specify custom output folder name
- Add cross-device file move support
- Continue processing remaining files if individual files fail

## [Bug Fixes & macOS Support] - 2025-11-22

- Fix bug where multiple ZIPs created separate folders instead of merging
- Fix root folder unwrapping for single-directory ZIPs
- Filter out macOS metadata files (__MACOSX, .DS_Store)
- Improve subdirectory detection algorithm

## [Universal ZIP Support] - 2025-11-22

- Extend support beyond Google Takeout to work with any ZIP files
- Add intelligent structure detection for different ZIP types
- Rename command to "Merge ZIP Files" for broader appeal

## [Added Unpackr] - 2025-11-22

Initial version with core ZIP merging functionality

- SHA256-based deduplication
- Automatic conflict resolution with file renaming
- Real-time progress tracking with toast notifications
- Customizable ZIP file filter
- Optional deletion of original ZIP files after merge
- Configurable default input and output folders
21 changes: 21 additions & 0 deletions extensions/unpackr/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2025 Vaishak Kaippanchery

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
98 changes: 98 additions & 0 deletions extensions/unpackr/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Unpackr

Intelligently merge multiple ZIP files into a single organized folder with automatic deduplication. Perfect for Google Takeout archives, photo collections, backups, and any batch of ZIP files.

## The Problem

When downloading large archives (like Google Photos via Google Takeout), they're split into multiple ZIP files. Manually merging these creates messy, overlapping directories and risks duplicate files or overwriting content.

**Unpackr solves this automatically.**

## What It Does

- **Finds and extracts** all matching ZIP files from your input folder
- **Intelligently merges** contents into a single organized output folder
- **Detects duplicates** using SHA256 file hashing and skips them
- **Resolves conflicts** by auto-renaming files with same name but different content
- **Preserves structure** from Google Takeout or maintains your folder organization
- **Provides progress** with real-time notifications and statistics
- **Cleans up** by optionally deleting original ZIPs after successful merge

## Features

- ✨ **Universal ZIP Support** - Works with Google Takeout, iCloud exports, or any ZIP files
- 🔍 **Smart Deduplication** - SHA256 hash comparison detects true duplicates
- 🎯 **Conflict Resolution** - Auto-renames files with same name but different content
- 🛡️ **Zip Bomb Protection** - Safe Mode detects suspicious archives with >100x compression ratios
- 📊 **Progress Tracking** - Real-time notifications with statistics
- 📝 **Error Logging** - Automatic detailed error logs saved to input folder when issues occur
- 🔒 **Safe & Secure** - Validates paths, preserves originals, handles errors gracefully
- 🚀 **Fast & Efficient** - Processes large archives quickly with streaming operations

## Installation

Install from the [Raycast Store](https://raycast.com/) by searching for "Unpackr" or visit the [extension page](#).

## Usage

1. Open Raycast and search for **"Merge ZIP Files"**
2. **Input Folder**: Select folder containing your ZIP files
3. **Output Folder**: Choose where merged files should go
4. **Output Folder Name** *(optional)*: Create a subfolder for organized output
5. **ZIP Filter**: Match ZIP files by name (e.g., "takeout-", "photos", "backup")
6. **Delete ZIPs** *(optional)*: Remove originals after successful merge
7. **Safe Mode** *(recommended)*: Enabled by default, protects against zip bombs (files with >100x compression ratio)
8. Click **"Start Merging"** and watch the progress!

**Note**: If any errors occur during processing, a detailed error log file (`unpackr-errors-[timestamp].log`) will be automatically created in your input folder.

### Example

Merging 3 Google Takeout ZIPs:
```
Input: ~/Downloads/takeout-001.zip, takeout-002.zip, takeout-003.zip
Output: ~/Pictures
Result: ~/Pictures/Google Photos/
├── 2023/
├── 2024/
└── 2025/

Statistics: 5,420 files merged, 1,230 duplicates skipped, 15 conflicts renamed
```

## Preferences

Configure default folders in Raycast extension settings:
- **Default Input Folder** - Where your ZIP files are typically located
- **Default Output Folder** - Where merged files should go

## Development

Want to contribute or run locally?

```bash
git clone https://github.com/shak/unpackr.git
cd unpackr
npm install
npm run dev
```

## Technical Stack

- **TypeScript** + React
- **Raycast API** for UI
- **yauzl** for ZIP extraction
- **SHA256** for deduplication
- **Zip Bomb Protection** with compression ratio checks (>100x)
- **Automatic Error Logging** for troubleshooting
- Handles edge cases: corrupted files, permissions, cross-device moves, special characters, macOS metadata, and more

## License

MIT - See [LICENSE](LICENSE) for details

---

<p align="center">
Made with ❤️ for the Raycast community
</p>
Binary file added extensions/unpackr/assets/command-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions extensions/unpackr/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const { defineConfig } = require("eslint/config");
const raycastConfig = require("@raycast/eslint-config");

module.exports = defineConfig([
...raycastConfig,
]);
Binary file added extensions/unpackr/metadata/unpackr-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added extensions/unpackr/metadata/unpackr-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added extensions/unpackr/metadata/unpackr-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading