{"id":37063054,"url":"https://github.com/texzk/hexrec","last_synced_at":"2026-01-14T07:02:02.218Z","repository":{"id":45573327,"uuid":"138935502","full_name":"TexZK/hexrec","owner":"TexZK","description":"Library to handle hexadecimal record files","archived":false,"fork":false,"pushed_at":"2025-07-25T21:51:28.000Z","size":1390,"stargazers_count":20,"open_issues_count":2,"forks_count":5,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-11-29T10:15:35.458Z","etag":null,"topics":["binary-data","data-convertion","file-merge","hex","hex-viewer","hexadecimal","hexadecimal-dump","hexdump","hexdumper","intel","intel-hex","motorola","motorola-srecord","records","sparse-data","srec","srecord","srecord-files","virtual-memory","xxd"],"latest_commit_sha":null,"homepage":"https://hexrec.readthedocs.io/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TexZK.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.rst","contributing":"CONTRIBUTING.rst","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":"AUTHORS.rst","dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-06-27T21:37:38.000Z","updated_at":"2025-09-11T09:13:47.000Z","dependencies_parsed_at":"2023-12-15T21:12:11.659Z","dependency_job_id":"234ab7fd-95f3-408f-84b2-22612ff15444","html_url":"https://github.com/TexZK/hexrec","commit_stats":{"total_commits":213,"total_committers":1,"mean_commits":213.0,"dds":0.0,"last_synced_commit":"bba1f7ebeb397b879fcc2bc8b3cda92950dfd8c1"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/TexZK/hexrec","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TexZK%2Fhexrec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TexZK%2Fhexrec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TexZK%2Fhexrec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TexZK%2Fhexrec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TexZK","download_url":"https://codeload.github.com/TexZK/hexrec/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TexZK%2Fhexrec/sbom","scorecard":{"id":139492,"data":{"date":"2025-08-11","repo":{"name":"github.com/TexZK/hexrec","commit":"faee7b76f8d67aafc0fa90b0c3e9004395caafbb"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.3,"checks":[{"name":"Maintained","score":10,"reason":"10 commit(s) and 2 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":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","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":"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":"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":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/packaging.yml:1","Info: no jobLevel write permissions found"],"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":"Binary-Artifacts","score":9,"reason":"binaries present in source code","details":["Warn: binary detected: tests/test_readme/appelf.elf:1"],"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":"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":"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:34: update your workflow using https://app.stepsecurity.io/secureworkflow/TexZK/hexrec/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/TexZK/hexrec/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/TexZK/hexrec/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:57: update your workflow using https://app.stepsecurity.io/secureworkflow/TexZK/hexrec/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/packaging.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/TexZK/hexrec/packaging.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/packaging.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/TexZK/hexrec/packaging.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/packaging.yml:45: update your workflow using https://app.stepsecurity.io/secureworkflow/TexZK/hexrec/packaging.yml/main?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:43","Warn: pipCommand not pinned by hash: .github/workflows/packaging.yml:37","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   2 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":"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":"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: BSD 2-Clause \"Simplified\" 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":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"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":"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"}}]},"last_synced_at":"2025-08-16T07:36:45.611Z","repository_id":45573327,"created_at":"2025-08-16T07:36:45.611Z","updated_at":"2025-08-16T07:36:45.611Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28412486,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T05:26:33.345Z","status":"ssl_error","status_checked_at":"2026-01-14T05:21:57.251Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["binary-data","data-convertion","file-merge","hex","hex-viewer","hexadecimal","hexadecimal-dump","hexdump","hexdumper","intel","intel-hex","motorola","motorola-srecord","records","sparse-data","srec","srecord","srecord-files","virtual-memory","xxd"],"created_at":"2026-01-14T07:02:01.408Z","updated_at":"2026-01-14T07:02:02.212Z","avatar_url":"https://github.com/TexZK.png","language":"Python","readme":"********\nOverview\n********\n\n.. start-badges\n\n.. list-table::\n    :stub-columns: 1\n\n    * - docs\n      - |docs|\n    * - tests\n      - | |gh_actions|\n        | |codecov|\n    * - package\n      - | |version| |wheel|\n        | |supported-versions|\n        | |supported-implementations|\n\n.. |docs| image:: https://app.readthedocs.org/projects/hexrec/badge/?style=flat\n    :target: https://app.readthedocs.org/projects/hexrec\n    :alt: Documentation Status\n\n.. |gh_actions| image:: https://github.com/TexZK/hexrec/workflows/CI/badge.svg\n    :alt: GitHub Actions Status\n    :target: https://github.com/TexZK/hexrec\n\n.. |codecov| image:: https://codecov.io/gh/TexZK/hexrec/branch/main/graphs/badge.svg?branch=main\n    :alt: Coverage Status\n    :target: https://app.codecov.io/github/TexZK/hexrec\n\n.. |version| image:: https://img.shields.io/pypi/v/hexrec.svg\n    :alt: PyPI Package latest release\n    :target: https://pypi.org/project/hexrec/\n\n.. |wheel| image:: https://img.shields.io/pypi/wheel/hexrec.svg\n    :alt: PyPI Wheel\n    :target: https://pypi.org/project/hexrec/\n\n.. |supported-versions| image:: https://img.shields.io/pypi/pyversions/hexrec.svg\n    :alt: Supported versions\n    :target: https://pypi.org/project/hexrec/\n\n.. |supported-implementations| image:: https://img.shields.io/pypi/implementation/hexrec.svg\n    :alt: Supported implementations\n    :target: https://pypi.org/project/hexrec/\n\n.. end-badges\n\n\nLibrary to handle hexadecimal record files\n\n* Free software: BSD 2-Clause License\n\n\nIntroduction\n============\n\nThe purpose of this library is to provide simple but useful methods to load,\nedit, and save hexadecimal record files.\n\nIn the field of embedded systems, hexadecimal record files are the most common\nway to share binary data to be written to the target non-volatile memory, such\nas a EEPROM or microcontroller code flash.\nSuch binary data can contain compiled executable code, configuration data,\nvolatile memory dumps, etc.\n\nThe most common file formats for hexadecimal record files are *Intel HEX*\n(.hex) and *Motorola S-record* (.srec).\nOther common formats for binary data exchange for embedded systems include the\n*Executable and Linkable Format* (.elf), hex dumps (by *hexdump* or *xxd*),\nand raw binary files (.bin).\n\nA good thing about hexadecimal record files is that they are almost *de-facto*,\nso every time a supplier has to give away its binary data it is either in HEX\nor SREC, although ELF is arguably the most common for debuggable executables.\n\nA bad thing is that their support in embedded software toolsets is sometimes\nflawed or only one of the formats is supported, while the supplier provides its\nbinary data in the other format.\n\nAnother feature is that binary data is split into text record lines (thus their\nname) protected by some kind of checksum. This is good for data exchange and\nline-by-line writing to the target memory (in the old days), but this makes\nin-place editing by humans rather tedious as data should be split, and the\nchecksum and other metadata have to be updated.\n\nAll of the above led to the development of this library, which allows to,\nfor example:\n\n* convert between hexadecimal record formats;\n* merge/patch multiple hexadecimal record files of different formats;\n* access every single record of a hexadecimal record file;\n* build records through handy methods;\n* edit sparse data in a virtual memory behaving like a ``bytearray``;\n* extract or update only some parts of the binary data.\n\n\nDocumentation\n=============\n\nFor the full documentation, please refer to:\n\nhttps://hexrec.readthedocs.io/en/latest/\n\n\nArchitecture\n============\n\nWithin the ``hexrec`` package itself are the symbols of the most commonly used\nclasses and functions.\n\nAs the core of this library are record files, the ``hexrec.base`` is the\nfirst module a user should look up.\nIt provides high-level functions to deal with record files, as well as classes\nholding record data.\n\nThe ``hexrec.base`` allows to load ``bytesparse`` virtual memories, which\nare as easy to use as the native ``bytearray``, but with sparse data blocks.\n\nThe ``hexrec.utils`` module provides some miscellaneous utility stuff.\n\n``hexrec.xxd`` is an emulation of the ``xxd`` command line utility delivered\nby ``vim``.\n\nThe package can also be run as a command line tool, by running the ``hexrec``\npackage itself (``python -m hexrec``), providing some record file  utilities.\n\nThe codebase is written in a simple fashion, to be easily readable and\nmaintainable, following some naive pythonic *K.I.S.S.* approach by choice.\n\n\nExamples\n========\n\nTo have a glimpse of the features provided by this library, some simple but\ncommon examples are shown in the following.\n\n\nConvert format\n--------------\n\nIt happens that some software tool only supports some hexadecimal record file\nformats, or the format given to you is not handled properly, or simply you\nprefer a format against another (*e.g.* SREC has *linear* addressing, while HEX\nis in a *segment:offset* fashion).\n\nIn this example, a HEX file is converted to SREC.\n\n.. code-block:: python3\n\n    from hexrec import convert\n\n    convert('data.hex', 'data.srec')\n\nThis can also be done by running `hexrec` as a command line tool:\n\n.. code-block:: sh\n\n    $ hexrec convert data.hex data.srec\n\nAlternatively, by executing the package itself:\n\n.. code-block:: sh\n\n    $ python -m hexrec convert data.hex data.srec\n\n\nMerge files\n-----------\n\nIt is very common that the board factory prefers to receive a single file to\nprogram the microcontroller, because a single file is simpler to manage for\nthem, and might be faster for their workers or machine, where every second\ncounts.\n\nThis example shows how to merge a bootloader, an executable, and some\nconfiguration data into a single file, in the order they are listed.\n\n.. code-block:: python3\n\n    from hexrec import merge\n\n    in_paths = ['bootloader.hex', 'executable.mot', 'configuration.xtek']\n    out_path = 'merged.srec'\n    merge(in_paths, out_path)\n\nAlternatively, these files can be merged via manual load:\n\n.. code-block:: python3\n\n    from hexrec import load, SrecFile\n\n    in_paths = ['bootloader.hex', 'executable.mot', 'configuration.xtek']\n    in_files = [load(path) for path in in_paths]\n    out_file = SrecFile().merge(*in_files)\n    out_file.save('merged.srec')\n\nThis can also be accomplished by running the `hexrec` package itself as a\ncommand line tool:\n\n.. code-block:: sh\n\n    $ hexrec merge bootloader.hex executable.mot configuration.xtek merged.srec\n\n\nDataset generator\n-----------------\n\nLet us suppose we are early in the development of the embedded system and we\nneed to test the current executable with some data stored in EEPROM.\nWe lack the software tool to generate such data, and even worse we need to test\n100 configurations.\nFor the sake of simplicity, the data structure consists of 4096 random values\n(0 to 1) of ``float`` type, stored in little-endian at the address\n``0xDA7A0000``.\n\n.. code-block:: python3\n\n    import struct, random\n    from hexrec import SrecFile\n\n    for index in range(100):\n        values = [random.random() for _ in range(4096)]\n        data = struct.pack('\u003c4096f', *values)\n        file = SrecFile.from_bytes(data, offset=0xDA7A0000)\n        file.save(f'dataset_{index:02d}.mot')\n\n\nWrite a CRC\n-----------\n\nUsually, the executable or the configuration data of an embedded system are\nprotected by a CRC, so that their integrity can be self-checked.\n\nLet us suppose that for some reason the compiler does not calculate such CRC\nthe expected way, and we prefer to do it with a script.\n\nThis example shows how to load a HEX file, compute a CRC32 from the address\n``0x1000`` to ``0x3FFB`` (``0x3FFC`` exclusive), and write the calculated CRC\nto ``0x3FFC`` in big-endian as a SREC file.\nThe rest of the data is left untouched.\n\n.. code-block:: python3\n\n    import binascii, struct\n    from hexrec import load\n\n    file = load('checkme.srec')\n\n    with file.view(0x1000, 0x3FFC) as view:\n        crc = binascii.crc32(view) \u0026 0xFFFFFFFF  # remove sign\n\n    file.write(0x3FFC, struct.pack('\u003eL', crc))\n    file.save('checkme_crc.srec')\n\n\nTrim for bootloader\n-------------------\n\nWhen using a bootloader, it is very important that the application being\nwritten does not overlap with the bootloader.  Sometimes the compiler still\ngenerates stuff like a default interrupt table which should reside in the\nbootloader, and we need to get rid of it, as well as everything outside the\naddress range allocated for the application itself.\n\nThis example shows how to trim the application executable record file to the\nallocated address range ``0x8000``-``0x1FFFF``.  Being written to a flash\nmemory, unused memory byte cells default to ``0xFF``.\n\n.. code-block:: python3\n\n    from hexrec import load, SrecFile\n\n    in_file = load('application.mot')\n    data = in_file.read(0x8000, 0x1FFFF+1, fill=0xFF)\n\n    out_file = SrecFile.from_bytes(data, offset=0x8000)\n    out_file.save('app_trimmed.mot')\n\nThis can also be done by running the `hexrec` package as a command line tool:\n\n.. code-block:: sh\n\n    $ hexrec crop -s 0x8000 -e 0x20000 -v 0xFF app_original.hex app_trimmed.srec\n\nBy contrast, we need to fill the application range within the bootloader image\nwith ``0xFF``, so that no existing application will be available again.\nAlso, we need to preserve the address range ``0x3F800``-``0x3FFFF`` because it\nalready contains some important data.\n\n.. code-block:: python3\n\n    from hexrec import load\n\n    file = load('bootloader.hex')\n    file.fill(0x8000, 0x1FFFF+1, 0xFF)\n    file.clear(0x3F800, 0x3FFFF+1)\n    file.save('boot_fixed.hex')\n\nWith the command line interface, it can be done via a two-pass processing,\nfirst to fill the application range, then to clear the reserved range.\nPlease note that the first command is chained to the second one via standard\noutput/input buffering (the virtual ``-`` file path, in ``ihex`` format as\nper ``boot_original.hex``).\n\n.. code-block:: sh\n\n    $ hexrec fill -s 0x8000 -e 0x20000 -v 0xFF boot_original.hex - | \\\n      hexrec clear -s 0x3F800 -e 0x40000 -i ihex - boot_fixed.srec\n\n(newline continuation is backslash ``\\`` for a *Unix-like* shell, caret ``^``\nfor a *DOS* prompt).\n\n\nExport ELF sections\n-------------------\n\nThe following example shows how to export *sections* stored within an\n*Executable and Linkable File* (*ELF*), compiled for a microcontroller.\nAs per the previous example, only data within the range ``0x8000``-``0x1FFFF``\nare kept, with the rest of the memory filled with the ``0xFF`` value.\n\n.. code-block:: python3\n\n    from hexrec import SrecFile\n    from bytesparse import Memory\n    from elftools.elf.elffile import ELFFile  # \"pyelftools\" package\n\n    with open('appelf.elf', 'rb') as elf_stream:\n        elf_file = ELFFile(elf_stream)\n\n        memory = Memory(start=0x8000, endex=0x1FFFF+1)  # bounds set\n        memory.fill(pattern=0xFF)  # between bounds\n\n        for section in elf_file.iter_sections():\n            if (section.header.sh_flags \u0026 3) == 3:  # SHF_WRITE | SHF_ALLOC\n                address = section.header.sh_addr\n                data = section.data()\n                memory.write(address, data)\n\n    out_file = SrecFile.from_memory(memory, header=b'Source: appelf.elf\\0')\n    out_file.save('appelf.srec')\n\n\nInstallation\n============\n\nFrom PyPI (might not be the latest version found on *github*):\n\n.. code-block:: sh\n\n    $ pip install hexrec\n\nFrom the source code root directory:\n\n.. code-block:: sh\n\n    $ pip install .\n\n\nDevelopment\n===========\n\nTo run the all the tests:\n\n.. code-block:: sh\n\n    $ pip install tox\n    $ tox\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftexzk%2Fhexrec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftexzk%2Fhexrec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftexzk%2Fhexrec/lists"}