{"id":32176443,"url":"https://github.com/moemusic/moe","last_synced_at":"2025-10-21T20:00:02.519Z","repository":{"id":42939195,"uuid":"285353653","full_name":"MoeMusic/Moe","owner":"MoeMusic","description":"The ultimate tool for managing your music.","archived":false,"fork":false,"pushed_at":"2025-08-17T17:42:49.000Z","size":1558,"stargazers_count":94,"open_issues_count":1,"forks_count":4,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-10-21T19:59:54.577Z","etag":null,"topics":["music","music-library","python3"],"latest_commit_sha":null,"homepage":"https://mrmoe.readthedocs.io/","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/MoeMusic.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.rst","contributing":null,"funding":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-08-05T17:01:00.000Z","updated_at":"2025-10-04T05:01:52.000Z","dependencies_parsed_at":"2024-03-02T19:32:23.166Z","dependency_job_id":"91b6111a-73d9-48d0-922e-657fe91ef820","html_url":"https://github.com/MoeMusic/Moe","commit_stats":{"total_commits":633,"total_committers":6,"mean_commits":105.5,"dds":0.1437598736176935,"last_synced_commit":"fdd14c152fe42ccd1702f3280602b0d7407c3db9"},"previous_names":[],"tags_count":65,"template":false,"template_full_name":null,"purl":"pkg:github/MoeMusic/Moe","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MoeMusic%2FMoe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MoeMusic%2FMoe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MoeMusic%2FMoe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MoeMusic%2FMoe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MoeMusic","download_url":"https://codeload.github.com/MoeMusic/Moe/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MoeMusic%2FMoe/sbom","scorecard":{"id":95519,"data":{"date":"2025-08-11","repo":{"name":"github.com/MoeMusic/Moe","commit":"29a246eda1d2faba66c8cb0e4387817813096d54"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.3,"checks":[{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":5,"reason":"Found 10/18 approved changesets -- score normalized to 5","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":10,"reason":"30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:43: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:46: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:49: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:66: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:69: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:86: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:89: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:92: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:106: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/prep_release.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/prep_release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/prep_release.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/prep_release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/preview_docs.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/preview_docs.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:64: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:67: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:79: update your workflow using https://app.stepsecurity.io/secureworkflow/MoeMusic/Moe/release.yml/main?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:27","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:55","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:75","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:98","Warn: pipCommand not pinned by hash: .github/workflows/prep_release.yml:22","Warn: pipCommand not pinned by hash: .github/workflows/release.yml:27","Warn: pipCommand not pinned by hash: .github/workflows/release.yml:73","Info:   0 out of  14 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   6 third-party GitHubAction dependencies pinned","Info:   0 out of   7 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/release.yml:61","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release.yml:16","Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/prep_release.yml:1","Warn: no topLevel permission defined: .github/workflows/release.yml:1"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 25 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-15T08:55:37.726Z","repository_id":42939195,"created_at":"2025-08-15T08:55:37.726Z","updated_at":"2025-08-15T08:55:37.726Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280325298,"owners_count":26311419,"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-10-21T02:00:06.614Z","response_time":58,"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":["music","music-library","python3"],"created_at":"2025-10-21T20:00:00.900Z","updated_at":"2025-10-21T20:00:02.511Z","avatar_url":"https://github.com/MoeMusic.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"###############\nWelcome to Moe!\n###############\nMoe is our resident Music-Organizer-Extraordinaire who's sole purpose is to give you full control over your music library by streamlining the process between downloading/ripping music to your filesystem and listening to it with your favorite music player.\n\nIn short, Moe maintains a database of your music library that can be updated with various metadata sources, queried, edited, etc. through either an API or command-line interface. All of these features, and more, are made available by a highly extensible plugin ecosystem.\n\nBecause all of this functionality is available as a python API which doesn't always require a database of music to operate on, Moe also provides an extensive suite of tools for handling and operating on music files. This can greatly simplify or enhance any other script/program that deals with music.\n\nUsage\n=====\n\nCLI\n---\nMoe comes with a command-line interface which is how most users will take advantage of the library management features. Below is a screenshot of Moe importing an album from the filesystem and adding it to the underlying database all while fixing tags, relocating the files, and anything else you can imagine.\n\n.. image:: _static/import_example.png\n\nOnce added to Moe, querying your library or manipulating your music by editing tags, renaming files, etc. is all just a single command away. The ultimate goal is to automate away any tedius and time-consuming steps you have in your workflow without sacrificing the attention to detail. With the help of an *extremely* flexible plugin system, you can easily fine-tune your music library exactly how you like.\n\nLibrary\n-------\nAs previously mentioned, all of Moe's music management logic and functionality is also available as a python library. As an example, below is a standalone script that takes an album directory and Musicbrainz release ID from the command-line, and then updates the underlying files' tags with any changes from Musicbrainz.\n\n.. code:: python\n\n    #!/usr/bin/env python3\n\n    import argparse\n    from pathlib import Path\n\n    from moe.config import Config, ConfigValidationError\n    from moe.library import Album\n    from moe.write import write_tags\n    import moe.plugins.musicbrainz as moe_mb\n\n    def main():\n        try:\n            Config(config_dir=Path.home() / \".config\" / \"my_script\", init_db=False)\n        except ConfigValidationError as err:\n            raise SystemExit(1) from err\n\n        parser = argparse.ArgumentParser(\n            description=\"Update an album with musicbrainz tags.\"\n        )\n        parser.add_argument(\"path\", help=\"dir of the album to update\")\n        parser.add_argument(\"mb_id\", help=\"musicbrainz id of the album to fetch\")\n        args = parser.parse_args()\n\n        album = Album.from_dir(Path(args.path))\n\n        album.merge(moe_mb.get_album_by_id(args.mb_id), overwrite=True)\n\n        for track in album.tracks:\n            write_tags(track)\n\n\n    if __name__ == \"__main__\":\n        main()\n\nThis is just a small taste of what Moe is capable of and how it can make your life easier when dealing with music.\n\nWhy Moe?\n--------\nWhile powerful music taggers like `beets`_ exist, Moe was developed to address several fundamental, long-standing issues in the music tagging space and aims to provide a more modern and extensible platform for both users and developers.\n\nKey Differentiators\n~~~~~~~~~~~~~~~~~~~\n* **First-Class Support for \"Extras\":** Moe treats \"extra\" files like artwork, booklets, and log files as integral components of an album and manages them as first-class objects in your library.\n* **Multi-Value Tag Support:** Moe supports multi-valued tags, addressing a common limitation in other taggers often restricted to single values or limited multi-value tag support.\n* **Highly Extensible Plugin System:** Moe's plugin system is inspired by pytest, utilizing a powerful hook system. This allows plugins to extend or modify the behavior of Moe's core components and even other plugins, simplifying plugin development and providing lots of customization options. It's extremely easy to create local plugins to complement your configuration, or to publish ones to PyPI for others to use.\n* **Metadata-Source Agnostic:** Metadata sources such as Musicbrainz are implemented as standalone plugins that can be added or removed based on your preferences.\n* **Modern, Maintainable, and Library-First Architecture:**\n\n  * **Library First:** Moe is built as a library before a CLI. This enables easy integration of Moe's logic into other programs and supports the development of alternative user interfaces.\n  * **Modern Tooling:** It leverages mature libraries such as `SQLAlchemy`_ for database management and `pathlib`_ for path handling. This approach greatly reduces the maintenance overhead that comes with hand-rolled solutions for complex issues.\n  * **Contribution Friendly:** A lean core, high test coverage, and modern architecture make Moe approachable for new contributors and make it easy to introduce new changes.\n\n.. _beets: https://github.com/beetbox/beets\n.. _SQLAlchemy: https://www.sqlalchemy.org/\n.. _pathlib: https://docs.python.org/3/library/pathlib.html\n\nIf you want to learn more, check out the `Getting Started \u003chttps://mrmoe.readthedocs.io/en/latest/getting_started.html\u003e`_ docs.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoemusic%2Fmoe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoemusic%2Fmoe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoemusic%2Fmoe/lists"}