snippet-manager
About
This skill enables developers to save, organize, and retrieve code snippets with metadata like language and tags. It provides smart search capabilities to find relevant code patterns based on context, keywords, or frameworks. Use it to build a personal library of reusable code and enhance snippets with documentation and examples.
Documentation
Snippet Manager Skill
Save, organize, search, and retrieve code snippets with tags, categories, and smart search capabilities.
Instructions
You are a code snippet management expert. When invoked:
-
Save Code Snippets:
- Extract reusable code patterns
- Add metadata (language, tags, description)
- Organize by category and use case
- Version snippet variations
-
Search and Retrieve:
- Search by language, tags, or keywords
- Find similar patterns
- Suggest relevant snippets based on context
- Filter by framework or library
-
Snippet Organization:
- Categorize snippets logically
- Tag with relevant keywords
- Group related snippets
- Create snippet collections
-
Snippet Enhancement:
- Add usage examples
- Document parameters and options
- Include edge cases
- Provide alternative implementations
Snippet Categories
- Language Basics: Common patterns, idioms, syntax helpers
- Data Structures: Arrays, objects, maps, sets manipulation
- Algorithms: Sorting, searching, recursion, dynamic programming
- API Patterns: REST clients, error handling, authentication
- Database: Queries, migrations, ORM patterns
- Testing: Test setups, mocks, assertions
- React/Vue/Angular: Component patterns, hooks, directives
- Node.js: Express middleware, streams, file operations
- Python: Decorators, context managers, generators
- DevOps: Docker, CI/CD, deployment scripts
- Utilities: Date/time, string manipulation, validation
Usage Examples
@snippet-manager Save API error handler
@snippet-manager --search "react hooks"
@snippet-manager --category testing
@snippet-manager --language python
@snippet-manager --tag async
@snippet-manager --collection "authentication patterns"
Snippet Format
Basic Snippet Structure
# Snippet: Async Error Handler Wrapper
**Language**: JavaScript/TypeScript
**Category**: Error Handling
**Tags**: async, error-handling, middleware, express
**Framework**: Express.js
**Use Case**: Wrap async route handlers to catch errors
## Code
```javascript
const asyncHandler = (fn) => (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
// Usage
app.get('/users/:id', asyncHandler(async (req, res) => {
const user = await User.findById(req.params.id);
res.json(user);
}));
Parameters
fn: Async function to wrap (Request, Response, NextFunction) => Promise<void>
Returns
Express middleware function that handles promise rejections
Notes
- Eliminates try-catch blocks in route handlers
- Passes errors to Express error handler middleware
- Works with any async function
Related Snippets
## JavaScript/TypeScript Snippets
### Debounce Function
```javascript
// Snippet: Debounce
// Category: Performance
// Tags: debounce, performance, optimization
function debounce(func, wait, immediate = false) {
let timeout;
return function executedFunction(...args) {
const later = () => {
timeout = null;
if (!immediate) func.apply(this, args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(this, args);
};
}
// Usage
const handleSearch = debounce((query) => {
fetchResults(query);
}, 300);
// In React
const [searchTerm, setSearchTerm] = useState('');
const debouncedSearch = useMemo(
() => debounce((term) => {
// Perform search
console.log('Searching for:', term);
}, 500),
[]
);
useEffect(() => {
debouncedSearch(searchTerm);
}, [searchTerm, debouncedSearch]);
Deep Clone Object
// Snippet: Deep Clone
// Category: Data Structures
// Tags: clone, deep-copy, objects
// Method 1: JSON (simple objects only)
const deepClone = (obj) => JSON.parse(JSON.stringify(obj));
// Method 2: Structured Clone (modern browsers/Node.js)
const deepClone2 = (obj) => structuredClone(obj);
// Method 3: Custom recursive (handles complex types)
function deepClone3(obj, hash = new WeakMap()) {
if (Object(obj) !== obj) return obj; // primitives
if (hash.has(obj)) return hash.get(obj); // cyclic reference
const result = Array.isArray(obj)
? []
: obj.constructor
? new obj.constructor()
: Object.create(null);
hash.set(obj, result);
return Object.assign(
result,
...Object.keys(obj).map(key => ({
[key]: deepClone3(obj[key], hash)
}))
);
}
// Usage
const original = { a: 1, b: { c: 2 }, d: [3, 4] };
const cloned = deepClone(original);
cloned.b.c = 999; // original.b.c remains 2
Retry with Exponential Backoff
// Snippet: Retry with Exponential Backoff
// Category: Error Handling
// Tags: retry, async, error-handling, resilience
async function retryWithBackoff<T>(
fn: () => Promise<T>,
options: {
maxRetries?: number;
initialDelay?: number;
maxDelay?: number;
factor?: number;
} = {}
): Promise<T> {
const {
maxRetries = 3,
initialDelay = 1000,
maxDelay = 30000,
factor = 2,
} = options;
let lastError: Error;
let delay = initialDelay;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error as Error;
if (attempt === maxRetries) {
throw new Error(
`Failed after ${maxRetries} retries: ${lastError.message}`
);
}
console.log(`Attempt ${attempt + 1} failed, retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
delay = Math.min(delay * factor, maxDelay);
}
}
throw lastError!;
}
// Usage
const data = await retryWithBackoff(
() => fetch('https://api.example.com/data').then(r => r.json()),
{ maxRetries: 5, initialDelay: 500 }
);
Local Storage with Expiry
// Snippet: Local Storage with Expiry
// Category: Browser APIs
// Tags: localstorage, cache, expiry
const storage = {
set(key, value, expiryMs = null) {
const item = {
value,
expiry: expiryMs ? Date.now() + expiryMs : null,
};
localStorage.setItem(key, JSON.stringify(item));
},
get(key) {
const itemStr = localStorage.getItem(key);
if (!itemStr) return null;
const item = JSON.parse(itemStr);
if (item.expiry && Date.now() > item.expiry) {
localStorage.removeItem(key);
return null;
}
return item.value;
},
remove(key) {
localStorage.removeItem(key);
},
clear() {
localStorage.clear();
},
};
// Usage
storage.set('user', { id: 1, name: 'John' }, 3600000); // 1 hour
const user = storage.get('user');
React Snippets
Custom useDebounce Hook
// Snippet: useDebounce Hook
// Category: React Hooks
// Tags: react, hooks, debounce, performance
import { useEffect, useState } from 'react';
function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
}
// Usage
function SearchComponent() {
const [searchTerm, setSearchTerm] = useState('');
const debouncedSearchTerm = useDebounce(searchTerm, 500);
useEffect(() => {
if (debouncedSearchTerm) {
// Perform search
fetchResults(debouncedSearchTerm);
}
}, [debouncedSearchTerm]);
return (
<input
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
);
}
Custom useAsync Hook
// Snippet: useAsync Hook
// Category: React Hooks
// Tags: react, hooks, async, data-fetching
import { useEffect, useState, useCallback } from 'react';
type Status = 'idle' | 'loading' | 'success' | 'error';
interface AsyncState<T> {
status: Status;
data: T | null;
error: Error | null;
}
function useAsync<T>(
asyncFunction: () => Promise<T>,
immediate = true
) {
const [state, setState] = useState<AsyncState<T>>({
status: 'idle',
data: null,
error: null,
});
const execute = useCallback(async () => {
setState({ status: 'loading', data: null, error: null });
try {
const data = await asyncFunction();
setState({ status: 'success', data, error: null });
return data;
} catch (error) {
setState({ status: 'error', data: null, error: error as Error });
throw error;
}
}, [asyncFunction]);
useEffect(() => {
if (immediate) {
execute();
}
}, [execute, immediate]);
return { ...state, execute };
}
// Usage
function UserProfile({ userId }) {
const { status, data, error } = useAsync(
() => fetch(`/api/users/${userId}`).then(r => r.json()),
true
);
if (status === 'loading') return <div>Loading...</div>;
if (status === 'error') return <div>Error: {error.message}</div>;
if (status === 'success') return <div>User: {data.name}</div>;
return null;
}
Custom useLocalStorage Hook
// Snippet: useLocalStorage Hook
// Category: React Hooks
// Tags: react, hooks, localstorage, persistence
import { useState, useEffect } from 'react';
function useLocalStorage<T>(
key: string,
initialValue: T
): [T, (value: T | ((val: T) => T)) => void] {
// Get from local storage then parse stored json or return initialValue
const readValue = (): T => {
if (typeof window === 'undefined') {
return initialValue;
}
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.warn(`Error reading localStorage key "${key}":`, error);
return initialValue;
}
};
const [storedValue, setStoredValue] = useState<T>(readValue);
const setValue = (value: T | ((val: T) => T)) => {
try {
const valueToStore =
value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
if (typeof window !== 'undefined') {
window.localStorage.setItem(key, JSON.stringify(valueToStore));
}
} catch (error) {
console.warn(`Error setting localStorage key "${key}":`, error);
}
};
useEffect(() => {
setStoredValue(readValue());
}, []);
return [storedValue, setValue];
}
// Usage
function App() {
const [theme, setTheme] = useLocalStorage('theme', 'light');
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Current theme: {theme}
</button>
);
}
Python Snippets
Retry Decorator
# Snippet: Retry Decorator
# Category: Error Handling
# Tags: python, decorator, retry, error-handling
import time
import functools
from typing import Callable, Type
def retry(
max_attempts: int = 3,
delay: float = 1.0,
backoff: float = 2.0,
exceptions: tuple[Type[Exception], ...] = (Exception,)
):
"""
Retry decorator with exponential backoff
Args:
max_attempts: Maximum number of retry attempts
delay: Initial delay between retries in seconds
backoff: Multiplier for delay after each retry
exceptions: Tuple of exceptions to catch
"""
def decorator(func: Callable):
@functools.wraps(func)
def wrapper(*args, **kwargs):
current_delay = delay
last_exception = None
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except exceptions as e:
last_exception = e
if attempt == max_attempts - 1:
raise
print(f"Attempt {attempt + 1} failed: {e}")
print(f"Retrying in {current_delay}s...")
time.sleep(current_delay)
current_delay *= backoff
raise last_exception
return wrapper
return decorator
# Usage
@retry(max_attempts=5, delay=0.5, exceptions=(ConnectionError, TimeoutError))
def fetch_data(url: str):
response = requests.get(url, timeout=10)
response.raise_for_status()
return response.json()
Context Manager for Timing
# Snippet: Timing Context Manager
# Category: Performance
# Tags: python, context-manager, timing, profiling
import time
from contextlib import contextmanager
from typing import Optional
@contextmanager
def timer(name: Optional[str] = None):
"""
Context manager to time code execution
Usage:
with timer("Database query"):
result = db.query(...)
"""
start = time.perf_counter()
try:
yield
finally:
elapsed = time.perf_counter() - start
label = f"{name}: " if name else ""
print(f"{label}Elapsed time: {elapsed:.4f}s")
# Usage
with timer("API call"):
response = requests.get("https://api.example.com/data")
data = response.json()
# Alternative: As a decorator
def timed(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
elapsed = time.perf_counter() - start
print(f"{func.__name__} took {elapsed:.4f}s")
return result
return wrapper
@timed
def process_data(data):
# Process data
pass
Memoization with LRU Cache
# Snippet: Memoization
# Category: Performance
# Tags: python, cache, memoization, optimization
from functools import lru_cache, wraps
import pickle
import hashlib
# Simple memoization with lru_cache
@lru_cache(maxsize=128)
def fibonacci(n: int) -> int:
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
# Custom memoization for unhashable arguments
def memoize(func):
cache = {}
@wraps(func)
def wrapper(*args, **kwargs):
# Create hashable key from arguments
key = hashlib.md5(
pickle.dumps((args, tuple(sorted(kwargs.items()))))
).hexdigest()
if key not in cache:
cache[key] = func(*args, **kwargs)
return cache[key]
wrapper.cache_clear = lambda: cache.clear()
wrapper.cache_info = lambda: f"Cache size: {len(cache)}"
return wrapper
# Usage with unhashable types (lists, dicts)
@memoize
def expensive_computation(data: list[int]) -> int:
return sum(x ** 2 for x in data)
result = expensive_computation([1, 2, 3, 4, 5])
Node.js Snippets
Rate Limiter Middleware
// Snippet: Rate Limiter
// Category: Middleware
// Tags: nodejs, express, rate-limiting, security
class RateLimiter {
constructor(options = {}) {
this.windowMs = options.windowMs || 60000; // 1 minute
this.maxRequests = options.maxRequests || 100;
this.requests = new Map();
}
middleware() {
return (req, res, next) => {
const key = req.ip || req.connection.remoteAddress;
const now = Date.now();
if (!this.requests.has(key)) {
this.requests.set(key, []);
}
const userRequests = this.requests.get(key);
// Remove old requests outside the window
const validRequests = userRequests.filter(
timestamp => now - timestamp < this.windowMs
);
if (validRequests.length >= this.maxRequests) {
const oldestRequest = validRequests[0];
const resetTime = oldestRequest + this.windowMs;
const retryAfter = Math.ceil((resetTime - now) / 1000);
res.set('Retry-After', retryAfter.toString());
return res.status(429).json({
error: 'Too many requests',
retryAfter: retryAfter,
});
}
validRequests.push(now);
this.requests.set(key, validRequests);
res.set('X-RateLimit-Limit', this.maxRequests.toString());
res.set('X-RateLimit-Remaining',
(this.maxRequests - validRequests.length).toString()
);
next();
};
}
// Cleanup old entries periodically
cleanup() {
const now = Date.now();
for (const [key, timestamps] of this.requests.entries()) {
const valid = timestamps.filter(t => now - t < this.windowMs);
if (valid.length === 0) {
this.requests.delete(key);
} else {
this.requests.set(key, valid);
}
}
}
}
// Usage
const limiter = new RateLimiter({
windowMs: 15 * 60 * 1000, // 15 minutes
maxRequests: 100,
});
app.use('/api', limiter.middleware());
// Cleanup every 5 minutes
setInterval(() => limiter.cleanup(), 5 * 60 * 1000);
Stream Pipeline Helper
// Snippet: Stream Pipeline
// Category: Streams
// Tags: nodejs, streams, pipeline, files
const { pipeline } = require('stream');
const { promisify } = require('util');
const fs = require('fs');
const zlib = require('zlib');
const { Transform } = require('stream');
const pipelineAsync = promisify(pipeline);
// Custom transform stream
class LineCounter extends Transform {
constructor(options) {
super(options);
this.lineCount = 0;
}
_transform(chunk, encoding, callback) {
const lines = chunk.toString().split('\n').length - 1;
this.lineCount += lines;
this.push(chunk);
callback();
}
}
// Usage: Compress file and count lines
async function compressAndCount(inputFile, outputFile) {
const counter = new LineCounter();
await pipelineAsync(
fs.createReadStream(inputFile),
counter,
zlib.createGzip(),
fs.createWriteStream(outputFile)
);
console.log(`Processed ${counter.lineCount} lines`);
return counter.lineCount;
}
// Usage: Process large CSV
async function processCsv(inputFile) {
const processLine = new Transform({
transform(chunk, encoding, callback) {
const lines = chunk.toString().split('\n');
const processed = lines
.map(line => line.toUpperCase())
.join('\n');
callback(null, processed);
}
});
await pipelineAsync(
fs.createReadStream(inputFile),
processLine,
fs.createWriteStream('output.csv')
);
}
SQL Snippets
Safe Upsert Pattern
-- Snippet: Upsert (Insert or Update)
-- Category: Database
-- Tags: sql, upsert, postgresql
-- PostgreSQL
INSERT INTO users (id, email, name, updated_at)
VALUES (1, '[email protected]', 'John Doe', NOW())
ON CONFLICT (id)
DO UPDATE SET
email = EXCLUDED.email,
name = EXCLUDED.name,
updated_at = NOW()
RETURNING *;
-- Multiple rows upsert
INSERT INTO products (sku, name, price)
VALUES
('SKU001', 'Product 1', 29.99),
('SKU002', 'Product 2', 39.99)
ON CONFLICT (sku)
DO UPDATE SET
name = EXCLUDED.name,
price = EXCLUDED.price,
updated_at = NOW();
Pagination Query
-- Snippet: Efficient Pagination
-- Category: Database
-- Tags: sql, pagination, performance
-- Offset-based (simple but slower for large offsets)
SELECT *
FROM posts
ORDER BY created_at DESC
LIMIT 20 OFFSET 40; -- Page 3
-- Cursor-based (more efficient)
SELECT *
FROM posts
WHERE created_at < '2024-01-01 12:00:00'
ORDER BY created_at DESC
LIMIT 20;
-- Keyset pagination (best performance)
SELECT *
FROM posts
WHERE (created_at, id) < ('2024-01-01 12:00:00', 12345)
ORDER BY created_at DESC, id DESC
LIMIT 20;
Best Practices
Snippet Organization
- Consistent naming: Use clear, descriptive names
- Comprehensive tags: Add multiple relevant tags
- Version tracking: Keep track of snippet versions
- Dependencies: Document required libraries
Documentation
- Usage examples: Show real-world usage
- Parameter docs: Document all parameters
- Edge cases: Mention limitations and edge cases
- Alternatives: Suggest related patterns
Maintenance
- Regular review: Update snippets periodically
- Test snippets: Ensure snippets still work
- Deprecation: Mark outdated snippets
- Contribution: Share useful snippets with team
Snippet Management Tools
File-based Storage
snippets/
├── javascript/
│ ├── async/
│ │ ├── retry.js
│ │ └── debounce.js
│ └── react/
│ ├── hooks/
│ └── components/
├── python/
│ ├── decorators/
│ └── context-managers/
└── sql/
├── queries/
└── migrations/
Metadata Format (frontmatter)
---
title: "Async Retry with Backoff"
language: javascript
category: error-handling
tags: [async, retry, error-handling, resilience]
framework: nodejs
version: 1.2.0
author: team
created: 2024-01-15
updated: 2024-01-20
---
Notes
- Keep snippets focused and single-purpose
- Include error handling in examples
- Document performance characteristics
- Test snippets before saving
- Use consistent coding style
- Add comments for complex logic
- Version snippets when making changes
- Share snippets within team
- Regular cleanup of outdated snippets
Quick Install
/plugin add https://github.com/CuriousLearner/devkit/tree/main/snippet-managerCopy and paste this command in Claude Code to install this skill
GitHub 仓库
Related Skills
subagent-driven-development
DevelopmentThis skill executes implementation plans by dispatching a fresh subagent for each independent task, with code review between tasks. It enables fast iteration while maintaining quality gates through this review process. Use it when working on mostly independent tasks within the same session to ensure continuous progress with built-in quality checks.
algorithmic-art
MetaThis Claude Skill creates original algorithmic art using p5.js with seeded randomness and interactive parameters. It generates .md files for algorithmic philosophies, plus .html and .js files for interactive generative art implementations. Use it when developers need to create flow fields, particle systems, or other computational art while avoiding copyright issues.
executing-plans
DesignUse the executing-plans skill when you have a complete implementation plan to execute in controlled batches with review checkpoints. It loads and critically reviews the plan, then executes tasks in small batches (default 3 tasks) while reporting progress between each batch for architect review. This ensures systematic implementation with built-in quality control checkpoints.
cost-optimization
OtherThis Claude Skill helps developers optimize cloud costs through resource rightsizing, tagging strategies, and spending analysis. It provides a framework for reducing cloud expenses and implementing cost governance across AWS, Azure, and GCP. Use it when you need to analyze infrastructure costs, right-size resources, or meet budget constraints.
