A local-first web application that orchestrates multiple AI coding agents to work on code changes in isolated Git worktrees, with PR-first workflow, review capabilities, and deterministic patch-based imports.
- Features
- Architecture
- Tech Stack
- Getting Started
- Usage
- Project Structure
- API Endpoints
- Storage
- Workspace Locking
- Project Concurrency
- Agent Adapters
- Development
- Troubleshooting
- License
- Project Management: Register and manage source Git repositories with relay repository support
- Target Repos: Configure destination repositories for importing patches
- WorkItems: Create work items that own persistent worktree workspaces for code changes
- Pull Requests: First-class PR model with merge gates, conflict detection, and review
- Agent Integration: Trigger multiple AI coding agents (OpenCode, ClaudeCode) to modify code in serialized runs
- Workspace Locking: Ensures only one agent run per WorkItem at a time
- Auto-Commit: Backend automatically commits changes after each agent run
- Diff Viewing: View code changes with inline diff viewer
- Review System: Add review threads and comments to PRs with severity levels
- Patch Import: Import changes to target repositories using patch files
- Full Audit Trail: Track all agent runs, commits, and imports
- Session-based Resume: Continue conversations across multiple agent runs using session IDs
- Multiple Merge Strategies: Support for merge, squash, and rebase strategies
- Patch Export: Export PR changes as patch files
- Model Cache: Cached list of available models for each agent
- Review Addressing: Trigger agent corrections based on review comments
- Base Update: Update PR base branch and optionally rebase head
- Real-time Log Streaming: View agent logs in real-time with separate stdout/stderr
GitVibe uses a PR-centric and WorkItem-workspace-centric model:
- Workspaces are owned by WorkItems, not by PRs
- PRs control review and merge - they are the gatekeepers for code changes
- Agent runs are serialized - only one run per WorkItem at a time
- Auto-commit after runs - produces clean commit history and stable PR diffs
- sessionId is required - enables resume functionality with conversation continuity
┌─────────────────────────────────────────────────────────────────────────┐
│ GitVibe System │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Frontend │◄──►│ Backend │◄──►│ Database │ │
│ │ (React) │ │ (Fastify) │ │ (SQLite) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌──────────────┐ │ │
│ │ │ Agent Service │ │ │
│ │ └──────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌──────────────┐ │ │
│ │ │ Agent │ │ │
│ │ │ Adapters │ │ │
│ │ │ (OpenCode, │ │ │
│ │ │ ClaudeCode) │ │ │
│ │ └──────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌──────────────┐ │ │
│ └─────────────►│ Git │ │ │
│ │ Service │ │ │
│ └──────────────┘ │ │
│ │ │ │
│ ▼ │ │
│ ┌──────────────┐ │ │
│ │ Relay Repo │ │ │
│ │ + Worktrees │ │ │
│ └──────────────┘ │ │
│ │ │ │
│ ▼ │ │
│ ┌──────────────┐ │ │
│ │ Source Repo │ │ │
│ └──────────────┘ │ │
└─────────────────────────────────────────────────────────────────────────┘
- User creates WorkItem in UI
- Backend initializes workspace (git worktree + branch)
- User triggers agent run with prompt
- Backend spawns agent in worktree workspace
- Agent edits files in worktree
- Backend auto-commits changes after run
- PR is created/updated with new diff
- User reviews PR and optionally adds comments
- User merges PR (or imports to target repo)
- Node.js 20+ + TypeScript
- Fastify web framework
- SQLite database with Drizzle ORM
- Git CLI integration via child_process
- Agent adapter system (OpenCode, ClaudeCode)
- Zod for runtime validation
- Pino for logging
- React 18 + TypeScript
- Vite build tool
- TanStack Query for data fetching and caching
- TanStack Router for routing
- Tailwind CSS for styling
- React Hook Form for form management
- Lucide React for icons
- React Syntax Highlighter for code display
- TypeScript types and Zod schemas
- Shared between backend and frontend packages
- Node.js >= 20
- npm >= 10
- Git (must be available in PATH)
- AI Agent CLI (OpenCode or Claude Code) - see agent configuration below
- Clone the repository:
git clone <repository-url>
cd git-vibe- Install dependencies for all packages:
npm run install:all- Run database migrations:
npm run db:migrateStart both backend and frontend in development mode:
npm run devThis will start:
- Backend API server at
http://127.0.0.1:11031 - Frontend UI at
http://localhost:11990
Create a .env file in the backend directory:
PORT=11031
HOST=127.0.0.1
DATABASE_URL=./data/db.sqlite
STORAGE_BASE_DIR=/tmp/git-vibe
LOG_LEVEL=infoNote: Agent executable paths are configured per-project in the UI, not via environment variables. See "Agent Configuration" section below.
Build all packages:
npm run buildOr build individual packages:
npm run build:backend
npm run build:frontend
npm run build:sharedNavigate to Projects and add a source Git repository:
- Name: My Project
- Source Repo Path:
/path/to/repo - Source Repo URL: https://github.com/user/repo (optional, for reference)
- Default Branch:
main(or your default branch) - Default Agent: Choose
opencodeorclaudecode - Agent Executable Path: Path to the agent CLI (e.g.,
/usr/local/bin/opencodeor/usr/local/bin/claude) - Agent Parameters: JSON configuration for model selection, arguments, etc.
- Max Concurrency: Maximum concurrent agent runs across all WorkItems in the project (default: 3)
Navigate to Target Repos and add a destination repository:
- Name: My Target Repo
- Repo Path:
/path/to/target/repo - Default Branch:
main(or target's default branch)
Navigate to WorkItems and create a new work item:
- Select Project: Choose the project this work item belongs to
- Title: Feature description
- Body: Detailed description (optional)
- Type: Task type (
issueorfeature-request)
This creates a WorkItem that will own a persistent workspace.
The workspace is automatically initialized on the first agent run, or you can explicitly initialize it:
- WorkItem creates a git worktree on a dedicated branch
- Branch name format:
wi/<work_item_id> - Worktree path:
<storage_base_dir>/worktrees/<work_item_id>/
Navigate to the WorkItem and open a PR:
- Base branch: The branch to merge into (e.g.,
main) - The PR is automatically created with 1:1 relationship to the WorkItem
- PR tracks base SHA, head SHA, and merge status
Each project can be configured with agent settings:
- Default Agent: Choose
opencodeorclaudecode - Agent Executable Path: Path to the agent CLI (e.g.,
/usr/local/bin/opencodeor/usr/local/bin/claude) - Agent Parameters: JSON configuration for model selection, arguments, etc.
- Max Concurrency: Maximum concurrent agent runs across all WorkItems in the project (default: 3)
In the WorkItem detail view, trigger agent runs:
- Agent runs use the project's default agent configuration
- Prompt: Your task description
- Session ID: Auto-generated as
wi-<work_item_id>for conversation continuity - The system automatically initializes the workspace if needed
Workspace Locking: Only one agent run can be active per WorkItem at a time. If a run is in progress, new runs will be rejected with an error.
Project Concurrency: The project's max_agent_concurrency setting limits how many agent runs can execute simultaneously across all WorkItems in that project.
Auto-Commit: After each agent run completes successfully, the backend automatically stages and commits any changes made by the agent. This produces a clean commit history and stable PR diffs.
Session Continuity: Agent runs use WorkItem-scoped session IDs (wi-<work_item_id>) by default, enabling resume functionality where agents can continue previous conversations.
View the PR to review changes:
- Overview: PR details, status, and mergeability
- Diff: Code changes between base and head
- Commits: Commit history for the PR, grouped by agent runs
- Files Changed: List of files modified in the PR
- Checks: Agent run history and status
- Reviews: Review threads and comments
Create review threads on PRs:
- Severity: Choose
info,warning, orerror - Anchor: Select file and line number
- Comments: Add multiple comments to a thread
- Address with Agent: Trigger agent to address review comments
- Resolve/Unresolve: Mark threads as resolved or open
When satisfied with changes, merge the PR:
- Check mergeability: No conflicts, no running agent runs
- Choose merge strategy:
merge,squash, orrebase - Merge into base branch: Execute merge operation
Merge Gates:
- PR must be in
openstatus - No agent runs can be running for the WorkItem
- Workspace lock must be free
- No merge conflicts
Update PR base to latest base branch:
- Update Base: Refresh base SHA to latest base branch
- Rebase: Optionally rebase head branch onto new base
- Useful when base branch has moved forward
Export PR changes as a patch file:
- Navigate to PR detail view
- Click "Export Patch"
- Patch is generated from
base_sha..head_sha - Save patch file for manual application
Optionally import changes to your target repository:
- Navigate to PR detail view
- Select target repo
- Click Import
GitVibe will:
- Generate a patch from PR diff
- Apply patch to target repo using
git apply --3way - Create a commit with PR metadata
- Record import in history
When done, delete the WorkItem to:
- Remove the worktree
- Delete the PR
- Delete all associated records
git-vibe/
├── backend/ # Fastify API + SQLite + Git integration
│ ├── src/
│ │ ├── routes/ # API route handlers
│ │ │ ├── projects.ts
│ │ │ ├── targetRepos.ts
│ │ │ ├── pullRequests.ts
│ │ │ ├── agentRuns.ts
│ │ │ ├── reviews.ts
│ │ │ └── workitems.ts
│ │ ├── services/ # Business logic
│ │ │ ├── AgentService.ts
│ │ │ ├── AgentAdapter.ts
│ │ │ ├── OpenCodeAgentAdapter.ts
│ │ │ ├── ClaudeCodeAgentAdapter.ts
│ │ │ ├── GitService.ts
│ │ │ ├── GitWorktreeService.ts
│ │ │ ├── GitCommitService.ts
│ │ │ ├── GitFileService.ts
│ │ │ ├── GitRelayService.ts
│ │ │ ├── PRService.ts
│ │ │ ├── WorkspaceService.ts
│ │ │ ├── PromptBuilder.ts
│ │ │ └── ModelsCache.ts
│ │ ├── repositories/ # Database access layer
│ │ │ ├── ProjectsRepository.ts
│ │ │ ├── TargetReposRepository.ts
│ │ │ ├── WorkItemsRepository.ts
│ │ │ ├── PullRequestsRepository.ts
│ │ │ ├── AgentRunsRepository.ts
│ │ │ ├── ReviewThreadsRepository.ts
│ │ │ └── ReviewCommentsRepository.ts
│ │ ├── mappers/ # Database to DTO mappers
│ │ │ ├── projects.ts
│ │ │ ├── targetRepos.ts
│ │ │ ├── workItems.ts
│ │ │ ├── pullRequests.ts
│ │ │ ├── agentRuns.ts
│ │ │ └── reviews.ts
│ │ ├── models/ # Drizzle schema
│ │ │ └── schema.ts
│ │ ├── middleware/ # Fastify middleware
│ │ │ └── setup.ts
│ │ ├── db/ # Database client and migrations
│ │ │ ├── client.ts
│ │ │ ├── migrate-cli.ts
│ │ │ └── migrations.ts
│ │ ├── config/ # Configuration
│ │ │ └── storage.ts
│ │ ├── types/ # TypeScript types
│ │ │ └── models.ts
│ │ ├── utils/ # Utilities
│ │ │ └── storage.ts
│ │ └── server.ts # Server entry point
│ ├── drizzle/ # Database migrations
│ ├── package.json
│ ├── tsconfig.json
│ └── vitest.config.mjs
├── frontend/ # React + Vite application
│ ├── src/
│ │ ├── components/ # UI components
│ │ │ ├── ui/ # Base UI components
│ │ │ │ ├── Button.tsx
│ │ │ │ ├── Input.tsx
│ │ │ │ ├── Modal.tsx
│ │ │ │ ├── Tabs.tsx
│ │ │ │ ├── Select.tsx
│ │ │ │ ├── Textarea.tsx
│ │ │ │ ├── Pagination.tsx
│ │ │ │ ├── LogPane.tsx
│ │ │ │ ├── StatusBadge.tsx
│ │ │ │ ├── EmptyState.tsx
│ │ │ │ └── Skeleton.tsx
│ │ │ ├── project/ # Project-related components
│ │ │ │ ├── ProjectHeader.tsx
│ │ │ │ ├── ProjectShell.tsx
│ │ │ │ ├── OverviewTab.tsx
│ │ │ │ ├── CodeTab.tsx
│ │ │ │ ├── PullRequestsTab.tsx
│ │ │ │ ├── WorkItemsTab.tsx
│ │ │ │ ├── SettingsTab.tsx
│ │ │ │ ├── ActionsTab.tsx
│ │ │ │ └── TabNavigation.tsx
│ │ │ ├── pr/ # PR-related components
│ │ │ │ ├── PRDetail.tsx
│ │ │ │ ├── OverviewTab.tsx
│ │ │ │ ├── DiffReviewTab.tsx
│ │ │ │ ├── CommitsTab.tsx
│ │ │ │ ├── FilesChangedTab.tsx
│ │ │ │ ├── ChecksTab.tsx
│ │ │ │ ├── ConversationTab.tsx
│ │ │ │ └── AgentRunsTab.tsx
│ │ │ ├── workitem/ # WorkItem-related components
│ │ │ │ ├── WorkItemDetail.tsx
│ │ │ │ ├── DiscussionTab.tsx
│ │ │ │ ├── LogDetailTab.tsx
│ │ │ │ ├── PRStatusTab.tsx
│ │ │ │ ├── TaskManagementTab.tsx
│ │ │ │ ├── AgentConfigTab.tsx
│ │ │ │ └── CreateWorkItemModal.tsx
│ │ │ ├── review/ # Review-related components
│ │ │ │ ├── ThreadComposer.tsx
│ │ │ │ ├── ThreadActions.tsx
│ │ │ │ ├── CommentComposer.tsx
│ │ │ │ └── ThreadStatusBadge.tsx
│ │ │ ├── diff/ # Diff viewer
│ │ │ │ └── DiffViewer.tsx
│ │ │ ├── agent/ # Agent-related components
│ │ │ │ └── AgentRunConfigForm.tsx
│ │ │ ├── worktree/ # Worktree status
│ │ │ │ ├── WorktreeStatus.tsx
│ │ │ │ └── WorktreeStatusBadge.tsx
│ │ │ └── shared/ # Shared components
│ │ │ ├── Layout.tsx
│ │ │ ├── ErrorBoundary.tsx
│ │ │ └── Toast.tsx
│ │ ├── routes/ # TanStack Router config
│ │ │ ├── __root.tsx
│ │ │ ├── index.tsx
│ │ │ ├── projects/
│ │ │ │ ├── index.tsx
│ │ │ │ ├── $projectName.tsx
│ │ │ │ ├── $projectName.index.tsx
│ │ │ │ ├── $projectName.code.tsx
│ │ │ │ ├── $projectName.actions.tsx
│ │ │ │ ├── $projectName.pullrequests.tsx
│ │ │ │ ├── $projectName.workitems.tsx
│ │ │ │ └── $projectName.settings.tsx
│ │ │ └── target-repos/
│ │ │ ├── index.tsx
│ │ │ └── $id.tsx
│ │ ├── hooks/ # React hooks
│ │ │ ├── useAgentRunPolling.ts
│ │ │ ├── useBranchSelector.ts
│ │ │ ├── useDiffView.ts
│ │ │ ├── useKeyboardShortcuts.ts
│ │ │ ├── useModels.ts
│ │ │ ├── usePR.ts
│ │ │ ├── useReviewThreads.ts
│ │ │ ├── useStreamingLogs.ts
│ │ │ ├── useWorkItem.ts
│ │ │ ├── useWorkItemRefresh.ts
│ │ │ └── useWorktreeManagement.ts
│ │ ├── lib/ # API client and utilities
│ │ │ ├── api.ts
│ │ │ ├── datetime.ts
│ │ │ ├── utils.ts
│ │ │ └── validation.ts
│ │ ├── types/ # TypeScript types
│ │ │ └── index.ts
│ │ ├── index.css
│ │ └── main.tsx
│ ├── package.json
│ ├── tsconfig.json
│ ├── vite.config.ts
│ ├── tailwind.config.js
│ └── postcss.config.js
├── shared/ # Shared types and utilities
│ ├── src/
│ │ ├── types/ # Common types
│ │ │ ├── models.ts
│ │ │ ├── requests.ts
│ │ │ ├── responses.ts
│ │ │ └── common.ts
│ │ ├── codec/ # Custom codecs
│ │ │ └── datetime.ts
│ │ └── index.ts
│ ├── package.json
│ └── tsconfig.json
├── package.json # Root package.json with workspace scripts
├── PLAN.md # Architecture and design document
└── README.md # This file
GET /api/projects- List all projects with paginationPOST /api/projects- Create a projectGET /api/projects/:id- Get project detailsPATCH /api/projects/:id- Update project settingsDELETE /api/projects/:id- Delete a projectPOST /api/projects/:id/sync- Sync relay repo with source repoGET /api/projects/:id/branches- List branchesGET /api/projects/:id/files- List repository filesGET /api/projects/:id/files/content- Get file contentGET /api/models- List available agent modelsPOST /api/models/refresh- Refresh model cacheGET /api/branches- List branches by repo path
GET /api/target-repos- List all target reposPOST /api/target-repos- Create a target repoGET /api/target-repos/:id- Get target repo details
GET /api/workitems- List work items with optional project filter and paginationPOST /api/projects/:projectId/work-items- Create a work itemGET /api/workitems/:id- Get work item detailsPATCH /api/workitems/:id- Update work itemDELETE /api/workitems/:id- Delete work itemPOST /api/work-items/:id/init-workspace- Initialize workspace (optional)POST /api/workitems/:id/start- Start agent runPOST /api/workitems/:id/resume- Resume task with same session_idGET /api/workitems/:id/tasks- List all runs for work itemPOST /api/workitems/:id/tasks/:taskId/cancel- Cancel running taskPOST /api/workitems/:id/tasks/:taskId/restart- Restart task with same promptGET /api/workitems/:id/tasks/:taskId/status- Get task statusGET /api/workitems/:id/prs- Get PRs for work itemPOST /api/workitems/:id/create-pr- Create PR from work item
GET /api/pull-requests- List PRs (with optional project filter and pagination)GET /api/pull-requests/:id- Get PR detailsGET /api/pull-requests/:id/diff- Get PR diffGET /api/pull-requests/:id/commits- Get PR commitsGET /api/pull-requests/:id/commits-with-tasks- Get PR commits grouped by tasksGET /api/pull-requests/:id/statistics- Get PR statisticsPOST /api/pull-requests/:id/merge- Merge PRPOST /api/pull-requests/:id/close- Close PR without mergePOST /api/pull-requests/:id/update-base- Update base branch and optionally rebaseGET /api/pull-requests/:id/patch- Export patch
GET /api/agent-runs/:id- Get run status and logsPOST /api/agent-runs/:id/cancel- Cancel running agentGET /api/agent-runs/:id/stdout- Get stdout logGET /api/agent-runs/:id/stderr- Get stderr logGET /api/agent-runs/:id/logs- Get both stdout and stderr logs
GET /api/pull-requests/:id/reviews/threads- List review threadsPOST /api/pull-requests/:id/reviews/threads- Create threadGET /api/pull-requests/:id/reviews/threads/:threadId- Get thread detailsPOST /api/pull-requests/:id/reviews/threads/:threadId/resolve- Resolve threadPOST /api/pull-requests/:id/reviews/threads/:threadId/unresolve- Unresolve threadPOST /api/pull-requests/:id/reviews/threads/:threadId/comments- Add commentPOST /api/pull-requests/:id/reviews/threads/:threadId/address- Address with agentPOST /api/pull-requests/:id/reviews/threads/:threadId/resume- Resume from thread
All data is stored in the system temp directory:
- Linux/Mac:
/tmp/git-vibe/ - Windows:
%TEMP%\git-vibe\
Directory structure:
git-vibe/
├── data/
│ └── db.sqlite # SQLite database
├── logs/ # Agent run logs
│ ├── agent-run-<id>.log
│ ├── agent-run-<id>-stdout.log
│ └── agent-run-<id>-stderr.log
└── worktrees/ # Git worktrees for WorkItems
└── <work_item_id>/ # WorkItem workspace
To use a custom storage location, set the STORAGE_BASE_DIR environment variable in backend/.env:
STORAGE_BASE_DIR=/custom/path/to/git-vibe-dataGitVibe implements workspace locking at the WorkItem level to ensure serialized agent runs:
- Lock Fields:
lock_owner_run_idandlock_expires_aton WorkItem table - Acquisition: Before starting an agent run, the system acquires a lock on the WorkItem
- TTL: Locks have a time-to-live (TTL, default: 6 hours) for crash recovery
- Release: Lock is released after agent run finalization (success/failure/cancel)
- Conflict: If a lock is already held and not expired, new runs are rejected with an error
This prevents concurrent agent runs from corrupting the workspace state.
In addition to WorkItem-level locking, projects have configurable concurrency limits:
- Per-Project Limit:
max_agent_concurrencysetting (default: 3) - Enforcement: Limits concurrent agent runs across all WorkItems in a project
- Purpose: Prevents resource exhaustion when multiple WorkItems are active
- Tracking: Managed in-memory by
AgentService
GitVibe supports multiple AI coding agents through an adapter system:
- Key:
opencode - Executable:
opencodeCLI - Features: Full agent execution, model selection, session management
- Key:
claudecode - Executable:
claudeCLI - Features: Full agent execution with
--session-idsupport for conversation continuity
To add a new agent adapter:
- Create a new adapter class extending
AgentAdapter - Implement required methods:
validate(): Check executable availabilityrun(): Execute agent with promptcorrectWithReviewComments(): Resume/correct with review feedbackgetModels(): List available modelscancel(): Cancel running processgetStatus(): Check run status
- Register the adapter in
AgentServiceconstructor - Update
AgentTypeunion type in shared types
Run tests for the backend:
cd backend
npm testRun tests once:
cd backend
npm run test:runThe project uses:
- ESLint for linting
- Prettier for code formatting
- TypeScript strict mode
Run linting and formatting:
npm run lint
npm run formatLint/format individual packages:
npm run lint:backend
npm run format:backend
# etc.Generate new migrations:
cd backend
npm run db:generateRun migrations:
npm run db:migrateView database with Drizzle Studio:
cd backend
npm run db:studioWhen adding new API endpoints:
- Add route handler in
backend/src/routes/ - Add repository methods in
backend/src/repositories/ - Add service methods in
backend/src/services/ - Add DTOs in
shared/src/types/ - Update frontend API client in
frontend/src/lib/api.ts
When adding new UI components:
- Create component in
frontend/src/components/ - Add hook in
frontend/src/hooks/if needed - Add route in
frontend/src/routes/ - Update API client if needed
- Agent runs use WorkItem-scoped session IDs by default:
wi-<work_item_id> - This enables conversation continuity across multiple runs
- Resume functionality creates new AgentRun records but reuses the same session_id
- Only successful agent runs trigger auto-commit
- Failed runs leave workspace unchanged for debugging
- Commit messages follow format:
AgentRun <id>: <input_summary>
- Review threads can be created on PRs with file/line anchors
- Comments can be added to threads
- Threads can be resolved/unresolved
- Review comments can trigger agent corrections via
addressendpoint
- Patch-based import strategy (currently only strategy)
- Generates patch from PR diff (
base_sha..head_sha) - Applies patch to target repository using
git apply --3way - Creates commit with PR metadata
- Tracks import history with status and logs
If you get "Executable not found" errors:
- Verify that the agent executable is in your PATH
- Or provide the full path in project settings
- Check that the executable has execute permissions
If a WorkItem is stuck in locked state:
- Check if an agent run is actually running
- If not, the lock TTL will expire (default: 6 hours)
- Or manually release the lock via the database
If worktree operations fail:
- Ensure that the relay repository path is correct
- Check that the repository is a valid Git repo
- Run
git worktree pruneto clean up stale worktrees
If merge fails due to conflicts:
- Update the PR base to the latest base branch
- Rebase the head branch onto the new base
- Resolve conflicts manually in the worktree
- Try merge again
If you encounter database issues:
- Delete the database file:
data/db.sqlite - Run migrations again:
npm run db:migrate - Note: This will delete all your data
If you get "Port already in use" error:
- Check if another instance is running
- Or change the PORT in
backend/.env - Default port is 11031
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new features
- Ensure all tests pass
- Submit a pull request
MIT
For detailed architecture and design decisions, see PLAN.md.