Skip to main content

git-buckets

gb is the end-user CLI for a git-buckets deployment: git repos and Python package indexes over HTTPS, backed by S3. Someone else runs the deployment. You log in once and then use stock git and uv.

Install

Prereqs:

  • git (≥ 2.13, ≥ 2.40 for bundle-accelerated clones)
  • git-lfs
  • Python ≥ 3.14
uv tool install git-buckets
# or: pipx install git-buckets

First login

gb login git.example.com

Once per deployment, never per bucket. This signs you in through the browser, stores the session, writes the credential-helper stanza for https://*.git.example.com plus transfer.bundleURI = true into your global gitconfig, and records the deployment.

On a box with no browser, --no-browser prints a URL to open elsewhere and reads the code back at a masked prompt.

gb auth status              # deployments known, the user on each, where each secret lives
gb logout git.example.com   # revoke the session token, erase the stored credentials

Daily use

Remote URLs are https://<bucket>.<deployment-domain>/<repo>: the first hostname label is the bucket's public label, the path is the repo name, as deep as you like. git clone https://my-bucket.git.example.com/tools/cli/my-project, then fetch, pull and push are stock git as well.

New repos are made by pushing. There is no create command, simply push to a new path on an existing bucket and you've created a new repo.

git init && git remote add origin https://my-bucket.git.example.com/tools/gui/my-new-project
git push -u origin main

Signed commits. Buckets require them by default: every commit a push introduces is checked, so set up signing before the first push (gpg.format ssh + user.signingkey + commit.gpgsign is the short route).

LFS. Downloads at any size and uploads up to 5 GB per file need nothing installed: objects come from the same host under the same credential. Above 5 GB an upload needs gb's transfer agent, which also makes both directions parallel and resumable. Once per repo:

gb lfs install [--remote <name>]

Packages. Each bucket is one Python index. In the consuming project's pyproject.toml:

[[tool.uv.index]]
name = "my-bucket-index"
url = "https://gb@my-bucket.git.example.com/packages/pypi/"
explicit = true

[tool.uv.sources]
my-package = { index = "my-bucket-index" }

[tool.uv]
keyring-provider = "subprocess"

Then just uv sync as normal. The gb@ is required: uv only does keyring discovery when the index URL carries a username.

Publishing needs one more line on the index, in the publishing project rather than the consuming one, naming the repo the package belongs to:

[[tool.uv.index]]
name = "my-bucket-index"
url = "https://gb@my-bucket.git.example.com/packages/pypi/"
publish-url = "https://gb@my-bucket.git.example.com/packages/pypi/upload/tools/cli/my-project/"
explicit = true

Then uv build && uv publish --index my-bucket-index. Push rights are publish rights: the repo in the upload URL is the one your token must reach with rw.

CI. A runner has no login session: it assumes the team's token role via OIDC and sets UV_KEYRING_PROVIDER=subprocess and GB_KEYRING_HOSTS="*.git.example.com". GB_KEYRING_HOSTS is CI only, never needed on a user machine.

Repo lifecycle

Every subcommand takes <bucket>/<repo>, plus -H/--host <domain> when more than one deployment is registered.

gb repo list
gb repo info my-bucket/tools/cli/my-project          # head, refs, size, last push; -v lists every ref
gb repo protect my-bucket/tools/cli/my-project main  # blocks delete while the ref exists
gb repo unprotect my-bucket/tools/cli/my-project main
gb repo delete my-bucket/tools/cli/my-project --yes  # without --yes it only prints what would go

Delete takes the repo's LFS objects, locks, bundles, packages and rendered web tree with it. The undo path is S3 versioning on the operator's side, not a gb command. There is no rename.

Package lifecycle

Published files are immutable, so a bad release is yanked rather than replaced: it stays downloadable for anything that already pinned it, and every other resolve skips it.

gb package list                                          # every bucket, grouped by repo
gb package list -b my-bucket -r tools/cli/my-project     # one repo; -v lists every file with size and sha256
gb package yank my-bucket/tools/cli/my-project my-project 1.2.0 --reason "bad wheel"
gb package unyank my-bucket/tools/cli/my-project my-project 1.2.0
gb package delete my-bucket/tools/cli/my-project my-project 1.2.0 --yes  # the bytes go; lockfiles that pin it 404

Where the secrets live

The refresh token (one year, fixed from sign-in) goes in your OS keyring, or in ~/.config/gb/hosts.yml at 0600 when no keyring works: gb says which, once. On a headless Linux box, pass + gpg-agent is the supported keyring. The hourly ID and session tokens are just caches under ~/.local/state/gb/<domain>/.

Troubleshooting

  • git prompts for a username and password: the host isn't registered. gb auth status, then gb login.
  • the session for <domain> has expired: the refresh token is past its year, or was revoked. Log in again.
  • A push is refused but a fetch works: your grant on that prefix is read-only.
  • A package index won't authenticate: GB_KEYRING_DEBUG=1 uv sync prints why the keyring backend declined.

Release files for git-buckets 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for git-buckets 0.4.0
File Size Uploaded
git_buckets-0.4.0.tar.gz 37.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for git-buckets 0.4.0
File Interpreter ABI Platform
git_buckets-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 84.4 kB

Release files / git_buckets-0.4.0.tar.gz

Download URL git_buckets-0.4.0.tar.gz
Size 37.7 kB
Tags Source
SHA-256 checksum
How to use checksums
00b52cc54f9983b5da27665eadfb70657ea68d09e18a2907ca474e42619f5206
BLAKE2b-256 checksum
How to use checksums
003212fb8067c4f69fdcecd4d9d28829db71fc0109164b8c94ab1e5058959931
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.

Transparency log

Release files / git_buckets-0.4.0-py3-none-any.whl

Download URL git_buckets-0.4.0-py3-none-any.whl
Size 46.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e4bd643b149e186905cae21d2ca8c4e38d7a2a66e06ef70dfb9e212833c786ac
BLAKE2b-256 checksum
How to use checksums
609f63ea4d7efbfd1741a5eda2986f62f7d6be7602348e77735653be3bb97cd1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page