Files

5.0 KiB

AGENTS.md

Project Overview

opencode-multi-model is a Bun/TypeScript project that provides multi-model tmux session management for AI coding assistants. It allows running multiple AI models simultaneously in isolated tmux windows with separate git worktrees.

Available as three integration modes:

  • OpenCode Plugin: Loaded via opencode.json plugin array
  • Standalone CLI: Install globally and run opencode-multi-model open <session> -m <models...>
  • Project Tool: Import core functions from "opencode-multi-model/core" for project-level commands (used during development).

Requires: tmux, git, opencode or kilo binary, Bun runtime.

Build, Lint, and Test Commands

# Install dependencies
bun install

# Build for production
bun run build

# Run tests
bun test

# Run tests with coverage (HTML report in ./coverage)
bun run coverage
# Run a specific test by name
bun test --test-name-pattern "fails if session name is empty"

# TypeScript type checking
bun run typecheck

# Lint with Biome
bun run lint

# Auto-fix lint issues
bun run lint:fix

# Format code with Biome
bun run format

# Full quality check
bun run typecheck && bun run lint

Code Style Guidelines

General

  • Use TypeScript with strict mode
  • Use Bun as the runtime and package manager
  • Use ESM modules ("type": "module" in package.json)
  • Use node: prefix for Node.js built-ins

Formatting (Biome)

  • Indent: 2 spaces (not tabs)
  • Quote style: Double quotes for JS strings
  • Semicolons: Required
  • Run bun run format to format files

TypeScript Conventions

  • Use interface for object shapes; avoid type aliases unless needed
  • Use explicit return types on exported functions
  • Avoid any when possible
  • Use noUncheckedIndexedAccess: true and noImplicitOverride: true in tsconfig
  • All types/interfaces go in src/types.ts

Naming Conventions

  • Files: kebab-case (multi-model-open.ts)
  • Functions: camelCase (openMultiModel)
  • Types/Interfaces: PascalCase (MultiModelOptions)
  • Constants: UPPER_SNAKE_CASE (e.g., MAX_SUGGESTIONS)

Imports

  • Use import type for type-only imports
  • Group imports: external packages, internal modules, types
  • Biome automatically organizes imports

Documentation

  • Use JSDoc for all exported functions
  • Include @example, @param, and @returns descriptions
  • Add inline comments for hard-to-understand code
  • Modify Readme.md, if implementation details have changed.

Error Handling

  • Return result objects (e.g., MultiModelResult, CloseSessionResult, CleanupResult) with success: boolean
  • Include descriptive error messages prefixed with Error:
  • Provide actionable error messages (e.g., suggest valid models on invalid model name)
  • Use chalk for colored terminal output (red for errors, dim for secondary info, bold for primary info)

Shell Commands

  • Use Bun.$ template tag for shell commands
  • Always use quiet().nothrow() to capture output without throwing
  • Wrap command execution in runCommand() utility from core/utils.ts
  • Use shellQuote() for user-provided values in shell commands

Testing

  • Use bun:test framework
  • Mock Bun.$ using the mock() function from bun:test
  • Use spyOn() for fs/os module mocking
  • Group tests with describe() blocks
  • Test file naming: *.test.ts in tests/ directory

Project Structure

src/
├── index.ts          # Plugin entry point (default export)
├── cli.ts            # CLI entry point (commander setup)
├── types.ts          # All TypeScript interfaces/types
├── core/
│   ├── index.ts      # Core exports
│   ├── open.ts       # Session launch logic
│   ├── close.ts      # Session close logic
│   ├── cleanup.ts    # Archive tag cleanup logic
│   └── utils.ts      # Shared utilities (runCommand, shellQuote, etc.)
└── tools/
    ├── open.ts       # OpenCode tool definition
    ├── close.ts      # CloseCode tool definition
    └── cleanup.ts    # Cleanup tool definition
tests/
├── open.test.ts         # Open command tests
├── close.test.ts        # Close command tests
├── cleanup.test.ts      # Cleanup command tests
├── open_error.test.ts   # Open error handling tests
├── close_error.test.ts  # Close error handling tests
└── utils.test.ts        # Utility function tests

Git Branch and Tag Naming

  • Session branches: opencode/<session-name>/<window-name>
  • Archive tags: archive/<branch-name>-<timestamp> (created by close command)
  • Worktrees: ~/.local/share/opencode/multi-model/<session>/<window>/

Common Pitfalls

  • Tmux session names use raw input; git branches/paths use sanitized names
  • Window names must be unique; collisions get numeric suffixes (e.g., gpt-5-2, gpt-5-2-2)
  • Window names are truncated to 24 characters to fit tmux limits
  • Worktree paths are checked for existence before creation to avoid conflicts
  • Archive tags preserve branch state before deletion for recovery