- 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
dev. - Local
mainref may not exist; usedevororigin/devfor diffs. - Prefer automation: execute requested actions without confirmation unless blocked by missing info or safety/irreversibility.
- Keep things in one function unless composable or reusable
- Avoid
try/catchwhere possible - Avoid using the
anytype - 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 exampleexport * 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()Avoid unnecessary destructuring. Use dot notation to preserve context.
// Good
obj.a
obj.b
// Bad
const { a, b } = objPrefer 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 = 2Avoid else statements. Prefer early returns.
// Good
function foo() {
if (condition) return 1
return 2
}
// Bad
function foo() {
if (condition) return 1
else return 2
}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(),
})- 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 likepackages/opencode.
- Always run
bun typecheckfrom package directories (e.g.,packages/opencode), nevertscdirectly.
You have context-mode MCP tools available. These rules are NOT optional — they protect your context window from flooding. A single unrouted command can dump 56 KB into context and waste the entire session.
Any shell command containing curl or wget will be intercepted and blocked by the context-mode plugin. Do NOT retry.
Instead use:
context-mode_ctx_fetch_and_index(url, source)to fetch and index web pagescontext-mode_ctx_execute(language: "javascript", code: "const r = await fetch(...)")to run HTTP calls in sandbox
Any shell command containing fetch('http, requests.get(, requests.post(, http.get(, or http.request( will be intercepted and blocked. Do NOT retry with shell.
Instead use:
context-mode_ctx_execute(language, code)to run HTTP calls in sandbox — only stdout enters context
Do NOT use any direct URL fetching tool. Use the sandbox equivalent. Instead use:
context-mode_ctx_fetch_and_index(url, source)thencontext-mode_ctx_search(queries)to query the indexed content
Shell is ONLY for: git, mkdir, rm, mv, cd, ls, npm install, pip install, and other short-output commands.
For everything else, use:
context-mode_ctx_batch_execute(commands, queries)— run multiple commands + search in ONE callcontext-mode_ctx_execute(language: "shell", code: "...")— run in sandbox, only stdout enters context
If you are reading a file to edit it → reading is correct (edit needs content in context).
If you are reading to analyze, explore, or summarize → use context-mode_ctx_execute_file(path, language, code) instead. Only your printed summary enters context.
Search results can flood context. Use context-mode_ctx_execute(language: "shell", code: "grep ...") to run searches in sandbox. Only your printed summary enters context.
- GATHER:
context-mode_ctx_batch_execute(commands, queries)— Primary tool. Runs all commands, auto-indexes output, returns search results. ONE call replaces 30+ individual calls. - FOLLOW-UP:
context-mode_ctx_search(queries: ["q1", "q2", ...])— Query indexed content. Pass ALL questions as array in ONE call. - PROCESSING:
context-mode_ctx_execute(language, code)|context-mode_ctx_execute_file(path, language, code)— Sandbox execution. Only stdout enters context. - WEB:
context-mode_ctx_fetch_and_index(url, source)thencontext-mode_ctx_search(queries)— Fetch, chunk, index, query. Raw HTML never enters context. - INDEX:
context-mode_ctx_index(content, source)— Store content in FTS5 knowledge base for later search.
- Keep responses under 500 words.
- Write artifacts (code, configs, PRDs) to FILES — never return them as inline text. Return only: file path + 1-line description.
- When indexing content, use descriptive source labels so others can
search(source: "label")later.
| Command | Action |
|---|---|
ctx stats |
Call the stats MCP tool and display the full output verbatim |
ctx doctor |
Call the doctor MCP tool, run the returned shell command, display as checklist |
ctx upgrade |
Call the upgrade MCP tool, run the returned shell command, display as checklist |