{"id":20118181,"url":"https://github.com/martinus/gra","last_synced_at":"2026-03-01T15:33:56.362Z","repository":{"id":66601168,"uuid":"598041544","full_name":"martinus/gra","owner":"martinus","description":"Git Repo Admin","archived":false,"fork":false,"pushed_at":"2026-01-23T16:53:46.000Z","size":40,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-24T01:13:12.839Z","etag":null,"topics":["admin","cli","git","linux","python3","repository-management","vscode"],"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/martinus.png","metadata":{"files":{"readme":"README.md","changelog":null,"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-02-06T09:18:01.000Z","updated_at":"2026-01-23T16:53:49.000Z","dependencies_parsed_at":"2024-12-19T07:29:44.553Z","dependency_job_id":null,"html_url":"https://github.com/martinus/gra","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/martinus/gra","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinus%2Fgra","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinus%2Fgra/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinus%2Fgra/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinus%2Fgra/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/martinus","download_url":"https://codeload.github.com/martinus/gra/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinus%2Fgra/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29973320,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-01T15:29:09.406Z","status":"ssl_error","status_checked_at":"2026-03-01T15:28:28.558Z","response_time":124,"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":["admin","cli","git","linux","python3","repository-management","vscode"],"created_at":"2024-11-13T19:09:41.144Z","updated_at":"2026-03-01T15:33:56.327Z","avatar_url":"https://github.com/martinus.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# gra - Git Repo Admin\n\nThe repository administrator helps organize and manage git repositories. It structures\nrepositories under gra's root location (default: `~/git`) like this: \n\n```\n~/git\n├── github.com\n│   ├── martinus\n│   │   ├── gra\n│   │   └── unordered_dense\n└── sourceware.org\n    └── git\n        └── glibc\n```\n\n`gra` is configured in your `~/.gitconfig`. Most importantly, set your `gra.root`\ne.g. like so:\n\n```sh\ngit config --global gra.root ~/develop\n```\n\n# Installation\n\n1. Use `gra` itself to clone `gra`, so it's in the proper directory.\n   ```sh\n   python3 -c \"$(curl -fsLS https://raw.githubusercontent.com/martinus/gra/refs/heads/main/gra)\" clone git@github.com:martinus/gra.git\n   ```\n\n2. Create a symlink in your path, e.g. like so:\n   ```sh\n   ln -s ~/git/github.com/martinus/gra/gra ~/.local/bin/\n   ```\n\n# Configuration\n\nIt is possible to add `pre` and `post` commands that can be automatically executed. Here is\na full sample configuration:\n\n```ini\n[gra]\n    root = ~/develop\n    post-clone = \"git maintenance register\"\n    pre-rm = \"git maintenance unregister\"\n```\n\n`gra` provides shell helpers. Add this to your `~/.bashrc` or similar:\n\n```sh\neval \"$(gra shell)\"\n```\n\nThis adds two aliases that make use of [fzf](https://github.com/junegunn/fzf), the fuzzy searcher:\n\n* `gra cd`: quickly change directory into any of the repositories\n* `gra rm`: remove one of the repositories\n\n## clone - clone one or more remote repository\n\nClones one or more repository into the gra root directory. The\nrepository directory is created based on the URL and it is registered into\ngra's database.\n\n## each - run a command in the working directory of each repository\n\nRuns the given command with all arguments for each repository. The working directory of each command\nis its repository, and the commands can use these strings which are automatically replaced:\n\n* `{{GRA_ROOT}}`: Replaced by gra root directory.\n* `{{GRA_REPO}}`: Replaced by the full path of each repository.\n\nHere are examples that you can try. Show short git status of each repository:\n\n```sh\ngra each git status -sb\n```\n\nShow disk usage of each repository. I use `{{GRA_REPO}}` so `du` shows the path, and the argument `-q`\nto hide gra's status output:\n\n```sh\ngra -q each du -h -d0 {{GRA_REPO}}\n```\n\n## ls - list all repositories\n\nSimply list all repositories. The list is updated automatically on each clone,\nbut if you add/remove repositories without the script, run `updatedb` to\nupdate the index.\n\n## updatedb - crawls the gra root to update the list of repositories\n\nWalks through the whole directory tree in the root path to find all\ndirectories that contain a `.git` folder. These are then set as the repositories\nin the database.\n\nUsually there is no need to call that command, unless you add repositories without\nthe `clone` command. The repositories are then sorted and stored into\n`~/.local/share/gra/db.json`.\n\n## root - shows repository root\n\nPrints the root path used by gra. The path is configured in the global\n`~/.gitconfig`. If not configured, the default is `~/git`. Set the\nconfiguration with e.g.\n\n```sh\ngit config --global gra.root ~/develop\n```\n\n## rm - removes a local repository\n\nRemoves a local git repository. This removes all empty parent directores (not including\nthe root) as well.\n\nYou have to confirm with 'y' before actual removal takes place.\n\n## vscode - generate list of projects for VSCode Project Manager\n\nRequires Visual Studio Code with the Project Manager extension, available here:\nhttps://marketplace.visualstudio.com/items?itemName=alefragnani.project-manager\n\nThis adds each repository to the project manager, with the netlocation as tag,\nand last two subdirectories as a name. Existing configuration is kept as-is.\n\n\n# Alternatives\n\n* [ghq](https://github.com/x-motemen/ghq) was the main inspiration for `gra`. gra is much simpler,\n  a single python file, git only, and integrates easily with VSCode.\n* [ghr](https://github.com/siketyan/ghr) is another ghq clone, written in Rust, but it currently\n  did not work with non github URLs. I like the bash integration.\n* [rhq](https://github.com/ubnt-intrepid/rhq) Another one in rust\n* [projj](https://github.com/popomore/projj)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinus%2Fgra","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmartinus%2Fgra","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinus%2Fgra/lists"}