{"id":19336798,"url":"https://github.com/samrocketman/cloneable","last_synced_at":"2025-04-23T01:30:52.661Z","repository":{"id":145441829,"uuid":"262541438","full_name":"samrocketman/cloneable","owner":"samrocketman","description":"A Java CLI utility which lists available GitHub repositories under a user or organization.","archived":false,"fork":false,"pushed_at":"2025-03-27T00:41:49.000Z","size":119,"stargazers_count":7,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-27T01:32:52.197Z","etag":null,"topics":["backups","github-backup"],"latest_commit_sha":null,"homepage":null,"language":"Groovy","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/samrocketman.png","metadata":{"files":{"readme":"README.md","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}},"created_at":"2020-05-09T10:00:43.000Z","updated_at":"2025-03-27T00:41:53.000Z","dependencies_parsed_at":"2023-06-03T18:32:21.806Z","dependency_job_id":null,"html_url":"https://github.com/samrocketman/cloneable","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samrocketman%2Fcloneable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samrocketman%2Fcloneable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samrocketman%2Fcloneable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samrocketman%2Fcloneable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/samrocketman","download_url":"https://codeload.github.com/samrocketman/cloneable/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250352183,"owners_count":21416454,"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","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":["backups","github-backup"],"created_at":"2024-11-10T03:12:28.586Z","updated_at":"2025-04-23T01:30:52.655Z","avatar_url":"https://github.com/samrocketman.png","language":"Groovy","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Cloneable :octocat: GitHub Backups\n\n- :arrow_forward: Download `cloneable.jar` from [GitHub releases\n  page][download].\n- :white_check_mark: Supports GitHub App or personal access token (PAT) for\n  querying and cloning.\n- :white_check_mark: Clone over HTTP with app or PAT via [`GIT_ASKPASS`\n  backend][git-credentials].\n- :white_check_mark: Query projects over HTTP and clone using SSH private key.\n- :white_check_mark: Flexibly query projects based on age, contents, and other\n  factors.  See CLI Documentation below for a full list.\n- :white_check_mark: Minimal dependencies: Java, `/bin/sh`, and standard\n  utilities; GNU or BSD coreutils, and busybox supported.\n\nA simple backup solution for offsite backups of GitHub repository source code.\n\nCloneable is a Java-based CLI application which queries GitHub and reports\ncloneable projects.  It only does one thing: lists repositories.  Other Linux\nutilities can be used in conjunction with cloneable to create and update a local\nbackup of GitHub.  Useful for personal backups of GitHub with minimal\ndependencies.\n\nCloneable utilizes [GitHub API v4 GraphQL][v4].  If you need a more thorough\nbackup solution, check out [other solutions on GitHub][other-backup].\n# Download\n\nBinary download is available in [GitHub releases][download].\n\n# Setup\n\nIn order to call cloneable, it is recommended install the wrapper shell script\nalong with the bash competion for it.\n\n    java -jar cloneable.jar --print-cli-script \u003e /usr/local/bin/cloneable\n    chmod 755 /usr/local/bin/cloneable\n\nInstall bash completion script for interactive auto-complete of options.\n\n    cloneable --print-bash-completion \u003e /etc/bash_completion.d/cloneable_completion\n\nYou need to also set up one of two methods for authentication to query GraphQL\nAPIs.\n\n### GitHub App authentication\n\nCreate and install a GitHub app.  Recommended permissions is repository\n`contents:readonly` for private repositories or no scopes for public\nrepositories.\n\nSet environment variables with GitHub App authentication.\n\n    export CLONEABLE_GITHUB_APP_ID=1234\n    export CLONEABLE_GITHUB_APP_KEY=/path/to/private_key\n\n### GitHub Personal Access Tokens\n\nRequires a [GitHub personal access token][github-token] with scopes:\n\n- `repo` and `read:org` for an organization with private repositories.\n- `repo` for a user with private repositories.\n- No scopes required for a user or organization with public repositories only.\n\nSetup authentication.\n\n    export GITHUB_TOKEN=\u003cgh pat\u003e\n\n# Example Usage\n\nExample usage covers HTTP and SSH cloning.  The following methods work with both\nApp and personal access token auth.\n\n### Backup over HTTP\n\nCloning over HTTP requires backend authentication via `GIT_ASKPASS`.  See\n[git-credentials][git-credentials] for details.\n\nInstall a `GIT_ASKPASS` script set up for cloning.\n\n    cloneable -o your-org --print-askpass-script | /bin/sh\n\n    # Or alternate location instead of /tmp/askpass\n    cloneable -o integralads --print-askpass-script | \\\n        CLONEABLE_ASKPASS_LOCATION=/alternate/askpass /bin/sh\n\nThe `GIT_ASKPASS` script will default to always auth against `your-org`.  If you\nwant to clone from another associated org for the GitHub App, you can set\nenvironment variable `CLONEABLE_OWNER`.\n\nClone all repositories.  You can pass any cloneable arguments.\n\n    export GIT_ASKPASS=/tmp/askpass\n    cloneable -o your-org --http --skip-local-bare-repos \\\n      --print-clone-script | /bin/sh -x\n\n    export CLONEABLE_OWNER=another-org\n    cloneable --http --skip-local-bare-repos \\\n      --print-clone-script | /bin/sh -x\n\nUpdate clones using HTTP.\n\n    cloneable --http --print-update-script | /bin/sh -x\n\n### Backup over SSH\n\nAssuming your already have an SSH clone key loaded within ssh-agent.  You can\nclone and update repositories using SSH.\n\n    cloneable --url --skip-local-bare-repos \\\n      --print-clone-script | /bin/sh -x\n\nUpdate clones using SSH.\n\n    cloneable --url --print-update-script | /bin/sh -x\n\n### Other usage\n\nList repository names under a user or organization.\n\n```\nexport GITHUB_TOKEN\nread -ersp token: GITHUB_TOKEN\ncloneable --owner samrocketman\n```\n\nShow samrocketman repositories which have a `jenkins` topic.\n\n```bash\ncloneable --owner samrocketman --match-topics jenkins\n```\n\n# Build Jar\n\n    ./gradlew clean jar\n\nRun tests\n\n    ./gradlew clean check\n\nRecent development done in the following environment.\n\n    Pop!_OS 22.04 LTS\n    Linux 6.9.3-76060903-generic x86_64\n    GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)\n    Gradle 8.13\n    Build time: 2025-02-25 09:22:14 UTC\n    Revision: 073314332697ba45c16c0a0ce1891fa6794179ff\n    Kotlin: 2.0.21\n    Groovy: 3.0.22\n    Ant: Apache Ant(TM) version 1.10.15 compiled on August 25 2024\n    Launcher JVM: 17.0.12 (Ubuntu 17.0.12+7-Ubuntu-1ubuntu222.04)\n    Daemon JVM: /usr/lib/jvm/java-17-openjdk-amd64 (no JDK specified, using current Java home)\n    OS: Linux 6.9.3-76060903-generic amd64\n    openjdk 17.0.12 2024-07-16\n\n# CLI Documentation\n\nThe following options are available from `java -jar cloneable.jar --help`.\n\n```\nUsage: cloneable [-abdefhipPsuV] [--http] [--owner-is-user]\n                 [--print-askpass-script] [--print-auth-token]\n                 [--print-bash-completion] [--print-cli-script]\n                 [--print-clone-script] [--print-update-script]\n                 [--after=\u003cafterTimeframe\u003e] [-B=\u003cbranch\u003e]\n                 [--before=\u003cbeforeTimeframe\u003e] [-g=\u003cghAppId\u003e] [-k=\u003cghAppKey\u003e]\n                 [-o=\u003cowner\u003e] [-t=\u003ctoken\u003e] [-E=\u003cexcludeAllFiles\u003e]...\n                 [-F=\u003cmatchAnyFiles\u003e]... [-m=\u003cmatchAnyTopics\u003e]...\nDescription:\n\n  Gets a list of repositories if given a GitHub user or GitHub organization.\n  The primary purpose of this program is to facilitate listing GitHub\n  repositories and cloning them for an offline backup.\n\n  Website: https://github.com/samrocketman/cloneable\n\nExample Usage:\n\n  Set up GitHub App authentication.\n    export CLONEABLE_GITHUB_APP_ID=1234\n    export CLONEABLE_GITHUB_APP_KEY=/path/to/private_key\n\n  Or you can use a GitHub personal access token.\n    export GITHUB_TOKEN=\u003cgithub_pat_...\u003e\n\n  Create CLI integration with bash completion.\n    java -jar cloneable.jar --print-cli-script \u003e /usr/local/bin/cloneable\n    chmod 755 /usr/local/bin/cloneable\n    cloneable --print-bash-completion \u003e /etc/bash_completion.\nd/cloneable_completion\n\n  Install GIT_ASKPASS script when using GitHub App auth.\n    cloneable -o your-org --print-askpass-script | /bin/bash\n\n  HTTP mirror clones using GIT_ASKPASS.\n    export GIT_ASKPASS=/tmp/askpass\n    cloneable -o your-org --http \\\n      --skip-local-bare-repos --print-clone-script \\\n      | /bin/sh\n\n    export CLONEABLE_OWNER=another-org\n    cloneable --http --skip-local-bare-repos --print-clone-script \\\n      | /bin/sh\n\n  Update HTTP mirrors.\n    cloneable --print-update-script | /bin/sh -x\n\nEnvironment Variables:\n\n  CLONEABLE_CACHE_KEY\n    RSA private key used to encrypt cache.  By default,\n    CLONEABLE_GITHUB_APP_KEY is used.\n\n  CLONEABLE_CACHE_PATH\n    Directory where persisted encrypted cache and lockfile get stored.\n\n  CLONEABLE_DEBUG\n    Same as --debug, enables debug mode showing more information.\n\n  CLONEABLE_GITHUB_APP_ID\n    GitHub App ID used in GitHub App authentication.\n\n  CLONEABLE_GITHUB_APP_KEY\n    GitHub App private key used in GitHub App authentication.\n\n  GITHUB_GRAPHQL_URL\n    GitHub API endpoint for GraphQL. Default: https://api.github.com/graphql\n\n  GITHUB_API_URL\n    GitHub API endpoint for REST.  Default: https://api.github.com/\n\n  GITHUB_TOKEN\n    GitHub personal token for API communication when GitHub App authentication\n    is not available.\n\nOptions:\n\n  -a, --skip-archived-repos  If a repository is archived, then it will be\n                               skipped.\n      --after=\u003cafterTimeframe\u003e\n                             Find all repositories updated after the given\n                               timeframe. Must be a positive integer followed\n                               by one of: d, m, y.  For example, 1y will find\n                               all repositories updated after 1 year ago; or\n                               within the past 12m or 12 months.  If d, m, or y\n                               is not provided then d will be assumed.\n  -b, --skip-local-bare-repos\n                             If a bare repository directory exists locally (the\n                               name of the repo ending with '.git'), then it\n                               will not be printed out.  This is useful for\n                               cloning only missing repositories.\n  -B, --branch=\u003cbranch\u003e      If using -F or -E options, then choose the Git\n                               branch to search for files.  The default branch\n                               will be queried if this option is not specified.\n      --before=\u003cbeforeTimeframe\u003e\n                             Find all repositories updated before the given\n                               timeframe. Must be a positive integer followed\n                               by one of: d, m, y.  For example, 1y will find\n                               all repositories updated before 1 year ago.  If\n                               d, m, or y is not provided then d will be\n                               assumed.\n  -d, --debug                Prints out stack traces.\n  -e, --skip-empty-repos     If a repository does not contain any Git commits,\n                               then it will be skipped.\n  -E, --exclude-repos-with=\u003cexcludeAllFiles\u003e\n                             Match any repository containing which does NOT\n                               contain the file at the repository root.  -E can\n                               be specified more than once to exclude a\n                               repository containing any or all of the listed\n                               files.\n  -f, --skip-forked-repos    If a repository is a fork from another user or\n                               organization, then it will be skipped.\n  -F, --contains=\u003cmatchAnyFiles\u003e\n                             Match any repository containing any file at the\n                               repository root.  -F can be specified more than\n                               once to match any one of multiple files.\n  -g, --github-app-id=\u003cghAppId\u003e\n                             GitHub App app ID associated with GitHub App\n                               private key.\n  -h, --help                 Show this help message and exit.\n      --http                 Prints HTTP clone URL instead of repository name.\n                               Also dictates output of --print-update-script\n                               and --print-clone-script\n  -i, --inverse-search       Inverse the search results.  For example, instead\n                               of skipping repositories it will match\n                               repositories.  Adding the option\n                               --inverse-search along side --skip-archived will\n                               find all archived repositories.  If you provide\n                               multiple options then the inverse finds any\n                               match.  For example, adding --inverse-search\n                               with options --skip-archived and --skip-empty\n                               will find BOTH empty or archived repositories.\n  -k, --github-app-key=\u003cghAppKey\u003e\n                             GitHub App private key.\n  -m, --match-topics=\u003cmatchAnyTopics\u003e\n                             Require all repositories to have one of the listed\n                               topics.  -m can be specified multiple times.\n  -o, --owner=\u003cowner\u003e        GitHub account or organization for querying a list\n                               of projects.\n      --owner-is-user        If using GitHub App auth this flag indicates app\n                               installation is for a user instead of\n                               organization.\n  -p, --skip-private-repos   If a repository is private, then it will be\n                               skipped.\n  -P, --skip-public-repos    If a repository is public, then it will be skipped.\n      --print-askpass-script Print a GIT_ASKPASS script meant for cloning HTTP\n                               repositories provided by --http option.  Pipe\n                               into /bin/sh.\n      --print-auth-token     Print GitHub token generated by GitHub app\n                               installation used for cloning.\n      --print-bash-completion\n                             Print bash-completion script meant to help with\n                               auto-complete on interactive command line. e.g.\n                               redirect stdout to '/etc/bash_completion.d'.\n      --print-cli-script     Prints 'cloneable' CLI wrapper script.  e.g.\n                               redirect stdout to '/usr/local/bin/cloneable'.\n      --print-clone-script   Prints a bash script meant for updating HTTP\n                               clones created by app auth.  Pipe into /bin/sh\n      --print-update-script  Prints a bash script meant for updating HTTP\n                               clones created by app auth.  Pipe into /bin/sh\n  -s, --skip-source-repos    If a repository is **not** a fork from another\n                               user or organization, then it will be skipped.\n  -t, --github-token=\u003ctoken\u003e GitHub personal access token or file containing a\n                               token.  Falls back to checking GITHUB_TOKEN\n                               environment variable.\n  -u, --url                  Prints out SSH clone URL instead of repository\n                               name.\n  -V, --version              Print version information and exit.\n```\n\n[download]: https://github.com/samrocketman/cloneable/releases\n[git-credentials]: https://git-scm.com/docs/gitcredentials\n[github-token]: https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line\n[other-backup]: https://github.com/topics/github-backup\n[v4]: https://developer.github.com/v4/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamrocketman%2Fcloneable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsamrocketman%2Fcloneable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamrocketman%2Fcloneable/lists"}