Token导航 LogoToken导航TokenDH.com
前端设计需要联网github未标认证来源可访问clear审计通过

recur-entitlements经常性权利

Agent Skill

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

总安装

737

周安装

31

GitHub Stars

公开资料未说明

下载量

258
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

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

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

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/recur-tw/skills --skill recur-entitlements

简介

recur-entitlements 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中整理协作事项。

  • 适用于围绕仓库状态、代码变更或协作事项进行信息整理的任务。
  • 可查询仓库状态、Issue 详情、PR 内容和协作历史。
  • 安装命令:npx skills add https://github.com/recur-tw/skills --skill recur-entitlements。
  • 建议确认权限范围和维护状态,注意是否触发联网或文件操作。

SKILL.md

Recur Entitlements & Access Control

You are helping implement access control using Recur's entitlements system. Entitlements let you check if a customer has access to your products (subscriptions or one-time purchases).

Quick Start: Client-Side Check

import { RecurProvider, useCustomer } from 'recur-tw'

// 1. Wrap app with provider and identify customer
function App() {
  return (
    <RecurProvider
      config={{ publishableKey: process.env.NEXT_PUBLIC_RECUR_PUBLISHABLE_KEY }}
      customer={{ email: 'user@example.com' }}
    >
      <MyApp />
    </RecurProvider>
  )
}

// 2. Check access anywhere in your app
function PremiumFeature() {
  const { check, isLoading } = useCustomer()

  if (isLoading) return <div>Loading...</div>

  const { allowed } = check('pro-plan')

  if (!allowed) {
    return <UpgradePrompt />
  }

  return <PremiumContent />
}

Customer Identification

Identify customers using one of these methods:

// By email (most common)
<RecurProvider customer={{ email: 'user@example.com' }}>

// By your system's user ID
<RecurProvider customer={{ externalId: 'user_123' }}>

// By Recur customer ID
<RecurProvider customer={{ id: 'cus_xxx' }}>

Checking Access

Synchronous Check (Cached)

Fast, uses cached data. Good for UI rendering.

const { check } = useCustomer()

// Check by product slug
const { allowed, entitlement } = check('pro-plan')

// Check by product ID
const { allowed } = check('prod_xxx')

if (allowed) {
  // User has access
  // entitlement contains details like status, expiresAt
}

Async Check (Live)

Fetches fresh data from API. Use for critical operations.

const { check } = useCustomer()

// Real-time check
const { allowed, entitlement } = await check('pro-plan', { live: true })

// Good for:
// - Before processing important actions
// - After checkout to confirm access
// - When cached data might be stale

Manual Refetch

const { refetch } = useCustomer()

// After checkout completion
onPaymentComplete: async () => {
  await refetch() // Refresh entitlements
  router.push('/dashboard')
}

Entitlement Response Structure

interface Entitlement {
  product: string        // Product slug
  productId: string      // Product ID
  status: EntitlementStatus
  source: 'subscription' | 'order'  // How they got access
  sourceId: string       // Subscription/Order ID
  grantedAt: string      // When access was granted
  expiresAt: string | null  // When access expires (null = permanent)
}

type EntitlementStatus =
  | 'active'      // Subscription active
  | 'trialing'    // In trial period
  | 'past_due'    // Payment failed, in grace period
  | 'canceled'    // Cancelled but access until period end
  | 'purchased'   // One-time purchase (permanent)

Server-Side Checking

Using Server SDK

import { Recur } from 'recur-tw/server'

const recur = new Recur(process.env.RECUR_SECRET_KEY!)

// In API route or server action
async function checkAccess(userEmail: string) {
  const { allowed, entitlement } = await recur.entitlements.check({
    product: 'pro-plan',
    customer: { email: userEmail },
  })

  if (!allowed) {
    throw new Error('Upgrade required')
  }

  return entitlement
}

Using REST API Directly

// GET /api/v1/customers/entitlements
const response = await fetch(
  `https://api.recur.tw/v1/customers/entitlements?email=${encodeURIComponent(email)}`,
  {
    headers: {
      'X-Recur-Secret-Key': process.env.RECUR_SECRET_KEY!,
    },
  }
)

const { customer, subscription, entitlements } = await response.json()

Common Patterns

Paywall Component

function Paywall({
  children,
  product,
  fallback
}: {
  children: React.ReactNode
  product: string
  fallback?: React.ReactNode
}) {
  const { check, isLoading } = useCustomer()

  if (isLoading) {
    return <div>Loading...</div>
  }

  const { allowed } = check(product)

  if (!allowed) {
    return fallback || <UpgradePrompt product={product} />
  }

  return <>{children}</>
}

// Usage
<Paywall product="pro-plan">
  <PremiumDashboard />
</Paywall>

Feature Flag Style

function useFeature(featureProduct: string) {
  const { check, isLoading } = useCustomer()

  if (isLoading) {
    return { enabled: false, loading: true }
  }

  const { allowed, entitlement } = check(featureProduct)

  return {
    enabled: allowed,
    loading: false,
    entitlement,
    isTrial: entitlement?.status === 'trialing',
    isPastDue: entitlement?.status === 'past_due',
  }
}

// Usage
function MyComponent() {
  const { enabled, isTrial } = useFeature('pro-plan')

  if (!enabled) return <UpgradeButton />

  return (
    <>
      {isTrial && <TrialBanner />}
      <ProFeature />
    </>
  )
}

API Middleware

// middleware/requireSubscription.ts
import { Recur } from 'recur-tw/server'

const recur = new Recur(process.env.RECUR_SECRET_KEY!)

export async function requireSubscription(
  req: Request,
  product: string
) {
  const userEmail = await getUserEmail(req) // Your auth logic

  const { allowed, denial } = await recur.entitlements.check({
    product,
    customer: { email: userEmail },
  })

  if (!allowed) {
    throw new Response(JSON.stringify({
      error: 'Subscription required',
      reason: denial?.reason, // 'no_customer', 'no_entitlement', etc.
    }), {
      status: 403,
      headers: { 'Content-Type': 'application/json' },
    })
  }
}

// Usage in API route
export async function GET(req: Request) {
  await requireSubscription(req, 'pro-plan')

  // User has access, continue...
  return Response.json({ data: 'premium content' })
}

Multiple Product Tiers

function PricingGate() {
  const { check } = useCustomer()

  const hasPro = check('pro-plan').allowed
  const hasEnterprise = check('enterprise-plan').allowed

  if (hasEnterprise) {
    return <EnterpriseDashboard />
  }

  if (hasPro) {
    return <ProDashboard />
  }

  return <FreeDashboard />
}

Handling Edge Cases

Past Due Subscriptions

const { allowed, entitlement } = check('pro-plan')

if (allowed && entitlement?.status === 'past_due') {
  // Show warning but allow access during grace period
  return (
    <>
      <PaymentFailedBanner />
      <PremiumContent />
    </>
  )
}

Trial Subscriptions

const { entitlement } = check('pro-plan')

if (entitlement?.status === 'trialing') {
  const trialEnds = new Date(entitlement.expiresAt!)
  const daysLeft = Math.ceil((trialEnds - Date.now()) / (1000 * 60 * 60 * 24))

  return <TrialBanner daysLeft={daysLeft} />
}

Cancelled but Active

const { entitlement } = check('pro-plan')

if (entitlement?.status === 'canceled') {
  // User cancelled but still has access until period end
  return (
    <>
      <ResubscribeBanner expiresAt={entitlement.expiresAt} />
      <PremiumContent />
    </>
  )
}

Denial Reasons

When allowed is false, check the denial reason:

const { allowed, denial } = check('pro-plan')

if (!allowed) {
  switch (denial?.reason) {
    case 'no_customer':
      // Customer not found
      return <CreateAccountPrompt />

    case 'no_entitlement':
      // No subscription to this product
      return <SubscribePrompt />

    case 'expired':
      // Subscription/access expired
      return <RenewPrompt />

    case 'insufficient_balance':
      // For credit-based products
      return <BuyCreditsPrompt />

    default:
      return <GenericUpgradePrompt />
  }
}

Best Practices

  1. Use cached checks for UI - Fast rendering, good UX
  2. Use live checks for actions - Ensure fresh data for important operations
  3. Handle all statuses - active, trialing, past_due, canceled
  4. Refetch after checkout - Ensure UI updates after purchase
  5. Implement graceful degradation - Show upgrade prompts, not errors

Related Skills

  • /recur-quickstart - Initial SDK setup
  • /recur-checkout - Implement purchase flows
  • /recur-webhooks - Sync entitlements with webhooks

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

26.69%
按下载量换算69

Antigravity

25.91%
按下载量换算67

Codex

15.92%
按下载量换算41

Gemini CLI

13.51%
按下载量换算35

OpenCode

7.07%
按下载量换算18

Cursor

3.55%
按下载量换算9

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

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

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

来源信息

继续浏览同类 Skills