Practical reference for the current tool-migration state in packages/opencode.
Tool.Def.execute and Tool.Info.init already return Effect on this branch, and the built-in tool surface is now largely on the target shape.
The current exported tools in src/tool all use Tool.define(...) with Effect-based initialization, and nearly all of them already build their tool body with Effect.gen(...) and Effect.fn(...).
So the remaining work is no longer "convert tools to Effect at all". The remaining work is mostly:
AppFileSystem, HttpClient, and ChildProcessSpawneryield* info.init() and real service graphsTool.define(...) is already the Effect-native helper here.
init is an Effectinfo.init() returns an Effectexecute(...) returns an EffectThat means a tool does not need a separate Tool.defineEffect(...) helper to count as migrated. A tool is effectively migrated when its init and execute path stay Effect-native, even if some internals still bridge to Promise-based or raw APIs.
Tool tests should use the existing Effect helpers in packages/opencode/test/lib/effect.ts:
testEffect(...) / it.live(...) instead of creating fake local wrappers around effectful tools.const info = yield* ReadTool, const tool = yield* info.init().provideTmpdirInstance(...) or provideInstance(tmpdirScoped(...)) so instance-scoped services resolve exactly as they do in production.This keeps tool tests aligned with the production service graph and makes follow-up cleanup mostly mechanical.
These exported tool definitions currently use Tool.define(...) in src/tool:
apply_patch.tsbash.tscodesearch.tsedit.tsglob.tsgrep.tsinvalid.tslsp.tsplan.tsquestion.tsread.tsskill.tstask.tstodo.tswebfetch.tswebsearch.tswrite.tsNotes:
ls.ts tool file on this branch.truncate.ts is an Effect service used by tools, not a tool definition itself.mcp-exa.ts, external-directory.ts, and schema.ts are support modules, not standalone tool definitions.Most exported tools are already on the intended Effect-native shape. The remaining cleanup is narrower than the old checklist implied.
Current spot cleanups worth tracking:
read.ts — still bridges to Node stream / readline helpers and Promise-based binary detectionbash.ts — already uses Effect child-process primitives; only keep tracking shell-specific platform bridges and parser/loading details as they come upwebfetch.ts — already uses HttpClient; remaining work is limited to smaller boundary helpers like HTML text extractionfile/ripgrep.ts — adjacent to tool migration; still has raw fs/process usage that affects grep.ts and file-search routespatch/index.ts — adjacent to tool migration; still has raw fs usage behind patch applicationNotable items that are already effectively on the target path and do not need separate migration bullets right now:
apply_patch.tsgrep.tswrite.tscodesearch.tswebsearch.tsedit.tsCurrent raw fs users that still appear relevant here:
tool/read.ts — fs.createReadStream, readlinefile/ripgrep.ts — fs/promisespatch/index.ts — fs, fs/promises