Alex Netsch add92d94f4 Fix PR creation remote/branch resolution for forks (Vibe Kanban) (#1976)
* So `git-url-parse` can give us `owner()` and `repo()` through the provider. That's cleaner than manual string parsing.

Let me present the options to you:

**Option 1: `git-url-parse` crate**
- Pros: Specifically designed for git URLs, gives owner/repo directly via provider
- Cons: New dependency (though small)

**Option 2: `gix-url` crate**
- Pros: Part of gitoxide (well-maintained), robust parsing
- Cons: New dependency, still need to extract owner/repo from path

**Option 3: Keep current approach but improve it**
- Use the `url` crate we already have for HTTPS URLs
- Handle SSH URLs as a special case (they use `:` instead of `/`)
- Less string magic, more structured

**Option 4: Use `gh` CLI to parse**
- `gh repo view <url> --json owner,name`
- Pros: No new deps, `gh` handles all edge cases
- Cons: Requires network/auth, slower

Which approach would you prefer? I'd recommend **Option 1 (`git-url-parse`)** since it's purpose-built for this exact use case.

* Cleanup script changes for workspace a07fdbcf-0608-4a84-a012-53d4fee6d115

* Let me provide a summary of all the changes made:

## Summary

Fixed the hardcoded remote handling to support fork workflows. Here's what changed:

### 1. `crates/services/src/services/git.rs`
- **`default_remote_name()`**: Now prefers "origin" (git's convention) instead of arbitrarily picking the first remote
- **`get_remote_url()`**: New helper to get the URL of a specific remote by name
- **`get_remote_url_from_branch_or_default()`**: New helper that gets the remote URL for a branch, falling back to default remote

### 2. `crates/services/src/services/git/cli.rs`
- **`default_remote_name()`**: Same fix as above - prefers "origin"
- **`get_remote_url()`**: New method to get remote URL by name

### 3. `crates/services/src/services/git_host/github/cli.rs`
- **`get_repo_info_from_url()`**: New method that uses `gh repo view <url> --json owner,name` to parse owner/repo from a remote URL (no string magic!)

### 4. `crates/services/src/services/git_host/github/mod.rs`
- **`get_repo_info_from_url()`**: Async wrapper for the new CLI method
- **`create_pr()`**: Now uses `get_repo_info_from_url()` with the `remote_url` parameter to determine which repo to create the PR against

### 5. `crates/server/src/routes/task_attempts/pr.rs`
- **Key fix**: Now extracts the target remote URL from the `target_branch` (e.g., `upstream/main`) instead of from `workspace.branch` (your task branch)
- This enables fork workflows: push to your fork (`origin`), but create PR against upstream (the target branch's remote)

### How fork workflows now work:
1. User selects target branch like `upstream/main`
2. Code pushes task branch to `origin` (your fork)
3. Code extracts remote URL from `upstream` remote (the upstream repo)
4. PR is created against the upstream repo using `gh pr create --repo upstream-owner/repo`

* Cleanup script changes for workspace a07fdbcf-0608-4a84-a012-53d4fee6d115

* Build passes. The response structs are now at module level alongside the other `Gh*` response types, which is cleaner and more consistent with the existing code style.

* Build passes. Now `gh repo view <url>` is run from the repo directory, which helps with GitHub Enterprise authentication context.

* Done. Removed all the redundant comments.

* Build passes.

* Build passes. Now the default remote logic follows git's behavior:

1. Check `remote.pushDefault` config first (user's explicit preference)
2. Fall back to "origin" if it exists (git's convention from `git clone`)
3. Fall back to first remote if no "origin"
4. Default to "origin" if no remotes exist

* I've fixed the bug in `check_remote_branch_exists` at `git.rs:1454-1484`. The issue was that when checking if a remote branch exists, the function was:

1. Using `default_remote_name()` (which returns "origin") to strip the prefix from branch names like `upstream/main`
2. Looking up the URL from the default remote instead of the actual remote the branch belongs to

Now the function:
1. For remote branches (like `upstream/main`), extracts the actual remote name from the branch using `get_remote_name_from_branch_name()`
2. Strips the correct prefix (`upstream/` not `origin/`)
3. Uses the correct remote's URL for the `git ls-remote` check

This allows fork workflows where you select `upstream/main` as the target branch - it will now correctly check if `main` exists on the `upstream` remote's URL.

* Cleanup script changes for workspace a07fdbcf-0608-4a84-a012-53d4fee6d115

* Fix cross-fork PR creation by formatting head branch with fork owner

When creating a PR from a fork to upstream, GitHub requires the head branch
to be formatted as "owner:branch" (e.g., "LSRCT:vk/feature-branch").
Added head_repo_url to CreatePrRequest and updated GitHubProvider to
compare owners and prefix the head branch accordingly.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Refactor PR remote handling: simplify by moving logic to caller

- Delete check_remote_branch_exists() from GitService (caller now composes
  the check directly using GitCli)
- Add default_remote_name_for_path() convenience method
- Rewrite pr.rs remote handling to be explicit and linear:
  1. Get push_remote and target_remote names
  2. Get their URLs
  3. Strip prefix to get base_branch
  4. Check, push, create PR

The string split happens once, visibly at the call site.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Remove origin preference in default_remote_name

Use first available remote instead of preferring "origin". The fallback
to "origin" only applies when there are no remotes configured at all.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix PR creation when target branch not fetched locally

When the target branch doesn't exist as a local remote-tracking ref
(e.g., user types a branch name that exists on remote but isn't fetched),
fall back to using the push remote instead of failing with BranchNotFound.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Reject cross-fork PRs for Azure DevOps

Azure DevOps fork PRs require different handling (--fork-id parameter).
Return a clear error instead of silently failing.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Remove get_repo_info, always use explicit URL

The parameterless get_repo_info relied on gh CLI guessing the repo from
local git config. This is wrong for fork workflows where we need to
operate on a specific remote's repo. Now list_prs_for_branch and
get_pr_comments use the remote_url they're passed instead of ignoring it.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Format git service default remote helper

* Fix clippy collapsible-if warnings

* Route remote branch checks through git service

* Remove Azure PR comment

* Consolidate git remote helpers

* Consolidate git remote resolution helpers

* Remove unnecessary comments

* Fix git service error match for remote check

* Remove unused GitCli::default_remote_name

GitService::default_remote_name (using git2) is used instead.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Refactor unused vars

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 12:46:43 +00:00
2025-08-08 13:53:27 +01:00
2026-01-14 11:12:48 +00:00
2025-11-14 15:37:56 +00:00
2025-12-16 10:55:27 +00:00
2025-11-14 15:37:56 +00:00
2026-01-14 11:12:48 +00:00
2026-01-08 11:29:44 +00:00
2025-07-11 15:57:30 +01:00
2025-12-15 19:42:13 +00:00
2025-07-11 16:31:08 +01:00
2026-01-14 11:12:48 +00:00
2025-06-25 09:27:29 +01:00

Vibe Kanban Logo

Get 10X more out of Claude Code, Gemini CLI, Codex, Amp and other coding agents...

npm Build status Ask DeepWiki

We're hiring!

Overview

AI coding agents are increasingly writing the world's code and human engineers now spend the majority of their time planning, reviewing, and orchestrating tasks. Vibe Kanban streamlines this process, enabling you to:

  • Easily switch between different coding agents
  • Orchestrate the execution of multiple coding agents in parallel or in sequence
  • Quickly review work and start dev servers
  • Track the status of tasks that your coding agents are working on
  • Centralise configuration of coding agent MCP configs
  • Open projects remotely via SSH when running Vibe Kanban on a remote server

You can watch a video overview here.

Installation

Make sure you have authenticated with your favourite coding agent. A full list of supported coding agents can be found in the docs. Then in your terminal run:

npx vibe-kanban

Documentation

Please head to the website for the latest documentation and user guides.

Support

We use GitHub Discussions for feature requests. Please open a discussion to create a feature request. For bugs please open an issue on this repo.

Contributing

We would prefer that ideas and changes are first raised with the core team via GitHub Discussions or Discord, where we can discuss implementation details and alignment with the existing roadmap. Please do not open PRs without first discussing your proposal with the team.

Development

Prerequisites

Additional development tools:

cargo install cargo-watch
cargo install sqlx-cli

Install dependencies:

pnpm i

Running the dev server

pnpm run dev

This will start the backend. A blank DB will be copied from the dev_assets_seed folder.

Building the frontend

To build just the frontend:

cd frontend
pnpm build

Build from source (macOS)

  1. Run ./local-build.sh
  2. Test with cd npx-cli && node bin/cli.js

Environment Variables

The following environment variables can be configured at build time or runtime:

Variable Type Default Description
POSTHOG_API_KEY Build-time Empty PostHog analytics API key (disables analytics if empty)
POSTHOG_API_ENDPOINT Build-time Empty PostHog analytics endpoint (disables analytics if empty)
PORT Runtime Auto-assign Production: Server port. Dev: Frontend port (backend uses PORT+1)
BACKEND_PORT Runtime 0 (auto-assign) Backend server port (dev mode only, overrides PORT+1)
FRONTEND_PORT Runtime 3000 Frontend dev server port (dev mode only, overrides PORT)
HOST Runtime 127.0.0.1 Backend server host
DISABLE_WORKTREE_ORPHAN_CLEANUP Runtime Not set Disable git worktree cleanup (for debugging)

Build-time variables must be set when running pnpm run build. Runtime variables are read when the application starts.

Remote Deployment

When running Vibe Kanban on a remote server (e.g., via systemctl, Docker, or cloud hosting), you can configure your editor to open projects via SSH:

  1. Access via tunnel: Use Cloudflare Tunnel, ngrok, or similar to expose the web UI
  2. Configure remote SSH in Settings → Editor Integration:
    • Set Remote SSH Host to your server hostname or IP
    • Set Remote SSH User to your SSH username (optional)
  3. Prerequisites:
    • SSH access from your local machine to the remote server
    • SSH keys configured (passwordless authentication)
    • VSCode Remote-SSH extension

When configured, the "Open in VSCode" buttons will generate URLs like vscode://vscode-remote/ssh-remote+user@host/path that open your local editor and connect to the remote server.

See the documentation for detailed setup instructions.

Description
Get 10X more out of Claude Code, Codex or any coding agent
https://www.vibekanban.com/
Readme Apache-2.0 48 MiB
Languages
Rust 51.1%
TypeScript 46.6%
CSS 1.1%
JavaScript 0.7%
PLpgSQL 0.2%
Other 0.2%