Skip to content

Latest commit

 

History

History
132 lines (98 loc) · 4.12 KB

File metadata and controls

132 lines (98 loc) · 4.12 KB
  • Use MiMoCode Compose skills when available, otherwise use superpowers skill if installed.
  • To regenerate the JavaScript SDK, run ./packages/sdk/js/script/build.ts.
  • ALWAYS USE PARALLEL TOOLS WHEN APPLICABLE.
  • The default branch in this repo is main.
  • CI triggers on both main and dev branches.
  • Prefer automation: execute requested actions without confirmation unless blocked by missing info or safety/irreversibility.
  • Install deps with bun ci (= bun install --frozen-lockfile) — install per bun.lock, don't mutate the lockfile. ⛔ Do NOT use bun install/npm install.

Core Focus (as of 2025-06-18)

Our core development focus is the TUI (terminal UI) implementation in packages/opencode/src/cli/cmd/tui/. We do not currently provide support for Web or App interfaces. All operations should default to checking the TUI implementation first.

Style Guide

General Principles

  • Keep things in one function unless composable or reusable
  • Avoid try/catch where possible
  • Avoid using the any type
  • Use Bun APIs when possible, like Bun.file()
  • Rely on type inference when possible; avoid explicit type annotations or interfaces unless necessary for exports or clarity
  • Prefer functional array methods (flatMap, filter, map) over for loops; use type guards on filter to maintain type inference downstream
  • In src/config, follow the existing self-export pattern at the top of the file (for example export * as ConfigAgent from "./agent") when adding a new config module.

Reduce total variable count by inlining when a value is only used once.

// Good
const journal = await Bun.file(path.join(dir, "journal.json")).json()

// Bad
const journalPath = path.join(dir, "journal.json")
const journal = await Bun.file(journalPath).json()

Destructuring

Avoid unnecessary destructuring. Use dot notation to preserve context.

// Good
obj.a
obj.b

// Bad
const { a, b } = obj

Variables

Prefer const over let. Use ternaries or early returns instead of reassignment.

// Good
const foo = condition ? 1 : 2

// Bad
let foo
if (condition) foo = 1
else foo = 2

Control Flow

Avoid else statements. Prefer early returns.

// Good
function foo() {
  if (condition) return 1
  return 2
}

// Bad
function foo() {
  if (condition) return 1
  else return 2
}

Schema Definitions (Drizzle)

Use snake_case for field names so column names don't need to be redefined as strings.

// Good
const table = sqliteTable("session", {
  id: text().primaryKey(),
  project_id: text().notNull(),
  created_at: integer().notNull(),
})

// Bad
const table = sqliteTable("session", {
  id: text("id").primaryKey(),
  projectID: text("project_id").notNull(),
  createdAt: integer("created_at").notNull(),
})

Reading a nullable column

Two independent absences meet in one expression, and only one of them is undefined. .get() yields undefined when no row matches — Drizzle normalises the driver's null there — while a nullable column's SQL NULL arrives as null. So row?.some_column is T | null | undefined.

When a caller only asks "is there a value", flatten to undefined, and write the flattening as an annotation rather than an as cast:

// Good — the compiler enforces it; deleting the `?? undefined` is a type error
const boundary: MessageID | undefined = row?.last_checkpoint_message_id ?? undefined

// Bad — the cast removes `null` from the union without converting anything,
// so the declared type is untrue at runtime
return row?.last_checkpoint_message_id as MessageID | undefined

Discriminate a possibly-absent value with truthiness or == null, never with === undefined / !== undefined. Because null !== undefined is true, such a guard typechecks, reads correctly in review, and does nothing.

Testing

  • Avoid mocks as much as possible
  • Test actual implementation, do not duplicate logic into tests
  • Tests cannot run from repo root (guard: do-not-run-tests-from-root); run from package dirs like packages/opencode.

Type Checking

  • Always run bun typecheck from package directories (e.g., packages/opencode), never tsc directly.