Token导航 LogoToken导航

Agent Skill · 前端设计

effect-core-patterns(效果核心模式)

effect-core-patterns 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

effect-core-patterns 是前端设计类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描已通过,按安装量在前端设计类的 10,216 个 Skill 里排第 5,465。

总安装 665周安装 28GitHub Stars 142下载 233核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:effect-core-patterns(效果核心模式)
来源仓库:https://github.com/thebushidocollective/han
仓库路径:skills/effect-core-patterns
安装命令:
npx skills add https://github.com/thebushidocollective/han --skill effect-core-patterns
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/thebushidocollective/han --skill effect-core-patterns

这个 Skill 是做什么的

前端设计类 Skill 关注页面结构、视觉规范和组件写法,输出通常是可运行的界面代码。

effect-core-patterns 讲解 Effect 核心编程模式,包括 Effect.gen 生成器与管道组合。适合初学者掌握 Effect 的类型安全与声明式风格。通过 GitHub 安装,使用 npx skills add 命令添加指定仓库的 skill/effect-core-patterns 路径。

重点在于理解 Effect 三型参含义与作用域管理。适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

来源仓库内路径:skills/effect-core-patterns

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/thebushidocollective/han --skill effect-core-p…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

effect-core-patterns 怎么安装?

在终端执行 npx skills add https://github.com/thebushidocollective/han --skill effect-core-patterns。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

effect-core-patterns 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

effect-core-patterns 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

effect-core-patterns 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

effect-core-patterns 用的人多吗?

公开数据是累计安装 665 次,近一周安装 28 次,下载 233 次,GitHub 142 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

effect-core-patterns 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理前端设计类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

前端设计类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
frontend-design

前端设计 · Codex、Claude

8,823,360126,072只读MIT通过
vercel-composition-patterns

Vercel 组合模式 · Codex、Claude

3,858,81625,893需要联网MIT通过
vercel-react-native-skills

Vercel React native skills 前端 · Codex、Claude

2,468,66425,878只读MIT通过
adapt

adapt 搜索 · Codex、Claude

2,027,04023,125操作浏览器未明确通过
bolder

bolder 分析 · Codex、Claude

2,004,28823,130只读未明确通过
effect-core-patterns

效果核心模式 · 本页

665142需要联网未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Effect Core Patterns

Master the core Effect patterns for building type-safe, composable applications with Effect. This skill covers the Effect type, constructors, and composition patterns using Effect.gen.

The Effect Type

The Effect type has three type parameters:

Effect<Success, Error, Requirements>
  • Success (A): The type of value that an effect can succeed with
  • Error (E): The expected errors that can occur (use never for no errors)
  • Requirements (R): The contextual dependencies required (use never for no dependencies)
import { Effect } from "effect"

// Effect that succeeds with number, never fails, no requirements
const simpleEffect: Effect.Effect<number, never, never> = Effect.succeed(42)

// Effect that can fail with string error
const failableEffect: Effect.Effect<number, string, never> =
  Effect.fail("Something went wrong")

// Effect that requires a UserService
interface UserService {
  getUser: (id: string) => Effect.Effect<User, DbError, never>
}

const effectWithDeps: Effect.Effect<User, DbError, UserService> =
  Effect.gen(function* () {
    const userService = yield* Effect.service(UserService)
    const user = yield* userService.getUser("123")
    return user
  })

Creating Effects

Effect.succeed - Always Succeeds

Use when you have a pure value and need an Effect:

import { Effect } from "effect"

const result = Effect.succeed(42)
// Effect<number, never, never>

const user = Effect.succeed({ id: "1", name: "Alice" })
// Effect<User, never, never>

// Void effect (produces no useful value)
const voidEffect = Effect.succeed(undefined)
// Effect<void, never, never>

Effect.fail - Expected Failure

Use for recoverable, expected errors:

import { Effect } from "effect"

interface ValidationError {
  _tag: "ValidationError"
  message: string
}

const validateAge = (age: number): Effect.Effect<number, ValidationError, never> => {
  if (age < 0) {
    return Effect.fail({
      _tag: "ValidationError",
      message: "Age must be positive"
    })
  }
  return Effect.succeed(age)
}

// Usage with Effect.gen
const program = Effect.gen(function* () {
  const age = yield* validateAge(-5) // This will fail
  return age
})

Effect.sync - Synchronous Side Effects

Use for synchronous operations with side effects:

import { Effect } from "effect"

// Reading from a mutable variable
let counter = 0

const incrementCounter = Effect.sync(() => {
  counter++
  return counter
})

// Logging
const log = (message: string) =>
  Effect.sync(() => {
    console.log(message)
  })

// Current timestamp
const now = Effect.sync(() => Date.now())

// IMPORTANT: The function should not throw
// Thrown errors become "defects" (unexpected failures)

Effect.try - Synchronous Operations That May Fail

Use for sync operations that might throw:

import { Effect } from "effect"

// Parse JSON safely
const parseJSON = (text: string): Effect.Effect<unknown, Error, never> =>
  Effect.try(() => JSON.parse(text))

// With custom error mapping
interface ParseError {
  _tag: "ParseError"
  message: string
}

const parseJSONCustom = (text: string): Effect.Effect<unknown, ParseError, never> =>
  Effect.try({
    try: () => JSON.parse(text),
    catch: (error) => ({
      _tag: "ParseError",
      message: error instanceof Error ? error.message : String(error)
    })
  })

// Usage
const program = Effect.gen(function* () {
  const data = yield* parseJSON('{"name": "Alice"}')
  return data
})

Effect.promise - Async Operations (No Errors)

Use for promises that should never reject:

import { Effect } from "effect"

// Delayed execution
const delay = (ms: number): Effect.Effect<void, never, never> =>
  Effect.promise(() =>
    new Promise<void>((resolve) => setTimeout(resolve, ms))
  )

// Fetch with assumption it won't fail
const fetchData = (url: string): Effect.Effect<Response, never, never> =>
  Effect.promise(() => fetch(url))

// IMPORTANT: If promise rejects, it becomes a "defect"
// Use Effect.tryPromise for operations that can fail

Effect.tryPromise - Async Operations That May Fail

Use for promises that might reject:

import { Effect } from "effect"

interface NetworkError {
  _tag: "NetworkError"
  message: string
  statusCode?: number
}

const fetchUser = (id: string): Effect.Effect<User, NetworkError, never> =>
  Effect.tryPromise({
    try: async () => {
      const response = await fetch(`/api/users/${id}`)
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}`)
      }
      return response.json()
    },
    catch: (error) => ({
      _tag: "NetworkError",
      message: error instanceof Error ? error.message : String(error),
      statusCode: error instanceof Error && 'status' in error
        ? (error as any).status
        : undefined
    })
  })

// Simplified version (errors become UnknownException)
const fetchUserSimple = (id: string): Effect.Effect<User, UnknownException, never> =>
  Effect.tryPromise(() => fetch(`/api/users/${id}`).then(r => r.json()))

Effect.async - Callback-Based APIs

Use for wrapping callback-style APIs:

import { Effect } from "effect"

// Wrap setTimeout
const sleep = (ms: number): Effect.Effect<void, never, never> =>
  Effect.async<void>((resume) => {
    const timeoutId = setTimeout(() => {
      resume(Effect.succeed(undefined))
    }, ms)

    // Optional cleanup on interruption
    return Effect.sync(() => {
      clearTimeout(timeoutId)
    })
  })

// Wrap Node.js callback API
interface FileError {
  _tag: "FileError"
  message: string
}

const readFile = (path: string): Effect.Effect<string, FileError, never> =>
  Effect.async<string, FileError>((resume) => {
    fs.readFile(path, 'utf8', (error, data) => {
      if (error) {
        resume(Effect.fail({
          _tag: "FileError",
          message: error.message
        }))
      } else {
        resume(Effect.succeed(data))
      }
    })
  })

Composing Effects with Effect.gen

Effect.gen allows you to write effect code using generator syntax:

import { Effect } from "effect"

// Basic composition
const program = Effect.gen(function* () {
  const a = yield* Effect.succeed(10)
  const b = yield* Effect.succeed(20)
  return a + b
})

// With error handling
const programWithErrors = Effect.gen(function* () {
  const age = yield* validateAge(25)
  const user = yield* createUser({ age })
  return user
})

// Sequential operations
const fetchUserProfile = (userId: string) =>
  Effect.gen(function* () {
    const user = yield* fetchUser(userId)
    const posts = yield* fetchPosts(user.id)
    const comments = yield* fetchComments(user.id)
    return { user, posts, comments }
  })

// Using control flow
const processData = (data: unknown) =>
  Effect.gen(function* () {
    const validated = yield* validateData(data)

    if (validated.type === "user") {
      const user = yield* createUser(validated)
      return { type: "user", user }
    } else {
      const post = yield* createPost(validated)
      return { type: "post", post }
    }
  })

// Error handling with short-circuiting
const safeDivide = (a: number, b: number) =>
  Effect.gen(function* () {
    if (b === 0) {
      yield* Effect.fail({ _tag: "DivideByZero" })
      return // Explicit return for type narrowing
    }
    return a / b
  })

Running Effects

Effect.runSync - Synchronous Execution

Use for effects with no async operations or requirements:

import { Effect } from "effect"

const result = Effect.runSync(Effect.succeed(42))
// 42

// Throws if effect can fail
try {
  Effect.runSync(Effect.fail("error"))
} catch (error) {
  // Caught
}

// CANNOT use with async effects or requirements
// Effect.runSync(Effect.promise(() => fetch("..."))) // Runtime error!

Effect.runPromise - Async Execution

Use for async effects without requirements:

import { Effect } from "effect"

const program = Effect.gen(function* () {
  yield* delay(1000)
  return "Done"
})

const result = await Effect.runPromise(program)
// "Done" after 1 second

// Rejects on failure
try {
  await Effect.runPromise(Effect.fail("error"))
} catch (error) {
  // error === "error"
}

Effect.runPromiseExit - Get Full Exit Information

Use when you need detailed success/failure information:

import { Effect, Exit } from "effect"

const program = Effect.succeed(42)

const exit = await Effect.runPromiseExit(program)

if (Exit.isSuccess(exit)) {
  console.log("Success:", exit.value)
} else if (Exit.isFailure(exit)) {
  console.log("Failure:", exit.cause)
}

Building Pipelines

Effect.map - Transform Success Values

import { Effect, pipe } from "effect"

const double = (n: number) => n * 2

// Using pipe
const result = pipe(
  Effect.succeed(21),
  Effect.map(double)
)
// Effect<42, never, never>

// Using method
const result2 = Effect.succeed(21).pipe(
  Effect.map(double)
)

// Chaining transformations
const program = pipe(
  Effect.succeed("hello"),
  Effect.map(s => s.toUpperCase()),
  Effect.map(s => s.length)
)
// Effect<5, never, never>

Effect.flatMap - Chain Dependent Effects

import { Effect, pipe } from "effect"

const getUser = (id: string): Effect.Effect<User, DbError, never> => {
  // ...
}

const getUserPosts = (userId: string): Effect.Effect<Post[], DbError, never> => {
  // ...
}

// Using pipe
const program = pipe(
  getUser("123"),
  Effect.flatMap(user => getUserPosts(user.id))
)

// Using Effect.gen (more readable)
const program2 = Effect.gen(function* () {
  const user = yield* getUser("123")
  const posts = yield* getUserPosts(user.id)
  return posts
})

Effect.andThen - Sequential Composition

import { Effect, pipe } from "effect"

// Chain effects, ignoring previous result
const program = pipe(
  log("Starting..."),
  Effect.andThen(processData()),
  Effect.andThen(log("Done!"))
)

// Provide value to next effect
const program2 = pipe(
  Effect.succeed(5),
  Effect.andThen(n => Effect.succeed(n * 2))
)

Effect.tap - Side Effects Without Changing Value

import { Effect, pipe } from "effect"

const program = pipe(
  fetchUser("123"),
  Effect.tap(user => log(`Fetched user: ${user.name}`)),
  Effect.tap(user => saveToCache(user)),
  Effect.map(user => user.email)
)

// The taps run but don't change the flowing value

Effect Transformations

Effect.mapError - Transform Errors

import { Effect, pipe } from "effect"

interface DbError {
  _tag: "DbError"
  message: string
}

interface AppError {
  _tag: "AppError"
  message: string
  context: string
}

const program = pipe(
  queryDatabase(),
  Effect.mapError((dbError: DbError): AppError => ({
    _tag: "AppError",
    message: dbError.message,
    context: "user-service"
  }))
)

Effect.mapBoth - Transform Success and Error

import { Effect, pipe } from "effect"

const program = pipe(
  Effect.succeed(10),
  Effect.mapBoth({
    onSuccess: (n) => n * 2,
    onFailure: (e) => ({ _tag: "MappedError", original: e })
  })
)

Effect.orElse - Fallback on Failure

import { Effect, pipe } from "effect"

const program = pipe(
  fetchFromPrimaryDb(),
  Effect.orElse(() => fetchFromSecondaryDb())
)

// Fallback to different effect based on error
const programWithCheck = pipe(
  riskyOperation(),
  Effect.orElse((error) =>
    error._tag === "Timeout"
      ? retryOperation()
      : Effect.fail(error)
  )
)

Best Practices

  1. Use Effect.gen for Readability: Prefer Effect.gen over pipe for complex compositions with multiple steps.
  2. Type Your Errors: Always use tagged unions for error types to enable catchTag and better error handling.
  3. Distinguish Errors from Defects: Use Effect.try/tryPromise for operations that can fail. Let unexpected errors become defects.
  4. Keep Effects Pure: Don't perform side effects outside of Effect constructors. Use Effect.sync for side effects.
  5. Use Descriptive Names: Name effects based on what they do, not how they do it (e.g., fetchUser not makeHttpRequest).
  6. Compose Small Effects: Build complex operations from small, focused effects that do one thing well.
  7. Handle Requirements Explicitly: Use Effect.service and layers to manage dependencies rather than importing directly.
  8. Document Effect Types: Explicitly type effects to make requirements, errors, and success types clear.
  9. Use pipe for Transformations: For simple transformations, pipe is more concise than Effect.gen.
  10. Test Effects Independently: Design effects to be testable by injecting dependencies via requirements.

Common Pitfalls

  1. Using runSync on Async Effects: runSync throws on async effects. Use runPromise instead.
  2. Not Handling Errors: Forgetting that effects can fail. Always consider the error channel.
  3. Mixing Promises and Effects: Converting between promises and effects incorrectly. Use Effect.promise/tryPromise.
  4. Ignoring Requirements: Not providing required services causes runtime errors. Use layers properly.
  5. Throwing in Effect.sync: Thrown errors become defects. Use Effect.try for operations that can throw.
  6. Not Using Effect.gen: Complex pipe chains are hard to read. Use Effect.gen for better readability.
  7. Incorrect Error Types: Using unknown or Error instead of specific tagged error types.
  8. Sequential When Parallel Is Better: Using Effect.gen sequentially when operations could run in parallel with Effect.all.
  9. Over-Using map/flatMap: Effect.gen is clearer for multi-step operations than nested maps.
  10. Not Leveraging Type Safety: Not using TypeScript's type system to catch errors at compile time.

When to Use This Skill

Use effect-core-patterns when you need to:

  • Build type-safe applications with Effect
  • Create and compose effectful operations
  • Handle errors in a type-safe manner
  • Work with async operations and promises
  • Manage side effects explicitly
  • Create pipelines of transformations
  • Convert callback-based APIs to Effect
  • Build maintainable, composable code
  • Leverage functional programming patterns
  • Ensure compile-time safety for effects

Resources

Official Documentation

Guides

平台分布

Codex

32.62%
按下载量换算76

Claude

30.48%
按下载量换算71

Cursor

20.09%
按下载量换算47

Gemini CLI

9.39%
按下载量换算22

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills