* Excellent! I've successfully implemented the pre-flight check for target branch existence before PR creation. Here's what I did: ## Summary I've added a pre-flight check that verifies the target branch exists on the remote before attempting to create a pull request. This provides a clear, early error message instead of failing during the GitHub API call. ### Changes Made 1. **Added `fetch_and_check_branch_exists()` method** in `crates/services/src/services/git.rs:1414-1446`: - Fetches from the remote to update tracking refs - Checks if the target branch exists (both local and remote branches) - Uses best-effort fetching (doesn't fail if fetch fails) - Returns `Ok(true)` if branch exists, `Ok(false)` if not 2. **Added pre-flight check** in `crates/server/src/routes/task_attempts.rs:639-667`: - Placed before pushing the branch to GitHub - Fetches and verifies the target branch exists - Returns a clear error message if the branch doesn't exist - Continues with PR creation even if the check fails (fallback to GitHub API error) - Includes logging for debugging ### Key Features - **Fail-fast approach**: Catches missing target branch before wasting time on the GitHub API call - **Clear error messages**: Users get an actionable error message: "Target branch 'X' does not exist on remote. Please ensure the branch exists before creating a pull request." - **Graceful degradation**: If the fetch/check fails for any reason, the code continues and lets the GitHub API handle the error (existing fallback behavior) - **Works with all git remotes**: Not GitHub-specific, uses git fetch - **Performance trade-off**: Adds 1-3 seconds for the fetch operation, but provides better UX ### Testing All checks passed: - ✅ Rust compilation (cargo clippy) - ✅ TypeScript type generation (npm run generate-types:check) The implementation follows the "Option A - Fetch-then-check" approach from the task description, providing early detection of missing target branches while maintaining backward compatibility with the existing error handling. * Cleanup script changes for task attempt 607cef96-2669-46e6-bee9-fd2d524be0bd * Perfect! All the review comments have been addressed: ## Changes Made 1. **Simplified `fetch_and_check_branch_exists()` in git.rs** - Now uses the existing `Self::find_branch()` helper method instead of manually calling `repo.find_branch()` twice, making the code cleaner and more consistent with the rest of the codebase. 2. **Removed all comments** from both files - The code is now self-explanatory without the verbose comments. 3. **Removed all logging** from task_attempts.rs - No more `tracing::info!`, `tracing::warn!`, or `tracing::error!` calls for the pre-flight check. 4. **Simplified control flow** - Changed from a match statement to a cleaner if-let pattern as suggested by clippy. The implementation is now more concise while maintaining the same functionality: - Fetches from remote and checks if the target branch exists - Returns a clear error if the branch doesn't exist - Silently continues on success or fetch errors (letting GitHub API handle any remaining issues) All compilation checks pass successfully. * Perfect! All checks pass. Let me create a summary of the changes: I've successfully added a typed error for the missing target branch case. Here's what was changed: 1. **Added `TargetBranchNotFound` variant to `GitHubServiceError`** in `crates/services/src/services/github.rs:38-40`: - Takes a `String` parameter for the branch name - Includes a clear error message - Marked with `#[ts(skip)]` since it has a parameter 2. **Updated `is_api_data()` method** in `crates/services/src/services/github.rs:93`: - Added `GitHubServiceError::TargetBranchNotFound(_)` to the match pattern - This ensures the error is properly typed and won't be retried 3. **Updated `create_github_pr()`** in `crates/server/src/routes/task_attempts.rs:643-645`: - Replaced the string error message with `GitHubServiceError::TargetBranchNotFound(target_branch.clone())` - Now uses `ApiResponse::error_with_data()` instead of `ApiResponse::error()`, consistent with other typed errors in the function - **Type-safe error handling**: Frontend can now properly discriminate this error type - **Consistent with existing patterns**: Follows the same pattern as `TokenInvalid`, `InsufficientPermissions`, etc. - **Better API design**: The error is now part of the function's return type signature All compilation and type generation checks pass successfully! * Great! All checks pass. Let me create a summary: I've successfully added frontend error handling for the `target_branch_not_found` error. Here's what was done: 1. **Added translation key** in `frontend/src/i18n/locales/en/tasks.json:345`: - Key: `createPrDialog.errors.targetBranchNotFound` - Message: `"Target branch '{{branch}}' does not exist on remote. Please ensure the branch exists before creating a pull request."` - Uses interpolation to inject the branch name dynamically 2. **Added error handler** in `frontend/src/components/dialogs/tasks/CreatePRDialog.tsx:187-195`: - Checks if `result.error.type === 'target_branch_not_found'` - Extracts the `branch` field from the error object - Displays localized error message with the branch name interpolated - Clears the GH CLI helper UI state When a user tries to create a PR with a non-existent target branch: 1. **Backend pre-flight check** fetches from remote and checks if the target branch exists 2. **If branch doesn't exist**: Returns `CreatePrError::TargetBranchNotFound { branch: "xyz" }` 3. **Frontend receives** typed error with discriminant `type: "target_branch_not_found"` and `branch: "xyz"` 4. **Dialog displays**: "Target branch 'xyz' does not exist on remote. Please ensure the branch exists before creating a pull request." All checks pass (TypeScript compilation, linting, type generation). * Excellent! All checks pass. Here's the summary: I've successfully added the `targetBranchNotFound` translation key to all 3 missing locale files: 1. **Spanish (es)** - `frontend/src/i18n/locales/es/tasks.json:121`: - `"La rama objetivo '{{branch}}' no existe en el remoto. Por favor, asegúrese de que la rama exista antes de crear una solicitud de extracción."` 2. **Japanese (ja)** - `frontend/src/i18n/locales/ja/tasks.json:121`: - `"ターゲットブランチ '{{branch}}' がリモートに存在しません。プルリクエストを作成する前にブランチが存在することを確認してください。"` 3. **Korean (ko)** - `frontend/src/i18n/locales/ko/tasks.json:121`: - `"대상 브랜치 '{{branch}}'이(가) 원격에 존재하지 않습니다. 풀 리퀘스트를 생성하기 전에 브랜치가 존재하는지 확인하세요."` All translations follow the same pattern with the `{{branch}}` interpolation parameter and maintain consistency with the existing error messages in each locale. All checks pass (TypeScript compilation, frontend and backend checks)! Fix i18n * Perfect! All checks pass. Here's the complete summary: ## Summary I've successfully fixed the branch name format handling issue in `check_remote_branch_exists()`. ### The Problem The method only tried the exact branch name provided (e.g., "main"), but git2's `find_branch()` with `BranchType::Remote` requires the full remote branch name (e.g., "origin/main"). This meant: - ❌ User provides "main" → check fails (should succeed if origin/main exists) - ✅ User provides "origin/main" → check succeeds ### The Fix Updated `check_remote_branch_exists()` in `crates/services/src/services/git.rs:1414-1428` to try both formats: 1. **First attempt**: Try the branch name as-is (handles "origin/main" format) 2. **Fallback**: Prepend default remote name (handles "main" format → "origin/main") This follows the same pattern used by `find_branch()`, `find_branch_type()`, and `check_branch_exists()` throughout the codebase. ### Complete Implementation The full pre-flight check implementation now includes: **Backend:** - ✅ Fetches from remote to get latest refs - ✅ Checks if target branch exists (handles both "main" and "origin/main" formats) - ✅ Returns typed error `CreatePrError::TargetBranchNotFound { branch }` - ✅ Handles auth errors during fetch → `CreatePrError::GitCliNotLoggedIn` - ✅ Handles missing git CLI → `CreatePrError::GitCliNotInstalled` **Frontend:** - ✅ Handles `target_branch_not_found` error type in CreatePRDialog - ✅ Displays localized error message with branch name - ✅ Translations added for all 4 locales (en, es, ja, ko) All checks pass! * Lint * Change pre-flight check for create PR (vibe-kanban 4f79fbc8) to use git ls-remote --branches to check for remote branche existence instead of libgit2. To do this add an appropriate method to crates/services/src/services/git/cli.rs and modify the preflight check. * Perfect! All checks pass. The implementation is now complete: ## Complete Implementation Summary ### What Was Built A pre-flight check for PR creation that verifies the target branch exists on the remote before attempting to create the pull request. ### Key Changes **Backend:** 1. **`check_remote_branch_exists()`** in `git.rs:1414-1428` - Checks if a branch exists remotely, handles both "main" and "origin/main" formats 2. **`fetch_and_check_branch_exists()`** in `git.rs:1430-1439` - Fetches from remote then checks existence, propagates errors 3. **`CreatePrError::TargetBranchNotFound`** in `task_attempts.rs:616` - New typed error variant with branch name 4. **Pre-flight check** in `create_github_pr()` in `task_attempts.rs:639-662` - Validates target branch exists, handles auth errors **Frontend:** 1. **Error handler** in `CreatePRDialog.tsx:187-195` - Displays localized error message 2. **Translations** in all 4 locales (en, es, ja, ko) - Localized error messages with branch name interpolation ### What Works - ✅ Detects missing target branches before push/PR creation - ✅ Handles "main" and "origin/main" branch name formats - ✅ Fails fast on auth errors during fetch - ✅ Returns typed errors the frontend can handle - ✅ Displays clear, localized error messages with the branch name - ✅ All checks pass (Rust clippy, TypeScript, type generation)
macos-13 to macos-15-intel for the x86_64-apple-darwin build, with a comment explaining this is the last Intel runner image. (#1326)
Get 10X more out of Claude Code, Gemini CLI, Codex, Amp and other coding agents...
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
- Run
build-npm-package.sh - In the
npx-clifolder runnpm pack - You can run your build with
npx [GENERATED FILE].tgz
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) |
BACKEND_PORT |
Runtime | 0 (auto-assign) |
Backend server port |
FRONTEND_PORT |
Runtime | 3000 |
Frontend development server 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:
- Access via tunnel: Use Cloudflare Tunnel, ngrok, or similar to expose the web UI
- 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)
- 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.
