[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71H6A19AEV0BJCGJC65ZG8K":3,"skill-same:01M71H6A19AEV0BJCGJC65ZG8K":53},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":28,"linkOnly":29,"markdownContent":30,"markdownBody":31,"frontMatter":32,"refName":33,"commitSha":34,"skillDirectory":35,"forksCount":13,"repositoryHtmlUrl":36,"repositoryHomepageUrl":6,"ownerHtmlUrl":37,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":38,"install":39,"resources":52},"01M71H6A19AEV0BJCGJC65ZG8K","01-best-practices",null,"Effect-TS 4 best practices — Effect.fn, Effect.fnUntraced, Context.Service, Layer conventions, and FP style","lambda-solver\u002Flambdabench-pro","lambda-solver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F279071046?v=4","01M71H55W2WK3PM6RRAY9JZWAJ","01M71H55WRT9XAFDAVACTCC2XP",0,"MIT","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Feffect-ts\u002Fpatterns\u002F01-best-practices\u002FSKILL.md",[],[18,19,20,21,22,23,24,25,26,27],"01 best practices","best practices","effect","fn","opencode","style","conventions","layer","service","context","2026-11-10 10:12:30",false,"---\nname: 01-best-practices\ndescription: Effect-TS 4 best practices — Effect.fn, Effect.fnUntraced, Context.Service, Layer conventions, and FP style\nlicense: MIT\ncompatibility: opencode\n---\n\n# Effect-TS Best Practices\n\n## Effect.fn — all exported named functions\n\nEvery exported function that returns an Effect must use `Effect.fn`.\nIt adds span tracing, stack frames, and the name appears in traces.\n\n```typescript\nexport const processItem = Effect.fn(\"processItem\")(function* (id: string) {\n  yield* Effect.log(\"processing:\", id);\n  return yield* doWork(id);\n});\n```\n\nExtra operators go as **additional arguments to `Effect.fn`**, not in `.pipe`:\n\n```typescript\n\u002F\u002F ✅ correct — operators receive the function's arguments too\nexport const processItem = Effect.fn(\"processItem\")(\n  function* (id: string) {\n    return yield* doWork(id)\n  },\n  Effect.withSpan(\"processItem\"),\n  Effect.annotateLogs({ component: \"worker\" }),\n)\n\n\u002F\u002F ❌ wrong — .pipe after Effect.fn loses the span context\nexport const processItem = Effect.fn(\"processItem\")(function* () { ... })\n  .pipe(Effect.withSpan(\"processItem\"))\n```\n\n## Effect.fnUntraced — internal helpers\n\nFor private\u002Finternal functions where tracing adds no value.\n\n```typescript\n\u002F\u002F ✅ simpler — no name string needed\nconst buildPayload = Effect.fnUntraced(function* (id: string) {\n  const data = yield* loadData(id);\n  return { id, data };\n});\n```\n\n## Context.Service — the canonical service definition\n\n**Always use `Context.Service`, not `ServiceMap.Service`.**\nThe reference codebase (effect-smol) uses only `Context.Service`.\n\n```typescript\nimport { Context, Effect, Layer } from \"effect\";\n\nexport class MyService extends Context.Service\u003C\n  MyService,\n  {\n    doThing(input: string): Effect.Effect\u003CResult, MyError>;\n  }\n>()(\"myapp\u002FMyService\") {\n  static readonly layer = Layer.effect(\n    MyService,\n    Effect.gen(function* () {\n      const doThing = Effect.fn(\"MyService.doThing\")(function* (input: string) {\n        return yield* compute(input);\n      });\n      return MyService.of({ doThing });\n    }),\n  );\n}\n```\n\n## Service key naming\n\nUse `\"package\u002Fpath\u002FName\"` convention:\n\n```\n\"myapp\u002Fdb\u002FDatabase\"\n\"@repo\u002Fdomain\u002FBenchmarkService\"\n\"effect\u002Fcluster\u002FEntity\u002FEntityAddress\"\n```\n\n## Services return `.of(...)` — never plain objects\n\n```typescript\nreturn MyService.of({ doThing }); \u002F\u002F ✅ preserves prototype chain\nreturn { doThing }; \u002F\u002F ❌ breaks Context.Service\n```\n\n## No let reassignment inside Effect.gen\n\nExtract each branch as a helper Effect; bind once with `const`.\n\n```typescript\n\u002F\u002F ❌ let reassignment obscures which branch ran\nconst program = Effect.gen(function* () {\n  let result: string;\n  if (condition) result = yield* branchA();\n  else result = yield* branchB();\n  return result;\n});\n\n\u002F\u002F ✅ const, no mutation\nconst resolveResult = (condition: boolean) => (condition ? branchA() : branchB());\n\nconst program = Effect.gen(function* () {\n  const result = yield* resolveResult(condition);\n  return result;\n});\n```\n\n## No try\u002Fcatch, no async\u002Fawait inside Effect.gen\n\n```typescript\n\u002F\u002F ❌ escapes the error channel\nEffect.gen(function* () {\n  try { return yield* risky() } catch (e) { return default }\n})\n\n\u002F\u002F ✅ use Effect combinators\nrisky().pipe(\n  Effect.catchTag(\"MyError\", (_) => Effect.succeed(default)),\n)\n\n\u002F\u002F ❌ await mixes runtimes\nEffect.gen(function* () {\n  const data = await fetch(url).then(r => r.json())\n})\n\n\u002F\u002F ✅ Effect.tryPromise\nEffect.gen(function* () {\n  const data = yield* Effect.tryPromise({\n    try: () => fetch(url).then(r => r.json()),\n    catch: (e) => new FetchError({ cause: e }),\n  })\n})\n```\n\n## Schema.Record — positional args only\n\n```typescript\nSchema.Record(Schema.String, Schema.Number)          \u002F\u002F ✅ Effect 4\nSchema.Record({ key: Schema.String, value: ... })    \u002F\u002F ❌ Effect 3 — compile error\n```\n\n## Domain package — no platform imports\n\n```typescript\n\u002F\u002F ✅ domain package\nimport { Effect, Schema } from \"effect\";\n\n\u002F\u002F ❌ domain package — platform-specific, must stay in apps\u002F\nimport { HttpClient } from \"effect\u002Funstable\u002Fhttp\";\n```\n\n## Bun script entrypoint pattern\n\n```typescript\nif (import.meta.main) {\n  Effect.runPromise(program).catch((e: unknown) => {\n    process.stderr.write(String(e) + \"\\n\");\n    process.exit(1);\n  });\n}\n```\n","# Effect-TS Best Practices\n\n## Effect.fn — all exported named functions\n\nEvery exported function that returns an Effect must use `Effect.fn`.\nIt adds span tracing, stack frames, and the name appears in traces.\n\n```typescript\nexport const processItem = Effect.fn(\"processItem\")(function* (id: string) {\n  yield* Effect.log(\"processing:\", id);\n  return yield* doWork(id);\n});\n```\n\nExtra operators go as **additional arguments to `Effect.fn`**, not in `.pipe`:\n\n```typescript\n\u002F\u002F ✅ correct — operators receive the function's arguments too\nexport const processItem = Effect.fn(\"processItem\")(\n  function* (id: string) {\n    return yield* doWork(id)\n  },\n  Effect.withSpan(\"processItem\"),\n  Effect.annotateLogs({ component: \"worker\" }),\n)\n\n\u002F\u002F ❌ wrong — .pipe after Effect.fn loses the span context\nexport const processItem = Effect.fn(\"processItem\")(function* () { ... })\n  .pipe(Effect.withSpan(\"processItem\"))\n```\n\n## Effect.fnUntraced — internal helpers\n\nFor private\u002Finternal functions where tracing adds no value.\n\n```typescript\n\u002F\u002F ✅ simpler — no name string needed\nconst buildPayload = Effect.fnUntraced(function* (id: string) {\n  const data = yield* loadData(id);\n  return { id, data };\n});\n```\n\n## Context.Service — the canonical service definition\n\n**Always use `Context.Service`, not `ServiceMap.Service`.**\nThe reference codebase (effect-smol) uses only `Context.Service`.\n\n```typescript\nimport { Context, Effect, Layer } from \"effect\";\n\nexport class MyService extends Context.Service\u003C\n  MyService,\n  {\n    doThing(input: string): Effect.Effect\u003CResult, MyError>;\n  }\n>()(\"myapp\u002FMyService\") {\n  static readonly layer = Layer.effect(\n    MyService,\n    Effect.gen(function* () {\n      const doThing = Effect.fn(\"MyService.doThing\")(function* (input: string) {\n        return yield* compute(input);\n      });\n      return MyService.of({ doThing });\n    }),\n  );\n}\n```\n\n## Service key naming\n\nUse `\"package\u002Fpath\u002FName\"` convention:\n\n```\n\"myapp\u002Fdb\u002FDatabase\"\n\"@repo\u002Fdomain\u002FBenchmarkService\"\n\"effect\u002Fcluster\u002FEntity\u002FEntityAddress\"\n```\n\n## Services return `.of(...)` — never plain objects\n\n```typescript\nreturn MyService.of({ doThing }); \u002F\u002F ✅ preserves prototype chain\nreturn { doThing }; \u002F\u002F ❌ breaks Context.Service\n```\n\n## No let reassignment inside Effect.gen\n\nExtract each branch as a helper Effect; bind once with `const`.\n\n```typescript\n\u002F\u002F ❌ let reassignment obscures which branch ran\nconst program = Effect.gen(function* () {\n  let result: string;\n  if (condition) result = yield* branchA();\n  else result = yield* branchB();\n  return result;\n});\n\n\u002F\u002F ✅ const, no mutation\nconst resolveResult = (condition: boolean) => (condition ? branchA() : branchB());\n\nconst program = Effect.gen(function* () {\n  const result = yield* resolveResult(condition);\n  return result;\n});\n```\n\n## No try\u002Fcatch, no async\u002Fawait inside Effect.gen\n\n```typescript\n\u002F\u002F ❌ escapes the error channel\nEffect.gen(function* () {\n  try { return yield* risky() } catch (e) { return default }\n})\n\n\u002F\u002F ✅ use Effect combinators\nrisky().pipe(\n  Effect.catchTag(\"MyError\", (_) => Effect.succeed(default)),\n)\n\n\u002F\u002F ❌ await mixes runtimes\nEffect.gen(function* () {\n  const data = await fetch(url).then(r => r.json())\n})\n\n\u002F\u002F ✅ Effect.tryPromise\nEffect.gen(function* () {\n  const data = yield* Effect.tryPromise({\n    try: () => fetch(url).then(r => r.json()),\n    catch: (e) => new FetchError({ cause: e }),\n  })\n})\n```\n\n## Schema.Record — positional args only\n\n```typescript\nSchema.Record(Schema.String, Schema.Number)          \u002F\u002F ✅ Effect 4\nSchema.Record({ key: Schema.String, value: ... })    \u002F\u002F ❌ Effect 3 — compile error\n```\n\n## Domain package — no platform imports\n\n```typescript\n\u002F\u002F ✅ domain package\nimport { Effect, Schema } from \"effect\";\n\n\u002F\u002F ❌ domain package — platform-specific, must stay in apps\u002F\nimport { HttpClient } from \"effect\u002Funstable\u002Fhttp\";\n```\n\n## Bun script entrypoint pattern\n\n```typescript\nif (import.meta.main) {\n  Effect.runPromise(program).catch((e: unknown) => {\n    process.stderr.write(String(e) + \"\\n\");\n    process.exit(1);\n  });\n}\n```\n",{"name":5,"license":14,"description":7,"compatibility":22},"main","816c073aaf171300af3605b06f7ec5aa7370ef0b",".opencode\u002Fskills\u002Feffect-ts\u002Fpatterns\u002F01-best-practices","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro","https:\u002F\u002Fgithub.com\u002Flambda-solver","2026-05-31 17:08:46",{"source":8,"skillName":5,"commands":40,"prompt":50,"zipAvailable":51},[41,44,47],{"tool":42,"command":43},"npx","npx skills add lambda-solver\u002Flambdabench-pro --skill 01-best-practices",{"tool":45,"command":46},"bunx","bunx skills add lambda-solver\u002Flambdabench-pro --skill 01-best-practices",{"tool":48,"command":49},"pnpm","pnpm dlx skills add lambda-solver\u002Flambdabench-pro --skill 01-best-practices","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Feffect-ts\u002Fpatterns\u002F01-best-practices\u002FSKILL.md",true,[],[54,85,107,126,147,163],{"skillNo":55,"name":56,"nameZh":6,"description":57,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":58,"categories":59,"keywords":65,"publishedAt":28},"01M71H9FNA5D6Y4ANXD18Z1Z3X","tmux-workflow","Development workflow with tmux — run dev servers, Storybook, and background processes in persistent sessions with live logs, while keeping OpenCode free for chat","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Ftmux\u002FSKILL.md",[60],{"categoryNo":61,"categoryName":62,"taxonomyType":63,"taxonomyTypeDesc":64},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[66,67,68,69,70,71,72,73,74,75,76,22,77,78,79,80,81,82,83,84],"tmux","workflow","tmux workflow","chat","dev servers","background","processes","storybook","live","servers","run","with","logs","development workflow","free","dev","sessions","for","development",{"skillNo":86,"name":87,"nameZh":6,"description":88,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":89,"categories":90,"keywords":94,"publishedAt":28},"01M71H9DQJDAJVZX37NDN99D3P","04-anti-patterns","React anti-patterns to avoid — manual JSX repetition, useEffect misuse, reference instability, prop drilling, conditional hooks, and common performance traps","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F04-anti-patterns\u002FSKILL.md",[91],{"categoryNo":92,"categoryName":93,"taxonomyType":63,"taxonomyTypeDesc":64},"01JBSEEDCAT000000000000009","前端开发",[95,96,97,98,99,100,101,102,103,104,105,22,106],"patterns","anti patterns","04 anti patterns","common","jsx","reference","conditional","hooks","manual","performance","anti-patterns","react",{"skillNo":108,"name":109,"nameZh":6,"description":110,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":111,"categories":112,"keywords":114,"publishedAt":28},"01M71H9BXF511W2R3B73S5P9ZN","03-state-management","React state management patterns — lifting state, colocation, URL state, server state with TanStack Query, local state with useState\u002FuseReducer","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F03-state-management\u002FSKILL.md",[113],{"categoryNo":92,"categoryName":93,"taxonomyType":63,"taxonomyTypeDesc":64},[115,116,117,118,106,119,95,120,121,122,123,22,124,77,125],"management","state management","state","03 state management","query","URL","tanstack","react state management","local","server","tanstack query",{"skillNo":127,"name":128,"nameZh":6,"description":129,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":130,"categories":131,"keywords":133,"publishedAt":28},"01M71H9AAGVWMYQ4NG82QPYCTE","02-component-composition","React component composition patterns — render props, compound components, list rendering with map, slot patterns, and layout primitives","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F02-component-composition\u002FSKILL.md",[132],{"categoryNo":92,"categoryName":93,"taxonomyType":63,"taxonomyTypeDesc":64},[134,135,136,22,77,137,138,106,139,95,140,141,142,143,144,145,146],"02 component composition","component","Composition","compound","components","primitives","composition patterns","list","map","rendering","render","react component","layout",{"skillNo":148,"name":149,"nameZh":6,"description":150,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":151,"categories":152,"keywords":154,"publishedAt":28},"01M71H98RDXRQZDR496SRD906M","01-fp-style","React functional programming style — pure components, hooks conventions, Effect Atom integration, and Tailwind patterns","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fpatterns\u002F01-fp-style\u002FSKILL.md",[153],{"categoryNo":92,"categoryName":93,"taxonomyType":63,"taxonomyTypeDesc":64},[155,23,156,95,24,157,22,158,106,159,138,102,160,161,162,20],"01 fp style","atom","integration","functional","programming","Tailwind","tailwind patterns","functional programming",{"skillNo":164,"name":165,"nameZh":6,"description":166,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":167,"categories":168,"keywords":170,"publishedAt":28},"01M71H95PYGAWBS5C8KN0C4WGT","react-animation","React animation with react\u002Fmotion (Framer Motion) — declarative animations, gestures, layout animations, and performance best practices","https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Freact\u002Fanimation\u002FSKILL.md",[169],{"categoryNo":92,"categoryName":93,"taxonomyType":63,"taxonomyTypeDesc":64},[106,171,172,104,173,22,146,174,19,77,175,176,177,178],"react animation","Animation","framer motion","motion","framer","gestures","animations","declarative"]