Development Patterns
This page turns architecture boundaries into contributor decisions. Read Architecture Overview and relevant subsystem page first, then use this guide before editing architecture-facing code in stemcat/biggi or its cross-repository contracts.
Prefer BIGGI-owned seams over broad changes to shared OpenCode files. Follow neighboring style when changing existing modules.
How to use this page
- Identify owning subsystem in architecture docs.
- Choose narrowest source boundary that can hold change.
- Update generated or cross-repository contracts when public surface changes.
- Run smallest relevant checks plus affected repository guards.
Where should change live?
| Change shape | Preferred location or action | Reason |
|---|---|---|
| Additive BIGGI runtime behavior | packages/opencode/src/biggicode/ | Keeps BIGGI-only behavior out of upstream-owned files |
| BIGGI runtime test for additive behavior | packages/opencode/test/biggicode/ | Avoids shared tests that encode only BIGGI behavior |
| Required shared OpenCode edit | Small import, route, or injection seam in shared file plus biggi_change marker | Keeps upstream diff narrow and merge review obvious |
| VS Code, docs, indexing, UI, gateway, or telemetry change | Existing BIGGI-owned package | These packages are BIGGI-owned; do not add biggi_change markers |
| Embedded runtime endpoint change | Effect HttpApi route plus handler; then run root SDK generator | Keeps the runtime contract and generated JavaScript SDK aligned |
| BIGGI-only config-key change | Update the runtime Effect Schema and cloud JSON Schema overlay | Runtime acceptance and editor validation are separate cross-repository paths |
| Docs page move or removal | Update nav and add permanent redirect | Preserves external links and bookmarks |
BIGGI-owned boundaries
BIGGI's embedded runtime forks upstream OpenCode. Prefer BIGGI-owned directories and packages for additive behavior:
| Prefer | Avoid unless necessary |
|---|---|
packages/opencode/src/biggicode/ | Broad edits to shared packages/opencode/src/ files |
packages/opencode/test/biggicode/ | Shared tests that encode only BIGGI behavior |
packages/biggi-vscode/, packages/biggi-docs/, packages/biggi-indexing/ | Moving BIGGI-only behavior into upstream-owned modules |
| Narrow import or route seams in shared files | Refactors that enlarge upstream merge conflicts |
Shared OpenCode files
Use biggi_change markers when BIGGI-specific code must modify shared upstream files.
| Change shape | Marker |
|---|---|
| One line | Trailing // biggi_change |
| Multi-line block | // biggi_change start and // biggi_change end |
| New file in shared path | Top-level // biggi_change - new file |
| JSX or TSX | JSX comment equivalents |
Marker exemptions apply to paths already owned by BIGGI, including paths whose names contain biggicode and BIGGI packages such as packages/biggi-vscode/ or packages/biggi-ui/. Do not add markers there.
| Guard | When to run |
|---|---|
bun run script/check-opencode-annotations.ts | PR touches packages/opencode/; verifies shared OpenCode BIGGI edits are annotated |
bun run script/check-opencode-promise-facades.ts | Service adapter changes; prevents new runtime-backed Promise facades in shared Effect services |
bun run check-biggicode-change from packages/biggi-vscode/ | VS Code or BIGGI UI changes; markers must not appear in fully BIGGI-owned packages |
bun run script/check-workflows.ts | Workflow add or remove changes; keeps workflow allowlist explicit |
Embedded runtime API
The embedded runtime server uses Effect HttpApi and publishes OpenAPI-compatible HTTP + SSE surfaces consumed by the JavaScript SDK and active clients.
| Rule | Reason |
|---|---|
Define shared routes under packages/opencode/src/server/routes/instance/httpapi/ | Keeps route contract close to runtime handlers |
Normalize public spec in packages/opencode/src/server/routes/instance/httpapi/public.ts | Preserves legacy-compatible request and response shapes during Effect migration |
Put additive BIGGI groups and handlers under packages/opencode/src/biggicode/server/httpapi/ | Reduces edits in shared upstream-owned files |
| Inject BIGGI APIs through narrow shared seam | Keeps upstream diff small and marker placement obvious |
| Preserve route spans and stable attributes | Keeps diagnostics and telemetry understandable |
SDK generation
Embedded Runtime SDK contract owns generation pipeline detail. Contributor rules are short:
| Change | Action |
|---|---|
| Add or change an embedded runtime endpoint | Run root ./script/generate.ts after route and handler edits |
JavaScript SDK generated files under packages/sdk/js/src/v2/gen/ | Do not edit by hand |
| JavaScript SDK wrapper behavior | Edit handwritten packages/sdk/js/src/v2/client.ts |
Runtime config schema
Runtime config loading and editor validation are separate paths. A new BIGGI-only config key requires an embedded runtime Effect Schema change in stemcat/biggi and a JSON Schema overlay change in BIGGI-Org/cloud. Follow Runtime Config Schema for the exact workflow.
Module export pattern
For new public APIs, prefer flat ESM exports inside module, then namespace re-exports from index files when grouped access helps callers.
// packages/opencode/src/session/session.ts
export const create = fn(CreateSchema, async (input) => {
// ...
})
export const list = fn(ListSchema, async (input) => {
// ...
})
// packages/opencode/src/session/index.ts
export * as Session from "./session"
Import specific export when practical. Use namespace shape (Session.create) when preserving existing API or grouped module access improves clarity. Existing BIGGI-owned namespaces remain valid; do not refactor them solely for style.
Tool implementation
Tools use Tool.define("id", Effect.gen(...)) with Effect Schema validation and typed execution.
export const ExampleTool = Tool.define(
"example",
Effect.gen(function* () {
return {
description: "Example tool",
parameters: Schema.Struct({
value: Schema.String,
}),
execute(args) {
return Effect.succeed({
title: args.value,
metadata: {},
output: args.value,
})
},
}
}),
)
Reuse tool helpers, permission gates, and telemetry conventions before adding abstractions. Tests should exercise implementation behavior rather than duplicating logic in mocks.
Build system
| Area | Tooling |
|---|---|
| Package manager | Bun workspaces |
| Task orchestration | Turborepo |
| Embedded runtime executable | Bun compile build in packages/opencode/script/build.ts |
| VS Code extension and webviews | esbuild |
| Type checking | tsgo through bun turbo typecheck |
| Tests | Package-level Bun test or Vitest depending on package |
| Docs | Next.js, Markdoc, Mermaid, and custom Markdoc components |
Documentation changes
When adding or moving docs pages:
- Create page under
pages/. - Update matching navigation file in
lib/nav/. - Add redirects when removing or moving routes.
- Use compact markdown tables with unpadded cells.
- Use
/docsprefix for docs image paths.
Source map
Paths below are relative to stemcat/biggi.
| Concern | Source path |
|---|---|
| Tool definition API | packages/opencode/src/tool/tool.ts |
| Tool example | packages/opencode/src/tool/read.ts |
| Server APIs | packages/opencode/src/server/routes/instance/httpapi/ |
| Public OpenAPI normalization | packages/opencode/src/server/routes/instance/httpapi/public.ts |
| BIGGI route seam | packages/opencode/src/biggicode/server/httpapi/ |
| JavaScript SDK generation | packages/sdk/js/script/build.tsscript/generate.ts |
| Upstream merge automation | script/upstream/ |
Upstream merge workflow
bun install runs script/setup-git.ts, which sets repo-local merge conflict style to zdiff3. Base-aware markers make manual resolution and syntax-aware tooling more useful. Upstream automation under script/upstream/ applies transforms before merge, forces zdiff3 for merge operation, and runs mergiraf against remaining textual conflicts. mergiraf is required by merge script.
From script/upstream/, use:
bun run analyze.ts --version <tag> bun run merge.ts --version <tag> --dry-run bun run merge.ts --version <tag>
Keep BIGGI-specific logic extracted, shared seams narrow, markers accurate, and CI guards green before upstream merge work lands.
Related pages
- Architecture Overview - system layers and reading paths
- Embedded Runtime - local runtime ownership and SDK contract
- Runtime Config Schema - cross-repository config-key workflow