CrossTray
A lightweight, unified Python library for creating system tray/menu bar icons across Windows, macOS, and Linux. No heavy GUI dependencies—just pure Python simplicity for status indicators, notifications, and menus.
Why CrossTray?
- Cross-Platform Magic: Handles OS-specific quirks automatically (e.g., Windows notification area, macOS menu bar, Linux systray).
- Minimal Footprint: Dependency-free core (uses stdlib where possible, optional extras for icons/notifications).
- Easy API: Object-oriented and chainable, inspired by
pathlibfor intuitive use. - Async-Friendly: Supports asyncio for real-time updates without blocking.
Perfect for building desktop utilities like monitors, trackers, or background apps.
Installation
pip install crosstray
Quick Start
from crosstray import Tray
tray = Tray(icon="path/to/icon.png", title="My App")
tray.add_menu_item("Quit", lambda: tray.quit())
tray.run()
For more examples, see Usage.
Features
- Create tray icons with custom images or text fallbacks.
- Build nested menus with callbacks.
- Show balloon notifications/toasts.
- Dynamic updates (e.g., change icon or menu on the fly).
- Event loop integration for async apps.
- Error handling for unsupported platforms.
Usage
Basic Tray Icon
from crosstray import Tray
def on_click(tray: ct.Tray):
tray.send_notification("Tray Clicked", "You clicked the tray icon!", icon="file.ico", timeout=9000)
tray = Tray(icon="icon.ico", tooltip="Hello World")
tray.on_click = tray.on_click = lambda: on_click(tray) # Or use tray.add_action("Click", on_click)
tray.run() # Blocks until quit
With Menu
from crosstray import Tray, MenuItem
tray = Tray(title="Status Monitor")
menu = tray.menu
menu.add_item(MenuItem("Refresh", lambda: print("Refreshing...")))
menu.add_separator()
submenu = menu.add_submenu("Settings")
submenu.add_item(MenuItem("Option 1", lambda: print("Selected 1")))
menu.add_item(MenuItem("Quit", tray.quit))
tray.run()
Async Example
import asyncio
from crosstray import Tray
async def main():
tray = Tray(icon="icon.png")
tray.add_menu_item("Update", lambda: print("Updating"))
# Simulate real-time update
async def updater():
while True:
tray.tooltip = f"Time: {asyncio.get_event_loop().time()}"
await asyncio.sleep(1)
asyncio.create_task(updater())
await tray.run_async() # Non-blocking
asyncio.run(main())
Contributing
Contributions welcome! Fork the repo, create a branch, and submit a PR. See CONTRIBUTING.md for guidelines.
License
MIT License. See LICENSE for details.
Built with ❤️ by Uman Sheikh. Inspired by community needs for simpler desktop tools.
Metadata
Release files for crosstray 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| crosstray-0.1.1.tar.gz | 17.1 kB | Without provenance | Details for crosstray-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| crosstray-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for crosstray-0.1.1-py3-none-any.whl |
Total release size: 27.7 kB
Release files / crosstray-0.1.1.tar.gz
| Download URL | crosstray-0.1.1.tar.gz |
|---|---|
| Size | 17.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
52f20acf83534907aebaf6fb3fa78a66e35ab35584411bb6c5c398e9c1944638
|
|
BLAKE2b-256 checksum How to use checksums |
0979f887ec7a8bdbefb23d3e04fcb71fdc169f1ab52587e2b119ef256f349d4e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.1
|
Release files / crosstray-0.1.1-py3-none-any.whl
| Download URL | crosstray-0.1.1-py3-none-any.whl |
|---|---|
| Size | 10.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
71246a63bca4e5b0fad445b563bff14e5ccff56b26b9bf496a28f1b3458c4c84
|
|
BLAKE2b-256 checksum How to use checksums |
bc16cacab56059ed7f7d148b877205c60c623e7a06660da580ecc24ef3b6415c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.1
|
Security for crosstray 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.