[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71H8YEN4DMJ69FB3MCK9BJ1":3,"skill-same:01M71H8YEN4DMJ69FB3MCK9BJ1":59},{"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":34,"linkOnly":35,"markdownContent":36,"markdownBody":37,"frontMatter":38,"refName":39,"commitSha":40,"skillDirectory":41,"forksCount":13,"repositoryHtmlUrl":42,"repositoryHomepageUrl":6,"ownerHtmlUrl":43,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":44,"install":45,"resources":58},"01M71H8YEN4DMJ69FB3MCK9BJ1","02-vitest-patterns",null,"Effect-TS 4 Vitest patterns — it.effect, it.scoped, it.layer, @effect\u002Fvitest\u002Futils assertions, ConfigProvider for env, and platform-node-shared for FileSystem","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\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Feffect-ts\u002Ftesting\u002F02-vitest-patterns\u002FSKILL.md",[],[18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33],"vitest","02 vitest patterns","patterns","shared","effect","platform","for","filesystem","scoped","utils","assertions","env","opencode","node","layer","it","2026-11-10 10:12:30",false,"---\nname: 02-vitest-patterns\ndescription: Effect-TS 4 Vitest patterns — it.effect, it.scoped, it.layer, @effect\u002Fvitest\u002Futils assertions, ConfigProvider for env, and platform-node-shared for FileSystem\nlicense: MIT\ncompatibility: opencode\n---\n\n# Testing with @effect\u002Fvitest\n\n**Package**: `@effect\u002Fvitest`\n**Version**: `@effect\u002Fvitest@4.0.0-beta.41`\n\n## Canonical import pattern\n\n```typescript\nimport { describe, it } from \"@effect\u002Fvitest\";\nimport { assertSome, assertTrue, strictEqual } from \"@effect\u002Fvitest\u002Futils\";\nimport { Effect, Layer } from \"effect\";\n```\n\n- `it` and `describe` — always from `@effect\u002Fvitest`\n- assertions — always from `@effect\u002Fvitest\u002Futils` (Effect-aware, uses `Equal.equals`)\n- **never** import `it`\u002F`describe` from `\"vitest\"`\n- **never** use `expect` from `\"vitest\"` for Effect values — use `@effect\u002Fvitest\u002Futils`\n\n## @effect\u002Fvitest\u002Futils — full assertion API\n\n```typescript\nimport {\n  assertDefined, \u002F\u002F assertDefined(value)\n  assertExitFailure, \u002F\u002F assertExitFailure(exit, cause)\n  assertExitSuccess, \u002F\u002F assertExitSuccess(exit, expected)\n  assertFailure, \u002F\u002F assertFailure(result, expected)\n  assertFalse, \u002F\u002F assertFalse(value)\n  assertInclude, \u002F\u002F assertInclude(actual, expected)\n  assertInstanceOf, \u002F\u002F assertInstanceOf(value, Constructor)\n  assertMatch, \u002F\u002F assertMatch(actual, regExp)\n  assertNone, \u002F\u002F assertNone(option)\n  assertSome, \u002F\u002F assertSome(option, expected)\n  assertSuccess, \u002F\u002F assertSuccess(result, expected)\n  assertTrue, \u002F\u002F assertTrue(value)\n  assertUndefined, \u002F\u002F assertUndefined(value)\n  deepStrictEqual, \u002F\u002F deep equality via Equal.equals\n  fail, \u002F\u002F fail(\"message\")\n  strictEqual, \u002F\u002F strictEqual(actual, expected)\n} from \"@effect\u002Fvitest\u002Futils\";\n```\n\n## it.effect — basic Effect test\n\n```typescript\nit.effect(\"processes item correctly\", () =>\n  Effect.gen(function* () {\n    const svc = yield* MyService;\n    const result = yield* svc.process(\"input\");\n    strictEqual(result, \"expected\");\n  }).pipe(Effect.provide(MyService.layerTest)),\n);\n```\n\n## it.effect with timeout\n\nPass timeout (ms) as the last argument:\n\n```typescript\nit.effect(\n  \"calls real API\",\n  () =>\n    Effect.gen(function* () {\n      const result = yield* callRealApi();\n      assertTrue(result.length > 0);\n    }).pipe(Effect.provide(realLayer)),\n  30_000,\n);\n```\n\n## it.scoped — test needs a Scope (resources, temp files)\n\n```typescript\nit.scoped(\"cleans up temp file\", () =>\n  Effect.gen(function* () {\n    const fs = yield* FileSystem.FileSystem;\n    const path = yield* fs.makeTempFileScoped(); \u002F\u002F auto-cleaned on scope close\n    yield* fs.writeFileString(path, \"hello\");\n    const content = yield* fs.readFileString(path);\n    strictEqual(content, \"hello\");\n  }).pipe(Effect.provide(NodeFileSystem.layer)),\n);\n```\n\n## it.layer — shared layer for all tests in a describe block\n\nProvide a layer once; all `it.effect` \u002F `it.scoped` inside share it:\n\n```typescript\nimport * as NodeFileSystem from \"@effect\u002Fplatform-node-shared\u002FNodeFileSystem\";\nimport * as NodePath from \"@effect\u002Fplatform-node-shared\u002FNodePath\";\n\nconst platformLayer = Layer.mergeAll(NodeFileSystem.layer, NodePath.layer);\n\ndescribe(\"MyService\", () => {\n  it.layer(platformLayer)((it) => {\n    it.effect(\"reads a file\", () =>\n      Effect.gen(function* () {\n        const fs = yield* FileSystem.FileSystem;\n        const content = yield* fs.readFileString(\"\u002Ftmp\u002Ftest.txt\");\n        assertDefined(content);\n      }),\n    );\n  });\n});\n```\n\n## it.effect.skipIf — conditional skip\n\n```typescript\nit.effect.skipIf(!process.env[\"OPENROUTER_API_KEY\"])(\n  \"calls real OpenRouter\",\n  () =>\n    Effect.gen(function* () {\n      const result = yield* LanguageModel.generateText({ prompt: \"hello\" });\n      assertTrue(result.text.length > 0);\n    }).pipe(Effect.provide(realLayer)),\n  30_000,\n);\n```\n\n## it.effect.each — parameterised tests\n\n```typescript\nit.effect.each([\n  { input: \" Ada \", expected: \"ada\" },\n  { input: \" Lin \", expected: \"lin\" },\n])(\"trims and lowercases $input\", ({ input, expected }) =>\n  Effect.gen(function* () {\n    strictEqual(input.trim().toLowerCase(), expected);\n  }),\n);\n```\n\n## Loading env vars for integration tests — ConfigProvider\n\nDo **not** use `vitest.setup.ts` or manual `.env` parsing. Use\n`ConfigProvider.fromUnknown(process.env)` inside the test — this is the\nidiomatic Effect way to load env:\n\n```typescript\nimport { ConfigProvider, Effect, Layer } from \"effect\";\nimport { FetchHttpClient } from \"effect\u002Funstable\u002Fhttp\";\n\nit.effect.skipIf(!process.env[\"OPENROUTER_API_KEY\"])(\n  \"calls real OpenRouter\",\n  () =>\n    Effect.gen(function* () {\n      const layer = makeOpenRouterLayer(\"minimax\u002Fminimax-m2.5:free\").pipe(Layer.provide(FetchHttpClient.layer));\n      const result = yield* LanguageModel.generateText({ prompt: \"hello\" }).pipe(\n        Effect.map((r) => r.text),\n        Effect.provide(layer),\n        Effect.provide(ConfigProvider.layer(ConfigProvider.fromUnknown(process.env))),\n      );\n      assertTrue(result.length > 0);\n    }),\n  30_000,\n);\n```\n\nVitest does **not** load `.env` automatically. The key must already be in\n`process.env` when Vitest starts. Pass it via shell:\n\n```bash\n# inline\nOPENROUTER_API_KEY=sk-... bun run test\n\n# or source first\nsource .env && bun run test\n```\n\nWithout the key, `skipIf(!process.env[\"OPENROUTER_API_KEY\"])` skips the test\ncleanly — no failure.\n\n## FileSystem in tests — use @effect\u002Fplatform-node-shared\n\nVitest runs under **Node**, not Bun. Never import `BunFileSystem` or the\n`@effect\u002Fplatform-bun` barrel in test files — it pulls in `BunRedis` which\nrequires `bun:*` native modules unavailable under Node.\n\nUse subpath imports from `@effect\u002Fplatform-node-shared` instead:\n\n```typescript\nimport * as NodeFileSystem from \"@effect\u002Fplatform-node-shared\u002FNodeFileSystem\";\nimport * as NodePath from \"@effect\u002Fplatform-node-shared\u002FNodePath\";\n\nconst testLayer = Layer.mergeAll(NodeFileSystem.layer, NodePath.layer);\n```\n\n`@effect\u002Fplatform-node-shared` must be an **explicit `devDependency`** — it is\na transitive dep of `@effect\u002Fplatform-bun` but Vite cannot resolve transitive\ndeps from `.bun\u002F` without a direct entry:\n\n```json\n\"devDependencies\": {\n  \"@effect\u002Fplatform-node-shared\": \"4.0.0-beta.41\"\n}\n```\n\nThe package has **no barrel `index.js`** — always use subpath imports:\n\n- `@effect\u002Fplatform-node-shared\u002FNodeFileSystem`\n- `@effect\u002Fplatform-node-shared\u002FNodePath`\n- `@effect\u002Fplatform-node-shared\u002FNodeChildProcessSpawner`\n\n## HTTP in tests — use FetchHttpClient\n\n`BunHttpClient` is a re-export of `FetchHttpClient` with no `bun:*` deps, but\nimporting via the `@effect\u002Fplatform-bun` barrel pulls in `BunRedis`. Use\n`FetchHttpClient` directly:\n\n```typescript\nimport { FetchHttpClient } from \"effect\u002Funstable\u002Fhttp\";\n\nconst layer = makeOpenRouterLayer(\"minimax\u002Fminimax-m2.5:free\").pipe(Layer.provide(FetchHttpClient.layer));\n```\n\n## Mock LanguageModel layer\n\n```typescript\nimport { LanguageModel } from \"effect\u002Funstable\u002Fai\";\n\nconst mockLmLayer = (responses: ReadonlyArray\u003Cstring>): Layer.Layer\u003CLanguageModel.LanguageModel> =>\n  Layer.effect(\n    LanguageModel.LanguageModel,\n    Effect.gen(function* () {\n      const idx = yield* Ref.make(0);\n      return {\n        generateText: (_options: unknown) =>\n          Effect.gen(function* () {\n            const i = yield* Ref.getAndUpdate(idx, (n) => n + 1);\n            const text = responses[Math.min(i, responses.length - 1)] ?? \"\";\n            return {\n              text,\n              usage: { inputTokens: 0, outputTokens: 0 },\n              toolCalls: [],\n              finishReason: \"stop\" as const,\n            };\n          }),\n        generateObject: () => Effect.die(new Error(\"not mocked\")),\n        streamText: () => Effect.die(new Error(\"not mocked\")),\n      } as unknown as LanguageModel.Service;\n    }),\n  );\n```\n\n## File structure convention\n\n```typescript\nimport { describe, it } from \"@effect\u002Fvitest\"\nimport { strictEqual, assertTrue } from \"@effect\u002Fvitest\u002Futils\"\nimport { Effect, Layer } from \"effect\"\n\n\u002F\u002F ─── Fixtures ────────────────────────────────────────────────────────────────\n\nconst fixture = { id: \"test\", value: 42 }\n\n\u002F\u002F ─── Mock helpers ─────────────────────────────────────────────────────────────\n\nconst mockLayer = Layer.succeed(MyService, { ... } as unknown as MyService)\n\n\u002F\u002F ─── Tests ────────────────────────────────────────────────────────────────────\n\ndescribe(\"MyService\", () => {\n  it.effect(\"does the thing\", () =>\n    Effect.gen(function* () {\n      const result = yield* doThing()\n      strictEqual(result, \"expected\")\n    }).pipe(Effect.provide(mockLayer)),\n  )\n})\n```\n\n## Linting Discipline\n\n**Never disable linter rules with `\u002F\u002F oxlint-disable-next-line` or similar comments.**\n\nIf a lint warning appears:\n1. Fix the underlying code issue (rename shadowed variables, remove unused imports, etc.)\n2. If the warning is a false positive, refactor the code to avoid triggering the rule\n3. Only as a last resort after team discussion, add a disable comment with a detailed explanation\n\nAdding disable comments without fixing the root cause is technical debt and hides real issues.\n```\n","# Testing with @effect\u002Fvitest\n\n**Package**: `@effect\u002Fvitest`\n**Version**: `@effect\u002Fvitest@4.0.0-beta.41`\n\n## Canonical import pattern\n\n```typescript\nimport { describe, it } from \"@effect\u002Fvitest\";\nimport { assertSome, assertTrue, strictEqual } from \"@effect\u002Fvitest\u002Futils\";\nimport { Effect, Layer } from \"effect\";\n```\n\n- `it` and `describe` — always from `@effect\u002Fvitest`\n- assertions — always from `@effect\u002Fvitest\u002Futils` (Effect-aware, uses `Equal.equals`)\n- **never** import `it`\u002F`describe` from `\"vitest\"`\n- **never** use `expect` from `\"vitest\"` for Effect values — use `@effect\u002Fvitest\u002Futils`\n\n## @effect\u002Fvitest\u002Futils — full assertion API\n\n```typescript\nimport {\n  assertDefined, \u002F\u002F assertDefined(value)\n  assertExitFailure, \u002F\u002F assertExitFailure(exit, cause)\n  assertExitSuccess, \u002F\u002F assertExitSuccess(exit, expected)\n  assertFailure, \u002F\u002F assertFailure(result, expected)\n  assertFalse, \u002F\u002F assertFalse(value)\n  assertInclude, \u002F\u002F assertInclude(actual, expected)\n  assertInstanceOf, \u002F\u002F assertInstanceOf(value, Constructor)\n  assertMatch, \u002F\u002F assertMatch(actual, regExp)\n  assertNone, \u002F\u002F assertNone(option)\n  assertSome, \u002F\u002F assertSome(option, expected)\n  assertSuccess, \u002F\u002F assertSuccess(result, expected)\n  assertTrue, \u002F\u002F assertTrue(value)\n  assertUndefined, \u002F\u002F assertUndefined(value)\n  deepStrictEqual, \u002F\u002F deep equality via Equal.equals\n  fail, \u002F\u002F fail(\"message\")\n  strictEqual, \u002F\u002F strictEqual(actual, expected)\n} from \"@effect\u002Fvitest\u002Futils\";\n```\n\n## it.effect — basic Effect test\n\n```typescript\nit.effect(\"processes item correctly\", () =>\n  Effect.gen(function* () {\n    const svc = yield* MyService;\n    const result = yield* svc.process(\"input\");\n    strictEqual(result, \"expected\");\n  }).pipe(Effect.provide(MyService.layerTest)),\n);\n```\n\n## it.effect with timeout\n\nPass timeout (ms) as the last argument:\n\n```typescript\nit.effect(\n  \"calls real API\",\n  () =>\n    Effect.gen(function* () {\n      const result = yield* callRealApi();\n      assertTrue(result.length > 0);\n    }).pipe(Effect.provide(realLayer)),\n  30_000,\n);\n```\n\n## it.scoped — test needs a Scope (resources, temp files)\n\n```typescript\nit.scoped(\"cleans up temp file\", () =>\n  Effect.gen(function* () {\n    const fs = yield* FileSystem.FileSystem;\n    const path = yield* fs.makeTempFileScoped(); \u002F\u002F auto-cleaned on scope close\n    yield* fs.writeFileString(path, \"hello\");\n    const content = yield* fs.readFileString(path);\n    strictEqual(content, \"hello\");\n  }).pipe(Effect.provide(NodeFileSystem.layer)),\n);\n```\n\n## it.layer — shared layer for all tests in a describe block\n\nProvide a layer once; all `it.effect` \u002F `it.scoped` inside share it:\n\n```typescript\nimport * as NodeFileSystem from \"@effect\u002Fplatform-node-shared\u002FNodeFileSystem\";\nimport * as NodePath from \"@effect\u002Fplatform-node-shared\u002FNodePath\";\n\nconst platformLayer = Layer.mergeAll(NodeFileSystem.layer, NodePath.layer);\n\ndescribe(\"MyService\", () => {\n  it.layer(platformLayer)((it) => {\n    it.effect(\"reads a file\", () =>\n      Effect.gen(function* () {\n        const fs = yield* FileSystem.FileSystem;\n        const content = yield* fs.readFileString(\"\u002Ftmp\u002Ftest.txt\");\n        assertDefined(content);\n      }),\n    );\n  });\n});\n```\n\n## it.effect.skipIf — conditional skip\n\n```typescript\nit.effect.skipIf(!process.env[\"OPENROUTER_API_KEY\"])(\n  \"calls real OpenRouter\",\n  () =>\n    Effect.gen(function* () {\n      const result = yield* LanguageModel.generateText({ prompt: \"hello\" });\n      assertTrue(result.text.length > 0);\n    }).pipe(Effect.provide(realLayer)),\n  30_000,\n);\n```\n\n## it.effect.each — parameterised tests\n\n```typescript\nit.effect.each([\n  { input: \" Ada \", expected: \"ada\" },\n  { input: \" Lin \", expected: \"lin\" },\n])(\"trims and lowercases $input\", ({ input, expected }) =>\n  Effect.gen(function* () {\n    strictEqual(input.trim().toLowerCase(), expected);\n  }),\n);\n```\n\n## Loading env vars for integration tests — ConfigProvider\n\nDo **not** use `vitest.setup.ts` or manual `.env` parsing. Use\n`ConfigProvider.fromUnknown(process.env)` inside the test — this is the\nidiomatic Effect way to load env:\n\n```typescript\nimport { ConfigProvider, Effect, Layer } from \"effect\";\nimport { FetchHttpClient } from \"effect\u002Funstable\u002Fhttp\";\n\nit.effect.skipIf(!process.env[\"OPENROUTER_API_KEY\"])(\n  \"calls real OpenRouter\",\n  () =>\n    Effect.gen(function* () {\n      const layer = makeOpenRouterLayer(\"minimax\u002Fminimax-m2.5:free\").pipe(Layer.provide(FetchHttpClient.layer));\n      const result = yield* LanguageModel.generateText({ prompt: \"hello\" }).pipe(\n        Effect.map((r) => r.text),\n        Effect.provide(layer),\n        Effect.provide(ConfigProvider.layer(ConfigProvider.fromUnknown(process.env))),\n      );\n      assertTrue(result.length > 0);\n    }),\n  30_000,\n);\n```\n\nVitest does **not** load `.env` automatically. The key must already be in\n`process.env` when Vitest starts. Pass it via shell:\n\n```bash\n# inline\nOPENROUTER_API_KEY=sk-... bun run test\n\n# or source first\nsource .env && bun run test\n```\n\nWithout the key, `skipIf(!process.env[\"OPENROUTER_API_KEY\"])` skips the test\ncleanly — no failure.\n\n## FileSystem in tests — use @effect\u002Fplatform-node-shared\n\nVitest runs under **Node**, not Bun. Never import `BunFileSystem` or the\n`@effect\u002Fplatform-bun` barrel in test files — it pulls in `BunRedis` which\nrequires `bun:*` native modules unavailable under Node.\n\nUse subpath imports from `@effect\u002Fplatform-node-shared` instead:\n\n```typescript\nimport * as NodeFileSystem from \"@effect\u002Fplatform-node-shared\u002FNodeFileSystem\";\nimport * as NodePath from \"@effect\u002Fplatform-node-shared\u002FNodePath\";\n\nconst testLayer = Layer.mergeAll(NodeFileSystem.layer, NodePath.layer);\n```\n\n`@effect\u002Fplatform-node-shared` must be an **explicit `devDependency`** — it is\na transitive dep of `@effect\u002Fplatform-bun` but Vite cannot resolve transitive\ndeps from `.bun\u002F` without a direct entry:\n\n```json\n\"devDependencies\": {\n  \"@effect\u002Fplatform-node-shared\": \"4.0.0-beta.41\"\n}\n```\n\nThe package has **no barrel `index.js`** — always use subpath imports:\n\n- `@effect\u002Fplatform-node-shared\u002FNodeFileSystem`\n- `@effect\u002Fplatform-node-shared\u002FNodePath`\n- `@effect\u002Fplatform-node-shared\u002FNodeChildProcessSpawner`\n\n## HTTP in tests — use FetchHttpClient\n\n`BunHttpClient` is a re-export of `FetchHttpClient` with no `bun:*` deps, but\nimporting via the `@effect\u002Fplatform-bun` barrel pulls in `BunRedis`. Use\n`FetchHttpClient` directly:\n\n```typescript\nimport { FetchHttpClient } from \"effect\u002Funstable\u002Fhttp\";\n\nconst layer = makeOpenRouterLayer(\"minimax\u002Fminimax-m2.5:free\").pipe(Layer.provide(FetchHttpClient.layer));\n```\n\n## Mock LanguageModel layer\n\n```typescript\nimport { LanguageModel } from \"effect\u002Funstable\u002Fai\";\n\nconst mockLmLayer = (responses: ReadonlyArray\u003Cstring>): Layer.Layer\u003CLanguageModel.LanguageModel> =>\n  Layer.effect(\n    LanguageModel.LanguageModel,\n    Effect.gen(function* () {\n      const idx = yield* Ref.make(0);\n      return {\n        generateText: (_options: unknown) =>\n          Effect.gen(function* () {\n            const i = yield* Ref.getAndUpdate(idx, (n) => n + 1);\n            const text = responses[Math.min(i, responses.length - 1)] ?? \"\";\n            return {\n              text,\n              usage: { inputTokens: 0, outputTokens: 0 },\n              toolCalls: [],\n              finishReason: \"stop\" as const,\n            };\n          }),\n        generateObject: () => Effect.die(new Error(\"not mocked\")),\n        streamText: () => Effect.die(new Error(\"not mocked\")),\n      } as unknown as LanguageModel.Service;\n    }),\n  );\n```\n\n## File structure convention\n\n```typescript\nimport { describe, it } from \"@effect\u002Fvitest\"\nimport { strictEqual, assertTrue } from \"@effect\u002Fvitest\u002Futils\"\nimport { Effect, Layer } from \"effect\"\n\n\u002F\u002F ─── Fixtures ────────────────────────────────────────────────────────────────\n\nconst fixture = { id: \"test\", value: 42 }\n\n\u002F\u002F ─── Mock helpers ─────────────────────────────────────────────────────────────\n\nconst mockLayer = Layer.succeed(MyService, { ... } as unknown as MyService)\n\n\u002F\u002F ─── Tests ────────────────────────────────────────────────────────────────────\n\ndescribe(\"MyService\", () => {\n  it.effect(\"does the thing\", () =>\n    Effect.gen(function* () {\n      const result = yield* doThing()\n      strictEqual(result, \"expected\")\n    }).pipe(Effect.provide(mockLayer)),\n  )\n})\n```\n\n## Linting Discipline\n\n**Never disable linter rules with `\u002F\u002F oxlint-disable-next-line` or similar comments.**\n\nIf a lint warning appears:\n1. Fix the underlying code issue (rename shadowed variables, remove unused imports, etc.)\n2. If the warning is a false positive, refactor the code to avoid triggering the rule\n3. Only as a last resort after team discussion, add a disable comment with a detailed explanation\n\nAdding disable comments without fixing the root cause is technical debt and hides real issues.\n```\n",{"name":5,"license":14,"description":7,"compatibility":30},"main","816c073aaf171300af3605b06f7ec5aa7370ef0b","reference\u002Fghui\u002F.opencode\u002Fskills\u002Feffect-ts\u002Ftesting\u002F02-vitest-patterns","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":46,"prompt":56,"zipAvailable":57},[47,50,53],{"tool":48,"command":49},"npx","npx skills add lambda-solver\u002Flambdabench-pro --skill 02-vitest-patterns",{"tool":51,"command":52},"bunx","bunx skills add lambda-solver\u002Flambdabench-pro --skill 02-vitest-patterns",{"tool":54,"command":55},"pnpm","pnpm dlx skills add lambda-solver\u002Flambdabench-pro --skill 02-vitest-patterns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Flambda-solver\u002Flambdabench-pro\u002Fblob\u002Fmain\u002Freference\u002Fghui\u002F.opencode\u002Fskills\u002Feffect-ts\u002Ftesting\u002F02-vitest-patterns\u002FSKILL.md",true,[],[60,90,111,130,151,169],{"skillNo":61,"name":62,"nameZh":6,"description":63,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":64,"categories":65,"keywords":71,"publishedAt":34},"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",[66],{"categoryNo":67,"categoryName":68,"taxonomyType":69,"taxonomyTypeDesc":70},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[72,73,74,75,76,77,78,79,80,81,82,30,83,84,85,86,87,88,24,89],"tmux","workflow","tmux workflow","chat","dev servers","background","processes","storybook","live","servers","run","with","logs","development workflow","free","dev","sessions","development",{"skillNo":91,"name":92,"nameZh":6,"description":93,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":94,"categories":95,"keywords":99,"publishedAt":34},"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",[96],{"categoryNo":97,"categoryName":98,"taxonomyType":69,"taxonomyTypeDesc":70},"01JBSEEDCAT000000000000009","前端开发",[20,100,101,102,103,104,105,106,107,108,109,30,110],"anti patterns","04 anti patterns","common","jsx","reference","conditional","hooks","manual","performance","anti-patterns","react",{"skillNo":112,"name":113,"nameZh":6,"description":114,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":115,"categories":116,"keywords":118,"publishedAt":34},"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",[117],{"categoryNo":97,"categoryName":98,"taxonomyType":69,"taxonomyTypeDesc":70},[119,120,121,122,110,123,20,124,125,126,127,30,128,83,129],"management","state management","state","03 state management","query","URL","tanstack","react state management","local","server","tanstack query",{"skillNo":131,"name":132,"nameZh":6,"description":133,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":134,"categories":135,"keywords":137,"publishedAt":34},"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",[136],{"categoryNo":97,"categoryName":98,"taxonomyType":69,"taxonomyTypeDesc":70},[138,139,140,30,83,141,142,110,143,20,144,145,146,147,148,149,150],"02 component composition","component","Composition","compound","components","primitives","composition patterns","list","map","rendering","render","react component","layout",{"skillNo":152,"name":153,"nameZh":6,"description":154,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":155,"categories":156,"keywords":158,"publishedAt":34},"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",[157],{"categoryNo":97,"categoryName":98,"taxonomyType":69,"taxonomyTypeDesc":70},[159,160,161,20,162,163,30,164,110,165,142,106,166,167,168,22],"01 fp style","style","atom","conventions","integration","functional","programming","Tailwind","tailwind patterns","functional programming",{"skillNo":170,"name":171,"nameZh":6,"description":172,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":173,"categories":174,"keywords":176,"publishedAt":34},"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",[175],{"categoryNo":97,"categoryName":98,"taxonomyType":69,"taxonomyTypeDesc":70},[110,177,178,108,179,30,150,180,181,83,182,183,184,185],"react animation","Animation","framer motion","motion","best practices","framer","gestures","animations","declarative"]