Skip to main content

CrossTray

PyPI version License: MIT Python versions

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 pathlib for 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)

Source distribution for crosstray 0.1.1
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)

Table of built distributions (wheels) for crosstray 0.1.1
File Interpreter ABI Platform Actions
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.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page