- OCaml 99.7%
- Dune 0.3%
| .github/workflows | Initial commit | |
| bin | Initial commit | |
| lib | Initial commit | |
| man | Initial commit | |
| test | Initial commit | |
| .gitignore | Initial commit | |
| CHANGES.md | Initial commit | |
| dune-project | Initial commit | |
| LICENSE | Initial commit | |
| README.md | Initial commit | |
chex
Convert a Threema iOS chat export into a self-contained HTML archive.
Table of contents
- Overview
- Features
- License
- Quick start
- Installation
- Locales
- Exit codes
- Exporting a chat
- Limitations
- About the format
- Contributing
Overview
chex converts a decrypted Threema iOS chat export into a portable
semantic HTML archive.
The generated archive consists of:
index.html— complete conversation in chronological order, with all CSS inlined and no external dependencies.media/— copies of media files found in the export.
The output renders correctly in any modern web browser without requiring JavaScript, network access, or additional assets.
Features
- renders text messages
- renders images, video, audio and file attachments
- renders quoted messages
- renders locations
- renders polls
- explicitly reports files referenced by the export but missing from the directory instead of silently omitting them
Supported locales:
Bulgarian, Czech, German, English, Spanish, French, Swiss German, Italian, Japanese, Korean, Dutch, Polish, Brazilian Portuguese, Slovak, Turkish, Ukrainian, Simplified Chinese and Traditional Chinese.
Supported platforms:
- Linux
- macOS
- Windows
Native executable. No runtime or external dependencies required.
License
ISC. See LICENSE.
chex is not affiliated with or endorsed by
Threema.
Threema is a registered trademark of Threema GmbH.
Quick start
- Export a chat from Threema.
- Install
chex. - Run:
chex Threema_Export_20260630
Unless --output is specified, chex creates the output directory next
to the input directory:
~/Threema_Export_20260630
~/Threema_Export_20260630-chex-output
Finally, open index.html in any browser installed on your device.
NOTE: Very large exports (tens of thousands of messages) produce a correspondingly large index.html. Browser rendering performance may degrade for exports spanning many years of active conversation.
Installation
Linux (x86_64)
Using curl:
curl -L \
https://codeberg.org/duras/chex/releases/download/v0.1.0/chex-linux-x86_64 \
-o ~/.local/bin/chex &&
chmod +x ~/.local/bin/chex
Using wget:
wget -O ~/.local/bin/chex \
https://codeberg.org/duras/chex/releases/download/v0.1.0/chex-linux-x86_64 &&
chmod +x ~/.local/bin/chex
macOS (Apple Silicon)
curl -L \
https://codeberg.org/duras/chex/releases/download/v0.1.0/chex-macos-arm64 \
-o /usr/local/bin/chex &&
chmod +x /usr/local/bin/chex
If macOS blocks the unsigned executable:
xattr -d com.apple.quarantine /usr/local/bin/chex
Verify (Linux & macOS)
chex --version
If ~/.local/bin is not in your PATH, add this to your shell
configuration file (~/.bashrc, ~/.zshrc, etc.):
export PATH="$HOME/.local/bin:$PATH"
Windows (x86_64)
-
Download chex-windows-x86_64.exe
-
Rename it to
chex.exeand move it to a folder of your choice, for exampleC:\Tools\chex.exe. -
Add that folder to your PATH:
- Open Start, search for "environment variables", and open "Edit the system environment variables"
- Click Environment Variables
- Under User variables, select Path and click Edit
- Click New and enter
C:\Tools - Click OK on all dialogs
-
Open a new PowerShell or Command Prompt window and verify:
chex --version
Locales
chex normally detects the export locale automatically. If detection
fails, it exits with code 3.
List supported locales:
chex --list-locales
Specify the locale explicitly:
chex --locale de ~/Exports/Threema_Chat
See man page man chex for the complete command-line reference.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success. Prints chex: wrote {output_dir}/index.html. |
| 1 | Invalid or missing command-line arguments. |
| 2 | Invalid input (not a directory, missing messages.txt, invalid UTF-8). |
| 3 | Locale detection failed. Rerun with --locale. |
| 4 | Output error (cannot create the output directory or write index.html). |
Exporting a chat
The Threema iOS app can export an individual conversation (direct or group chat) as an encrypted ZIP archive.
This is not a full account backup. Full iOS backups use the device-to-device Rendezvous protocol.
The export is initiated from within a conversation via the share/export action. The user optionally includes media files.
The user is prompted to set a password. The resulting ZIP is AES-encrypted with that password.
Before running chex, decrypt the exported ZIP. Decryption is the
user's responsibility before any programmatic processing.
After decryption:
- all files are located in the archive root
messages.txtis always present- media files are present only when exported with media
Limitations
The completeness of the generated archive is limited by the information contained in the Threema iOS app export format.
messages.txt is not a structured data format. It is localized
human-readable text whose exact syntax depends entirely on the iOS
locale used during export, including:
- month names
- word order
- connecting words
- 12-hour versus 24-hour time
The export also lacks important metadata:
- locale identifier
- export format version
- conversation name
- participant list
- Threema IDs (only display names are present)
Attachments are identified only by the generic -file- filename
pattern. Images, video, audio, documents, contacts and other attachment
types cannot be distinguished from filenames alone.
The export format does not contain:
- emoji reactions
- GIF messages
- poll votes (questions and choices are preserved)
- message edit history
- deleted-message markers
- participant Threema IDs
About the format
Threema has not published a specification for either the encrypted ZIP
export format or messages.txt, and has confirmed they have no plans to
publish any. The format implemented by chex has been reconstructed
from observed exports and from the published source code of the
Threema App for iOS (AGPLv3).
Contributing
Bug reports: Codeberg issues.
Pull requests are welcome. A PR should pass dune test.