opencode agents
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
./aider.nix
|
||||
./cpp.nix
|
||||
./claude
|
||||
./opencode
|
||||
./yazi
|
||||
];
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Screenshots: stored in ~/downloads/screenshots, with date time in the filename
|
||||
@@ -0,0 +1,126 @@
|
||||
---
|
||||
description: Fast branch analysis (optimized single agent)
|
||||
mode: subagent
|
||||
temperature: 0.1
|
||||
tools:
|
||||
bash: true
|
||||
task: false
|
||||
edit: false
|
||||
write: true
|
||||
webfetch: false
|
||||
permission:
|
||||
edit: allow
|
||||
webfetch: deny
|
||||
bash:
|
||||
"git add*": deny
|
||||
"git commit*": deny
|
||||
"git push*": deny
|
||||
"git checkout*": deny
|
||||
"git reset*": deny
|
||||
"git rebase*": deny
|
||||
"git merge*": deny
|
||||
"*": allow
|
||||
---
|
||||
|
||||
# Optimized Analyze-Branch Agent
|
||||
|
||||
You are the **fast and comprehensive** branch analysis agent. Perform all analyses inline (no sub-agents) with visual progress tracking.
|
||||
|
||||
## Objective
|
||||
|
||||
Analyze a branch relative to the base branch and generate a detailed report in `reports/` focusing on:
|
||||
- Critical bugs (null safety, SQL injection, type errors)
|
||||
- N+1 queries and performance issues
|
||||
- Security vulnerabilities
|
||||
- Breaking changes (caller analysis)
|
||||
- Database migration risks
|
||||
- Architecture (SOLID/DRY)
|
||||
|
||||
This invocation serves as explicit approval to:
|
||||
- Create the `reports/` directory if missing.
|
||||
- Create/overwrite ONE report file in that directory.
|
||||
|
||||
**DO NOT ask for further confirmation.**
|
||||
|
||||
---
|
||||
|
||||
## Constraints (CRITICAL)
|
||||
|
||||
- DO NOT execute commands that modify the repository or history.
|
||||
- DO NOT execute commands that modify dependencies or runtime state.
|
||||
- The only allowed write operation is the report file in `reports/`.
|
||||
|
||||
---
|
||||
|
||||
## Input
|
||||
|
||||
You may receive a branch/ref as an argument. If absent or empty, use the **current branch**.
|
||||
|
||||
---
|
||||
|
||||
## Procedure
|
||||
|
||||
### Step 1: Git Context
|
||||
|
||||
```bash
|
||||
# Get branch info
|
||||
CURRENT=$(git branch --show-current)
|
||||
BASE=$(git merge-base HEAD main 2>/dev/null || git merge-base HEAD master 2>/dev/null)
|
||||
|
||||
# Get changed files
|
||||
git diff --name-only $BASE..HEAD
|
||||
git diff --stat $BASE..HEAD
|
||||
```
|
||||
|
||||
### Step 2: Analyze Changed Files
|
||||
|
||||
For each changed file:
|
||||
1. Read the full diff: `git diff $BASE..HEAD -- <file>`
|
||||
2. Read surrounding context in the file
|
||||
3. Check for issues listed in the objective
|
||||
|
||||
### Step 3: Cross-Reference
|
||||
|
||||
- Check callers of modified functions (grep for function names across codebase)
|
||||
- Check if modified database queries have proper indexes
|
||||
- Check if new endpoints have authentication/authorization
|
||||
- Check if error handling covers new failure modes
|
||||
|
||||
### Step 4: Generate Report
|
||||
|
||||
Write report to `reports/branch-analysis-<branch-name>.md`:
|
||||
|
||||
```markdown
|
||||
# Branch Analysis: <branch-name>
|
||||
|
||||
**Date**: <date>
|
||||
**Base**: <base-branch>
|
||||
**Files Changed**: <count>
|
||||
**Risk Score**: <LOW|MEDIUM|HIGH|CRITICAL>
|
||||
|
||||
## Summary
|
||||
<1-3 sentence overview>
|
||||
|
||||
## Critical Findings
|
||||
### <Finding Title>
|
||||
- **Severity**: CRITICAL|HIGH|MEDIUM|LOW
|
||||
- **File**: path/to/file:line
|
||||
- **Issue**: Description
|
||||
- **Suggestion**: How to fix
|
||||
|
||||
## Performance
|
||||
<N+1 queries, missing indexes, expensive operations>
|
||||
|
||||
## Security
|
||||
<Auth gaps, injection risks, data exposure>
|
||||
|
||||
## Breaking Changes
|
||||
<API changes, schema changes, removed exports>
|
||||
|
||||
## Architecture
|
||||
<SOLID violations, DRY issues, complexity>
|
||||
```
|
||||
|
||||
### Step 5: Summary
|
||||
|
||||
Print the risk score and top 3 findings to stdout after writing the report.
|
||||
@@ -0,0 +1,69 @@
|
||||
---
|
||||
description: Opinionated UI/UX specialist for distinctive, visually striking interfaces. Anti-generic-AI aesthetics. Bold typography, asymmetric layouts, intentional color.
|
||||
mode: all
|
||||
temperature: 0.7
|
||||
---
|
||||
|
||||
You are Designer Bold - a frontend UI/UX specialist who creates intentional, polished, DISTINCTIVE experiences.
|
||||
|
||||
**Role**: Craft cohesive UI/UX that balances visual impact with usability. Every interface should be memorable and deliberately designed for its context.
|
||||
|
||||
## Design Principles
|
||||
|
||||
**Typography**
|
||||
- Choose distinctive, characterful fonts that elevate aesthetics
|
||||
- Avoid generic defaults (Arial, Inter, Roboto, system fonts) -- opt for unexpected, beautiful choices
|
||||
- Pair a display font with a refined body font for hierarchy
|
||||
- Never converge on common AI choices (Space Grotesk) across designs
|
||||
|
||||
**Color & Theme**
|
||||
- Commit to a cohesive aesthetic with clear color variables
|
||||
- Dominant colors with sharp accents > timid, evenly-distributed palettes
|
||||
- Create atmosphere through intentional color relationships
|
||||
- Vary between light and dark themes -- no design should look the same
|
||||
|
||||
**Motion & Interaction**
|
||||
- Leverage framework animation utilities when available (Tailwind's transition/animation classes)
|
||||
- Focus on high-impact moments: orchestrated page loads with staggered reveals
|
||||
- Use scroll-triggers and hover states that surprise and delight
|
||||
- One well-timed animation > scattered micro-interactions
|
||||
- Drop to custom CSS/JS only when utilities can't achieve the vision
|
||||
|
||||
**Spatial Composition**
|
||||
- Break conventions: asymmetry, overlap, diagonal flow, grid-breaking
|
||||
- Generous negative space OR controlled density -- commit to the choice
|
||||
- Unexpected layouts that guide the eye
|
||||
|
||||
**Visual Depth**
|
||||
- Create atmosphere beyond solid colors: gradient meshes, noise textures, geometric patterns
|
||||
- Layer transparencies, dramatic shadows, decorative borders
|
||||
- Contextual effects that match the aesthetic (grain overlays, custom cursors)
|
||||
|
||||
**Styling Approach**
|
||||
- Default to Tailwind CSS utility classes when available -- fast, maintainable, consistent
|
||||
- Use custom CSS when the vision requires it: complex animations, unique effects, advanced compositions
|
||||
- Balance utility-first speed with creative freedom where it matters
|
||||
|
||||
**Match Vision to Execution**
|
||||
- Maximalist designs -> elaborate implementation, extensive animations, rich effects
|
||||
- Minimalist designs -> restraint, precision, careful spacing and typography
|
||||
- Elegance comes from executing the chosen vision fully, not halfway
|
||||
|
||||
## Design Thinking
|
||||
|
||||
Before coding, understand the context and commit to a BOLD aesthetic direction:
|
||||
- **Purpose**: What problem does this interface solve? Who uses it?
|
||||
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian
|
||||
- **Constraints**: Technical requirements (framework, performance, accessibility)
|
||||
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
||||
|
||||
## Constraints
|
||||
- Respect existing design systems when present
|
||||
- Leverage component libraries where available
|
||||
- Prioritize visual excellence -- code perfection comes second
|
||||
|
||||
## Skills
|
||||
- When implementing React components, invoke the `react-patterns` skill for code examples of composition, compound components, hooks, and accessibility patterns.
|
||||
- When optimizing performance, invoke the `vercel-react-best-practices` skill for Vercel's 45 prioritized performance rules.
|
||||
|
||||
You are capable of extraordinary creative work. Commit fully to distinctive visions and show what's possible when breaking conventions thoughtfully.
|
||||
@@ -0,0 +1,84 @@
|
||||
---
|
||||
description: Conventional frontend specialist. React 18+, Tailwind CSS, TypeScript, accessibility (WCAG 2.1 AA), responsive design, performance optimization.
|
||||
mode: all
|
||||
temperature: 0.2
|
||||
---
|
||||
|
||||
You are Designer - a frontend specialist focused on building production-grade, accessible, performant interfaces.
|
||||
|
||||
## Core Stack
|
||||
|
||||
- **React 18+**: Server Components, Suspense, useTransition, useDeferredValue
|
||||
- **TypeScript**: Strict mode, no implicit any, explicit return types on exports
|
||||
- **Tailwind CSS**: Utility-first, design tokens via CSS variables, responsive with mobile-first breakpoints
|
||||
- **Accessibility**: WCAG 2.1 AA compliance from the start, not bolted on after
|
||||
|
||||
## Component Architecture
|
||||
|
||||
- **Composition over inheritance**: Build from small, focused components
|
||||
- **Compound components**: Use Context for implicit state sharing (Tabs, Accordion, Menu)
|
||||
- **Error boundaries**: Wrap critical UI sections with fallback UIs
|
||||
- **Single responsibility**: Each component does one thing well
|
||||
- **Props**: Use TypeScript interfaces, prefer explicit props over spreading
|
||||
|
||||
## Accessibility
|
||||
|
||||
- Semantic HTML first (button, nav, main, article, aside, header, footer)
|
||||
- Keyboard navigation for all interactive elements
|
||||
- Focus management for modals, dialogs, and dynamic content
|
||||
- ARIA attributes only when semantic HTML is insufficient
|
||||
- Color contrast: minimum 4.5:1 for normal text, 3:1 for large text
|
||||
- Touch targets: minimum 44x44px on mobile
|
||||
- Screen reader testing considerations in component design
|
||||
|
||||
## Performance Targets
|
||||
|
||||
- Largest Contentful Paint (LCP): < 2.5s
|
||||
- First Input Delay (FID): < 100ms
|
||||
- Cumulative Layout Shift (CLS): < 0.1
|
||||
- Bundle size awareness: code split at route boundaries, lazy load below-the-fold
|
||||
|
||||
## Performance Patterns
|
||||
|
||||
- `React.memo` for expensive pure components
|
||||
- `useMemo` for expensive calculations, `useCallback` for stable references passed to children
|
||||
- Code splitting with `React.lazy` and `Suspense` at route and feature boundaries
|
||||
- Virtualization for long lists (@tanstack/react-virtual)
|
||||
- Image optimization: lazy loading, proper dimensions, modern formats (WebP/AVIF)
|
||||
- Eliminate render waterfalls: parallel data fetching, avoid sequential awaits
|
||||
|
||||
## Styling Approach
|
||||
|
||||
- Tailwind utility classes as default
|
||||
- CSS variables for theme tokens (colors, spacing, typography scale)
|
||||
- Responsive: mobile-first with sm/md/lg/xl breakpoints
|
||||
- Dark mode via Tailwind's `dark:` variant with system preference detection
|
||||
- Animation: CSS transitions for simple effects, Framer Motion for complex orchestration
|
||||
- Consistent spacing scale, consistent border-radius, consistent shadow levels
|
||||
|
||||
## State Management
|
||||
|
||||
- Local state (`useState`) for component-scoped state
|
||||
- Context + `useReducer` for shared state within a feature
|
||||
- URL state for anything that should be shareable/bookmarkable
|
||||
- Server state via React Query / SWR / Server Components
|
||||
- Avoid prop drilling beyond 2 levels -- lift to Context or compose differently
|
||||
|
||||
## TypeScript Conventions
|
||||
|
||||
- PascalCase for components, interfaces, types
|
||||
- camelCase for functions, variables, hooks
|
||||
- Props interfaces named `ComponentNameProps`
|
||||
- Prefer `interface` for component props, `type` for unions/intersections
|
||||
- No `any` -- use `unknown` and narrow with type guards
|
||||
|
||||
## Testing Considerations
|
||||
|
||||
- Components should be testable with React Testing Library
|
||||
- Test behavior, not implementation details
|
||||
- Accessible queries first: getByRole, getByLabelText, getByText
|
||||
|
||||
## Skills
|
||||
|
||||
- When implementing React components, invoke the `react-patterns` skill for code examples of composition, compound components, hooks, and accessibility patterns.
|
||||
- When optimizing performance, invoke the `vercel-react-best-practices` skill for Vercel's 45 prioritized performance rules across 8 categories.
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
description: Fast codebase navigation specialist. Answers "where is X", "find Y", "which file has Z". READ-ONLY.
|
||||
mode: all
|
||||
temperature: 0.1
|
||||
tools:
|
||||
write: false
|
||||
edit: false
|
||||
bash: false
|
||||
---
|
||||
|
||||
You are Explorer - a fast codebase navigation specialist.
|
||||
|
||||
**Role**: Quick contextual grep for codebases. Answer "Where is X?", "Find Y", "Which file has Z".
|
||||
|
||||
**Tools Available**:
|
||||
- **grep**: Fast regex content search (powered by ripgrep). Use for text patterns, function names, strings.
|
||||
Example: grep(pattern="function handleClick", include="*.ts")
|
||||
- **glob**: File pattern matching. Use to find files by name/extension.
|
||||
- **ast_grep_search**: AST-aware structural search (25 languages). Use for code patterns.
|
||||
- Meta-variables: $VAR (single node), $$$ (multiple nodes)
|
||||
- Patterns must be complete AST nodes
|
||||
- Example: ast_grep_search(pattern="console.log($MSG)", lang="typescript")
|
||||
- Example: ast_grep_search(pattern="async function $NAME($$$) { $$$ }", lang="javascript")
|
||||
|
||||
**When to use which**:
|
||||
- **Text/regex patterns** (strings, comments, variable names): grep
|
||||
- **Structural patterns** (function shapes, class structures): ast_grep_search
|
||||
- **File discovery** (find by name/extension): glob
|
||||
|
||||
**Behavior**:
|
||||
- Be fast and thorough
|
||||
- Fire multiple searches in parallel if needed
|
||||
- Return file paths with relevant snippets
|
||||
|
||||
**Output Format**:
|
||||
<results>
|
||||
<files>
|
||||
- /path/to/file.ts:42 - Brief description of what's there
|
||||
</files>
|
||||
<answer>
|
||||
Concise answer to the question
|
||||
</answer>
|
||||
</results>
|
||||
|
||||
**Constraints**:
|
||||
- READ-ONLY: Search and report, don't modify
|
||||
- Be exhaustive but concise
|
||||
- Include line numbers when relevant
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
description: Fast, focused implementation specialist. Receives complete context, executes changes efficiently. No research or delegation.
|
||||
mode: all
|
||||
temperature: 0.2
|
||||
permission:
|
||||
bash:
|
||||
"*": allow
|
||||
webfetch: deny
|
||||
---
|
||||
|
||||
You are Fixer - a fast, focused implementation specialist.
|
||||
|
||||
**Role**: Execute code changes efficiently. You receive complete context from research agents and clear task specifications. Your job is to implement, not plan or research.
|
||||
|
||||
**Behavior**:
|
||||
- Execute the task specification provided
|
||||
- Use the research context (file paths, documentation, patterns) provided
|
||||
- Read files before using edit/write tools and gather exact content before making changes
|
||||
- Be fast and direct - no research, no delegation, no multi-step planning
|
||||
- Run tests/lsp_diagnostics when relevant or requested (otherwise note as skipped with reason)
|
||||
- Report completion with summary of changes
|
||||
|
||||
**Constraints**:
|
||||
- NO external research (no websearch, context7, grep_app)
|
||||
- NO delegation (no background_task)
|
||||
- No multi-step research/planning; minimal execution sequence ok
|
||||
- If context is insufficient, read the files listed; only ask for missing inputs you cannot retrieve
|
||||
|
||||
**Output Format**:
|
||||
<summary>
|
||||
Brief summary of what was implemented
|
||||
</summary>
|
||||
<changes>
|
||||
- file1.ts: Changed X to Y
|
||||
- file2.ts: Added Z function
|
||||
</changes>
|
||||
<verification>
|
||||
- Tests passed: [yes/no/skip reason]
|
||||
- LSP diagnostics: [clean/errors found/skip reason]
|
||||
</verification>
|
||||
|
||||
**Skills**:
|
||||
- When implementing React components, invoke the `react-patterns` skill for reference on composition, hooks, and component patterns.
|
||||
- When optimizing frontend performance, invoke the `vercel-react-best-practices` skill for Vercel's prioritized performance rules.
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
description: Research specialist for external documentation, library APIs, and open source examples. READ-ONLY.
|
||||
mode: all
|
||||
temperature: 0.1
|
||||
tools:
|
||||
write: false
|
||||
edit: false
|
||||
bash: false
|
||||
---
|
||||
|
||||
You are Librarian - a research specialist for codebases and documentation.
|
||||
|
||||
**Role**: Multi-repository analysis, official docs lookup, GitHub examples, library research.
|
||||
|
||||
**Capabilities**:
|
||||
- Search and analyze external repositories
|
||||
- Find official documentation for libraries
|
||||
- Locate implementation examples in open source
|
||||
- Understand library internals and best practices
|
||||
|
||||
**Tools to Use**:
|
||||
- context7: Official documentation lookup
|
||||
- grep_app: Search GitHub repositories
|
||||
- websearch: General web search for docs
|
||||
|
||||
**Request Types**:
|
||||
|
||||
1. **Conceptual**: "How does X work?" - Explain architecture and design decisions
|
||||
2. **Implementation**: "How do I use X?" - Provide code examples and API signatures
|
||||
3. **Context**: "What's the best practice for X?" - Compare approaches with tradeoffs
|
||||
4. **Comprehensive**: "Tell me everything about X" - Full deep-dive with sources
|
||||
|
||||
**Behavior**:
|
||||
- Provide evidence-based answers with sources
|
||||
- Quote relevant code snippets
|
||||
- Link to official docs when available
|
||||
- Distinguish between official and community patterns
|
||||
- Use GitHub permalinks with commit SHA when referencing code
|
||||
|
||||
**Constraints**:
|
||||
- READ-ONLY: Research and report, don't implement
|
||||
- Always cite sources
|
||||
- Distinguish between stable APIs and experimental features
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
description: Strategic technical advisor. Architecture decisions, debugging strategy, code review guidance. READ-ONLY.
|
||||
mode: all
|
||||
temperature: 0.1
|
||||
tools:
|
||||
write: false
|
||||
edit: false
|
||||
bash: false
|
||||
---
|
||||
|
||||
You are Oracle - a strategic technical advisor.
|
||||
|
||||
**Role**: High-IQ debugging, architecture decisions, code review, and engineering guidance.
|
||||
|
||||
**Capabilities**:
|
||||
- Analyze complex codebases and identify root causes
|
||||
- Propose architectural solutions with tradeoffs
|
||||
- Review code for correctness, performance, and maintainability
|
||||
- Guide debugging when standard approaches fail
|
||||
|
||||
**Behavior**:
|
||||
- Be direct and concise
|
||||
- Provide actionable recommendations
|
||||
- Explain reasoning briefly
|
||||
- Acknowledge uncertainty when present
|
||||
|
||||
**Constraints**:
|
||||
- READ-ONLY: You advise, you don't implement
|
||||
- Focus on strategy, not execution
|
||||
- Point to specific files/lines when relevant
|
||||
|
||||
**Skills**:
|
||||
- When advising on git strategy, invoke the `git-master` skill for reference on atomic commits, rebase strategy, and history search techniques.
|
||||
- When planning complex multi-step tasks, invoke the `planning-with-files` skill for structured planning methodology.
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
description: Analyze and fix a GitHub issue end-to-end (plan, branch, implement, test, PR)
|
||||
model: claude-sonnet-4-0
|
||||
---
|
||||
|
||||
Please analyze and fix the GitHub issue: $ARGUMENTS.
|
||||
|
||||
Follow these steps:
|
||||
|
||||
# PLAN
|
||||
1. Use 'gh issue view' to get the issue details (or open the issue in the browser/API explorer if the GitHub CLI is unavailable)
|
||||
2. Understand the problem described in the issue
|
||||
3. Ask clarifying questions if necessary
|
||||
4. Understand the prior art for this issue
|
||||
- Search the scratchpads for previous thoughts related to the issue
|
||||
- Search PRs to see if you can find history on this issue
|
||||
- Search the codebase for relevant files
|
||||
5. Think harder about how to break the issue down into a series of small, manageable tasks.
|
||||
6. Document your plan in a new scratchpad
|
||||
- include the issue name in the filename
|
||||
- include a link to the issue in the scratchpad.
|
||||
|
||||
# CREATE
|
||||
- Create a new branch for the issue
|
||||
- Solve the issue in small, manageable steps, according to your plan.
|
||||
- Commit your changes after each step.
|
||||
|
||||
# TEST
|
||||
- Use playwright via MCP to test the changes if you have made changes to the UI
|
||||
- Write tests to describe the expected behavior of your code
|
||||
- Run the full test suite to ensure you haven't broken anything
|
||||
- If the tests are failing, fix them
|
||||
- Ensure that all tests are passing before moving on to the next step
|
||||
|
||||
# DEPLOY
|
||||
- Open a PR and request a review.
|
||||
|
||||
Prefer the GitHub CLI (`gh`) for GitHub-related tasks, but fall back to subagents or the GitHub web UI/REST API when the CLI is not installed.
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Merge a worktree branch back into the base branch
|
||||
---
|
||||
Merge a branch from the worktree.
|
||||
If you're currently working on a worktree, assume that's the one I'm referring to.
|
||||
|
||||
Start by committing any staged and unstaged changes. I may have made changes to the worktree manually.
|
||||
Then merge back the new main branch, since I may have made changes to it.
|
||||
|
||||
# Language specific:
|
||||
|
||||
## Rust
|
||||
|
||||
Ensure cargo check is happy.
|
||||
Ensure clippy is happy. clean up any new warnings.
|
||||
|
||||
## Typescript
|
||||
|
||||
Ensure tsc is happy.
|
||||
|
||||
# Finally
|
||||
|
||||
Squash the commits into a single one, merge into the base branch, and delete the worktree.
|
||||
@@ -0,0 +1,323 @@
|
||||
---
|
||||
description: Remove unused code with LSP-verified safety, atomic commits
|
||||
---
|
||||
|
||||
<command-instruction>
|
||||
You are a dead code removal specialist. Execute the FULL dead code removal workflow.
|
||||
|
||||
Your core weapon: **LSP FindReferences**. If a symbol has ZERO external references, it's dead. Remove it.
|
||||
|
||||
## CRITICAL RULES
|
||||
|
||||
1. **LSP is law.** Never guess. Always verify with `LspFindReferences` before removing ANYTHING.
|
||||
2. **One removal = one commit.** Every dead code removal gets its own atomic commit.
|
||||
3. **Test after every removal.** Run tests after each. If it fails, REVERT and skip.
|
||||
4. **Leaf-first order.** Remove deepest unused symbols first, then work up the dependency chain. Removing a leaf may expose new dead code upstream.
|
||||
5. **Never remove entry points.** `src/index.ts`, `src/cli/index.ts`, test files, config files, and files in `packages/` are off-limits unless explicitly targeted.
|
||||
|
||||
---
|
||||
|
||||
## STEP 0: REGISTER TODO LIST (MANDATORY FIRST ACTION)
|
||||
|
||||
```
|
||||
TodoWrite([
|
||||
{"id": "scan", "content": "PHASE 1: Scan codebase for dead code candidates using LSP + explore agents", "status": "pending", "priority": "high"},
|
||||
{"id": "verify", "content": "PHASE 2: Verify each candidate with LspFindReferences - zero false positives", "status": "pending", "priority": "high"},
|
||||
{"id": "plan", "content": "PHASE 3: Plan removal order (leaf-first dependency order)", "status": "pending", "priority": "high"},
|
||||
{"id": "remove", "content": "PHASE 4: Remove dead code one-by-one (remove -> test -> commit loop)", "status": "pending", "priority": "high"},
|
||||
{"id": "final", "content": "PHASE 5: Final verification - full test suite + build + typecheck", "status": "pending", "priority": "high"}
|
||||
])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## PHASE 1: SCAN FOR DEAD CODE CANDIDATES
|
||||
|
||||
**Mark scan as in_progress.**
|
||||
|
||||
### 1.1: Launch Parallel Explore Agents (ALL BACKGROUND)
|
||||
|
||||
Fire ALL simultaneously:
|
||||
|
||||
```
|
||||
// Agent 1: Find all exported symbols
|
||||
delegate_task(subagent_type="explore", run_in_background=true,
|
||||
prompt="Find ALL exported functions, classes, types, interfaces, and constants across src/.
|
||||
List each with: file path, line number, symbol name, export type (named/default).
|
||||
EXCLUDE: src/index.ts root exports, test files.
|
||||
Return as structured list.")
|
||||
|
||||
// Agent 2: Find potentially unused files
|
||||
delegate_task(subagent_type="explore", run_in_background=true,
|
||||
prompt="Find files in src/ that are NOT imported by any other file.
|
||||
Check import/require statements across the entire codebase.
|
||||
EXCLUDE: index.ts files, test files, entry points, config files, .md files.
|
||||
Return list of potentially orphaned files.")
|
||||
|
||||
// Agent 3: Find unused imports within files
|
||||
delegate_task(subagent_type="explore", run_in_background=true,
|
||||
prompt="Find unused imports across src/**/*.ts files.
|
||||
Look for import statements where the imported symbol is never referenced in the file body.
|
||||
Return: file path, line number, imported symbol name.")
|
||||
|
||||
// Agent 4: Find functions/variables only used in their own declaration
|
||||
delegate_task(subagent_type="explore", run_in_background=true,
|
||||
prompt="Find private/non-exported functions, variables, and types in src/**/*.ts that appear
|
||||
to have zero usage beyond their declaration. Return: file path, line number, symbol name.")
|
||||
```
|
||||
|
||||
### 1.2: Direct AST-Grep Scans (WHILE AGENTS RUN)
|
||||
|
||||
```typescript
|
||||
// Find unused imports pattern
|
||||
ast_grep_search(pattern="import { $NAME } from '$PATH'", lang="typescript", paths=["src/"])
|
||||
|
||||
// Find empty export objects
|
||||
ast_grep_search(pattern="export {}", lang="typescript", paths=["src/"])
|
||||
```
|
||||
|
||||
### 1.3: Collect All Results
|
||||
|
||||
Collect background agent results. Compile into a master candidate list:
|
||||
|
||||
```
|
||||
## DEAD CODE CANDIDATES
|
||||
|
||||
| # | File | Line | Symbol | Type | Confidence |
|
||||
|---|------|------|--------|------|------------|
|
||||
| 1 | src/foo.ts | 42 | unusedFunc | function | HIGH |
|
||||
| 2 | src/bar.ts | 10 | OldType | type | MEDIUM |
|
||||
```
|
||||
|
||||
**Mark scan as completed.**
|
||||
|
||||
---
|
||||
|
||||
## PHASE 2: VERIFY WITH LSP (ZERO FALSE POSITIVES)
|
||||
|
||||
**Mark verify as in_progress.**
|
||||
|
||||
For EVERY candidate from Phase 1, run this verification:
|
||||
|
||||
### 2.1: The LSP Verification Protocol
|
||||
|
||||
For each candidate symbol:
|
||||
|
||||
```typescript
|
||||
// Step 1: Find the symbol's exact position
|
||||
LspDocumentSymbols(filePath) // Get line/character of the symbol
|
||||
|
||||
// Step 2: Find ALL references across the ENTIRE workspace
|
||||
LspFindReferences(filePath, line, character, includeDeclaration=false)
|
||||
// includeDeclaration=false -> only counts USAGES, not the definition itself
|
||||
|
||||
// Step 3: Evaluate
|
||||
// 0 references -> CONFIRMED DEAD CODE
|
||||
// 1+ references -> NOT dead, remove from candidate list
|
||||
```
|
||||
|
||||
### 2.2: False Positive Guards
|
||||
|
||||
**NEVER mark as dead code if:**
|
||||
- Symbol is in `src/index.ts` (package entry point)
|
||||
- Symbol is in any `index.ts` that re-exports (barrel file check: look if it's re-exported)
|
||||
- Symbol is referenced in test files (tests are valid consumers)
|
||||
- Symbol has `@public` or `@api` JSDoc tags
|
||||
- Symbol is in a file listed in `package.json` exports
|
||||
- Symbol is a hook factory registered in an index file
|
||||
- Symbol is a tool factory registered in tool loading
|
||||
- Symbol is an agent definition registered in agent sources
|
||||
- File is a command template, skill definition, or MCP config
|
||||
|
||||
### 2.3: Build Confirmed Dead Code List
|
||||
|
||||
After verification, produce:
|
||||
|
||||
```
|
||||
## CONFIRMED DEAD CODE (LSP-verified, 0 external references)
|
||||
|
||||
| # | File | Line | Symbol | Type | Safe to Remove |
|
||||
|---|------|------|--------|------|----------------|
|
||||
| 1 | src/foo.ts | 42 | unusedFunc | function | YES |
|
||||
```
|
||||
|
||||
**If ZERO confirmed dead code found: Report "No dead code found" and STOP.**
|
||||
|
||||
**Mark verify as completed.**
|
||||
|
||||
---
|
||||
|
||||
## PHASE 3: PLAN REMOVAL ORDER
|
||||
|
||||
**Mark plan as in_progress.**
|
||||
|
||||
### 3.1: Dependency Analysis
|
||||
|
||||
For each confirmed dead symbol:
|
||||
1. Check if removing it would expose other dead code
|
||||
2. Check if other dead symbols depend on this one
|
||||
3. Build removal dependency graph
|
||||
|
||||
### 3.2: Order by Leaf-First
|
||||
|
||||
```
|
||||
Removal Order:
|
||||
1. [Leaf symbols - no other dead code depends on them]
|
||||
2. [Intermediate symbols - depended on only by already-removed dead code]
|
||||
3. [Dead files - entire files with no live exports]
|
||||
```
|
||||
|
||||
### 3.3: Register Granular Todos
|
||||
|
||||
Create one todo per removal.
|
||||
|
||||
**Mark plan as completed.**
|
||||
|
||||
---
|
||||
|
||||
## PHASE 4: ITERATIVE REMOVAL LOOP
|
||||
|
||||
**Mark remove as in_progress.**
|
||||
|
||||
For EACH dead code item, execute this exact loop:
|
||||
|
||||
### 4.1: Pre-Removal Check
|
||||
|
||||
```typescript
|
||||
// Re-verify it's still dead (previous removals may have changed things)
|
||||
LspFindReferences(filePath, line, character, includeDeclaration=false)
|
||||
// If references > 0 now -> SKIP (previous removal exposed a new consumer)
|
||||
```
|
||||
|
||||
### 4.2: Remove the Dead Code
|
||||
|
||||
Use appropriate tool:
|
||||
|
||||
**For unused imports:**
|
||||
```typescript
|
||||
Edit(filePath, oldString="import { deadSymbol } from '...';\n", newString="")
|
||||
```
|
||||
|
||||
**For unused functions/classes/types:**
|
||||
```typescript
|
||||
Read(filePath, offset=startLine, limit=endLine-startLine+1)
|
||||
Edit(filePath, oldString="[full symbol text]", newString="")
|
||||
```
|
||||
|
||||
**For dead files:**
|
||||
```bash
|
||||
rm "path/to/dead-file.ts"
|
||||
```
|
||||
|
||||
**After removal, also clean up:**
|
||||
- Remove any imports that were ONLY used by the removed code
|
||||
- Remove any now-empty import statements
|
||||
- Fix any trailing whitespace / double blank lines left behind
|
||||
|
||||
### 4.3: Post-Removal Verification
|
||||
|
||||
```typescript
|
||||
// 1. LSP diagnostics on changed file
|
||||
LspDiagnostics(filePath, severity="error")
|
||||
|
||||
// 2. Run tests
|
||||
bash("npm test") // or bun test, cargo test, etc.
|
||||
|
||||
// 3. Typecheck
|
||||
bash("npm run typecheck") // or equivalent
|
||||
```
|
||||
|
||||
### 4.4: Handle Failures
|
||||
|
||||
If ANY verification fails:
|
||||
1. **REVERT** the change immediately (`git checkout -- [file]`)
|
||||
2. Mark this removal todo as `cancelled` with note: "Removal caused [error]. Skipped."
|
||||
3. Proceed to next item
|
||||
|
||||
### 4.5: Commit
|
||||
|
||||
```bash
|
||||
git add [changed-files]
|
||||
git commit -m "refactor: remove unused [symbolType] [symbolName] from [filePath]"
|
||||
```
|
||||
|
||||
Mark this removal todo as `completed`.
|
||||
|
||||
### 4.6: Re-scan After Removal
|
||||
|
||||
After removing a symbol, check if its removal exposed NEW dead code:
|
||||
- Were there imports that only existed to serve the removed symbol?
|
||||
- Are there other symbols in the same file now unreferenced?
|
||||
|
||||
If new dead code is found, add it to the removal queue.
|
||||
|
||||
**Repeat 4.1-4.6 for every item. Mark remove as completed when done.**
|
||||
|
||||
---
|
||||
|
||||
## PHASE 5: FINAL VERIFICATION
|
||||
|
||||
**Mark final as in_progress.**
|
||||
|
||||
### 5.1: Full Test Suite
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
### 5.2: Full Typecheck
|
||||
```bash
|
||||
npm run typecheck
|
||||
```
|
||||
|
||||
### 5.3: Full Build
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
### 5.4: Summary Report
|
||||
|
||||
```markdown
|
||||
## Dead Code Removal Complete
|
||||
|
||||
### Removed
|
||||
| # | Symbol | File | Type | Commit |
|
||||
|---|--------|------|------|--------|
|
||||
| 1 | unusedFunc | src/foo.ts | function | abc1234 |
|
||||
|
||||
### Skipped (caused failures)
|
||||
| # | Symbol | File | Reason |
|
||||
|---|--------|------|--------|
|
||||
| 1 | riskyFunc | src/bar.ts | Test failure: [details] |
|
||||
|
||||
### Verification
|
||||
- Tests: PASSED (X/Y passing)
|
||||
- Typecheck: CLEAN
|
||||
- Build: SUCCESS
|
||||
- Total dead code removed: N symbols across M files
|
||||
- Total commits: K atomic commits
|
||||
```
|
||||
|
||||
**Mark final as completed.**
|
||||
|
||||
---
|
||||
|
||||
## SCOPE CONTROL
|
||||
|
||||
**If $ARGUMENTS is provided**, narrow the scan to the specified scope:
|
||||
- File path: Only scan that file
|
||||
- Directory: Only scan that directory
|
||||
- Symbol name: Only check that specific symbol
|
||||
- "all" or empty: Full project scan (default)
|
||||
|
||||
## ABORT CONDITIONS
|
||||
|
||||
**STOP and report to user if:**
|
||||
- 3 consecutive removals cause test failures
|
||||
- Build breaks and cannot be fixed by reverting
|
||||
- More than 50 candidates found (ask user to narrow scope)
|
||||
|
||||
</command-instruction>
|
||||
|
||||
<user-request>
|
||||
$ARGUMENTS
|
||||
</user-request>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,69 @@
|
||||
---
|
||||
description: Debug complex issues with root cause analysis and multiple fix approaches
|
||||
model: claude-sonnet-4-0
|
||||
---
|
||||
|
||||
Debug complex issues using specialized debugging agents:
|
||||
|
||||
## Debugging Approach
|
||||
|
||||
### 1. Primary Debug Analysis
|
||||
Use Task tool with subagent_type="debugger" to:
|
||||
- Analyze error messages and stack traces
|
||||
- Identify code paths leading to the issue
|
||||
- Reproduce the problem systematically
|
||||
- Isolate the root cause
|
||||
- Suggest multiple fix approaches
|
||||
|
||||
Prompt: "Debug issue: $ARGUMENTS. Provide detailed analysis including:
|
||||
1. Error reproduction steps
|
||||
2. Root cause identification
|
||||
3. Code flow analysis leading to the error
|
||||
4. Multiple solution approaches with trade-offs
|
||||
5. Recommended fix with implementation details"
|
||||
|
||||
### 2. Performance Debugging (if performance-related)
|
||||
If the issue involves performance problems, also use Task tool with subagent_type="performance-engineer" to:
|
||||
- Profile code execution
|
||||
- Identify bottlenecks
|
||||
- Analyze resource usage
|
||||
- Suggest optimization strategies
|
||||
|
||||
Prompt: "Profile and debug performance issue: $ARGUMENTS. Include:
|
||||
1. Performance metrics and profiling data
|
||||
2. Bottleneck identification
|
||||
3. Resource usage analysis
|
||||
4. Optimization recommendations
|
||||
5. Before/after performance projections"
|
||||
|
||||
## Debug Output Structure
|
||||
|
||||
### Root Cause Analysis
|
||||
- Precise identification of the bug source
|
||||
- Explanation of why the issue occurs
|
||||
- Impact analysis on other components
|
||||
|
||||
### Reproduction Guide
|
||||
- Step-by-step reproduction instructions
|
||||
- Required environment setup
|
||||
- Test data or conditions needed
|
||||
|
||||
### Solution Options
|
||||
1. **Quick Fix** - Minimal change to resolve issue
|
||||
- Implementation details
|
||||
- Risk assessment
|
||||
|
||||
2. **Proper Fix** - Best long-term solution
|
||||
- Refactoring requirements
|
||||
- Testing needs
|
||||
|
||||
3. **Preventive Measures** - Avoid similar issues
|
||||
- Code patterns to adopt
|
||||
- Tests to add
|
||||
|
||||
### Implementation Guide
|
||||
- Specific code changes needed
|
||||
- Order of operations for the fix
|
||||
- Validation steps
|
||||
|
||||
Issue to debug: $ARGUMENTS
|
||||
@@ -0,0 +1,155 @@
|
||||
---
|
||||
description: Execute a full TDD red-green-refactor cycle
|
||||
model: claude-opus-4-1
|
||||
---
|
||||
|
||||
Execute a comprehensive Test-Driven Development (TDD) workflow with strict red-green-refactor discipline:
|
||||
|
||||
## Configuration
|
||||
|
||||
### Coverage Thresholds
|
||||
- Minimum line coverage: 80%
|
||||
- Minimum branch coverage: 75%
|
||||
- Critical path coverage: 100%
|
||||
|
||||
### Refactoring Triggers
|
||||
- Cyclomatic complexity > 10
|
||||
- Method length > 20 lines
|
||||
- Class length > 200 lines
|
||||
- Duplicate code blocks > 3 lines
|
||||
|
||||
## Phase 1: Test Specification and Design
|
||||
|
||||
### 1. Requirements Analysis
|
||||
- Use Task tool with subagent_type="architect-review"
|
||||
- Prompt: "Analyze requirements for: $ARGUMENTS. Define acceptance criteria, identify edge cases, and create test scenarios. Output a comprehensive test specification."
|
||||
- Output: Test specification, acceptance criteria, edge case matrix
|
||||
- Validation: Ensure all requirements have corresponding test scenarios
|
||||
|
||||
### 2. Test Architecture Design
|
||||
- Use Task tool with subagent_type="test-automator"
|
||||
- Prompt: "Design test architecture for: $ARGUMENTS based on test specification. Define test structure, fixtures, mocks, and test data strategy. Ensure testability and maintainability."
|
||||
- Output: Test architecture, fixture design, mock strategy
|
||||
- Validation: Architecture supports isolated, fast, reliable tests
|
||||
|
||||
## Phase 2: RED - Write Failing Tests
|
||||
|
||||
### 3. Write Unit Tests (Failing)
|
||||
- Use Task tool with subagent_type="test-automator"
|
||||
- Prompt: "Write FAILING unit tests for: $ARGUMENTS. Tests must fail initially. Include edge cases, error scenarios, and happy paths. DO NOT implement production code."
|
||||
- Output: Failing unit tests, test documentation
|
||||
- **CRITICAL**: Verify all tests fail with expected error messages
|
||||
|
||||
### 4. Verify Test Failure
|
||||
- Use Task tool with subagent_type="code-reviewer"
|
||||
- Prompt: "Verify that all tests for: $ARGUMENTS are failing correctly. Ensure failures are for the right reasons (missing implementation, not test errors). Confirm no false positives."
|
||||
- Output: Test failure verification report
|
||||
- **GATE**: Do not proceed until all tests fail appropriately
|
||||
|
||||
## Phase 3: GREEN - Make Tests Pass
|
||||
|
||||
### 5. Minimal Implementation
|
||||
- Use Task tool with subagent_type="backend-architect"
|
||||
- Prompt: "Implement MINIMAL code to make tests pass for: $ARGUMENTS. Focus only on making tests green. Do not add extra features or optimizations. Keep it simple."
|
||||
- Output: Minimal working implementation
|
||||
- Constraint: No code beyond what's needed to pass tests
|
||||
|
||||
### 6. Verify Test Success
|
||||
- Use Task tool with subagent_type="test-automator"
|
||||
- Prompt: "Run all tests for: $ARGUMENTS and verify they pass. Check test coverage metrics. Ensure no tests were accidentally broken."
|
||||
- Output: Test execution report, coverage metrics
|
||||
- **GATE**: All tests must pass before proceeding
|
||||
|
||||
## Phase 4: REFACTOR - Improve Code Quality
|
||||
|
||||
### 7. Code Refactoring
|
||||
- Use Task tool with subagent_type="code-reviewer"
|
||||
- Prompt: "Refactor implementation for: $ARGUMENTS while keeping tests green. Apply SOLID principles, remove duplication, improve naming, and optimize performance. Run tests after each refactoring."
|
||||
- Output: Refactored code, refactoring report
|
||||
- Constraint: Tests must remain green throughout
|
||||
|
||||
### 8. Test Refactoring
|
||||
- Use Task tool with subagent_type="test-automator"
|
||||
- Prompt: "Refactor tests for: $ARGUMENTS. Remove test duplication, improve test names, extract common fixtures, and enhance test readability. Ensure tests still provide same coverage."
|
||||
- Output: Refactored tests, improved test structure
|
||||
- Validation: Coverage metrics unchanged or improved
|
||||
|
||||
## Phase 5: Integration and System Tests
|
||||
|
||||
### 9. Write Integration Tests (Failing First)
|
||||
- Use Task tool with subagent_type="test-automator"
|
||||
- Prompt: "Write FAILING integration tests for: $ARGUMENTS. Test component interactions, API contracts, and data flow. Tests must fail initially."
|
||||
- Output: Failing integration tests
|
||||
- Validation: Tests fail due to missing integration logic
|
||||
|
||||
### 10. Implement Integration
|
||||
- Use Task tool with subagent_type="backend-architect"
|
||||
- Prompt: "Implement integration code for: $ARGUMENTS to make integration tests pass. Focus on component interaction and data flow."
|
||||
- Output: Integration implementation
|
||||
- Validation: All integration tests pass
|
||||
|
||||
## Phase 6: Continuous Improvement Cycle
|
||||
|
||||
### 11. Performance and Edge Case Tests
|
||||
- Use Task tool with subagent_type="test-automator"
|
||||
- Prompt: "Add performance tests and additional edge case tests for: $ARGUMENTS. Include stress tests, boundary tests, and error recovery tests."
|
||||
- Output: Extended test suite
|
||||
- Metric: Increased test coverage and scenario coverage
|
||||
|
||||
### 12. Final Code Review
|
||||
- Use Task tool with subagent_type="architect-review"
|
||||
- Prompt: "Perform comprehensive review of: $ARGUMENTS. Verify TDD process was followed, check code quality, test quality, and coverage. Suggest improvements."
|
||||
- Output: Review report, improvement suggestions
|
||||
- Action: Implement critical suggestions while maintaining green tests
|
||||
|
||||
## Validation Checkpoints
|
||||
|
||||
### RED Phase Validation
|
||||
- [ ] All tests written before implementation
|
||||
- [ ] All tests fail with meaningful error messages
|
||||
- [ ] Test failures are due to missing implementation
|
||||
- [ ] No test passes accidentally
|
||||
|
||||
### GREEN Phase Validation
|
||||
- [ ] All tests pass
|
||||
- [ ] No extra code beyond test requirements
|
||||
- [ ] Coverage meets minimum thresholds
|
||||
- [ ] No test was modified to make it pass
|
||||
|
||||
### REFACTOR Phase Validation
|
||||
- [ ] All tests still pass after refactoring
|
||||
- [ ] Code complexity reduced
|
||||
- [ ] Duplication eliminated
|
||||
- [ ] Performance improved or maintained
|
||||
- [ ] Test readability improved
|
||||
|
||||
## Failure Recovery
|
||||
|
||||
If TDD discipline is broken:
|
||||
1. **STOP** immediately
|
||||
2. Identify which phase was violated
|
||||
3. Rollback to last valid state
|
||||
4. Resume from correct phase
|
||||
5. Document lesson learned
|
||||
|
||||
## Anti-Patterns to Avoid
|
||||
|
||||
- Writing implementation before tests
|
||||
- Writing tests that already pass
|
||||
- Skipping the refactor phase
|
||||
- Writing multiple features without tests
|
||||
- Modifying tests to make them pass
|
||||
- Ignoring failing tests
|
||||
- Writing tests after implementation
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- 100% of code written test-first
|
||||
- All tests pass continuously
|
||||
- Coverage exceeds thresholds
|
||||
- Code complexity within limits
|
||||
- Zero defects in covered code
|
||||
- Clear test documentation
|
||||
- Fast test execution (< 5 seconds for unit tests)
|
||||
|
||||
TDD implementation for: $ARGUMENTS
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
description: Rebase/merge upstream changes into the current branch
|
||||
---
|
||||
This command should only work while in a secondary branch (not main or master).
|
||||
|
||||
Commit any unstaged changes
|
||||
Fetch updates from the origin repo
|
||||
If there are new commits on the parent branch (typically origin/main), then merge them back into the current branch
|
||||
Solve any conflicts, and analyze the incoming changes to see if additional changes are required to the branch's code (e.g.: if something was renamed in the meantime in main, our new code may need to be adjusted)
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
description: Start a new feature in a git worktree
|
||||
---
|
||||
In a worktrees directory inside the git project's root, create a new worktree for the requested feature.
|
||||
create the directory if it doesn't exist.
|
||||
keep the branch name concise, and don't include "opencode" in its name.
|
||||
do all the work for the feature in the new worktree.
|
||||
run "kitty @ set-tab-title" to set the tab title of this kitty session to "<project>/<feature>"
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
# Global config file
|
||||
xdg.configFile."opencode/opencode.json".source = ./opencode.json;
|
||||
|
||||
# Global rules (equivalent to ~/.claude/CLAUDE.md)
|
||||
xdg.configFile."opencode/AGENTS.md".source = ./AGENTS.md;
|
||||
|
||||
# Custom agents
|
||||
xdg.configFile."opencode/agents/oracle.md".source = ./agents/oracle.md;
|
||||
xdg.configFile."opencode/agents/explorer.md".source = ./agents/explorer.md;
|
||||
xdg.configFile."opencode/agents/librarian.md".source = ./agents/librarian.md;
|
||||
xdg.configFile."opencode/agents/fixer.md".source = ./agents/fixer.md;
|
||||
xdg.configFile."opencode/agents/designer.md".source = ./agents/designer.md;
|
||||
xdg.configFile."opencode/agents/designer-bold.md".source = ./agents/designer-bold.md;
|
||||
xdg.configFile."opencode/agents/analyze-branch.md".source = ./agents/analyze-branch.md;
|
||||
|
||||
# Global commands
|
||||
xdg.configFile."opencode/commands/work.md".source = ./commands/work.md;
|
||||
xdg.configFile."opencode/commands/merge.md".source = ./commands/merge.md;
|
||||
xdg.configFile."opencode/commands/update.md".source = ./commands/update.md;
|
||||
xdg.configFile."opencode/commands/smart-debug.md".source = ./commands/smart-debug.md;
|
||||
xdg.configFile."opencode/commands/tdd-cycle.md".source = ./commands/tdd-cycle.md;
|
||||
xdg.configFile."opencode/commands/security-scan.md".source = ./commands/security-scan.md;
|
||||
xdg.configFile."opencode/commands/issue.md".source = ./commands/issue.md;
|
||||
xdg.configFile."opencode/commands/remove-deadcode.md".source = ./commands/remove-deadcode.md;
|
||||
|
||||
# Skills
|
||||
xdg.configFile."opencode/skills/git-master/SKILL.md".source = ./skills/git-master/SKILL.md;
|
||||
xdg.configFile."opencode/skills/planning-with-files/SKILL.md".source =
|
||||
./skills/planning-with-files/SKILL.md;
|
||||
xdg.configFile."opencode/skills/react-patterns/SKILL.md".source = ./skills/react-patterns/SKILL.md;
|
||||
xdg.configFile."opencode/skills/vercel-react-best-practices/SKILL.md".source =
|
||||
./skills/vercel-react-best-practices/SKILL.md;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"autoupdate": false,
|
||||
"permission": {
|
||||
"read": "allow",
|
||||
"edit": "allow",
|
||||
"write": "allow",
|
||||
"fetch": "allow",
|
||||
"glob": "allow",
|
||||
"grep": "allow",
|
||||
"bash": "ask",
|
||||
"skill": {
|
||||
"*": "allow"
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,160 @@
|
||||
---
|
||||
name: planning-with-files
|
||||
description: Transforms workflow to use Manus-style persistent markdown files for planning, progress tracking, and knowledge storage. Use when starting complex tasks, multi-step projects, research tasks, or when the user mentions planning, organizing work, tracking progress, or wants structured output.
|
||||
---
|
||||
|
||||
# Planning with Files
|
||||
|
||||
Work like Manus: Use persistent markdown files as your "working memory on disk."
|
||||
|
||||
## Quick Start
|
||||
|
||||
Before ANY complex task:
|
||||
|
||||
1. **Create `task_plan.md`** in the working directory
|
||||
2. **Define phases** with checkboxes
|
||||
3. **Update after each phase** - mark [x] and change status
|
||||
4. **Read before deciding** - refresh goals in attention window
|
||||
|
||||
## The 3-File Pattern
|
||||
|
||||
For every non-trivial task, create THREE files:
|
||||
|
||||
| File | Purpose | When to Update |
|
||||
|------|---------|----------------|
|
||||
| `task_plan.md` | Track phases and progress | After each phase |
|
||||
| `notes.md` | Store findings and research | During research |
|
||||
| `[deliverable].md` | Final output | At completion |
|
||||
|
||||
## Core Workflow
|
||||
|
||||
```
|
||||
Loop 1: Create task_plan.md with goal and phases
|
||||
Loop 2: Research → save to notes.md → update task_plan.md
|
||||
Loop 3: Read notes.md → create deliverable → update task_plan.md
|
||||
Loop 4: Deliver final output
|
||||
```
|
||||
|
||||
### The Loop in Detail
|
||||
|
||||
**Before each major action:**
|
||||
```bash
|
||||
Read task_plan.md # Refresh goals in attention window
|
||||
```
|
||||
|
||||
**After each phase:**
|
||||
```bash
|
||||
Edit task_plan.md # Mark [x], update status
|
||||
```
|
||||
|
||||
**When storing information:**
|
||||
```bash
|
||||
Write notes.md # Don't stuff context, store in file
|
||||
```
|
||||
|
||||
## task_plan.md Template
|
||||
|
||||
Create this file FIRST for any complex task:
|
||||
|
||||
```markdown
|
||||
# Task Plan: [Brief Description]
|
||||
|
||||
## Goal
|
||||
[One sentence describing the end state]
|
||||
|
||||
## Phases
|
||||
- [ ] Phase 1: Plan and setup
|
||||
- [ ] Phase 2: Research/gather information
|
||||
- [ ] Phase 3: Execute/build
|
||||
- [ ] Phase 4: Review and deliver
|
||||
|
||||
## Key Questions
|
||||
1. [Question to answer]
|
||||
2. [Question to answer]
|
||||
|
||||
## Decisions Made
|
||||
- [Decision]: [Rationale]
|
||||
|
||||
## Errors Encountered
|
||||
- [Error]: [Resolution]
|
||||
|
||||
## Status
|
||||
**Currently in Phase X** - [What I'm doing now]
|
||||
```
|
||||
|
||||
## notes.md Template
|
||||
|
||||
For research and findings:
|
||||
|
||||
```markdown
|
||||
# Notes: [Topic]
|
||||
|
||||
## Sources
|
||||
|
||||
### Source 1: [Name]
|
||||
- URL: [link]
|
||||
- Key points:
|
||||
- [Finding]
|
||||
- [Finding]
|
||||
|
||||
## Synthesized Findings
|
||||
|
||||
### [Category]
|
||||
- [Finding]
|
||||
- [Finding]
|
||||
```
|
||||
|
||||
## Critical Rules
|
||||
|
||||
### 1. ALWAYS Create Plan First
|
||||
Never start a complex task without `task_plan.md`. This is non-negotiable.
|
||||
|
||||
### 2. Read Before Decide
|
||||
Before any major decision, read the plan file. This keeps goals in your attention window.
|
||||
|
||||
### 3. Update After Act
|
||||
After completing any phase, immediately update the plan file:
|
||||
- Mark completed phases with [x]
|
||||
- Update the Status section
|
||||
- Log any errors encountered
|
||||
|
||||
### 4. Store, Don't Stuff
|
||||
Large outputs go to files, not context. Keep only paths in working memory.
|
||||
|
||||
### 5. Log All Errors
|
||||
Every error goes in the "Errors Encountered" section. This builds knowledge for future tasks.
|
||||
|
||||
## When to Use This Pattern
|
||||
|
||||
**Use 3-file pattern for:**
|
||||
- Multi-step tasks (3+ steps)
|
||||
- Research tasks
|
||||
- Building/creating something
|
||||
- Tasks spanning multiple tool calls
|
||||
- Anything requiring organization
|
||||
|
||||
**Skip for:**
|
||||
- Simple questions
|
||||
- Single-file edits
|
||||
- Quick lookups
|
||||
|
||||
## Anti-Patterns to Avoid
|
||||
|
||||
| Don't | Do Instead |
|
||||
|-------|------------|
|
||||
| Use TodoWrite for persistence | Create `task_plan.md` file |
|
||||
| State goals once and forget | Re-read plan before each decision |
|
||||
| Hide errors and retry | Log errors to plan file |
|
||||
| Stuff everything in context | Store large content in files |
|
||||
| Start executing immediately | Create plan file FIRST |
|
||||
|
||||
## Advanced Patterns
|
||||
|
||||
See [reference.md](reference.md) for:
|
||||
- Attention manipulation techniques
|
||||
- Error recovery patterns
|
||||
- Context optimization from Manus
|
||||
|
||||
See [examples.md](examples.md) for:
|
||||
- Real task examples
|
||||
- Complex workflow patterns
|
||||
@@ -0,0 +1,631 @@
|
||||
---
|
||||
name: react-patterns
|
||||
description: React component patterns with TypeScript examples. Composition, compound components, custom hooks, Context+Reducer state, memoization, code splitting, virtualization, error boundaries, accessibility (keyboard nav, focus management), and animations.
|
||||
---
|
||||
|
||||
# Frontend Development Patterns
|
||||
|
||||
Modern frontend patterns for React, Next.js, and performant user interfaces.
|
||||
|
||||
## Component Patterns
|
||||
|
||||
### Composition Over Inheritance
|
||||
|
||||
```typescript
|
||||
// ✅ GOOD: Component composition
|
||||
interface CardProps {
|
||||
children: React.ReactNode
|
||||
variant?: 'default' | 'outlined'
|
||||
}
|
||||
|
||||
export function Card({ children, variant = 'default' }: CardProps) {
|
||||
return <div className={`card card-${variant}`}>{children}</div>
|
||||
}
|
||||
|
||||
export function CardHeader({ children }: { children: React.ReactNode }) {
|
||||
return <div className="card-header">{children}</div>
|
||||
}
|
||||
|
||||
export function CardBody({ children }: { children: React.ReactNode }) {
|
||||
return <div className="card-body">{children}</div>
|
||||
}
|
||||
|
||||
// Usage
|
||||
<Card>
|
||||
<CardHeader>Title</CardHeader>
|
||||
<CardBody>Content</CardBody>
|
||||
</Card>
|
||||
```
|
||||
|
||||
### Compound Components
|
||||
|
||||
```typescript
|
||||
interface TabsContextValue {
|
||||
activeTab: string
|
||||
setActiveTab: (tab: string) => void
|
||||
}
|
||||
|
||||
const TabsContext = createContext<TabsContextValue | undefined>(undefined)
|
||||
|
||||
export function Tabs({ children, defaultTab }: {
|
||||
children: React.ReactNode
|
||||
defaultTab: string
|
||||
}) {
|
||||
const [activeTab, setActiveTab] = useState(defaultTab)
|
||||
|
||||
return (
|
||||
<TabsContext.Provider value={{ activeTab, setActiveTab }}>
|
||||
{children}
|
||||
</TabsContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export function TabList({ children }: { children: React.ReactNode }) {
|
||||
return <div className="tab-list">{children}</div>
|
||||
}
|
||||
|
||||
export function Tab({ id, children }: { id: string, children: React.ReactNode }) {
|
||||
const context = useContext(TabsContext)
|
||||
if (!context) throw new Error('Tab must be used within Tabs')
|
||||
|
||||
return (
|
||||
<button
|
||||
className={context.activeTab === id ? 'active' : ''}
|
||||
onClick={() => context.setActiveTab(id)}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
// Usage
|
||||
<Tabs defaultTab="overview">
|
||||
<TabList>
|
||||
<Tab id="overview">Overview</Tab>
|
||||
<Tab id="details">Details</Tab>
|
||||
</TabList>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
### Render Props Pattern
|
||||
|
||||
```typescript
|
||||
interface DataLoaderProps<T> {
|
||||
url: string
|
||||
children: (data: T | null, loading: boolean, error: Error | null) => React.ReactNode
|
||||
}
|
||||
|
||||
export function DataLoader<T>({ url, children }: DataLoaderProps<T>) {
|
||||
const [data, setData] = useState<T | null>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
fetch(url)
|
||||
.then(res => res.json())
|
||||
.then(setData)
|
||||
.catch(setError)
|
||||
.finally(() => setLoading(false))
|
||||
}, [url])
|
||||
|
||||
return <>{children(data, loading, error)}</>
|
||||
}
|
||||
|
||||
// Usage
|
||||
<DataLoader<Market[]> url="/api/markets">
|
||||
{(markets, loading, error) => {
|
||||
if (loading) return <Spinner />
|
||||
if (error) return <Error error={error} />
|
||||
return <MarketList markets={markets!} />
|
||||
}}
|
||||
</DataLoader>
|
||||
```
|
||||
|
||||
## Custom Hooks Patterns
|
||||
|
||||
### State Management Hook
|
||||
|
||||
```typescript
|
||||
export function useToggle(initialValue = false): [boolean, () => void] {
|
||||
const [value, setValue] = useState(initialValue)
|
||||
|
||||
const toggle = useCallback(() => {
|
||||
setValue(v => !v)
|
||||
}, [])
|
||||
|
||||
return [value, toggle]
|
||||
}
|
||||
|
||||
// Usage
|
||||
const [isOpen, toggleOpen] = useToggle()
|
||||
```
|
||||
|
||||
### Async Data Fetching Hook
|
||||
|
||||
```typescript
|
||||
interface UseQueryOptions<T> {
|
||||
onSuccess?: (data: T) => void
|
||||
onError?: (error: Error) => void
|
||||
enabled?: boolean
|
||||
}
|
||||
|
||||
export function useQuery<T>(
|
||||
key: string,
|
||||
fetcher: () => Promise<T>,
|
||||
options?: UseQueryOptions<T>
|
||||
) {
|
||||
const [data, setData] = useState<T | null>(null)
|
||||
const [error, setError] = useState<Error | null>(null)
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const refetch = useCallback(async () => {
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
|
||||
try {
|
||||
const result = await fetcher()
|
||||
setData(result)
|
||||
options?.onSuccess?.(result)
|
||||
} catch (err) {
|
||||
const error = err as Error
|
||||
setError(error)
|
||||
options?.onError?.(error)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [fetcher, options])
|
||||
|
||||
useEffect(() => {
|
||||
if (options?.enabled !== false) {
|
||||
refetch()
|
||||
}
|
||||
}, [key, refetch, options?.enabled])
|
||||
|
||||
return { data, error, loading, refetch }
|
||||
}
|
||||
|
||||
// Usage
|
||||
const { data: markets, loading, error, refetch } = useQuery(
|
||||
'markets',
|
||||
() => fetch('/api/markets').then(r => r.json()),
|
||||
{
|
||||
onSuccess: data => console.log('Fetched', data.length, 'markets'),
|
||||
onError: err => console.error('Failed:', err)
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### Debounce Hook
|
||||
|
||||
```typescript
|
||||
export 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
|
||||
const [searchQuery, setSearchQuery] = useState('')
|
||||
const debouncedQuery = useDebounce(searchQuery, 500)
|
||||
|
||||
useEffect(() => {
|
||||
if (debouncedQuery) {
|
||||
performSearch(debouncedQuery)
|
||||
}
|
||||
}, [debouncedQuery])
|
||||
```
|
||||
|
||||
## State Management Patterns
|
||||
|
||||
### Context + Reducer Pattern
|
||||
|
||||
```typescript
|
||||
interface State {
|
||||
markets: Market[]
|
||||
selectedMarket: Market | null
|
||||
loading: boolean
|
||||
}
|
||||
|
||||
type Action =
|
||||
| { type: 'SET_MARKETS'; payload: Market[] }
|
||||
| { type: 'SELECT_MARKET'; payload: Market }
|
||||
| { type: 'SET_LOADING'; payload: boolean }
|
||||
|
||||
function reducer(state: State, action: Action): State {
|
||||
switch (action.type) {
|
||||
case 'SET_MARKETS':
|
||||
return { ...state, markets: action.payload }
|
||||
case 'SELECT_MARKET':
|
||||
return { ...state, selectedMarket: action.payload }
|
||||
case 'SET_LOADING':
|
||||
return { ...state, loading: action.payload }
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
const MarketContext = createContext<{
|
||||
state: State
|
||||
dispatch: Dispatch<Action>
|
||||
} | undefined>(undefined)
|
||||
|
||||
export function MarketProvider({ children }: { children: React.ReactNode }) {
|
||||
const [state, dispatch] = useReducer(reducer, {
|
||||
markets: [],
|
||||
selectedMarket: null,
|
||||
loading: false
|
||||
})
|
||||
|
||||
return (
|
||||
<MarketContext.Provider value={{ state, dispatch }}>
|
||||
{children}
|
||||
</MarketContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export function useMarkets() {
|
||||
const context = useContext(MarketContext)
|
||||
if (!context) throw new Error('useMarkets must be used within MarketProvider')
|
||||
return context
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Memoization
|
||||
|
||||
```typescript
|
||||
// ✅ useMemo for expensive computations
|
||||
const sortedMarkets = useMemo(() => {
|
||||
return markets.sort((a, b) => b.volume - a.volume)
|
||||
}, [markets])
|
||||
|
||||
// ✅ useCallback for functions passed to children
|
||||
const handleSearch = useCallback((query: string) => {
|
||||
setSearchQuery(query)
|
||||
}, [])
|
||||
|
||||
// ✅ React.memo for pure components
|
||||
export const MarketCard = React.memo<MarketCardProps>(({ market }) => {
|
||||
return (
|
||||
<div className="market-card">
|
||||
<h3>{market.name}</h3>
|
||||
<p>{market.description}</p>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
```
|
||||
|
||||
### Code Splitting & Lazy Loading
|
||||
|
||||
```typescript
|
||||
import { lazy, Suspense } from 'react'
|
||||
|
||||
// ✅ Lazy load heavy components
|
||||
const HeavyChart = lazy(() => import('./HeavyChart'))
|
||||
const ThreeJsBackground = lazy(() => import('./ThreeJsBackground'))
|
||||
|
||||
export function Dashboard() {
|
||||
return (
|
||||
<div>
|
||||
<Suspense fallback={<ChartSkeleton />}>
|
||||
<HeavyChart data={data} />
|
||||
</Suspense>
|
||||
|
||||
<Suspense fallback={null}>
|
||||
<ThreeJsBackground />
|
||||
</Suspense>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Virtualization for Long Lists
|
||||
|
||||
```typescript
|
||||
import { useVirtualizer } from '@tanstack/react-virtual'
|
||||
|
||||
export function VirtualMarketList({ markets }: { markets: Market[] }) {
|
||||
const parentRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const virtualizer = useVirtualizer({
|
||||
count: markets.length,
|
||||
getScrollElement: () => parentRef.current,
|
||||
estimateSize: () => 100, // Estimated row height
|
||||
overscan: 5 // Extra items to render
|
||||
})
|
||||
|
||||
return (
|
||||
<div ref={parentRef} style={{ height: '600px', overflow: 'auto' }}>
|
||||
<div
|
||||
style={{
|
||||
height: `${virtualizer.getTotalSize()}px`,
|
||||
position: 'relative'
|
||||
}}
|
||||
>
|
||||
{virtualizer.getVirtualItems().map(virtualRow => (
|
||||
<div
|
||||
key={virtualRow.index}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: `${virtualRow.size}px`,
|
||||
transform: `translateY(${virtualRow.start}px)`
|
||||
}}
|
||||
>
|
||||
<MarketCard market={markets[virtualRow.index]} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Form Handling Patterns
|
||||
|
||||
### Controlled Form with Validation
|
||||
|
||||
```typescript
|
||||
interface FormData {
|
||||
name: string
|
||||
description: string
|
||||
endDate: string
|
||||
}
|
||||
|
||||
interface FormErrors {
|
||||
name?: string
|
||||
description?: string
|
||||
endDate?: string
|
||||
}
|
||||
|
||||
export function CreateMarketForm() {
|
||||
const [formData, setFormData] = useState<FormData>({
|
||||
name: '',
|
||||
description: '',
|
||||
endDate: ''
|
||||
})
|
||||
|
||||
const [errors, setErrors] = useState<FormErrors>({})
|
||||
|
||||
const validate = (): boolean => {
|
||||
const newErrors: FormErrors = {}
|
||||
|
||||
if (!formData.name.trim()) {
|
||||
newErrors.name = 'Name is required'
|
||||
} else if (formData.name.length > 200) {
|
||||
newErrors.name = 'Name must be under 200 characters'
|
||||
}
|
||||
|
||||
if (!formData.description.trim()) {
|
||||
newErrors.description = 'Description is required'
|
||||
}
|
||||
|
||||
if (!formData.endDate) {
|
||||
newErrors.endDate = 'End date is required'
|
||||
}
|
||||
|
||||
setErrors(newErrors)
|
||||
return Object.keys(newErrors).length === 0
|
||||
}
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
|
||||
if (!validate()) return
|
||||
|
||||
try {
|
||||
await createMarket(formData)
|
||||
// Success handling
|
||||
} catch (error) {
|
||||
// Error handling
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<input
|
||||
value={formData.name}
|
||||
onChange={e => setFormData(prev => ({ ...prev, name: e.target.value }))}
|
||||
placeholder="Market name"
|
||||
/>
|
||||
{errors.name && <span className="error">{errors.name}</span>}
|
||||
|
||||
{/* Other fields */}
|
||||
|
||||
<button type="submit">Create Market</button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Error Boundary Pattern
|
||||
|
||||
```typescript
|
||||
interface ErrorBoundaryState {
|
||||
hasError: boolean
|
||||
error: Error | null
|
||||
}
|
||||
|
||||
export class ErrorBoundary extends React.Component<
|
||||
{ children: React.ReactNode },
|
||||
ErrorBoundaryState
|
||||
> {
|
||||
state: ErrorBoundaryState = {
|
||||
hasError: false,
|
||||
error: null
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
|
||||
return { hasError: true, error }
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
||||
console.error('Error boundary caught:', error, errorInfo)
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
return (
|
||||
<div className="error-fallback">
|
||||
<h2>Something went wrong</h2>
|
||||
<p>{this.state.error?.message}</p>
|
||||
<button onClick={() => this.setState({ hasError: false })}>
|
||||
Try again
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return this.props.children
|
||||
}
|
||||
}
|
||||
|
||||
// Usage
|
||||
<ErrorBoundary>
|
||||
<App />
|
||||
</ErrorBoundary>
|
||||
```
|
||||
|
||||
## Animation Patterns
|
||||
|
||||
### Framer Motion Animations
|
||||
|
||||
```typescript
|
||||
import { motion, AnimatePresence } from 'framer-motion'
|
||||
|
||||
// ✅ List animations
|
||||
export function AnimatedMarketList({ markets }: { markets: Market[] }) {
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{markets.map(market => (
|
||||
<motion.div
|
||||
key={market.id}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -20 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
>
|
||||
<MarketCard market={market} />
|
||||
</motion.div>
|
||||
))}
|
||||
</AnimatePresence>
|
||||
)
|
||||
}
|
||||
|
||||
// ✅ Modal animations
|
||||
export function Modal({ isOpen, onClose, children }: ModalProps) {
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{isOpen && (
|
||||
<>
|
||||
<motion.div
|
||||
className="modal-overlay"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
onClick={onClose}
|
||||
/>
|
||||
<motion.div
|
||||
className="modal-content"
|
||||
initial={{ opacity: 0, scale: 0.9, y: 20 }}
|
||||
animate={{ opacity: 1, scale: 1, y: 0 }}
|
||||
exit={{ opacity: 0, scale: 0.9, y: 20 }}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
</>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Accessibility Patterns
|
||||
|
||||
### Keyboard Navigation
|
||||
|
||||
```typescript
|
||||
export function Dropdown({ options, onSelect }: DropdownProps) {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [activeIndex, setActiveIndex] = useState(0)
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
switch (e.key) {
|
||||
case 'ArrowDown':
|
||||
e.preventDefault()
|
||||
setActiveIndex(i => Math.min(i + 1, options.length - 1))
|
||||
break
|
||||
case 'ArrowUp':
|
||||
e.preventDefault()
|
||||
setActiveIndex(i => Math.max(i - 1, 0))
|
||||
break
|
||||
case 'Enter':
|
||||
e.preventDefault()
|
||||
onSelect(options[activeIndex])
|
||||
setIsOpen(false)
|
||||
break
|
||||
case 'Escape':
|
||||
setIsOpen(false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
role="combobox"
|
||||
aria-expanded={isOpen}
|
||||
aria-haspopup="listbox"
|
||||
onKeyDown={handleKeyDown}
|
||||
>
|
||||
{/* Dropdown implementation */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Focus Management
|
||||
|
||||
```typescript
|
||||
export function Modal({ isOpen, onClose, children }: ModalProps) {
|
||||
const modalRef = useRef<HTMLDivElement>(null)
|
||||
const previousFocusRef = useRef<HTMLElement | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
// Save currently focused element
|
||||
previousFocusRef.current = document.activeElement as HTMLElement
|
||||
|
||||
// Focus modal
|
||||
modalRef.current?.focus()
|
||||
} else {
|
||||
// Restore focus when closing
|
||||
previousFocusRef.current?.focus()
|
||||
}
|
||||
}, [isOpen])
|
||||
|
||||
return isOpen ? (
|
||||
<div
|
||||
ref={modalRef}
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
tabIndex={-1}
|
||||
onKeyDown={e => e.key === 'Escape' && onClose()}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
```
|
||||
|
||||
**Remember**: Modern frontend patterns enable maintainable, performant user interfaces. Choose patterns that fit your project complexity.
|
||||
@@ -0,0 +1,121 @@
|
||||
---
|
||||
name: vercel-react-best-practices
|
||||
description: React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.
|
||||
---
|
||||
|
||||
# Vercel React Best Practices
|
||||
|
||||
Comprehensive performance optimization guide for React and Next.js applications, maintained by Vercel. Contains 45 rules across 8 categories, prioritized by impact to guide automated refactoring and code generation.
|
||||
|
||||
## When to Apply
|
||||
|
||||
Reference these guidelines when:
|
||||
- Writing new React components or Next.js pages
|
||||
- Implementing data fetching (client or server-side)
|
||||
- Reviewing code for performance issues
|
||||
- Refactoring existing React/Next.js code
|
||||
- Optimizing bundle size or load times
|
||||
|
||||
## Rule Categories by Priority
|
||||
|
||||
| Priority | Category | Impact | Prefix |
|
||||
|----------|----------|--------|--------|
|
||||
| 1 | Eliminating Waterfalls | CRITICAL | `async-` |
|
||||
| 2 | Bundle Size Optimization | CRITICAL | `bundle-` |
|
||||
| 3 | Server-Side Performance | HIGH | `server-` |
|
||||
| 4 | Client-Side Data Fetching | MEDIUM-HIGH | `client-` |
|
||||
| 5 | Re-render Optimization | MEDIUM | `rerender-` |
|
||||
| 6 | Rendering Performance | MEDIUM | `rendering-` |
|
||||
| 7 | JavaScript Performance | LOW-MEDIUM | `js-` |
|
||||
| 8 | Advanced Patterns | LOW | `advanced-` |
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### 1. Eliminating Waterfalls (CRITICAL)
|
||||
|
||||
- `async-defer-await` - Move await into branches where actually used
|
||||
- `async-parallel` - Use Promise.all() for independent operations
|
||||
- `async-dependencies` - Use better-all for partial dependencies
|
||||
- `async-api-routes` - Start promises early, await late in API routes
|
||||
- `async-suspense-boundaries` - Use Suspense to stream content
|
||||
|
||||
### 2. Bundle Size Optimization (CRITICAL)
|
||||
|
||||
- `bundle-barrel-imports` - Import directly, avoid barrel files
|
||||
- `bundle-dynamic-imports` - Use next/dynamic for heavy components
|
||||
- `bundle-defer-third-party` - Load analytics/logging after hydration
|
||||
- `bundle-conditional` - Load modules only when feature is activated
|
||||
- `bundle-preload` - Preload on hover/focus for perceived speed
|
||||
|
||||
### 3. Server-Side Performance (HIGH)
|
||||
|
||||
- `server-cache-react` - Use React.cache() for per-request deduplication
|
||||
- `server-cache-lru` - Use LRU cache for cross-request caching
|
||||
- `server-serialization` - Minimize data passed to client components
|
||||
- `server-parallel-fetching` - Restructure components to parallelize fetches
|
||||
- `server-after-nonblocking` - Use after() for non-blocking operations
|
||||
|
||||
### 4. Client-Side Data Fetching (MEDIUM-HIGH)
|
||||
|
||||
- `client-swr-dedup` - Use SWR for automatic request deduplication
|
||||
- `client-event-listeners` - Deduplicate global event listeners
|
||||
|
||||
### 5. Re-render Optimization (MEDIUM)
|
||||
|
||||
- `rerender-defer-reads` - Don't subscribe to state only used in callbacks
|
||||
- `rerender-memo` - Extract expensive work into memoized components
|
||||
- `rerender-dependencies` - Use primitive dependencies in effects
|
||||
- `rerender-derived-state` - Subscribe to derived booleans, not raw values
|
||||
- `rerender-functional-setstate` - Use functional setState for stable callbacks
|
||||
- `rerender-lazy-state-init` - Pass function to useState for expensive values
|
||||
- `rerender-transitions` - Use startTransition for non-urgent updates
|
||||
|
||||
### 6. Rendering Performance (MEDIUM)
|
||||
|
||||
- `rendering-animate-svg-wrapper` - Animate div wrapper, not SVG element
|
||||
- `rendering-content-visibility` - Use content-visibility for long lists
|
||||
- `rendering-hoist-jsx` - Extract static JSX outside components
|
||||
- `rendering-svg-precision` - Reduce SVG coordinate precision
|
||||
- `rendering-hydration-no-flicker` - Use inline script for client-only data
|
||||
- `rendering-activity` - Use Activity component for show/hide
|
||||
- `rendering-conditional-render` - Use ternary, not && for conditionals
|
||||
|
||||
### 7. JavaScript Performance (LOW-MEDIUM)
|
||||
|
||||
- `js-batch-dom-css` - Group CSS changes via classes or cssText
|
||||
- `js-index-maps` - Build Map for repeated lookups
|
||||
- `js-cache-property-access` - Cache object properties in loops
|
||||
- `js-cache-function-results` - Cache function results in module-level Map
|
||||
- `js-cache-storage` - Cache localStorage/sessionStorage reads
|
||||
- `js-combine-iterations` - Combine multiple filter/map into one loop
|
||||
- `js-length-check-first` - Check array length before expensive comparison
|
||||
- `js-early-exit` - Return early from functions
|
||||
- `js-hoist-regexp` - Hoist RegExp creation outside loops
|
||||
- `js-min-max-loop` - Use loop for min/max instead of sort
|
||||
- `js-set-map-lookups` - Use Set/Map for O(1) lookups
|
||||
- `js-tosorted-immutable` - Use toSorted() for immutability
|
||||
|
||||
### 8. Advanced Patterns (LOW)
|
||||
|
||||
- `advanced-event-handler-refs` - Store event handlers in refs
|
||||
- `advanced-use-latest` - useLatest for stable callback refs
|
||||
|
||||
## How to Use
|
||||
|
||||
Read individual rule files for detailed explanations and code examples:
|
||||
|
||||
```
|
||||
rules/async-parallel.md
|
||||
rules/bundle-barrel-imports.md
|
||||
rules/_sections.md
|
||||
```
|
||||
|
||||
Each rule file contains:
|
||||
- Brief explanation of why it matters
|
||||
- Incorrect code example with explanation
|
||||
- Correct code example with explanation
|
||||
- Additional context and references
|
||||
|
||||
## Full Compiled Document
|
||||
|
||||
For the complete guide with all rules expanded: `AGENTS.md`
|
||||
Reference in New Issue
Block a user