Skip to main content

A lightweight Python library for creating system tray icons on Windows. (Future versions will add macOS and Linux support.) No heavy GUI dependencies—just simple status indicators, notifications, and menus.

Project description

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():
    print("Tray clicked!")

tray = Tray(icon="icon.ico", tooltip="Hello World")
tray.on_click = on_click  # 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())

Roadmap

See ROADMAP.md for details.

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

crosstray-0.1.0.tar.gz (16.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

crosstray-0.1.0-py3-none-any.whl (10.2 kB view details)

Uploaded Python 3

File details

Details for the file crosstray-0.1.0.tar.gz.

File metadata

  • Download URL: crosstray-0.1.0.tar.gz
  • Upload date:
  • Size: 16.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for crosstray-0.1.0.tar.gz
Algorithm Hash digest
SHA256 faaf18353b424f8ac883b694b221ca57880360e2765e0b428ab0312e77ac4b35
MD5 dfd2a8873a29f7526fc96028cfc103f8
BLAKE2b-256 2485788283401ab18675a417c05f7bd7b129f0f331becde7883a467f4fd2d07f

See more details on using hashes here.

File details

Details for the file crosstray-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: crosstray-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for crosstray-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 63e04bfae7117ee01f5fc0ba66b450459296de5850ec4093a57bee962c02ab7a
MD5 e8bcfbd165fa6e746d1eeeb45bd7d556
BLAKE2b-256 3e758bd2ae16fed5d9abb26d339893da066d8cbb23dc08b157ee54fe3db5206c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page