* Perfect! I've successfully refactored the editor opening code to use the `CommandBuilder` pattern. Here's a summary of the changes: - Added `use executors::command::CommandBuilder;` - Changed return type from `Vec<String>` to `CommandBuilder` - Now returns a proper `CommandBuilder` that handles shell word splitting correctly - Supports quoted strings in custom commands (via `shlex` on Unix, `winsplit` on Windows) - Uses `CommandBuilder` pattern: `build_initial()` → `into_resolved()` - Resolves executables properly on **both Unix and Windows** (previously only Windows had resolution) - Better error messages that show which executable couldn't be found - Maps `ExecutorError` to `io::Error` for consistency with the function signature ✅ **Consistent cross-platform behavior**: Unix now also resolves executables properly ✅ **Sophisticated PATH resolution**: Uses login shell refresh logic for finding executables ✅ **Proper shell word splitting**: Handles quoted strings correctly in custom commands ✅ **Better error messages**: Shows exactly which executable couldn't be found ✅ **Follows established patterns**: Uses the same proven pattern as other executors in the codebase All checks pass: compilation, tests, and Clippy linting. The code is ready! Perfect! All changes have been successfully implemented and tested. Here's what was done: - Changed from: `Result<ResponseJson<ApiResponse<OpenEditorResponse>>, StatusCode>` - Changed to: `Result<ResponseJson<ApiResponse<OpenEditorResponse>>, ApiError>` - Changed from: `Err(StatusCode::INTERNAL_SERVER_ERROR)` (generic 500 error) - Changed to: `Err(ApiError::Io(e))` (passes actual error message) Now when the editor command fails (e.g., executable not found), the API will return a proper error response with the actual error message like: - `"IoError: Editor command not found: Executable 'cursor' not found in PATH"` This matches the pattern already used in `task_attempts.rs` and provides meaningful feedback to the frontend, which can display the error to users or fall back to the editor selection dialog. All checks pass: compilation, TypeScript type checking, and Clippy linting! Perfect! All changes have been successfully implemented and tested. Here's a summary: - New `EditorOpenError` enum with `ExecutableNotFound` variant - Contains structured fields: `executable` (the command that wasn't found) and `editor_type` (the configured editor) - Exports to TypeScript with discriminated union type - Changed `open_file()` return type: `Result<Option<String>, io::Error>` → `Result<Option<String>, EditorOpenError>` - Changed `spawn_local()` return type: `io::Result<()>` → `Result<(), EditorOpenError>` - Maps `ExecutorError::ExecutableNotFound` to structured `EditorOpenError::ExecutableNotFound` - Removed unused `io` import - Added `EditorOpen(#[from] EditorOpenError)` variant - Maps to `StatusCode::BAD_REQUEST` (400) instead of 500 - Returns proper error type: `"EditorOpenError"` - **`crates/server/src/routes/projects.rs:452`**: Changed from `ApiError::Io(e)` to `ApiError::EditorOpen(e)` - **`crates/server/src/routes/task_attempts.rs:965`**: Changed from generic `TaskAttemptError::ValidationError` to `ApiError::EditorOpen(e)` ```typescript export type EditorOpenError = { "type": "executable_not_found", executable: string, editor_type: string, }; ``` Now when an editor executable isn't found, the frontend receives: ```json { "type": "executable_not_found", "executable": "cursor", "editor_type": "CURSOR" } ``` Instead of a generic 500 error. This allows the frontend to: - Show specific error messages ("Cursor not found in PATH") - Suggest alternative editors - Provide installation links or PATH setup instructions - Offer to open the editor settings dialog All checks pass: compilation, TypeScript type checking, Clippy linting, and tests! Cleanup script changes for task attempt f9923e07-9b3b-4d18-b4d1-d4235cf0e12d * Refactor editor config (vibe-kanban a60c079b) Currently edit config is defined in crates/services/src/services/config/versions/v2.rs, we should consider moving it into a module instead. Weigh pros and cons, best practices and the current architecture * Review editor refactor (vibe-kanban 829ba3e5) Review the last 5 commits There's a rebase conflict in `GeneralSettings.tsx` that needs resolution. The conflict is in the imports: **Conflict (lines 41-49):** - **Your branch (HEAD)**: Imports from `ThemeProvider` and `ConfigProvider` (PascalCase) - **Main branch**: Imports from `theme-provider` and `config-provider` (kebab-case) + adds new editor availability features **Resolution needed:** Keep the main branch version because it: 1. Uses the newer kebab-case file naming convention 2. Adds `useEditorAvailability` and `EditorAvailabilityIndicator` features that complement your error handling work The resolved imports should be: ```typescript import { useEditorAvailability } from '@/hooks/useEditorAvailability'; import { EditorAvailabilityIndicator } from '@/components/EditorAvailabilityIndicator'; import { useTheme } from '@/components/theme-provider'; import { useUserSystem } from '@/components/config-provider'; ``` Would you like me to resolve this conflict and continue the rebase? Show available editors at startup (vibe-kanban 9f1ea85f) When onboarding, show a green checkmark next to installed editors. Use the editor struct refactored in the last 6 commits to make it work. Check eveyer editor in the enum at vk startup. Mkae sure editors being unailable does NOT break anything Fix imports after rebase - use PascalCase for ThemeProvider and ConfigProvider Perfect! All changes complete. Let me create a summary: ✅ **Changes made:** - Added `CheckEditorAvailabilityQuery::decl()` - Added `CheckEditorAvailabilityResponse::decl()` New types exported: ```typescript export type CheckEditorAvailabilityQuery = { editor_type: EditorType }; export type CheckEditorAvailabilityResponse = { available: boolean }; ``` - Added import for `CheckEditorAvailabilityResponse` - Updated `checkEditorAvailability` method: - Parameter type: `string` → `EditorType` (type-safe enum) - Return type: `{ available: boolean }` → `CheckEditorAvailabilityResponse` - ✅ Full type safety for editor availability checking - ✅ Frontend uses typed `EditorType` enum instead of strings - ✅ Consistent with other query/response type patterns - ✅ All checks pass (TypeScript + Rust compilation) The editor availability feature now has complete type safety from backend to frontend! * Fix i18n (vibe-kanban 57188642) For new editory avilability added in the last 3 commits. Run @scripts/check-i18n.sh until it passes. Make sure to check the script and set GITHUB_BASE_REF to main * Fix import: use github not github_service after rebase
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.
