[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CXGD8NV8RNAPP8ET0JHMB7":3,"skill-same:01M6CXGD8NV8RNAPP8ET0JHMB7":50},{"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":23,"linkOnly":24,"markdownContent":25,"markdownBody":26,"frontMatter":27,"refName":30,"commitSha":31,"skillDirectory":5,"forksCount":32,"repositoryHtmlUrl":33,"repositoryHomepageUrl":6,"ownerHtmlUrl":34,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":35,"install":36,"resources":49},"01M6CXGD8NV8RNAPP8ET0JHMB7","rate-limiting",null,"Rate limiting implementation and strategies","ffsshhttiikk\u002Fopencode-agents-skills","ffsshhttiikk","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F226346827?v=4","01M6CWD9RR3Y7VRQX3MXYC8FYH","01M6CWD9WVPYAZW0J82G1VKGHY",3,"MIT","https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills\u002Fblob\u002Fmain\u002Frate-limiting\u002FSKILL.md",[],[18,19,20,21,22],"rate limiting","security","opencode","implementation","strategies","2026-11-10 10:12:30",false,"---\nname: rate-limiting\ndescription: Rate limiting implementation and strategies\nlicense: MIT\ncompatibility: opencode\nmetadata:\n  audience: developers\n  category: security\n---\n## What I do\n- Implement rate limiting\n- Choose appropriate algorithms\n- Handle rate limit headers\n- Design tiered limits\n- Handle rate limit exceeded\n- Distribute rate limits\n- Monitor rate limit usage\n- Implement custom providers\n\n## When to use me\nWhen implementing rate limiting or throttling.\n\n## Rate Limiting Algorithms\n```python\nfrom dataclasses import dataclass\nfrom datetime import datetime, timedelta\nfrom typing import Dict, Optional\nimport asyncio\n\n\n# Fixed Window\nclass FixedWindowRateLimiter:\n    \"\"\"\n    Simple fixed window rate limiting.\n    \n    Pros: Simple, memory efficient\n    Cons: Can allow bursts at window boundaries\n    \"\"\"\n    \n    def __init__(self, max_requests: int, window_seconds: int):\n        self.max_requests = max_requests\n        self.window_seconds = window_seconds\n        self.windows: Dict[str, list] = {}\n    \n    def is_allowed(self, key: str) -> tuple[bool, dict]:\n        now = datetime.utcnow()\n        window_start = self._get_window_start(now)\n        \n        if key not in self.windows:\n            self.windows[key] = []\n        \n        # Remove old requests\n        self.windows[key] = [\n            t for t in self.windows[key]\n            if t >= window_start\n        ]\n        \n        if len(self.windows[key]) >= self.max_requests:\n            return False, {\n                \"limit\": self.max_requests,\n                \"remaining\": 0,\n                \"reset\": int((window_start + timedelta(seconds=self.window_seconds)).timestamp())\n            }\n        \n        self.windows[key].append(now)\n        \n        return True, {\n            \"limit\": self.max_requests,\n            \"remaining\": self.max_requests - len(self.windows[key]),\n            \"reset\": int((window_start + timedelta(seconds=self.window_seconds)).timestamp())\n        }\n    \n    def _get_window_start(self, now: datetime) -> datetime:\n        seconds_past_window = now.timestamp() % self.window_seconds\n        return now - timedelta(seconds=seconds_past_window)\n\n\n# Sliding Window\nclass SlidingWindowRateLimiter:\n    \"\"\"\n    Sliding window rate limiting.\n    \n    Pros: More accurate than fixed window\n    Cons: More complex, more memory\n    \"\"\"\n    \n    def __init__(self, max_requests: int, window_seconds: int):\n        self.max_requests = max_requests\n        self.window_seconds = window_seconds\n        self.requests: Dict[str, list] = {}\n    \n    def is_allowed(self, key: str) -> tuple[bool, dict]:\n        now = datetime.utcnow()\n        window_start = now - timedelta(seconds=self.window_seconds)\n        \n        if key not in self.requests:\n            self.requests[key] = []\n        \n        # Remove old requests\n        self.requests[key] = [\n            t for t in self.requests[key]\n            if t >= window_start\n        ]\n        \n        if len(self.requests[key]) >= self.max_requests:\n            return False, {\n                \"limit\": self.max_requests,\n                \"remaining\": 0,\n                \"reset\": int((now + timedelta(seconds=self.window_seconds)).timestamp())\n            }\n        \n        self.requests[key].append(now)\n        \n        return True, {\n            \"limit\": self.max_requests,\n            \"remaining\": self.max_requests - len(self.requests[key]),\n            \"reset\": int((now + timedelta(seconds=self.window_seconds)).timestamp())\n        }\n\n\n# Token Bucket\nclass TokenBucketRateLimiter:\n    \"\"\"\n    Token bucket rate limiting.\n    \n    Pros: Allows bursts, smooth rate limiting\n    Cons: More complex\n    \"\"\"\n    \n    def __init__(self, max_tokens: int, refill_rate: float):\n        self.max_tokens = max_tokens\n        self.refill_rate = refill_rate  # tokens per second\n        self.tokens: Dict[str, float] = {}\n        self.last_refill: Dict[str, datetime] = {}\n    \n    def _refill(self, key: str) -> float:\n        now = datetime.utcnow()\n        \n        if key not in self.tokens:\n            self.tokens[key] = self.max_tokens\n            self.last_refill[key] = now\n            return self.tokens[key]\n        \n        elapsed = (now - self.last_refill[key]).total_seconds()\n        tokens_to_add = elapsed * self.refill_rate\n        \n        self.tokens[key] = min(\n            self.max_tokens,\n            self.tokens[key] + tokens_to_add\n        )\n        self.last_refill[key] = now\n        \n        return self.tokens[key]\n    \n    def is_allowed(self, key: str, tokens: int = 1) -> tuple[bool, dict]:\n        self._refill(key)\n        \n        if self.tokens[key] >= tokens:\n            self.tokens[key] -= tokens\n            \n            return True, {\n                \"limit\": self.max_tokens,\n                \"remaining\": int(self.tokens[key]),\n            }\n        \n        return False, {\n            \"limit\": self.max_tokens\": 0,\n,\n            \"remaining        }\n```\n\n## API Rate Limiting Middleware\n```python\nfrom fastapi import Request, HTTPException\nfrom fastapi.responses import JSONResponse\nfrom starlette.middleware.base import BaseHTTPMiddleware\n\n\nclass RateLimitMiddleware(BaseHTTPMiddleware):\n    \"\"\"Rate limiting middleware for FastAPI.\"\"\"\n    \n    def __init__(\n        self,\n        app,\n        rate_limiter,\n        exempt_paths: list = None\n    ):\n        super().__init__(app)\n        self.rate_limiter = rate_limiter\n        self.exempt_paths = exempt_paths or []\n    \n    async def dispatch(self, request: Request, call_next):\n        # Skip rate limiting for exempt paths\n        if request.url.path in self.exempt_paths:\n            return await call_next(request)\n        \n        # Get client identifier\n        key = self._get_client_key(request)\n        \n        # Check rate limit\n        allowed, headers = self.rate_limiter.is_allowed(key)\n        \n        if not allowed:\n            return JSONResponse(\n                status_code=429,\n                headers={\n                    **headers,\n                    \"Retry-After\": str(headers.get(\"reset\", 60)),\n                },\n                content={\n                    \"error\": {\n                        \"code\": \"RATE_LIMIT_EXCEEDED\",\n                        \"message\": \"Too many requests. Please retry later.\"\n                    }\n                }\n            )\n        \n        response = await call_next(request)\n        \n        # Add rate limit headers\n        for key, value in headers.items():\n            response.headers[key] = str(value)\n        \n        return response\n    \n    def _get_client_key(self, request: Request) -> str:\n        \"\"\"Get unique key for client.\"\"\"\n        # Check for API key\n        api_key = request.headers.get(\"X-API-Key\")\n        if api_key:\n            return f\"apikey:{api_key}\"\n        \n        # Use user ID if authenticated\n        if hasattr(request.state, \"user_id\"):\n            return f\"user:{request.state.user_id}\"\n        \n        # Fall back to IP\n        client_ip = request.client.host\n        return f\"ip:{client_ip}\"\n```\n\n## Distributed Rate Limiting with Redis\n```python\nimport redis\nfrom typing import Dict, Any\n\n\nclass RedisRateLimiter:\n    \"\"\"Distributed rate limiter using Redis.\"\"\"\n    \n    def __init__(\n        self,\n        redis_url: str,\n        max_requests: int = 100,\n        window_seconds: int = 60\n    ):\n        self.redis = redis.from_url(redis_url)\n        self.max_requests = max_requests\n        self.window_seconds = window_seconds\n    \n    def is_allowed(self, key: str) -> tuple[bool, dict]:\n        now = datetime.utcnow()\n        window_key = f\"ratelimit:{key}:{int(now.timestamp() \u002F\u002F self.window_seconds)}\"\n        \n        pipe = self.redis.pipeline()\n        \n        # Increment counter\n        pipe.incr(window_key)\n        # Set expiry\n        pipe.expire(window_key, self.window_seconds * 2)\n        # Get current count\n        results = pipe.execute()\n        \n        current_count = results[0]\n        \n        headers = {\n            \"X-RateLimit-Limit\": str(self.max_requests),\n            \"X-RateLimit-Remaining\": str(max(0, self.max_requests - current_count)),\n            \"X-RateLimit-Reset\": str(\n                int(now.timestamp()) + self.window_seconds\n            ),\n        }\n        \n        if current_count > self.max_requests:\n            return False, headers\n        \n        return True, headers\n    \n    def sliding_window(self, key: str) -> tuple[bool, dict]:\n        \"\"\"More accurate sliding window using sorted sets.\"\"\"\n        now = datetime.utcnow()\n        window_start = now - timedelta(seconds=self.window_seconds)\n        \n        pipe = self.redis.pipeline()\n        \n        # Remove old entries\n        pipe.zremrangebyscore(\n            f\"ratelimit:sliding:{key}\",\n            0,\n            window_start.timestamp() - 1\n        )\n        \n        # Add current request\n        pipe.zadd(\n            f\"ratelimit:sliding:{key}\",\n            {f\"{now.timestamp()}:{uuid.uuid4()}\": now.timestamp()}\n        )\n        \n        # Count requests in window\n        pipe.zcard(f\"ratelimit:sliding:{key}\")\n        \n        # Set expiry\n        pipe.expire(\n            f\"ratelimit:sliding:{key}\",\n            self.window_seconds * 2\n        )\n        \n        results = pipe.execute()\n        current_count = results[2]\n        \n        allowed = current_count \u003C= self.max_requests\n        \n        return allowed, {\n            \"X-RateLimit-Limit\": str(self.max_requests),\n            \"X-RateLimit-Remaining\": str(\n                max(0, self.max_requests - current_count)\n            ),\n            \"X-RateLimit-Reset\": str(\n                int(now.timestamp()) + self.window_seconds\n            ),\n        }\n```\n\n## Best Practices\n```\nRate Limiting Best Practices:\n\n1. Choose appropriate algorithm\n   - Fixed window: simple, forgiving\n   - Sliding window: more accurate\n   - Token bucket: burst handling\n\n2. Use tiered limits\n   - Different limits for different users\n   - Public vs authenticated\n\n3. Return proper headers\n   - X-RateLimit-Limit\n   - X-RateLimit-Remaining\n   - X-RateLimit-Reset\n   - Retry-After\n\n4. Handle exceeded gracefully\n   - Clear error messages\n   - Appropriate retry headers\n\n5. Monitor and alert\n   - Track rate limit hits\n   - Alert on unusual patterns\n\n6. Distribute across instances\n   - Use shared storage (Redis)\n   - Consistent hashing\n\n7. Consider endpoint-specific\n   - Different limits per endpoint\n   - Expensive operations get lower limits\n\n8. Allow some burst\n   - Users expect occasional bursts\n   - Token bucket handles this well\n\n9. Test rate limiting\n   - Verify limits are enforced\n   - Test header values\n\n10. Document limits\n    - API documentation\n    - Developer portal\n```\n","## What I do\n- Implement rate limiting\n- Choose appropriate algorithms\n- Handle rate limit headers\n- Design tiered limits\n- Handle rate limit exceeded\n- Distribute rate limits\n- Monitor rate limit usage\n- Implement custom providers\n\n## When to use me\nWhen implementing rate limiting or throttling.\n\n## Rate Limiting Algorithms\n```python\nfrom dataclasses import dataclass\nfrom datetime import datetime, timedelta\nfrom typing import Dict, Optional\nimport asyncio\n\n\n# Fixed Window\nclass FixedWindowRateLimiter:\n    \"\"\"\n    Simple fixed window rate limiting.\n    \n    Pros: Simple, memory efficient\n    Cons: Can allow bursts at window boundaries\n    \"\"\"\n    \n    def __init__(self, max_requests: int, window_seconds: int):\n        self.max_requests = max_requests\n        self.window_seconds = window_seconds\n        self.windows: Dict[str, list] = {}\n    \n    def is_allowed(self, key: str) -> tuple[bool, dict]:\n        now = datetime.utcnow()\n        window_start = self._get_window_start(now)\n        \n        if key not in self.windows:\n            self.windows[key] = []\n        \n        # Remove old requests\n        self.windows[key] = [\n            t for t in self.windows[key]\n            if t >= window_start\n        ]\n        \n        if len(self.windows[key]) >= self.max_requests:\n            return False, {\n                \"limit\": self.max_requests,\n                \"remaining\": 0,\n                \"reset\": int((window_start + timedelta(seconds=self.window_seconds)).timestamp())\n            }\n        \n        self.windows[key].append(now)\n        \n        return True, {\n            \"limit\": self.max_requests,\n            \"remaining\": self.max_requests - len(self.windows[key]),\n            \"reset\": int((window_start + timedelta(seconds=self.window_seconds)).timestamp())\n        }\n    \n    def _get_window_start(self, now: datetime) -> datetime:\n        seconds_past_window = now.timestamp() % self.window_seconds\n        return now - timedelta(seconds=seconds_past_window)\n\n\n# Sliding Window\nclass SlidingWindowRateLimiter:\n    \"\"\"\n    Sliding window rate limiting.\n    \n    Pros: More accurate than fixed window\n    Cons: More complex, more memory\n    \"\"\"\n    \n    def __init__(self, max_requests: int, window_seconds: int):\n        self.max_requests = max_requests\n        self.window_seconds = window_seconds\n        self.requests: Dict[str, list] = {}\n    \n    def is_allowed(self, key: str) -> tuple[bool, dict]:\n        now = datetime.utcnow()\n        window_start = now - timedelta(seconds=self.window_seconds)\n        \n        if key not in self.requests:\n            self.requests[key] = []\n        \n        # Remove old requests\n        self.requests[key] = [\n            t for t in self.requests[key]\n            if t >= window_start\n        ]\n        \n        if len(self.requests[key]) >= self.max_requests:\n            return False, {\n                \"limit\": self.max_requests,\n                \"remaining\": 0,\n                \"reset\": int((now + timedelta(seconds=self.window_seconds)).timestamp())\n            }\n        \n        self.requests[key].append(now)\n        \n        return True, {\n            \"limit\": self.max_requests,\n            \"remaining\": self.max_requests - len(self.requests[key]),\n            \"reset\": int((now + timedelta(seconds=self.window_seconds)).timestamp())\n        }\n\n\n# Token Bucket\nclass TokenBucketRateLimiter:\n    \"\"\"\n    Token bucket rate limiting.\n    \n    Pros: Allows bursts, smooth rate limiting\n    Cons: More complex\n    \"\"\"\n    \n    def __init__(self, max_tokens: int, refill_rate: float):\n        self.max_tokens = max_tokens\n        self.refill_rate = refill_rate  # tokens per second\n        self.tokens: Dict[str, float] = {}\n        self.last_refill: Dict[str, datetime] = {}\n    \n    def _refill(self, key: str) -> float:\n        now = datetime.utcnow()\n        \n        if key not in self.tokens:\n            self.tokens[key] = self.max_tokens\n            self.last_refill[key] = now\n            return self.tokens[key]\n        \n        elapsed = (now - self.last_refill[key]).total_seconds()\n        tokens_to_add = elapsed * self.refill_rate\n        \n        self.tokens[key] = min(\n            self.max_tokens,\n            self.tokens[key] + tokens_to_add\n        )\n        self.last_refill[key] = now\n        \n        return self.tokens[key]\n    \n    def is_allowed(self, key: str, tokens: int = 1) -> tuple[bool, dict]:\n        self._refill(key)\n        \n        if self.tokens[key] >= tokens:\n            self.tokens[key] -= tokens\n            \n            return True, {\n                \"limit\": self.max_tokens,\n                \"remaining\": int(self.tokens[key]),\n            }\n        \n        return False, {\n            \"limit\": self.max_tokens\": 0,\n,\n            \"remaining        }\n```\n\n## API Rate Limiting Middleware\n```python\nfrom fastapi import Request, HTTPException\nfrom fastapi.responses import JSONResponse\nfrom starlette.middleware.base import BaseHTTPMiddleware\n\n\nclass RateLimitMiddleware(BaseHTTPMiddleware):\n    \"\"\"Rate limiting middleware for FastAPI.\"\"\"\n    \n    def __init__(\n        self,\n        app,\n        rate_limiter,\n        exempt_paths: list = None\n    ):\n        super().__init__(app)\n        self.rate_limiter = rate_limiter\n        self.exempt_paths = exempt_paths or []\n    \n    async def dispatch(self, request: Request, call_next):\n        # Skip rate limiting for exempt paths\n        if request.url.path in self.exempt_paths:\n            return await call_next(request)\n        \n        # Get client identifier\n        key = self._get_client_key(request)\n        \n        # Check rate limit\n        allowed, headers = self.rate_limiter.is_allowed(key)\n        \n        if not allowed:\n            return JSONResponse(\n                status_code=429,\n                headers={\n                    **headers,\n                    \"Retry-After\": str(headers.get(\"reset\", 60)),\n                },\n                content={\n                    \"error\": {\n                        \"code\": \"RATE_LIMIT_EXCEEDED\",\n                        \"message\": \"Too many requests. Please retry later.\"\n                    }\n                }\n            )\n        \n        response = await call_next(request)\n        \n        # Add rate limit headers\n        for key, value in headers.items():\n            response.headers[key] = str(value)\n        \n        return response\n    \n    def _get_client_key(self, request: Request) -> str:\n        \"\"\"Get unique key for client.\"\"\"\n        # Check for API key\n        api_key = request.headers.get(\"X-API-Key\")\n        if api_key:\n            return f\"apikey:{api_key}\"\n        \n        # Use user ID if authenticated\n        if hasattr(request.state, \"user_id\"):\n            return f\"user:{request.state.user_id}\"\n        \n        # Fall back to IP\n        client_ip = request.client.host\n        return f\"ip:{client_ip}\"\n```\n\n## Distributed Rate Limiting with Redis\n```python\nimport redis\nfrom typing import Dict, Any\n\n\nclass RedisRateLimiter:\n    \"\"\"Distributed rate limiter using Redis.\"\"\"\n    \n    def __init__(\n        self,\n        redis_url: str,\n        max_requests: int = 100,\n        window_seconds: int = 60\n    ):\n        self.redis = redis.from_url(redis_url)\n        self.max_requests = max_requests\n        self.window_seconds = window_seconds\n    \n    def is_allowed(self, key: str) -> tuple[bool, dict]:\n        now = datetime.utcnow()\n        window_key = f\"ratelimit:{key}:{int(now.timestamp() \u002F\u002F self.window_seconds)}\"\n        \n        pipe = self.redis.pipeline()\n        \n        # Increment counter\n        pipe.incr(window_key)\n        # Set expiry\n        pipe.expire(window_key, self.window_seconds * 2)\n        # Get current count\n        results = pipe.execute()\n        \n        current_count = results[0]\n        \n        headers = {\n            \"X-RateLimit-Limit\": str(self.max_requests),\n            \"X-RateLimit-Remaining\": str(max(0, self.max_requests - current_count)),\n            \"X-RateLimit-Reset\": str(\n                int(now.timestamp()) + self.window_seconds\n            ),\n        }\n        \n        if current_count > self.max_requests:\n            return False, headers\n        \n        return True, headers\n    \n    def sliding_window(self, key: str) -> tuple[bool, dict]:\n        \"\"\"More accurate sliding window using sorted sets.\"\"\"\n        now = datetime.utcnow()\n        window_start = now - timedelta(seconds=self.window_seconds)\n        \n        pipe = self.redis.pipeline()\n        \n        # Remove old entries\n        pipe.zremrangebyscore(\n            f\"ratelimit:sliding:{key}\",\n            0,\n            window_start.timestamp() - 1\n        )\n        \n        # Add current request\n        pipe.zadd(\n            f\"ratelimit:sliding:{key}\",\n            {f\"{now.timestamp()}:{uuid.uuid4()}\": now.timestamp()}\n        )\n        \n        # Count requests in window\n        pipe.zcard(f\"ratelimit:sliding:{key}\")\n        \n        # Set expiry\n        pipe.expire(\n            f\"ratelimit:sliding:{key}\",\n            self.window_seconds * 2\n        )\n        \n        results = pipe.execute()\n        current_count = results[2]\n        \n        allowed = current_count \u003C= self.max_requests\n        \n        return allowed, {\n            \"X-RateLimit-Limit\": str(self.max_requests),\n            \"X-RateLimit-Remaining\": str(\n                max(0, self.max_requests - current_count)\n            ),\n            \"X-RateLimit-Reset\": str(\n                int(now.timestamp()) + self.window_seconds\n            ),\n        }\n```\n\n## Best Practices\n```\nRate Limiting Best Practices:\n\n1. Choose appropriate algorithm\n   - Fixed window: simple, forgiving\n   - Sliding window: more accurate\n   - Token bucket: burst handling\n\n2. Use tiered limits\n   - Different limits for different users\n   - Public vs authenticated\n\n3. Return proper headers\n   - X-RateLimit-Limit\n   - X-RateLimit-Remaining\n   - X-RateLimit-Reset\n   - Retry-After\n\n4. Handle exceeded gracefully\n   - Clear error messages\n   - Appropriate retry headers\n\n5. Monitor and alert\n   - Track rate limit hits\n   - Alert on unusual patterns\n\n6. Distribute across instances\n   - Use shared storage (Redis)\n   - Consistent hashing\n\n7. Consider endpoint-specific\n   - Different limits per endpoint\n   - Expensive operations get lower limits\n\n8. Allow some burst\n   - Users expect occasional bursts\n   - Token bucket handles this well\n\n9. Test rate limiting\n   - Verify limits are enforced\n   - Test header values\n\n10. Document limits\n    - API documentation\n    - Developer portal\n```\n",{"name":5,"license":14,"metadata":28,"description":7,"compatibility":20},{"audience":29,"category":19},"developers","main","5f7a3e453c98261f93d19a6a7de44ad8f7b72d41",2,"https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills","https:\u002F\u002Fgithub.com\u002Fffsshhttiikk","2026-03-01 06:55:40",{"source":8,"skillName":5,"commands":37,"prompt":47,"zipAvailable":48},[38,41,44],{"tool":39,"command":40},"npx","npx skills add ffsshhttiikk\u002Fopencode-agents-skills --skill rate-limiting",{"tool":42,"command":43},"bunx","bunx skills add ffsshhttiikk\u002Fopencode-agents-skills --skill rate-limiting",{"tool":45,"command":46},"pnpm","pnpm dlx skills add ffsshhttiikk\u002Fopencode-agents-skills --skill rate-limiting","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills\u002Fblob\u002Fmain\u002Frate-limiting\u002FSKILL.md",true,[],[51,62,72,81,91,100],{"skillNo":52,"name":53,"nameZh":6,"description":54,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":55,"categories":56,"keywords":57,"publishedAt":23},"01M6CXT9TXDF79BWJTMQAPB49G","xamarin","Xamarin cross-platform development","https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills\u002Fblob\u002Fmain\u002Fxamarin\u002FSKILL.md",[],[53,58,59,60,20,61],"platform","cross-platform","mobile","development",{"skillNo":63,"name":64,"nameZh":6,"description":65,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":66,"categories":67,"keywords":68,"publishedAt":23},"01M6CXT8AD04MFYDA32VW3FKAG","wrangling","Data wrangling fundamentals","https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills\u002Fblob\u002Fmain\u002Fwrangling\u002FSKILL.md",[],[64,69,20,70,71],"data wrangling","science","data",{"skillNo":73,"name":74,"nameZh":6,"description":75,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":78,"publishedAt":23},"01M6CXT717GCN7SRRNPBDP4508","windows","Windows operating system administration and scripting","https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills\u002Fblob\u002Fmain\u002Fwindows\u002FSKILL.md",[],[74,79,20,80],"system","scripting",{"skillNo":82,"name":83,"nameZh":6,"description":84,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":85,"categories":86,"keywords":87,"publishedAt":23},"01M6CXT54K794NMEM3XAPZZDKT","wide-column","Wide-column data model","https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills\u002Fblob\u002Fmain\u002Fwide-column\u002FSKILL.md",[],[88,89,20,90,71],"wide column","databases","model",{"skillNo":92,"name":93,"nameZh":6,"description":94,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":95,"categories":96,"keywords":97,"publishedAt":23},"01M6CXT28FMT2P4V9GZE67WA8E","wide-column-stores","Wide-column database stores","https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills\u002Fblob\u002Fmain\u002Fwide-column-stores\u002FSKILL.md",[],[98,89,20,99],"wide column stores","database",{"skillNo":101,"name":102,"nameZh":6,"description":103,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":104,"categories":105,"keywords":106,"publishedAt":23},"01M6CXT0D0M0Q4T2N7C2RX7DSN","websockets","WebSocket implementation and best practices","https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills\u002Fblob\u002Fmain\u002Fwebsockets\u002FSKILL.md",[],[102,107,108,109,20,110,21],"websocket","real-time","time","best practices"]