Skip to content

Git Integration

wody edited this page May 26, 2026 · 3 revisions

Git Integration

For cloning private repositories into new projects (v0.9.0+).

/settings/git-integrations in the web UI.

Three sources of git credentials

  1. No credentialshttps://github.com/owner/public-repo.git works out of the box for public repos.
  2. HTTPS PAT (Personal Access Token) — for private HTTPS URLs. Registered per-host; the git CLI auto-picks via credential.helper=store.
  3. SSH key — for private SSH URLs (git@host:owner/repo.git). vibe-coder generates an ed25519 key pair; you register the public key in your git provider.

Storage

File Purpose Permissions
~/.config/vibe-coder/git-tokens.json Vibe-coder's normalized PAT store (UI reads from here) 0600
~/.git-credentials Standard git CLI store. URLs of the form https://x-access-token:TOKEN@host 0600
~/.ssh/id_ed25519 + .pub SSH key pair 0600 / 0644
~/.ssh/known_hosts Pre-seeded with github.com / gitlab.com / bitbucket.org host keys 0600

All paths are bind-mounted to ./vibe-coder-data/ so they survive image upgrades.

Register a PAT

Web UI

  1. /settings/git-integrations+ New token (auto-open on first visit).
  2. Pick provider (GitHub / GitLab / Gitea / Bitbucket / generic).
  3. Host: domain only (github.com, not https://github.com).
  4. Paste the token. Username auto-defaults per provider:
    • GitHub: x-access-token
    • GitLab: oauth2
    • Bitbucket: x-token-auth
    • Gitea: vibe-coder (host doesn't care, only token matters)
  5. Click Register.

REST API

curl -X POST http://<host>:17880/api/settings/git-integrations \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{
    "provider":"github",
    "host":"github.com",
    "token":"ghp_..."
  }'

Where do I get the PAT?

Provider URL Required scope
GitHub https://github.com/settings/tokens (classic) or fine-grained repo (classic) or "Contents: Read and write" (fine-grained)
GitLab https://gitlab.com/-/user_settings/personal_access_tokens read_repository (and write_repository if you'll push)
Gitea User Settings → Applications → Generate New Token read:repository
Bitbucket Personal settings → App passwords Repository: Read (and Write if push)

SSH key — auto-provisioning (v1.2.0+)

Since v1.2.0 the entrypoint script auto-generates an ED25519 keypair on first container boot at /home/vibe/.ssh/id_ed25519, persisted via the ./vibe-coder-data/dev-tools/ssh/ bind mount (see Data-Volumes). Once present it is never overwritten — your key survives docker compose pull && up -d and even ad-hoc --force-recreate.

v1.2.0 / v1.3.0 regression: those images shipped without openssh-client, so ssh-keygen failed on first boot and the container crashed in a restart loop. Fixed in v1.3.1 (image siamakerlab/vibe-coder-server:1.3.1 / :latest). Upgrade with docker compose pull && up -d.

Dedicated settings page (recommended)

Admin UI → Settings → SSH Key (/settings/ssh-key):

  1. Public key is displayed in a copyable monospace textbox.
  2. Click Copy.
  3. Paste it into your Git host's SSH Keys page (Gitea / GitHub / GitLab / Bitbucket).
  4. git@host:owner/repo.git URLs now work in project register and git clone/push over SSH.

The page also shows algorithm / fingerprint / comment / created-at, and a Regenerate card that backs up the current key as id_ed25519.bak.<ts> before issuing a fresh keypair (you must then re-register the new public key on every Git host you use).

REST API (v1.2.0+)

# View
curl -fsS http://<host>:17880/api/server/ssh-key \
  -H "Authorization: Bearer $TOKEN"
# {
#   "publicKey": "ssh-ed25519 AAAA... vibe-coder-server@host-20260526",
#   "algorithm": "ssh-ed25519",
#   "fingerprint": "SHA256:abc…",
#   "comment": "vibe-coder-server@host-20260526",
#   "createdAt": "2026-05-26T11:00:00Z"
# }

# Regenerate (backs up old → new key returned)
curl -X POST http://<host>:17880/api/server/ssh-key/regenerate \
  -H "Authorization: Bearer $TOKEN"

Legacy: lazy generation via /settings/git-integrations

Pre-v1.2.0 the SSH key was created lazily when the user clicked Generate SSH key under /settings/git-integrations (REST: POST /api/settings/git-integrations/ssh-keygen). That endpoint still works and is idempotent (no-op if the eager v1.2.0+ key already exists), but the dedicated /settings/ssh-key page above is the preferred path going forward.

Use the credentials — project register

# HTTPS (PAT auto-picked from ~/.git-credentials)
curl -X POST http://<host>:17880/api/projects/register \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{
    "projectId":"my-private",
    "appName":"My Private",
    "packageName":"com.example.priv",
    "sourceType":"clone",
    "cloneUrl":"https://github.com/owner/private-repo.git"
  }'

# SSH
curl -X POST http://<host>:17880/api/projects/register \
  ... -d '{ ..., "cloneUrl":"git@github.com:owner/private-repo.git" }'

The server runs git clone --progress with:

  • GIT_TERMINAL_PROMPT=0 (so an unauthenticated request fails fast instead of hanging on stdin)
  • GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=accept-new -o BatchMode=yes" (auto-accepts new host keys, never prompts)

If clone fails, the partial directory is automatically cleaned up.

Common errors

Code Cause Fix
400 missing_clone_url sourceType=clone but cloneUrl empty Provide cloneUrl
400 bad_url_scheme URL not https:// or git@host: Use a supported scheme
400 unsafe_url URL contains file:// or .. Don't try to clone local paths
409 target_not_empty Project folder already has files Pick a different projectId
502 clone_failed (exit 128) Authentication failed Register a PAT or SSH key; check cloneUrl typos
504 timeout clone exceeded 10 min Slow network or huge repo; clone manually inside the container with --depth=1

Security notes

  • PATs are stored in plaintext (0600 file). vibe-coder is a single-user LAN tool; OS file permissions are the boundary.
  • Tokens are masked in any UI response (last 4 chars + bullets).
  • Revoking a token: delete from the UI/API → the underlying ~/.git-credentials is rewritten without that entry.
  • Best practice: use short-lived fine-grained PATs scoped to specific repos; rotate quarterly.

Clone this wiki locally