See
--help-hooks for complete documentation and example hooks in the repository.Hook Types
Copyparty supports hooks for various events:Upload Hooks
Execute command before a file upload starts
Execute command after a file upload finishesMost commonly used hook type for notifications and post-processing.
Execute command after all uploads finish and volume is idleUnlike
xbu/xau (which execute for every file), xiu is given a list of recent uploads on STDIN after the server has been idle for N seconds.File Operation Hooks
Execute command before a file copy
Execute command after a file copy
Execute command before a file rename/move
Execute command after a file rename/move
Execute command before a file delete
Execute command after a file delete
Special Hooks
Execute command when a message is received (via
[📟] send-msg tab)Execute command when someone gets banned
Hook Flags
Hooks can have additional flags to modify their behavior:Hook exit code controls the action:
- Exit
0= allow the action, continue to next hook - Exit
100= allow the action, stop running remaining hooks - Any other = reject/prevent the action, don’t run remaining hooks
Send extended upload info as JSON instead of just the filesystem pathJSON includes: file path, uploader IP, username, size, timestamp, etc.
Timeout after N seconds (important for blocking hooks like REQ/PUSH)
Import hook as Python module (140x faster startup, but bugs may crash copyparty)
Hook Arguments
Basic Syntax
Information Passed to Hooks
By default, hooks receive the filesystem path as the first (and only) argument. With thej flag, hooks receive a JSON object on STDIN with:
ZeroMQ Hooks
Instead of running programs, hooks can send ZeroMQ messages:The PUSH and REQ patterns need
t[N] (timeout) because they block if no clients are connected.Example ZeroMQ Receiver
See zmq-recv.py for a complete example.Common Use Cases
Desktop Notifications
Discord Webhook Notifications
Using discord-announce.py:Reject Specific File Types
Using reject-extension.py:Remove EXIF from Images
Using image-noexif.py:Download URLs
Using wget.py:[📟] send-msg tab to download files.
Batch Processing
Using xiu-sha.py:Custom Error Messages
Using reject-and-explain.py:Hook Effects
Some hooks can return special instructions to copyparty:Relocation
Redirect an upload to another destination. Example from reloc-by-ext.py:Indexing
Tell copyparty about additional files to scan. Example from podcast-normalizer.py:Configuration Examples
Per-Volume Hooks
Multiple Hooks
Hooks are additive - you can specify multiple hooks of the same type:Global + Volume Hooks
Conditional Hooks by File Type
Create a wrapper script:check-and-process.sh
Writing Custom Hooks
Basic Template (Shell)
hook-template.sh
Basic Template (Python)
hook-template.py
JSON Input Template (Python)
json-hook-template.py
Check Hook Template
check-hook.py
Performance Considerations
Comparison: Hooks vs MTP Plugins
Copyparty has two systems for running external programs:| Feature | Event Hooks (xau, etc.) | MTP Plugins (mtp) |
|---|---|---|
| Simplicity | Simple, minimal setup | More complex |
| Information | File path (or basic JSON) | Full metadata (tags, codecs, etc.) |
| Blocking | Blocks upload | Non-blocking, multithreaded |
| Trigger | Every upload/action | Only new unique files |
| Pipeline | Single program | Can chain multiple programs |
| Use case | Notifications, simple checks | Metadata extraction, processing |
For complex metadata processing, consider mtp plugins instead of hooks.
Troubleshooting
Hook not executing
Hook not executing
- Check file permissions:
chmod +x /path/to/hook.sh - Verify path is absolute, not relative
- Check server logs for error messages
- Test hook manually:
/path/to/hook.sh /test/file.txt
Hook runs but action still fails
Hook runs but action still fails
For
c (check) hooks:- Exit 0 to allow action
- Exit non-zero to reject action
- Check stderr for error messages
ZeroMQ timeout
ZeroMQ timeout
- Add
t[N]timeout flag for PUSH/REQ patterns - Ensure receiver is running and connected
- Check ZeroMQ port is accessible
Hook crashes copyparty
Hook crashes copyparty
- Remove
I(import) flag - Fix Python syntax errors in hook
- Add error handling to hook script
JSON data not received
JSON data not received
- Add
jflag to hook configuration - Read from stdin, not command-line arguments
- Verify JSON parsing in hook script
Example Repository
See the official hooks directory for complete working examples:- notification hooks
- validation/rejection hooks
- message handlers
- batch processing
- webhook integrations