{"id":18084929,"url":"https://github.com/jwodder/ghtoken","last_synced_at":"2026-02-07T13:31:25.998Z","repository":{"id":197320078,"uuid":"698442338","full_name":"jwodder/ghtoken","owner":"jwodder","description":"Retrieve GitHub access tokens from various sources","archived":false,"fork":false,"pushed_at":"2025-11-24T00:13:10.000Z","size":50,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-12-01T04:01:47.683Z","etag":null,"topics":["available-on-pypi","gh-token","github","github-api","github-token","python"],"latest_commit_sha":null,"homepage":"","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/jwodder.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.md","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":"2023-09-30T00:02:56.000Z","updated_at":"2025-11-24T00:13:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"870e46b9-ed6b-4c2f-aa17-e064f81cc051","html_url":"https://github.com/jwodder/ghtoken","commit_stats":null,"previous_names":["jwodder/ghtoken"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/jwodder/ghtoken","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwodder%2Fghtoken","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwodder%2Fghtoken/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwodder%2Fghtoken/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwodder%2Fghtoken/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jwodder","download_url":"https://codeload.github.com/jwodder/ghtoken/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwodder%2Fghtoken/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29195066,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-07T12:38:28.597Z","status":"ssl_error","status_checked_at":"2026-02-07T12:38:23.888Z","response_time":63,"last_error":"SSL_read: 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":["available-on-pypi","gh-token","github","github-api","github-token","python"],"created_at":"2024-10-31T15:08:41.262Z","updated_at":"2026-02-07T13:31:25.993Z","avatar_url":"https://github.com/jwodder.png","language":"Python","readme":"|repostatus| |ci-status| |coverage| |pyversions| |conda| |license|\n\n.. |repostatus| image:: https://www.repostatus.org/badges/latest/active.svg\n    :target: https://www.repostatus.org/#active\n    :alt: Project Status: Active — The project has reached a stable, usable\n          state and is being actively developed.\n\n.. |ci-status| image:: https://github.com/jwodder/ghtoken/actions/workflows/test.yml/badge.svg\n    :target: https://github.com/jwodder/ghtoken/actions/workflows/test.yml\n    :alt: CI Status\n\n.. |coverage| image:: https://codecov.io/gh/jwodder/ghtoken/branch/master/graph/badge.svg\n    :target: https://codecov.io/gh/jwodder/ghtoken\n\n.. |pyversions| image:: https://img.shields.io/pypi/pyversions/ghtoken.svg\n    :target: https://pypi.org/project/ghtoken/\n\n.. |conda| image:: https://img.shields.io/conda/vn/conda-forge/ghtoken.svg\n    :target: https://anaconda.org/conda-forge/ghtoken\n    :alt: Conda Version\n\n.. |license| image:: https://img.shields.io/github/license/jwodder/ghtoken.svg\n    :target: https://opensource.org/licenses/MIT\n    :alt: MIT License\n\n`GitHub \u003chttps://github.com/jwodder/ghtoken\u003e`_\n| `PyPI \u003chttps://pypi.org/project/ghtoken/\u003e`_\n| `Issues \u003chttps://github.com/jwodder/ghtoken/issues\u003e`_\n| `Changelog \u003chttps://github.com/jwodder/ghtoken/blob/master/CHANGELOG.md\u003e`_\n\nWhen writing a Python program for interacting with GitHub's API, you'll likely\nwant to use the local user's GitHub access token for authentication.  Asking\nthe user to provide the token every time is undesirable, so you'd rather look\nup the token in some well-known storage location.  The problem is, there have\nbeen so many places to store GitHub tokens supported by different programs over\nthe years, and asking your users to migrate to a new one shouldn't be\nnecessary.\n\nThat's where ``ghtoken`` comes in: it provides a single function for checking\nmultiple well-known sources for GitHub access tokens plus separate functions\nfor querying individual sources in case you need to combine the queries in\nnovel ways.\n\nThe following token sources are currently supported:\n\n- ``.env`` files\n- environment variables\n- the gh_ command\n- the hub_ configuration file\n- the ``hub.oauthtoken`` Git config option\n\n.. _gh: https://github.com/cli/cli\n.. _hub: https://github.com/mislav/hub\n\n\nInstallation\n============\n``ghtoken`` requires Python 3.10 or higher.  Just use `pip\n\u003chttps://pip.pypa.io\u003e`_ for Python 3 (You have pip, right?) to install it::\n\n    python3 -m pip install ghtoken\n\n\nAPI\n===\n\nNote: When retrieving GitHub access tokens, no validation of the token format\nis performed other than rejecting empty strings.\n\n.. code:: python\n\n    ghtoken.get_ghtoken(\n        *,\n        dotenv: bool | str | os.PathLike[str] = True,\n        environ: bool = True,\n        gh: bool = True,\n        hub: bool = True,\n        hub_oauthtoken: bool = True,\n    ) -\u003e str\n\nRetrieve a locally-stored GitHub access token by checking various sources\n(listed below) and returning the first token found.  Individual sources can be\ndisabled by setting the corresponding keyword argument to ``False``.\n\nThe sources are as follows, listed in the order in which they are consulted:\n\n``dotenv``\n    Look for a ``.env`` file by searching from the current directory upwards\n    and reading the first file found.  Alternatively, a specific file may be\n    read by setting the ``dotenv`` keyword argument to the path to the file.\n    If the file (whether found by searching or explicitly specified) cannot be\n    read or parsed, control proceeds to the next enabled source.\n\n    If the file contains a ``GH_TOKEN=...`` or ``GITHUB_TOKEN=...`` assignment\n    with a non-empty value, that value is returned; otherwise, control proceeds\n    to the next enabled source.  If assignments for both keys are present,\n    ``GH_TOKEN`` takes precedence over ``GITHUB_TOKEN``.\n\n    Reading values from a ``.env`` file will not modify the process's\n    environment variables.\n\n``environ``\n    If the environment variable ``GH_TOKEN`` or ``GITHUB_TOKEN`` is set to a\n    nonempty string, that variable's value is returned; otherwise, control\n    proceeds to the next enabled source.  If both environment variables are\n    set, ``GH_TOKEN`` takes precedence over ``GITHUB_TOKEN``.\n\n``gh``\n    Retrieve a GitHub access token stored by the gh_ command by running ``gh\n    auth token --hostname github.com``.  If the command fails or outputs an\n    empty line, control proceeds to the next enabled source.\n\n    Note that, if gh has stored its access token in a system keyring, the user\n    may be prompted to unlock the keyring.\n\n    Note that, if the ``GH_TOKEN`` or ``GITHUB_TOKEN`` environment variable is\n    set to a nonempty string, gh will return the value of the envvar rather\n    than returning whatever access token may already be stored, and this\n    happens even if the ``environ`` argument to ``get_ghtoken()`` is ``False``.\n\n``hub``\n    Retrieve a GitHub access token from the hub_ configuration file.  If the\n    configuration file does not exist or is malformed, or if the file does not\n    contain a nonempty token for the ``github.com`` domain, control proceeds to\n    the next enabled source.\n\n``hub_oauthtoken``\n    Retrieve a GitHub access token from the Git config key ``hub.oauthtoken``,\n    used by the git-hub_ program.  If the key is set to the empty string, or if\n    the Git config key ``hub.baseurl`` is set to a value other than\n    ``https://api.github.com``, control proceeds to the next enabled source.\n\n    Git config values are retrieved by running ``git config --get ...``.  If\n    such a command fails, control proceeds to the next enabled source.\n\n    If the ``hub.oauthtoken`` value starts with ``!``, the rest of the value is\n    executed as a shell command, and the command's standard output (with\n    leading \u0026 trailing whitespace stripped) is returned.\n\n    .. _git-hub: https://github.com/sociomantic-tsunami/git-hub\n\nIf no enabled source returns a token, then a ``ghtoken.GHTokenNotFound``\nexception is raised.\n\n.. code:: python\n\n    ghtoken.ghtoken_from_dotenv(path: str | os.PathLike[str] | None = None) -\u003e str\n\nRetrieve a GitHub access token from an ``.env`` file as described above.  A\npath to a specific file may be supplied.  If no token is found, a\n``ghtoken.GHTokenNotFound`` exception is raised.\n\n.. code:: python\n\n    ghtoken.ghtoken_from_environ() -\u003e str\n\nRetrieve a GitHub access token from environment variables as described above.\nIf no token is found, a ``ghtoken.GHTokenNotFound`` exception is raised.\n\n.. code:: python\n\n    ghtoken.ghtoken_from_gh() -\u003e str\n\nRetrieve a GitHub access token from the ``gh`` command as described above.  If\nno token is found, a ``ghtoken.GHTokenNotFound`` exception is raised.\n\n.. code:: python\n\n    ghtoken.ghtoken_from_hub() -\u003e str\n\nRetrieve a GitHub access token from the ``hub`` configuration file as described\nabove.  If no token is found, a ``ghtoken.GHTokenNotFound`` exception is\nraised.\n\n.. code:: python\n\n    ghtoken.ghtoken_from_hub_oauthtoken() -\u003e str\n\nRetrieve a GitHub access token from the ``hub.oauthtoken`` Git config option as\ndescribed above.  If no token is found, a ``ghtoken.GHTokenNotFound`` exception\nis raised.\n\n\nCommand\n=======\n\n``ghtoken`` also provides a command of the same name for looking up a GitHub\ntoken from the command line::\n\n    ghtoken [\u003coptions\u003e]\n\n``ghtoken`` retrieves the local user's GitHub access token from local storage\nand prints it.  If no token can be found, a message is printed to standard\nerror, and the command exits with a nonzero status.\n\nOptions\n-------\n\n-E FILE, --env FILE             Use the given file as the ``.env`` file source\n\n--no-dotenv                     Do not consult a ``.env`` file\n\n--no-environ                    Do not consult environment variables\n\n--no-gh                         Do not consult ``gh``\n\n--no-hub                        Do not consult ``hub`` configuration file\n\n--no-hub-oauthtoken             Do not consult ``hub.oauthtoken`` Git config\n                                option\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjwodder%2Fghtoken","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjwodder%2Fghtoken","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjwodder%2Fghtoken/lists"}