Token导航 LogoToken导航

Agent Skill · 前端设计

rate-limiting(速率限制)

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

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

总安装 533周安装 22GitHub Stars 777下载 174核验 2026-05-01

安装说明

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

安装方式

通过对话安装

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

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

命令行安装

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

skills.shnpx skills
npx skills add https://github.com/dadbodgeoff/drift --skill rate-limiting

这个 Skill 是做什么的

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

rate-limiting 用于保护 API 免遭滥用与实现分级计费,适合在 Codex、Claude、Cursor、Gemini CLI 中需要按订阅 tier 控制请求频率时使用。它采用滑动窗口算法与分层配额,支持突发流量与公平使用策略,适用于 SaaS 平台。

使用时需设置合理阈值与拒绝响应格式,避免影响合法用户;建议结合 IP 与用户维度限流。安装前请确认限流存储后端,注意是否会引入 Redis 依赖,确保高并发下性能稳定。适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

来源仓库内路径:skills/rate-limiting

上手步骤

4 步
  1. 1

    确认自己的宿主工具

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

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/dadbodgeoff/drift --skill rate-limiting;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

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

  4. 4

    按最小权限试用

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

常见问题

6 条

rate-limiting 怎么安装?

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

rate-limiting 支持哪些 AI 工具?

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

rate-limiting 需要什么权限?

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

rate-limiting 是免费的吗?

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

rate-limiting 用的人多吗?

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

rate-limiting 安全吗?

第三方扫描有提醒项,说明存在需要人工确认的行为。安装前请打开源码看清它读了什么、联网到哪里。

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

值得选的地方

  • 同时适配 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只读未明确通过
rate-limiting

速率限制 · 本页

533777需要联网未明确有提醒

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

SKILL.md 原文

Rate Limiting

Protect your API with subscription-tier aware rate limiting.

When to Use This Skill

  • Building a SaaS API with different subscription tiers
  • Protecting endpoints from abuse
  • Implementing fair usage policies
  • Adding rate limits to existing APIs

Core Concepts

Sliding Window Algorithm

More accurate than fixed windows, prevents burst at window boundaries:

Window: [----older----][----current----]
Weight:      30%             70%

Tier-Based Limits

TierRequests/minBurst
Free6010
Pro600100
Enterprise60001000

TypeScript Implementation

// rate-limiter.ts
import { Redis } from 'ioredis';

interface RateLimitConfig {
  windowMs: number;
  maxRequests: number;
  burstLimit?: number;
}

interface RateLimitResult {
  allowed: boolean;
  remaining: number;
  resetAt: number;
  retryAfter?: number;
}

const TIER_LIMITS: Record<string, RateLimitConfig> = {
  free: { windowMs: 60000, maxRequests: 60, burstLimit: 10 },
  pro: { windowMs: 60000, maxRequests: 600, burstLimit: 100 },
  enterprise: { windowMs: 60000, maxRequests: 6000, burstLimit: 1000 },
};

class RateLimiter {
  constructor(private redis: Redis) {}

  async check(key: string, tier: string = 'free'): Promise<RateLimitResult> {
    const config = TIER_LIMITS[tier] || TIER_LIMITS.free;
    const now = Date.now();
    const windowStart = now - config.windowMs;

    const multi = this.redis.multi();

    // Remove old entries
    multi.zremrangebyscore(key, 0, windowStart);
    // Count current window
    multi.zcard(key);
    // Add current request
    multi.zadd(key, now.toString(), `${now}-${Math.random()}`);
    // Set expiry
    multi.expire(key, Math.ceil(config.windowMs / 1000) + 1);

    const results = await multi.exec();
    const currentCount = (results?.[1]?.[1] as number) || 0;

    const allowed = currentCount < config.maxRequests;
    const remaining = Math.max(0, config.maxRequests - currentCount - 1);
    const resetAt = now + config.windowMs;

    return {
      allowed,
      remaining,
      resetAt,
      retryAfter: allowed ? undefined : Math.ceil(config.windowMs / 1000),
    };
  }
}

export { RateLimiter, RateLimitConfig, RateLimitResult, TIER_LIMITS };

Express Middleware

// rate-limit-middleware.ts
import { Request, Response, NextFunction } from 'express';
import { RateLimiter } from './rate-limiter';

interface RateLimitOptions {
  keyGenerator?: (req: Request) => string;
  tierResolver?: (req: Request) => string;
  skip?: (req: Request) => boolean;
}

function createRateLimitMiddleware(
  limiter: RateLimiter,
  options: RateLimitOptions = {}
) {
  const {
    keyGenerator = (req) => req.ip || 'unknown',
    tierResolver = (req) => (req as any).user?.tier || 'free',
    skip = () => false,
  } = options;

  return async (req: Request, res: Response, next: NextFunction) => {
    if (skip(req)) return next();

    const key = `ratelimit:${keyGenerator(req)}`;
    const tier = tierResolver(req);
    const result = await limiter.check(key, tier);

    // Set rate limit headers
    res.set({
      'X-RateLimit-Limit': TIER_LIMITS[tier]?.maxRequests || 60,
      'X-RateLimit-Remaining': result.remaining,
      'X-RateLimit-Reset': Math.ceil(result.resetAt / 1000),
    });

    if (!result.allowed) {
      res.set('Retry-After', result.retryAfter?.toString() || '60');
      return res.status(429).json({
        error: 'Too Many Requests',
        message: `Rate limit exceeded. Retry after ${result.retryAfter} seconds.`,
        retryAfter: result.retryAfter,
      });
    }

    next();
  };
}

export { createRateLimitMiddleware };

Python Implementation

# rate_limiter.py
import time
from typing import Optional, NamedTuple
from redis import Redis

class RateLimitResult(NamedTuple):
    allowed: bool
    remaining: int
    reset_at: float
    retry_after: Optional[int] = None

TIER_LIMITS = {
    "free": {"window_ms": 60000, "max_requests": 60, "burst_limit": 10},
    "pro": {"window_ms": 60000, "max_requests": 600, "burst_limit": 100},
    "enterprise": {"window_ms": 60000, "max_requests": 6000, "burst_limit": 1000},
}

class RateLimiter:
    def __init__(self, redis: Redis):
        self.redis = redis

    def check(self, key: str, tier: str = "free") -> RateLimitResult:
        config = TIER_LIMITS.get(tier, TIER_LIMITS["free"])
        now = time.time() * 1000
        window_start = now - config["window_ms"]

        pipe = self.redis.pipeline()
        pipe.zremrangebyscore(key, 0, window_start)
        pipe.zcard(key)
        pipe.zadd(key, {f"{now}-{id(object())}": now})
        pipe.expire(key, int(config["window_ms"] / 1000) + 1)

        results = pipe.execute()
        current_count = results[1]

        allowed = current_count < config["max_requests"]
        remaining = max(0, config["max_requests"] - current_count - 1)
        reset_at = now + config["window_ms"]

        return RateLimitResult(
            allowed=allowed,
            remaining=remaining,
            reset_at=reset_at,
            retry_after=None if allowed else int(config["window_ms"] / 1000),
        )

FastAPI Middleware

# fastapi_middleware.py
from fastapi import Request, HTTPException
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware

class RateLimitMiddleware(BaseHTTPMiddleware):
    def __init__(self, app, limiter: RateLimiter):
        super().__init__(app)
        self.limiter = limiter

    async def dispatch(self, request: Request, call_next):
        # Get user tier from request (customize based on your auth)
        tier = getattr(request.state, "user_tier", "free")
        key = f"ratelimit:{request.client.host}"

        result = self.limiter.check(key, tier)

        if not result.allowed:
            return JSONResponse(
                status_code=429,
                content={
                    "error": "Too Many Requests",
                    "retry_after": result.retry_after,
                },
                headers={
                    "Retry-After": str(result.retry_after),
                    "X-RateLimit-Remaining": "0",
                },
            )

        response = await call_next(request)
        response.headers["X-RateLimit-Remaining"] = str(result.remaining)
        response.headers["X-RateLimit-Reset"] = str(int(result.reset_at / 1000))
        return response

In-Memory Alternative (No Redis)

// memory-rate-limiter.ts
class InMemoryRateLimiter {
  private windows = new Map<string, number[]>();

  check(key: string, tier: string = 'free'): RateLimitResult {
    const config = TIER_LIMITS[tier] || TIER_LIMITS.free;
    const now = Date.now();
    const windowStart = now - config.windowMs;

    // Get or create window
    let timestamps = this.windows.get(key) || [];

    // Remove old entries
    timestamps = timestamps.filter(t => t > windowStart);

    const allowed = timestamps.length < config.maxRequests;

    if (allowed) {
      timestamps.push(now);
      this.windows.set(key, timestamps);
    }

    return {
      allowed,
      remaining: Math.max(0, config.maxRequests - timestamps.length),
      resetAt: now + config.windowMs,
      retryAfter: allowed ? undefined : Math.ceil(config.windowMs / 1000),
    };
  }

  // Cleanup old entries periodically
  cleanup(): void {
    const now = Date.now();
    for (const [key, timestamps] of this.windows) {
      const filtered = timestamps.filter(t => t > now - 60000);
      if (filtered.length === 0) {
        this.windows.delete(key);
      } else {
        this.windows.set(key, filtered);
      }
    }
  }
}

Best Practices

  1. Use Redis for distributed systems: In-memory only works for single instances
  2. Set appropriate headers: Clients need X-RateLimit-* and Retry-After
  3. Return 429 status: Standard HTTP status for rate limiting
  4. Consider burst limits: Allow short bursts above sustained rate
  5. Key by user, not just IP: Authenticated users should have their own limits

Common Mistakes

  • Using fixed windows (causes burst at boundaries)
  • Not handling Redis failures gracefully
  • Forgetting to set response headers
  • Rate limiting health check endpoints
  • Not differentiating authenticated vs anonymous users

Integration with Stripe Tiers

// Resolve tier from Stripe subscription
const tierResolver = async (req: Request): Promise<string> => {
  const user = req.user;
  if (!user?.stripeSubscriptionId) return 'free';

  const subscription = await stripe.subscriptions.retrieve(
    user.stripeSubscriptionId
  );

  const priceId = subscription.items.data[0]?.price.id;
  return PRICE_TO_TIER[priceId] || 'free';
};

平台分布

Codex

33.16%
按下载量换算58

Claude

30.08%
按下载量换算52

Cursor

19.45%
按下载量换算34

Gemini CLI

9.58%
按下载量换算17

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

可疑

权限和风险

需要联网

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

安装前确认

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

继续浏览同类 Skills