| Dimension | Shared | Only in A | Only in B | Overlap |
|---|---|---|---|---|
| Sections | 0 | 15 | 3 | 0% |
| Commands | 0 | 2 | 0 | 0% |
| Section tags | 1 | 3 | 0 | 25% |
What each file covers
Sections
0 shared · 15 only in A · 3 only in B- − opencode database guide
- − Database
- − Development server
- − Module shape
- − When the file is an `index.ts`
- − Multi-sibling directories
- − opencode Effect rules
- − Core
- − Module conventions
- − Schemas and errors
- − Runtime vs InstanceState
- − Effect v4 beta API
- − Preferred Effect services
- − Effect.cached for deduplication
- − Callback boundaries
- + @opencode-ai/codemode
- + OpenAPI
- + Future Design Notes
Commands
0 shared · 2 only in A · 0 only in B- − bun dev
- − node-pty
Section tags
1 shared · 3 only in A · 0 only in B- − code-style
- − database
- − do-not
- api
Line diff
anomalyco/opencode · packages/opencode/AGENTS.md
@@ −1 @@
1# opencode database guide
2
3## Database
4
5- **Schema**: Drizzle schema lives in `packages/core/src/**/*.sql.ts`.
6- **Migrations**: database migrations live in `packages/core` and are applied by core.
7
8## Development server
9
10- Running `bun dev` from `packages/opencode` starts the live interactive TUI. Do not run it as a blocking foreground command when you need to inspect the result.
11- Start it in `tmux` instead: `tmux new-session -d -s opencode-dev 'bun dev'`.
12- Capture the current TUI output with: `tmux capture-pane -pt opencode-dev`.
13- Stop the session explicitly when done: `tmux kill-session -t opencode-dev`.
14
15# Module shape
16
17Do not use `export namespace Foo { ... }` for module organization. It is not
18standard ESM, it prevents tree-shaking, and it breaks Node's native TypeScript
19runner. Use flat top-level exports combined with a self-reexport at the bottom
20of the file:
21
22```ts
23// src/foo/foo.ts
24export interface Interface { ... }
25export class Service extends Context.Service<Service, Interface>()("@opencode/Foo") {}
26export const layer = Layer.effect(Service, ...)
27export const defaultLayer = layer.pipe(...)
28
29export * as Foo from "./foo"
30```
31
32Consumers import the namespace projection:
33
34```ts
35import { Foo } from "@/foo/foo"
36
37yield * Foo.Service
38Foo.layer
39Foo.defaultLayer
40```
41
42Namespace-private helpers stay as non-exported top-level declarations in the
43same file — they remain inaccessible to consumers (they are not projected by
44`export * as`) but are usable by the file's own code.
45
46## When the file is an `index.ts`
47
48If the module is `foo/index.ts` (single-namespace directory), use `"."` for
49the self-reexport source rather than `"./index"`:
50
51```ts
52// src/foo/index.ts
53export const thing = ...
54
55export * as Foo from "."
56```
57
58## Multi-sibling directories
59
60For directories with several independent modules (e.g. `src/session/`,
61`src/config/`), keep each sibling as its own file with its own self-reexport,
62and do not add a barrel `index.ts`. Consumers import the specific sibling:
63
64```ts
65import { SessionRetry } from "@/session/retry"
66import { SessionStatus } from "@/session/status"
67```
68
69Barrels in multi-sibling directories force every import through the barrel to
70evaluate every sibling, which defeats tree-shaking and slows module load.
71
72# opencode Effect rules
73
74Use these rules when writing or migrating Effect code.
75
76See `specs/effect/migration.md` for the compact pattern reference and examples.
77
78## Core
79
80- Use `Effect.gen(function* () { ... })` for composition.
81- Use `Effect.fn("Domain.method")` for named/traced effects and `Effect.fnUntraced` for internal helpers.
82- `Effect.fn` / `Effect.fnUntraced` accept pipeable operators as extra arguments, so avoid unnecessary outer `.pipe()` wrappers.
83- Use `Effect.callback` for callback-based APIs.
84- Use `Effect.void` instead of `Effect.succeed(undefined)` or `Effect.succeed(void 0)`.
85- Prefer `DateTime.nowAsDate` over `new Date(yield* Clock.currentTimeMillis)` when you need a `Date`.
86
87## Module conventions
88
89- 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.
90
91## Schemas and errors
92
93- Use `Schema.Class` for multi-field data.
94- Use branded schemas (`Schema.brand`) for single-value types.
95- Use `Schema.TaggedErrorClass` for typed errors.
96- Use `Schema.Defect` instead of `unknown` for defect-like causes.
97- In `Effect.gen` / `Effect.fn`, prefer `yield* new MyError(...)` over `yield* Effect.fail(new MyError(...))` for direct early-failure branches.
98
99## Runtime vs InstanceState
100
101- Use `makeRuntime` (from `src/effect/run-service.ts`) for all services. It returns `{ runPromise, runFork, runCallback }` backed by a shared `memoMap` that deduplicates layers.
102- Use `InstanceState` (from `src/effect/instance-state.ts`) for per-directory or per-project state that needs per-instance cleanup. It uses `ScopedCache` keyed by directory — each open project gets its own state, automatically cleaned up on disposal.
103- If two open directories should not share one copy of the service, it needs `InstanceState`.
104- Do the work directly in the `InstanceState.make` closure — `ScopedCache` handles run-once semantics. Don't add fibers, `ensure()` callbacks, or `started` flags on top.
105- Use `Effect.addFinalizer` or `Effect.acquireRelease` inside the `InstanceState.make` closure for cleanup (subscriptions, process teardown, etc.).
106- Use `Effect.forkScoped` inside the closure for background stream consumers — the fiber is interrupted when the instance is disposed.
107- To make a service's `init()` non-blocking, fork `InstanceState.get(state)` at the `init()` call site (e.g. `Effect.forkIn(scope)`), not by forking work inside the `InstanceState.make` closure. Forking inside the closure leaves state incomplete for other methods that read it.
108- `src/project/bootstrap.ts` already wraps every service `init()` in `Effect.forkDetach`, so `init()` is fire-and-forget in production. Keep `init()` methods synchronous internally; the caller controls concurrency.
109
110## Effect v4 beta API
111
112- `Effect.fork` and `Effect.forkDaemon` do not exist. Use `Effect.forkIn(scope)` to fork a fiber into a specific scope.
113
114## Preferred Effect services
115
116- In effectified services, prefer yielding existing Effect services over dropping down to ad hoc platform APIs.
117- Prefer `FileSystem.FileSystem` instead of raw `fs/promises` for effectful file I/O.
118- Prefer `ChildProcessSpawner.ChildProcessSpawner` with `ChildProcess.make(...)` instead of custom process wrappers.
119- Prefer `HttpClient.HttpClient` instead of raw `fetch`.
120- Prefer `Path.Path`, `Config`, `Clock`, and `DateTime` when those concerns are already inside Effect code.
121- For background loops or scheduled tasks, use `Effect.repeat` or `Effect.schedule` with `Effect.forkScoped` in the layer definition.
122
123## Effect.cached for deduplication
124
125Use `Effect.cached` when multiple concurrent callers should share a single in-flight computation rather than storing `Fiber | undefined` or `Promise | undefined` manually. See `specs/effect/migration.md` for the full pattern.
126
127## Callback boundaries
128
129Use `EffectBridge` for native or external callbacks (`@parcel/watcher`, `node-pty`, native `fs.watch`, plugin callbacks, etc.) that need to re-enter Effect services with instance/workspace context.
130
131Plain async code should pass explicit context or stay inside an Effect fiber; do not add ambient instance context shims.
132
anomalyco/opencode · packages/codemode/AGENTS.md
@@ +1 @@
1# @opencode-ai/codemode
2
3- This local package owns confined execution over explicit schema-described tools. Applications own authorization, persistence, external authority, and tool-specific delivery semantics.
4- Do not add a speculative generic permission or approval policy. A host omits tools it does not expose and enforces domain authorization inside each provided tool.
5- Keep Code Mode unaware of host session, channel, and conversation models. The hosting application supplies trusted execution scope around it.
6- Tool schemas are the model-facing Interface. Keep arguments minimal and natural to the operation; never add unrelated IDs as ambient capability tokens.
7
8## OpenAPI
9
10- Generate an operation only when its transport semantics are supported; otherwise return a precise `skipped` reason.
11- Never guess parameter serialization or malformed security semantics. Unsupported serialization is skipped and malformed security fails closed.
12- Render unresolved schema constructs as `unknown`, never as invented TypeScript names.
13- Keep network reads bounded and map expected encoding, transport, and decoding failures to model-safe `ToolError` values.
14- Test supported behavior directly; do not reproduce adapter algorithms in tests.
15
16## Future Design Notes
17
18- If a captured user-visible output channel returns (an earlier `output.text`/`output.file`/`output.image` API was removed from v1), keep `output` as its name, distinct from the program return value: `return` stays the structured result for the model, while `output.*` describes artifacts the host may render into a conversation or UI after execution. Keep this host-neutral and let applications decide how captured output is delivered. In v1, hosts collect media host-side (outside the sandbox) instead.
19- Improve the sandbox failure taxonomy. Distinguish parse/compile mistakes, unsupported syntax, user-thrown errors, invalid returned data, tool refusal, tool internal failure, timeout, and genuine runtime defects so agents can recover accurately instead of treating everything as a generic execution failure.
20- Preserve the public/private error split. Tool authors should be able to return a safe model-visible message while retaining a private cause for host diagnostics. Unknown host failures must remain sanitized by default.
21- Think deliberately about richer binary boundaries before allowing `Blob`, `File`, `ArrayBuffer`, streams, or typed arrays beyond today's JSON-like values. If CodeMode supports binary tool args/results, use explicit tagged data shapes and clear size limits rather than relying on ambient runtime serialization.
22- Keep host capabilities explicit. Globals such as `fetch`, `crypto`, filesystem handles, extra modules, or network clients should be opt-in runtime capabilities with obvious policy defaults, not ambient authority. Default to unavailable unless a host deliberately provides the capability.
23- If `fetch` is added, model it as a host-provided outbound capability with policy controls: allowed origins, methods, headers, response size, timeout, and whether response bodies may be returned, emitted, or only summarized through a tool.
24
@@ −1 +1 @@
1−# opencode database guide
1+# @opencode-ai/codemode
22
3−## Database
3+- This local package owns confined execution over explicit schema-described tools. Applications own authorization, persistence, external authority, and tool-specific delivery semantics.
4+- Do not add a speculative generic permission or approval policy. A host omits tools it does not expose and enforces domain authorization inside each provided tool.
5+- Keep Code Mode unaware of host session, channel, and conversation models. The hosting application supplies trusted execution scope around it.
6+- Tool schemas are the model-facing Interface. Keep arguments minimal and natural to the operation; never add unrelated IDs as ambient capability tokens.
47
5−- **Schema**: Drizzle schema lives in `packages/core/src/**/*.sql.ts`.
6−- **Migrations**: database migrations live in `packages/core` and are applied by core.
8+## OpenAPI
79
8−## Development server
10+- Generate an operation only when its transport semantics are supported; otherwise return a precise `skipped` reason.
11+- Never guess parameter serialization or malformed security semantics. Unsupported serialization is skipped and malformed security fails closed.
12+- Render unresolved schema constructs as `unknown`, never as invented TypeScript names.
13+- Keep network reads bounded and map expected encoding, transport, and decoding failures to model-safe `ToolError` values.
14+- Test supported behavior directly; do not reproduce adapter algorithms in tests.
915
10−- Running `bun dev` from `packages/opencode` starts the live interactive TUI. Do not run it as a blocking foreground command when you need to inspect the result.
11−- Start it in `tmux` instead: `tmux new-session -d -s opencode-dev 'bun dev'`.
12−- Capture the current TUI output with: `tmux capture-pane -pt opencode-dev`.
13−- Stop the session explicitly when done: `tmux kill-session -t opencode-dev`.
16+## Future Design Notes
1417
15−# Module shape
16−
17−Do not use `export namespace Foo { ... }` for module organization. It is not
18−standard ESM, it prevents tree-shaking, and it breaks Node's native TypeScript
19−runner. Use flat top-level exports combined with a self-reexport at the bottom
20−of the file:
21−
22−```ts
23−// src/foo/foo.ts
24−export interface Interface { ... }
25−export class Service extends Context.Service<Service, Interface>()("@opencode/Foo") {}
26−export const layer = Layer.effect(Service, ...)
27−export const defaultLayer = layer.pipe(...)
28−
29−export * as Foo from "./foo"
30−```
31−
32−Consumers import the namespace projection:
33−
34−```ts
35−import { Foo } from "@/foo/foo"
36−
37−yield * Foo.Service
38−Foo.layer
39−Foo.defaultLayer
40−```
41−
42−Namespace-private helpers stay as non-exported top-level declarations in the
43−same file — they remain inaccessible to consumers (they are not projected by
44−`export * as`) but are usable by the file's own code.
45−
46−## When the file is an `index.ts`
47−
48−If the module is `foo/index.ts` (single-namespace directory), use `"."` for
49−the self-reexport source rather than `"./index"`:
50−
51−```ts
52−// src/foo/index.ts
53−export const thing = ...
54−
55−export * as Foo from "."
56−```
57−
58−## Multi-sibling directories
59−
60−For directories with several independent modules (e.g. `src/session/`,
61−`src/config/`), keep each sibling as its own file with its own self-reexport,
62−and do not add a barrel `index.ts`. Consumers import the specific sibling:
63−
64−```ts
65−import { SessionRetry } from "@/session/retry"
66−import { SessionStatus } from "@/session/status"
67−```
68−
69−Barrels in multi-sibling directories force every import through the barrel to
70−evaluate every sibling, which defeats tree-shaking and slows module load.
71−
72−# opencode Effect rules
73−
74−Use these rules when writing or migrating Effect code.
75−
76−See `specs/effect/migration.md` for the compact pattern reference and examples.
77−
78−## Core
79−
80−- Use `Effect.gen(function* () { ... })` for composition.
81−- Use `Effect.fn("Domain.method")` for named/traced effects and `Effect.fnUntraced` for internal helpers.
82−- `Effect.fn` / `Effect.fnUntraced` accept pipeable operators as extra arguments, so avoid unnecessary outer `.pipe()` wrappers.
83−- Use `Effect.callback` for callback-based APIs.
84−- Use `Effect.void` instead of `Effect.succeed(undefined)` or `Effect.succeed(void 0)`.
85−- Prefer `DateTime.nowAsDate` over `new Date(yield* Clock.currentTimeMillis)` when you need a `Date`.
86−
87−## Module conventions
88−
89−- 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.
90−
91−## Schemas and errors
92−
93−- Use `Schema.Class` for multi-field data.
94−- Use branded schemas (`Schema.brand`) for single-value types.
95−- Use `Schema.TaggedErrorClass` for typed errors.
96−- Use `Schema.Defect` instead of `unknown` for defect-like causes.
97−- In `Effect.gen` / `Effect.fn`, prefer `yield* new MyError(...)` over `yield* Effect.fail(new MyError(...))` for direct early-failure branches.
98−
99−## Runtime vs InstanceState
100−
101−- Use `makeRuntime` (from `src/effect/run-service.ts`) for all services. It returns `{ runPromise, runFork, runCallback }` backed by a shared `memoMap` that deduplicates layers.
102−- Use `InstanceState` (from `src/effect/instance-state.ts`) for per-directory or per-project state that needs per-instance cleanup. It uses `ScopedCache` keyed by directory — each open project gets its own state, automatically cleaned up on disposal.
103−- If two open directories should not share one copy of the service, it needs `InstanceState`.
104−- Do the work directly in the `InstanceState.make` closure — `ScopedCache` handles run-once semantics. Don't add fibers, `ensure()` callbacks, or `started` flags on top.
105−- Use `Effect.addFinalizer` or `Effect.acquireRelease` inside the `InstanceState.make` closure for cleanup (subscriptions, process teardown, etc.).
106−- Use `Effect.forkScoped` inside the closure for background stream consumers — the fiber is interrupted when the instance is disposed.
107−- To make a service's `init()` non-blocking, fork `InstanceState.get(state)` at the `init()` call site (e.g. `Effect.forkIn(scope)`), not by forking work inside the `InstanceState.make` closure. Forking inside the closure leaves state incomplete for other methods that read it.
108−- `src/project/bootstrap.ts` already wraps every service `init()` in `Effect.forkDetach`, so `init()` is fire-and-forget in production. Keep `init()` methods synchronous internally; the caller controls concurrency.
109−
110−## Effect v4 beta API
111−
112−- `Effect.fork` and `Effect.forkDaemon` do not exist. Use `Effect.forkIn(scope)` to fork a fiber into a specific scope.
113−
114−## Preferred Effect services
115−
116−- In effectified services, prefer yielding existing Effect services over dropping down to ad hoc platform APIs.
117−- Prefer `FileSystem.FileSystem` instead of raw `fs/promises` for effectful file I/O.
118−- Prefer `ChildProcessSpawner.ChildProcessSpawner` with `ChildProcess.make(...)` instead of custom process wrappers.
119−- Prefer `HttpClient.HttpClient` instead of raw `fetch`.
120−- Prefer `Path.Path`, `Config`, `Clock`, and `DateTime` when those concerns are already inside Effect code.
121−- For background loops or scheduled tasks, use `Effect.repeat` or `Effect.schedule` with `Effect.forkScoped` in the layer definition.
122−
123−## Effect.cached for deduplication
124−
125−Use `Effect.cached` when multiple concurrent callers should share a single in-flight computation rather than storing `Fiber | undefined` or `Promise | undefined` manually. See `specs/effect/migration.md` for the full pattern.
126−
127−## Callback boundaries
128−
129−Use `EffectBridge` for native or external callbacks (`@parcel/watcher`, `node-pty`, native `fs.watch`, plugin callbacks, etc.) that need to re-enter Effect services with instance/workspace context.
130−
131−Plain async code should pass explicit context or stay inside an Effect fiber; do not add ambient instance context shims.
18+- If a captured user-visible output channel returns (an earlier `output.text`/`output.file`/`output.image` API was removed from v1), keep `output` as its name, distinct from the program return value: `return` stays the structured result for the model, while `output.*` describes artifacts the host may render into a conversation or UI after execution. Keep this host-neutral and let applications decide how captured output is delivered. In v1, hosts collect media host-side (outside the sandbox) instead.
19+- Improve the sandbox failure taxonomy. Distinguish parse/compile mistakes, unsupported syntax, user-thrown errors, invalid returned data, tool refusal, tool internal failure, timeout, and genuine runtime defects so agents can recover accurately instead of treating everything as a generic execution failure.
20+- Preserve the public/private error split. Tool authors should be able to return a safe model-visible message while retaining a private cause for host diagnostics. Unknown host failures must remain sanitized by default.
21+- Think deliberately about richer binary boundaries before allowing `Blob`, `File`, `ArrayBuffer`, streams, or typed arrays beyond today's JSON-like values. If CodeMode supports binary tool args/results, use explicit tagged data shapes and clear size limits rather than relying on ambient runtime serialization.
22+- Keep host capabilities explicit. Globals such as `fetch`, `crypto`, filesystem handles, extra modules, or network clients should be opt-in runtime capabilities with obvious policy defaults, not ambient authority. Default to unavailable unless a host deliberately provides the capability.
23+- If `fetch` is added, model it as a host-provided outbound capability with policy controls: allowed origins, methods, headers, response size, timeout, and whether response bodies may be returned, emitted, or only summarized through a tool.
13224
