{"id":25439966,"url":"https://github.com/skaplanofficial/pyxa","last_synced_at":"2025-08-02T07:33:21.960Z","repository":{"id":37688726,"uuid":"499702414","full_name":"SKaplanOfficial/PyXA","owner":"SKaplanOfficial","description":"Python for Automation","archived":false,"fork":false,"pushed_at":"2025-07-15T11:25:26.000Z","size":16585,"stargazers_count":143,"open_issues_count":6,"forks_count":6,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-07-25T05:17:50.195Z","etag":null,"topics":["applescript","automation","jxa","mac","macos","pyobjc","python"],"latest_commit_sha":null,"homepage":"https://skaplanofficial.github.io/PyXA/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SKaplanOfficial.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"SKaplanOfficial","custom":["https://www.paypal.com/donate/?hosted_button_id=2XFX5UXXR8M6J"]}},"created_at":"2022-06-04T02:18:43.000Z","updated_at":"2025-07-20T07:48:48.000Z","dependencies_parsed_at":"2023-02-02T03:16:24.065Z","dependency_job_id":"5812e008-b7b9-492f-aa79-42b800b149e8","html_url":"https://github.com/SKaplanOfficial/PyXA","commit_stats":{"total_commits":229,"total_committers":2,"mean_commits":114.5,"dds":"0.013100436681222738","last_synced_commit":"11c7d4db4623b91415bd962d41ff3747a2808163"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/SKaplanOfficial/PyXA","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SKaplanOfficial%2FPyXA","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SKaplanOfficial%2FPyXA/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SKaplanOfficial%2FPyXA/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SKaplanOfficial%2FPyXA/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SKaplanOfficial","download_url":"https://codeload.github.com/SKaplanOfficial/PyXA/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SKaplanOfficial%2FPyXA/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268348651,"owners_count":24236298,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["applescript","automation","jxa","mac","macos","pyobjc","python"],"created_at":"2025-02-17T11:18:37.848Z","updated_at":"2025-08-02T07:33:21.917Z","avatar_url":"https://github.com/SKaplanOfficial.png","language":"Python","funding_links":["https://github.com/sponsors/SKaplanOfficial","https://www.paypal.com/donate/?hosted_button_id=2XFX5UXXR8M6J"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/SKaplanOfficial/PyXA/main/docs/_static/assets/PyXALogoTransparent.png\" alt=\"The dark logo for PyXA\" height=\"250px\"\u003e\u003c/p\u003e\n\n# Python for Automation\nPython for Automation, or PyXA for short, is a wrapper around several macOS frameworks that enables AppleScript- and JXA-like control over macOS applications from within Python. PyXA's objects and methods are based on applications' scripting dictionaries and coupled with additional automation features supported by Apple's macOS APIs. \n\nPyXA was created with the goals of:\n1. Simplifying the way automation tasks can be accomplished via Python\n2. Introducing new features to macOS application scripting by simplifying complex procedures into simple, declarative methods\n3. Disambiguating the capabilities of application scripting on macOS by providing easy-to-follow documentation throughout the entire project\n\nPyXA fills a gap where currently available frameworks ultimately fall short: it aims to be easy to learn for users accustomed to Python (or users who _must_ use Python). To that end, the package's documentation contains numerous examples of how to use just about every method, and additional examples are provided covering specific use cases. PyXA's code also serves as a source of examples for how to use [PyObjC](https://pyobjc.readthedocs.io/en/latest/) to interact with various macOS frameworks.\n\nPyXA is not intended to replace AppleScript or even to cover 100% of AppleScript's capabilities. Instead, PyXA is meant to provide general convenience in accomplishing AppleScript and other automation tasks via Python, for the most commonly used applications. If you need a complete Apple Event bridge, or if you find that PyXA cannot handle your particular use case, consider using [appscript](https://appscript.sourceforge.io) or one of its derivatives. If you just need something that works in most circumstances, that has abundant examples for you to reference, and supports some additional automation features (such as opening Maps to a specific address), then PyXA might be a good fit for you.\n\n# Feature Overview\n- Support for most AppleScript commands in built-in macOS applications and some third-party applications (in progress)\n- Scripting capabilities for several non-scriptable applications by using APIs, URI schemes, and other methods\n- Support for direct operations on non-scriptable applications (e.g. `PyXA.application(\"Maps\").front_window.collapse()`)\n- Command Chaining similar to JXA (e.g. `PyXA.application(\"Reminders\").lists()[0].reminders().title()`)\n- Properties of scriptable elements accessible via object attributes (e.g. `note.name`, `tab.URL`, or `track.artist`)\n- Support for UI scripting of non-scriptable applications\n- Fast enumeration of scriptable objects\n- Automatic translation of clipboard items to PyXA objects\n- Support for compiling and executing AppleScript scripts via NSAppleScript\n- Full access to and control over the system clipboard\n- Support for dialogs, alerts, file/color pickers, and notifications\n- Classes for speech and speech recognition\n- Ability to create custom menu bar items\n\n# Some Examples\n## Example 1: Open a URL in Safari and print the loaded page.\nPyXA can control Safari and interact with its content. In this example, we use PyXA to obtain a reference to the Safari application, open a specific URL, then bring up the print dialog for the loaded page. If we wanted, we could pass additional parameters to the print() method to skip the print dialog and immediately print the page without any user interaction. \n```python\nimport PyXA\nfrom time import sleep\nsafari = PyXA.Safari()\nsafari.open(\"https://www.apple.com\")\nsleep(1)\nsafari.current_document.print()\n```\n\n## Example 2: Print Music track info whenever the track changes.\nPyXA can also be used to interact with the Music app. In this example, we use PyXA to get a reference to the Music app, begin playback of the next-up song, then repeatedly print out some information about the track whenever the current track changes. The information will be printed regardless of *how* the track changes, so you can test this script by running it and skipping to the next song. \n```python\nimport PyXA\nfrom time import sleep\nmusic = PyXA.Application(\"Music\")\n\n# Wait for Music.app to be ready to play\nmusic.activate()\nwhile not music.frontmost:\n    sleep(0.5)\nmusic.play()\n\ntrack_name = \"\"\nwhile True:\n    if music.current_track.name != track_name:\n        track_name = music.current_track.name\n        print(music.current_track.name)\n        print(music.current_track.album)\n        print(music.current_track.artist, \"\\n\")\n```\nWhen run, this script produces an output similar to the following:\n```\nDie Hard\nMr. Morale \u0026 The Big Steppers\nKendrick Lamar, Blxst \u0026 Amanda Reifer \n\nI Like You (A Happier Song) [feat. Doja Cat]\nTwelve Carat Toothache\nPost Malone \n\nWAIT FOR U (feat. Drake \u0026 Tems)\nI NEVER LIKED YOU\nFuture\n\n...\n```\n\n## Example 3: Create a new note with a list of all events and reminders for the day.\nPyXA can also be used for more complex tasks. In this example, we use PyXA to get a summary of upcoming reminders and events for the day. We obtain references to the Notes, Calendars, and Reminders applications, then we iterate through our reminders and events, creating a new line of text to summarize each item due today. We apply some HTML formatting to the note to make it look nice, then we create a new note containing the summarized content.\n```python\nimport PyXA\nfrom datetime import datetime, timedelta\n\n# Activate Reminders to speed up communication of Apple Events\nreminders = PyXA.Application(\"Reminders\").activate()\nnotes = PyXA.Application(\"Notes\")\ncalendar = PyXA.Application(\"Calendar\")\n\n# Get names of incomplete Reminders using a bulk method\nnames = reminders.reminders({ \"completed\": False }).name()\n\n# Create a string listing incomplete reminders\nnote_text = \"-- Reminders --\"\nfor name in names:\n    note_text += f\"\u003cbr /\u003eReminder: {name}\"\n\n# Get Calendar events starting within the next 2 days\nstart = datetime.now()\nevents = calendar.calendars().events().between(\"startDate\", start, start + timedelta(days=2))\n\n# Get event summaries (titles), start dates, and end dates using bulk methods\nsummaries = events.summary()\nstart_dates = events.start_date()\nend_dates = events.end_date()\n\n# Append the list of event information to the note text\nnote_text += \"\u003cbr/\u003e\u003cbr /\u003e-- Events --\"\nfor index, summary in enumerate(summaries):\n    note_text += \"\u003cbr /\u003eEvent: \" + summary + \", from \" + str(start_dates[index]) + \" to \" + str(end_dates[index])\n\n# Create and show the note\nnote = notes.new_note(f\"\u003ch1\u003eAgenda for {start.strftime('%Y-%m-%d')}\u003c/h1\u003e\", note_text)\nnote.show()\n```\nWhen run, the above script creates a note in the Notes application similar to the following:\n\n![A note in the Notes app showing a summary of reminders and events for the day](https://raw.githubusercontent.com/SKaplanOfficial/PyXA/main/docs/_static/assets/Example3_Notes.png)\n\n## Example 4: Copy your last sent file in iMessage to the clipboard\nLastly, PyXA has several convenient features for working with lists, interacting with the clipboard, and more soon to come. The example below highlights the simplicity of filtering lists of scriptable objects and setting the content of the clipboard. The filter method of PyXA's :class:`XABase.XAList` class enables straightforward construction of predicates to efficiently filter lists by. The content property of the :class:`XABase.XAClipboard` class can be set to both literal values and PyXA objects, allowing for concise scripts like the one below.\n\n```python\nimport PyXA\napp = PyXA.Application(\"Messages\")\nlast_file_transfer = app.file_transfers().filter(\"direction\", \"==\", app.MessageDirection.OUTGOING)[-1]\nPyXA.XAClipboard().content = last_file_transfer\n```\n\n# Installation\nTo install the latest version of PyXA on macOS, use the following pip command:\n```\npython -m pip install mac-pyxa\n```\n\n# Documentation\nThe best way to learn about PyXA is to read the [documentation](http://skaplanofficial.github.io/PyXA/). From there, you can find tutorials, examples, in-depth class and method documentation, and additional resources.\n\nFor further help, consider joining the (PyXA Discord Server](https://discord.gg/Crypg65dxK) and asking your questions there.\n\n# Known Limitations\n- Currently, PyXA only supports macOS automation. There is a goal to expand support to other operating systems, but no concrete plan exists at this time.\n- Since PyXA uses hard-coded class and method definitions, instead of deriving them automatically from existing sdef files, support for third-party applications is limited to the applications that contributors deem relevant. This is a sacrifice made in order to have detailed, consistent documentation for all supported applications.\n\nLimitations of specific applications and methods are noted in their respective reference documents.\n\n# Contributing\nContributions are welcome, big or small. Please refer to the [Contributing Guidelines](./CONTRIBUTING.md) for any contributions larger than a spelling correction. For small fixes such as spelling corrections, no issue needs to be created; you can go right to making a pull request. Other small issues include general grammar fixes, short comment additions, and formatting (whitespace) changes.\n\n# Contact\nIf you have any questions about PyXA that are not addressed in the documentation, or if you just want to talk, feel free to email [stephen.kaplan@maine.edu](mailto:stephen.kaplan@maine.edu).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskaplanofficial%2Fpyxa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskaplanofficial%2Fpyxa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskaplanofficial%2Fpyxa/lists"}