Local Development Setup

Guide for setting up a local development environment.

Prerequisites

  • Git - Required; pnpm dev checks for it
  • Node.js 24 - Matches the Docker image
  • pnpm 10 - Package manager (required for workspaces; the repo pins [email protected])
  • Bun - Backend runtime
  • OpenCode TUI 2.x, 2.1.2 or newer - curl -fsSL https://opencode.ai/v2/install | bash

Installation

# Clone the repository
git clone https://github.com/chriswritescode-dev/opencode-manager.git
cd opencode-manager

# Install dependencies
pnpm install

The pnpm dev command automatically runs scripts/setup-dev.sh first, which:

  • Checks prerequisites (pnpm, bun, git, and OpenCode 2.x at 2.1.2 or newer, below 3.0.0)
  • Creates workspace/ with repos/ and config/ if it is missing
  • Runs pnpm install
  • Copies .env.example to .env if missing

Then start development servers:

pnpm dev

This starts:

Project Structure

opencode-manager/
├── backend/              # Bun + Hono API server
│   ├── src/
│   │   ├── routes/       # API route handlers
│   │   ├── services/     # Business logic
│   │   ├── db/           # Database migrations and queries
│   │   │   └── migrations/  # Migration files, one per id
│   │   ├── types/        # TypeScript types
│   │   ├── utils/        # Utility functions
│   │   └── index.ts      # Entry point
│   └── test/             # Backend tests
├── frontend/             # React + Vite SPA
│   ├── src/
│   │   ├── components/   # UI components
│   │   ├── pages/        # Page components
│   │   ├── hooks/        # Custom React hooks
│   │   ├── api/          # API client
│   │   ├── lib/          # Utilities
│   │   ├── stores/       # Zustand stores
│   │   └── contexts/     # React contexts
│   └── public/           # Static assets
├── shared/               # @opencode-manager/shared types and utilities
├── ocm-cli/              # ocm CLI for attaching a local OpenCode TUI to Manager repos
├── workspace/            # Runtime workspace for OpenCode
├── scripts/              # Build and utility scripts
├── Dockerfile            # Docker image definition
└── docker-compose.yml    # Docker Compose configuration

Available Scripts

Root Level

pnpm dev          # Start both backend and frontend (runs setup-dev.sh first)
pnpm dev:backend  # Start backend only
pnpm dev:frontend # Start frontend only
pnpm build        # Build CLI, backend, and frontend
pnpm lint         # Lint CLI, frontend, and backend
pnpm test         # Run CLI, backend, and frontend tests

Backend

cd backend
bun --watch-path src --watch src/index.ts  # Start with hot reload
pnpm test                 # Run bun tests, then Vitest with coverage
vitest <file>             # Run single test file
vitest --ui               # Test UI
vitest --coverage         # Coverage report
eslint . --ext .ts        # Lint
tsc --noEmit              # TypeScript check

Frontend

cd frontend
pnpm dev          # Start Vite dev server
pnpm build        # Production build
pnpm lint         # ESLint
pnpm typecheck    # TypeScript check

Database

Using Bun's built-in SQLite (bun:sqlite). Migrations are identified by id and recorded in the applied_migrations table.

Location

  • Development: ./data/opencode.db
  • Docker: /app/data/opencode.db

Schema Changes

  1. Add backend/src/db/migrations/<YYYYMMDDHHmm>-<short-name>.ts, named with a UTC timestamp (e.g., 202610061345-schedule-workspace-mode.ts), and set the migration's id to the file name. Make up safe to run on a database that already has the change, because merged branches may apply migrations in a different order
  2. Import it and append it to allMigrations in backend/src/db/migrations/index.ts
  3. Migrations run automatically on startup

Inspection

sqlite3 ./data/opencode.db

# Useful commands
.tables                  # List tables
.schema user             # Show table schema
SELECT * FROM user;      # View data

Testing

Running Tests

# All tests
cd backend && pnpm test

# Single file
cd backend && pnpm exec vitest run test/services/repo.test.ts

# With UI
cd backend && pnpm test:ui

# Vitest suite only, with coverage
cd backend && pnpm test:vitest

Writing Tests

import path from 'path'
import { describe, it, expect } from 'vitest'
import { Database } from 'bun:sqlite'
import { getReposPath } from '@opencode-manager/shared/config/env'
import { migrate } from '../src/db/migration-runner'
import { allMigrations } from '../src/db/migrations'
import { createRepoRow } from '../src/services/repo'

describe('createRepoRow', () => {
  it('creates a ready local repo row', () => {
    const db = new Database(':memory:')
    migrate(db, allMigrations)

    const { repo, created } = createRepoRow(db, {
      name: 'demo',
      localPath: 'demo',
      fullPath: path.join(getReposPath(), 'demo'),
    })

    expect(created).toBe(true)
    expect(repo.cloneStatus).toBe('ready')
    expect(repo.isLocal).toBe(true)

    db.close()
  })
})

Coverage Requirements

Minimum 80% coverage is enforced.

Debugging

Backend

Logs output to terminal when running pnpm dev. For verbose debug logging:

# Add to .env
DEBUG=true

Frontend

  1. Open browser DevTools (F12)
  2. Check Console for errors
  3. Check Network tab for API calls
  4. Use React DevTools extension

Building

Development Build

pnpm build

Production Build

NODE_ENV=production pnpm build

Docker Build

docker build -t opencode-manager .

Common Issues

Port Already in Use

# Find process using port
lsof -i :5003

# Kill process
kill -9 <PID>

Module Not Found

# Clear node_modules and reinstall
rm -rf node_modules
rm -rf */node_modules
pnpm install

TypeScript Errors

# Check types
pnpm typecheck

# Clear TypeScript cache
rm -rf */tsconfig.tsbuildinfo

Database Issues

# Reset database
rm -f data/opencode.db
pnpm dev  # Database is recreated