From fa9cd03ee550d9c1c98acfd81ffa90eac38c97f1 Mon Sep 17 00:00:00 2001 From: Dylan Burkey Date: Sun, 22 Feb 2026 19:34:40 -0500 Subject: [PATCH 1/5] feat: add multi-model support for Claude, OpenAI, and Gemini New features: - .claude/config/models.yml - Configure multiple AI providers - Cross-validation for planning (Gemini reviews Claude's plans) - Cross-validation for code review (GPT-4 reviews Claude's code) - Cost optimization (use cheaper models for simple tasks) - Fallback chain if primary model fails - Per-agent model configuration Updated agents: - planner-agent.md - Added multi-model cross-validation docs - review-agent.md - Added cross-validation review process New documentation: - docs/guides/multi-model-setup.md - Complete setup guide Updated README with Multi-Model Support section (#6 Key Differentiator) --- .claude/agents/planner-agent.md | 53 +++++ .claude/agents/review-agent.md | 87 ++++++++ .claude/config.yml | 9 + .claude/config/models.yml | 186 +++++++++++++++++ README.md | 27 +++ docs/guides/multi-model-setup.md | 342 +++++++++++++++++++++++++++++++ 6 files changed, 704 insertions(+) create mode 100644 .claude/config/models.yml create mode 100644 docs/guides/multi-model-setup.md diff --git a/.claude/agents/planner-agent.md b/.claude/agents/planner-agent.md index 22450b0..4175930 100644 --- a/.claude/agents/planner-agent.md +++ b/.claude/agents/planner-agent.md @@ -169,6 +169,59 @@ Brief description of phase goals 4. **Appropriate Granularity**: Not too broad, not too detailed 5. **Realistic Sequencing**: Account for natural workflow +## Multi-Model Support + +The planner agent supports cross-validation with secondary models to get different perspectives on architecture decisions. + +### Configuration + +See `.claude/config/models.yml`: + +```yaml +agent_overrides: + planner: + primary: "claude-sonnet-4-20250514" + secondary: "gemini-2.5-pro" + cross_validate: true +``` + +### Cross-Validation Process + +When cross-validation is enabled: + +1. Primary model (Claude) generates the plan +2. Secondary model (Gemini/GPT-4) reviews the plan +3. Differences are highlighted for user review +4. User makes final decisions on conflicts + +### When to Use Cross-Validation + +**Recommended for:** +- Major architecture decisions +- Database schema design +- API structure planning +- Security-sensitive features + +**Optional for:** +- Simple feature planning +- Bug fix planning +- Documentation tasks + +### Disabling Cross-Validation + +For a single run: +``` +/project-planner --no-cross-validate +``` + +Permanently: +```yaml +# .claude/config/models.yml +agent_overrides: + planner: + cross_validate: false +``` + ## Communication Reports to: Orchestrator agent Triggers: dev-agent, test-agent, docs-agent diff --git a/.claude/agents/review-agent.md b/.claude/agents/review-agent.md index 07930b6..4ae2365 100644 --- a/.claude/agents/review-agent.md +++ b/.claude/agents/review-agent.md @@ -251,3 +251,90 @@ When complete, report: ### Status: {{Complete}} ``` + +## Multi-Model Cross-Validation + +The review agent supports cross-validation where a secondary model independently reviews the same code, catching issues that a single model might miss. + +### Configuration + +See `.claude/config/models.yml`: + +```yaml +agent_overrides: + review: + primary: "claude-sonnet-4-20250514" + secondary: "gpt-4o" + cross_validate: true +``` + +### Cross-Validation Process + +When enabled: + +1. **Primary Review** - Claude reviews the code +2. **Secondary Review** - GPT-4/Gemini independently reviews +3. **Comparison** - Findings are deduplicated and merged +4. **Conflict Highlighting** - Disagreements shown to user + +### Output with Cross-Validation + +```markdown +## Cross-Validated Review + +### Primary (Claude Sonnet 4) +- Found 3 issues +- Security: ✅ Passed +- Accessibility: ⚠️ 1 issue + +### Secondary (GPT-4o) +- Found 4 issues +- Security: ⚠️ 1 issue (XSS risk) +- Accessibility: ⚠️ 2 issues + +### Merged Findings (deduplicated) +| # | Issue | Found By | Severity | +|---|-------|----------|----------| +| 1 | XSS vulnerability | GPT-4 | Critical | +| 2 | Missing ARIA label | Both | Major | +| 3 | Focus trap missing | GPT-4 | Major | +| 4 | Consider memoization | Claude | Minor | + +### Disagreements +- Claude: Security passed +- GPT-4: Found potential XSS +→ Human review recommended for security concern +``` + +### When Cross-Validation Triggers + +By default: +- **Security-sensitive code** - Always +- **High complexity** - When cyclomatic complexity > 10 +- **On request** - When `--cross-validate` flag used + +### Requesting Cross-Validation + +```bash +# Single file +/review --cross-validate src/auth.ts + +# Always for security +# Configure in models.yml: +cross_validation: + triggers: + review: + on_security: true +``` + +### Disabling Cross-Validation + +```bash +# Single run +/review --no-cross-validate src/utils.ts + +# Permanently - edit models.yml +agent_overrides: + review: + cross_validate: false +``` diff --git a/.claude/config.yml b/.claude/config.yml index e001401..2f0c1a2 100644 --- a/.claude/config.yml +++ b/.claude/config.yml @@ -116,6 +116,15 @@ git: merge_strategy: "auto" # auto | manual | squash require_review: false # Require review-agent before merge +# Multi-model configuration +# Supports Claude, OpenAI, and Gemini for cross-validation and specialization +models: + enabled: true + config_file: ".claude/config/models.yml" + cross_validation: + enabled: true + tasks: ["planning", "review"] # Tasks that get second opinions + # Default MCP servers (always enabled) mcp: required: diff --git a/.claude/config/models.yml b/.claude/config/models.yml new file mode 100644 index 0000000..9b63ec1 --- /dev/null +++ b/.claude/config/models.yml @@ -0,0 +1,186 @@ +# Multi-Model Configuration +# Configure multiple AI providers for different tasks +# +# Use Cases: +# - Cross-validation: Have different models review each other's work +# - Cost optimization: Use cheaper models for simpler tasks +# - Specialization: Use models that excel at specific tasks +# - Redundancy: Fallback to alternative providers if one is down + +# Available model providers +providers: + anthropic: + enabled: true + env_key: "ANTHROPIC_API_KEY" + models: + - id: "claude-sonnet-4-20250514" + name: "Claude Sonnet 4" + context: 200000 + strengths: ["coding", "analysis", "reasoning"] + cost_tier: "medium" + - id: "claude-opus-4-20250514" + name: "Claude Opus 4" + context: 200000 + strengths: ["complex-reasoning", "nuanced-writing", "deep-analysis"] + cost_tier: "high" + + openai: + enabled: true # Set to true if OPENAI_API_KEY is available + env_key: "OPENAI_API_KEY" + models: + - id: "gpt-4o" + name: "GPT-4o" + context: 128000 + strengths: ["general", "speed", "multimodal"] + cost_tier: "medium" + - id: "gpt-4-turbo" + name: "GPT-4 Turbo" + context: 128000 + strengths: ["coding", "instruction-following"] + cost_tier: "medium" + - id: "o1" + name: "o1" + context: 200000 + strengths: ["reasoning", "math", "complex-problems"] + cost_tier: "high" + + google: + enabled: true # Set to true if GOOGLE_API_KEY is available + env_key: "GOOGLE_API_KEY" + models: + - id: "gemini-2.0-flash" + name: "Gemini 2.0 Flash" + context: 1000000 + strengths: ["speed", "large-context", "multimodal"] + cost_tier: "low" + - id: "gemini-2.5-pro" + name: "Gemini 2.5 Pro" + context: 2000000 + strengths: ["reasoning", "coding", "large-context"] + cost_tier: "medium" + +# Default model assignments per task type +defaults: + # Primary model for each task type + primary: + planning: "claude-sonnet-4-20250514" + development: "claude-sonnet-4-20250514" + review: "claude-sonnet-4-20250514" + testing: "claude-sonnet-4-20250514" + documentation: "claude-sonnet-4-20250514" + + # Secondary model for cross-validation (optional) + # Set to null to disable cross-validation + secondary: + planning: "gemini-2.5-pro" # Different perspective on architecture + review: "gpt-4o" # Independent code review + testing: null # No cross-validation for tests + documentation: null # No cross-validation for docs + +# Cross-validation configuration +cross_validation: + enabled: true + + # When to use cross-validation + triggers: + planning: + always: true # Always get second opinion on plans + description: "Architecture decisions benefit from multiple perspectives" + + review: + on_complexity: "high" # Only for complex code reviews + on_security: true # Always for security-sensitive code + on_request: true # When explicitly requested + description: "Critical code benefits from independent review" + + development: + on_request: true # Only when explicitly requested + description: "Optional second opinion on implementation" + + # How to handle disagreements + conflict_resolution: + strategy: "human" # human | primary | vote | merge + notify: true # Notify user of disagreements + + # Output format for cross-validation + output: + show_both: true # Show both model responses + highlight_differences: true # Highlight where models disagree + summary: true # Generate summary of consensus/conflicts + +# Agent-specific model overrides +# Override the default model for specific agents +agent_overrides: + planner: + primary: "claude-sonnet-4-20250514" + secondary: "gemini-2.5-pro" + cross_validate: true + + review: + primary: "claude-sonnet-4-20250514" + secondary: "gpt-4o" + cross_validate: true + + dev: + primary: "claude-sonnet-4-20250514" + secondary: null + cross_validate: false + + test: + primary: "claude-sonnet-4-20250514" + secondary: null + cross_validate: false + + docs: + primary: "gemini-2.0-flash" # Fast model for docs + secondary: null + cross_validate: false + +# Cost optimization settings +cost_optimization: + enabled: true + + # Use cheaper models for these tasks + use_budget_model: + - "simple-refactoring" + - "documentation-updates" + - "code-formatting" + - "simple-tests" + + budget_model: "gemini-2.0-flash" + + # Always use premium model for these tasks + use_premium_model: + - "architecture-decisions" + - "security-reviews" + - "complex-algorithms" + - "api-design" + + premium_model: "claude-opus-4-20250514" + +# Fallback chain if primary model fails +fallback: + enabled: true + chain: + - "claude-sonnet-4-20250514" + - "gpt-4o" + - "gemini-2.5-pro" + max_retries: 2 + retry_delay_ms: 1000 + +# Model-specific prompting adjustments +prompt_adjustments: + openai: + # OpenAI models prefer explicit JSON formatting + prefer_json_mode: true + system_prompt_style: "concise" + + google: + # Gemini handles large contexts well + include_full_context: true + system_prompt_style: "detailed" + + anthropic: + # Claude excels with examples + include_examples: true + system_prompt_style: "balanced" diff --git a/README.md b/README.md index 7dfa91b..81be12e 100644 --- a/README.md +++ b/README.md @@ -193,6 +193,33 @@ requirements first with EARS notation Clear, testable, unambiguous requirements that become your implementation roadmap. +### 6. Multi-Model Support + +**Others:** Locked into a single AI provider +**Sidekick:** Use Claude, GPT-4, and Gemini together + +```yaml +# .claude/config/models.yml +agent_overrides: + planner: + primary: "claude-sonnet-4-20250514" + secondary: "gemini-2.5-pro" # Second opinion on architecture + cross_validate: true + + review: + primary: "claude-sonnet-4-20250514" + secondary: "gpt-4o" # Independent code review + cross_validate: true +``` + +**Cross-Validation Benefits:** +- Different models catch different issues +- Architecture decisions get multiple perspectives +- Security reviews are more thorough +- Cost optimization (use cheaper models for simple tasks) + +[View Multi-Model Setup Guide →](docs/guides/multi-model-setup.md) + --- ## Comparison diff --git a/docs/guides/multi-model-setup.md b/docs/guides/multi-model-setup.md new file mode 100644 index 0000000..0389a88 --- /dev/null +++ b/docs/guides/multi-model-setup.md @@ -0,0 +1,342 @@ +# Multi-Model Setup Guide + +> Use Claude, GPT-4, and Gemini together for better results + +Claude Code Sidekick supports multiple AI providers. This guide shows you how to configure and use them together for cross-validation, cost optimization, and specialized tasks. + +--- + +## Why Use Multiple Models? + +### 1. Cross-Validation + +Different models have different strengths. Getting a second opinion can catch issues: + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ │ +│ Claude plans architecture │ +│ ↓ │ +│ Gemini reviews the plan │ +│ ↓ │ +│ Differences are highlighted │ +│ ↓ │ +│ You make the final decision │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### 2. Independent Code Review + +Have one model write code, another review it: + +``` +Claude writes code → GPT-4 reviews it → Issues caught early +``` + +### 3. Cost Optimization + +Use cheaper/faster models for simple tasks: + +| Task | Model | Why | +|------|-------|-----| +| Documentation | Gemini Flash | Fast, cheap, good enough | +| Architecture | Claude Opus | Complex reasoning needed | +| Code review | GPT-4o | Independent perspective | +| Simple refactoring | Gemini Flash | Cost-effective | + +--- + +## Setup + +### Step 1: Get API Keys + +You need API keys from the providers you want to use: + +| Provider | Get Key From | Env Variable | +|----------|--------------|--------------| +| Anthropic | [console.anthropic.com](https://console.anthropic.com) | `ANTHROPIC_API_KEY` | +| OpenAI | [platform.openai.com](https://platform.openai.com) | `OPENAI_API_KEY` | +| Google | [aistudio.google.com](https://aistudio.google.com) | `GOOGLE_API_KEY` | + +### Step 2: Set Environment Variables + +```bash +# Add to ~/.bashrc, ~/.zshrc, or .env +export ANTHROPIC_API_KEY="sk-ant-..." +export OPENAI_API_KEY="sk-..." +export GOOGLE_API_KEY="AIza..." +``` + +### Step 3: Configure Models + +Edit `.claude/config/models.yml`: + +```yaml +providers: + anthropic: + enabled: true + openai: + enabled: true # ← Enable if you have the key + google: + enabled: true # ← Enable if you have the key +``` + +--- + +## Configuration + +### Basic: Default Models Per Task + +```yaml +# .claude/config/models.yml + +defaults: + primary: + planning: "claude-sonnet-4-20250514" + development: "claude-sonnet-4-20250514" + review: "claude-sonnet-4-20250514" +``` + +### Cross-Validation: Second Opinion + +```yaml +defaults: + secondary: + planning: "gemini-2.5-pro" # Gemini reviews Claude's plans + review: "gpt-4o" # GPT-4 reviews Claude's code +``` + +### Per-Agent Configuration + +```yaml +agent_overrides: + planner: + primary: "claude-sonnet-4-20250514" + secondary: "gemini-2.5-pro" + cross_validate: true # ← Enable cross-validation + + review: + primary: "gpt-4o" # ← Use GPT-4 as primary reviewer + secondary: "claude-sonnet-4-20250514" + cross_validate: true +``` + +--- + +## Usage + +### Planning with Cross-Validation + +When you run `/project-planner` with cross-validation enabled: + +``` +> /project-planner + +┌──────────────────────────────────────────────────────────────────┐ +│ PROJECT PLANNER │ +├──────────────────────────────────────────────────────────────────┤ +│ │ +│ Primary Model: Claude Sonnet 4 │ +│ ▶ Analyzing PROJECT_STARTER.md... │ +│ ▶ Generating project plan... │ +│ ✅ Plan generated │ +│ │ +│ Cross-Validation: Gemini 2.5 Pro │ +│ ▶ Reviewing plan... │ +│ ✅ Review complete │ +│ │ +│ ┌────────────────────────────────────────────────────────────┐ │ +│ │ 📊 CROSS-VALIDATION RESULTS │ │ +│ ├────────────────────────────────────────────────────────────┤ │ +│ │ │ │ +│ │ ✅ Agreement: 8/10 decisions │ │ +│ │ │ │ +│ │ ⚠️ Differences: │ │ +│ │ │ │ +│ │ 1. Database Choice │ │ +│ │ Claude: SQLite for simplicity │ │ +│ │ Gemini: PostgreSQL for scalability │ │ +│ │ │ │ +│ │ 2. Auth Approach │ │ +│ │ Claude: Session-based │ │ +│ │ Gemini: JWT tokens │ │ +│ │ │ │ +│ │ → Review differences and choose your approach │ │ +│ │ │ │ +│ └────────────────────────────────────────────────────────────┘ │ +│ │ +└──────────────────────────────────────────────────────────────────┘ +``` + +### Code Review with Second Opinion + +``` +> /review src/components/Auth.tsx + +┌──────────────────────────────────────────────────────────────────┐ +│ CODE REVIEW │ +├──────────────────────────────────────────────────────────────────┤ +│ │ +│ Primary Review: Claude Sonnet 4 │ +│ ├─ Security: ✅ No issues found │ +│ ├─ Performance: ⚠️ Consider memoization │ +│ └─ Accessibility: ✅ ARIA labels present │ +│ │ +│ Secondary Review: GPT-4o │ +│ ├─ Security: ⚠️ Token stored in localStorage (XSS risk) │ +│ ├─ Performance: ✅ Looks good │ +│ └─ Accessibility: ⚠️ Missing focus management │ +│ │ +│ ┌────────────────────────────────────────────────────────────┐ │ +│ │ Combined Issues (deduplicated): │ │ +│ │ │ │ +│ │ 1. [HIGH] Token in localStorage - XSS risk (GPT-4) │ │ +│ │ 2. [MED] Add React.memo for performance (Claude) │ │ +│ │ 3. [MED] Add focus management on modal (GPT-4) │ │ +│ └────────────────────────────────────────────────────────────┘ │ +│ │ +└──────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Best Practices + +### 1. Use Cross-Validation for Important Decisions + +Enable for: +- Architecture planning +- Security-sensitive code +- API design +- Database schema + +Skip for: +- Simple bug fixes +- Documentation updates +- Formatting changes + +### 2. Match Model to Task + +| Model | Best For | +|-------|----------| +| Claude Opus | Complex reasoning, nuanced decisions | +| Claude Sonnet | General development, balanced | +| GPT-4o | Fast iteration, multimodal | +| GPT-4 Turbo | Instruction following | +| o1 | Math, algorithms, complex logic | +| Gemini Flash | Speed, large contexts, docs | +| Gemini Pro | Balanced, large codebase analysis | + +### 3. Cost-Conscious Configuration + +```yaml +cost_optimization: + enabled: true + + # Cheap model for simple stuff + use_budget_model: + - "documentation-updates" + - "code-formatting" + - "simple-tests" + budget_model: "gemini-2.0-flash" + + # Premium model only when needed + use_premium_model: + - "architecture-decisions" + - "security-reviews" + premium_model: "claude-opus-4-20250514" +``` + +--- + +## Commands + +### Check Available Models + +```bash +/models status +``` + +Output: +``` +Available Models: + +✅ Anthropic (ANTHROPIC_API_KEY set) + - claude-sonnet-4-20250514 + - claude-opus-4-20250514 + +✅ OpenAI (OPENAI_API_KEY set) + - gpt-4o + - gpt-4-turbo + - o1 + +❌ Google (GOOGLE_API_KEY not set) + - gemini-2.0-flash (unavailable) + - gemini-2.5-pro (unavailable) +``` + +### Switch Primary Model + +```bash +/models set-primary planning gemini-2.5-pro +``` + +### Enable/Disable Cross-Validation + +```bash +/models cross-validate on +/models cross-validate off +``` + +### One-Time Second Opinion + +```bash +/review --cross-validate src/auth.ts +``` + +--- + +## Troubleshooting + +### "API key not found" + +Check your environment: +```bash +echo $OPENAI_API_KEY +echo $GOOGLE_API_KEY +``` + +If empty, set them and restart your terminal. + +### "Model not available" + +The model ID may have changed. Check provider documentation for current model IDs. + +### "Cross-validation taking too long" + +Disable for non-critical tasks: +```yaml +cross_validation: + triggers: + planning: + always: false + on_request: true # Only when you ask +``` + +--- + +## Security Notes + +- API keys are never logged or committed +- Cross-validation sends code to multiple providers +- Review `.claude/config/models.yml` before enabling providers +- For sensitive code, limit to trusted providers only + +--- + +## Related + +- [Getting Started Tutorial](./getting-started-tutorial.md) +- [Agent Configuration](../.claude/agents.yml) +- [Model Configuration](../.claude/config/models.yml) From 6a5ec7b62c222ca7a9d6fffe968c6f75409cc802 Mon Sep 17 00:00:00 2001 From: Dylan Burkey Date: Mon, 23 Feb 2026 13:58:39 -0500 Subject: [PATCH 2/5] feat: Add multi-model AI toolkit - Add tools/multi-model/ with consensus code review, intelligent routing, and semantic search - Support for OpenAI (GPT-4o), Anthropic (Claude), and Google Gemini - CLI tools: mm-review, mm-index, mm-search - Examples: pre-commit hook, agent integration - Update README.md with multi-model documentation - Update CLAUDE.md with toolkit usage guide --- CLAUDE.md | 74 + README.md | 69 +- tools/multi-model/README.md | 275 +++ tools/multi-model/bin/index-codebase.js | 53 + tools/multi-model/bin/review.js | 77 + tools/multi-model/bin/search.js | 57 + .../multi-model/examples/agent-integration.js | 145 ++ tools/multi-model/examples/pre-commit-hook.js | 92 + tools/multi-model/index.js | 59 + tools/multi-model/lib/clients.js | 160 ++ tools/multi-model/lib/code-review.js | 231 +++ tools/multi-model/lib/embeddings.js | 310 +++ tools/multi-model/lib/model-router.js | 260 +++ tools/multi-model/package.json | 35 + tools/multi-model/pnpm-lock.yaml | 1657 +++++++++++++++++ 15 files changed, 3538 insertions(+), 16 deletions(-) create mode 100644 tools/multi-model/README.md create mode 100755 tools/multi-model/bin/index-codebase.js create mode 100755 tools/multi-model/bin/review.js create mode 100755 tools/multi-model/bin/search.js create mode 100644 tools/multi-model/examples/agent-integration.js create mode 100644 tools/multi-model/examples/pre-commit-hook.js create mode 100644 tools/multi-model/index.js create mode 100644 tools/multi-model/lib/clients.js create mode 100644 tools/multi-model/lib/code-review.js create mode 100644 tools/multi-model/lib/embeddings.js create mode 100644 tools/multi-model/lib/model-router.js create mode 100644 tools/multi-model/package.json create mode 100644 tools/multi-model/pnpm-lock.yaml diff --git a/CLAUDE.md b/CLAUDE.md index 0824f99..fe76de7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -88,6 +88,80 @@ These MCP servers are enabled by default: | `chrome-devtools` | Browser testing, accessibility audits | | `context7` | Documentation lookup, best practices | +## Multi-Model AI Toolkit + +The project includes a powerful multi-model toolkit at `tools/multi-model/` that leverages OpenAI, Anthropic, and Google Gemini together. + +### Available Tools + +| CLI Command | Purpose | Documentation | +|-------------|---------|---------------| +| `mm-review` | Consensus code review (multiple models) | [View](tools/multi-model/README.md#multi-model-code-review) | +| `mm-index` | Index codebase for semantic search | [View](tools/multi-model/README.md#codebase-indexing) | +| `mm-search` | Search code by meaning, not keywords | [View](tools/multi-model/README.md#semantic-search) | + +### Quick Start + +```bash +cd tools/multi-model +pnpm install + +# Review code with multiple AI models +pnpm review -- ../cli/src/scaffold.js --deep + +# Index the codebase +pnpm index -- ../ + +# Search semantically +pnpm search -- "project scaffolding" +``` + +### Programmatic Usage + +```javascript +import { reviewCode, createRouter, searchCodebase } from './tools/multi-model/index.js'; + +// Consensus code review +const results = await reviewCode(code, { filename: 'app.js' }); +console.log(results.confirmedIssues); // Issues 2+ models agree on + +// Intelligent routing (auto-selects best model per task) +const router = createRouter('balanced'); +const response = await router.route('Explain this architecture...'); + +// Semantic search +const matches = await searchCodebase('authentication logic', { + indexPath: '.code-index/index.json' +}); +``` + +### Model Routing Logic + +The router automatically selects the optimal model based on task type: + +| Task Type | Optimal Model | Reason | +|-----------|---------------|--------| +| Long context (>50k chars) | Claude Sonnet | 200k context window | +| Code generation | GPT-4o | Mature function calling | +| Documentation | Claude Sonnet | Nuanced, thorough | +| Security review | Claude Sonnet | Careful reasoning | +| Quick refactors | GPT-4o-mini | Fast, accurate | +| Linting/style | Gemini Flash | Cheapest | + +### Examples + +- [Pre-Commit Hook](tools/multi-model/examples/pre-commit-hook.js) - Block commits with critical issues +- [Agent Integration](tools/multi-model/examples/agent-integration.js) - Smart assistant workflows + +### Required Environment Variables + +```bash +# In .env at project root +OPENAI_API_KEY=sk-... +ANTHROPIC_API_KEY=sk-ant-... +GEMINI_API_KEY=... +``` + ### Commands | Command | Purpose | Output | diff --git a/README.md b/README.md index 81be12e..d35345a 100644 --- a/README.md +++ b/README.md @@ -193,32 +193,37 @@ requirements first with EARS notation Clear, testable, unambiguous requirements that become your implementation roadmap. -### 6. Multi-Model Support +### 6. Multi-Model AI Toolkit **Others:** Locked into a single AI provider -**Sidekick:** Use Claude, GPT-4, and Gemini together - -```yaml -# .claude/config/models.yml -agent_overrides: - planner: - primary: "claude-sonnet-4-20250514" - secondary: "gemini-2.5-pro" # Second opinion on architecture - cross_validate: true - - review: - primary: "claude-sonnet-4-20250514" - secondary: "gpt-4o" # Independent code review - cross_validate: true +**Sidekick:** Use Claude, GPT-4, and Gemini together with intelligent routing + +```bash +# Consensus code review (multiple models must agree) +cd tools/multi-model +pnpm review -- src/app.js --deep + +# Semantic code search +pnpm index -- /path/to/project +pnpm search -- "authentication middleware" ``` +**Built-in Multi-Model Tools:** + +| Tool | Purpose | Models Used | +|------|---------|-------------| +| `mm-review` | Consensus code review | GPT-4o + Claude + Gemini | +| `mm-index` | Codebase indexing | OpenAI Embeddings | +| `mm-search` | Semantic search | OpenAI Embeddings | +| `ModelRouter` | Intelligent task routing | Auto-selects optimal model | + **Cross-Validation Benefits:** - Different models catch different issues - Architecture decisions get multiple perspectives - Security reviews are more thorough - Cost optimization (use cheaper models for simple tasks) -[View Multi-Model Setup Guide →](docs/guides/multi-model-setup.md) +[View Multi-Model Toolkit →](tools/multi-model/README.md) --- @@ -333,6 +338,29 @@ agent-library/ └── templates/ # Create custom agents ``` +### Multi-Model Toolkit + +``` +tools/multi-model/ +├── bin/ +│ ├── review.js # mm-review CLI - consensus code review +│ ├── index-codebase.js # mm-index CLI - codebase indexing +│ └── search.js # mm-search CLI - semantic search +├── lib/ +│ ├── clients.js # Unified API for OpenAI, Anthropic, Gemini +│ ├── code-review.js # Multi-model consensus review system +│ ├── model-router.js # Intelligent task routing +│ └── embeddings.js # Codebase indexing & semantic search +├── examples/ +│ ├── pre-commit-hook.js # Git hook integration example +│ └── agent-integration.js # Claude Code workflow example +├── index.js # Main exports +├── package.json +└── README.md # Full documentation +``` + +[View Multi-Model Documentation →](tools/multi-model/README.md) + --- ## Documentation @@ -363,6 +391,15 @@ agent-library/ - [Hooks Configuration](.claude/hooks/README.md) - Automation hooks - [Agent Library](agent-library/README.md) - All available agents +### Multi-Model AI Tools + +- [Multi-Model Toolkit Overview](tools/multi-model/README.md) - Full documentation +- [Consensus Code Review](tools/multi-model/README.md#multi-model-code-review) - Run code through multiple AI models +- [Intelligent Model Routing](tools/multi-model/README.md#intelligent-model-routing) - Auto-select optimal model per task +- [Semantic Code Search](tools/multi-model/README.md#semantic-code-search) - Index and search codebase by meaning +- [Pre-Commit Hook Example](tools/multi-model/examples/pre-commit-hook.js) - CI/CD integration +- [Agent Integration Example](tools/multi-model/examples/agent-integration.js) - Claude Code workflows + ### Advanced - [Creating Custom Agents](agent-library/templates/README.md) diff --git a/tools/multi-model/README.md b/tools/multi-model/README.md new file mode 100644 index 0000000..6a891bb --- /dev/null +++ b/tools/multi-model/README.md @@ -0,0 +1,275 @@ +# Multi-Model AI Toolkit + +> Leverage OpenAI, Anthropic, and Google Gemini together for superior code quality. + +**Part of [Claude Code Sidekick](../../README.md)** + +--- + +## Features + +- **🔍 Consensus Code Review** - Run code through multiple models, find issues all agree on +- **🎯 Intelligent Routing** - Automatically route tasks to the optimal model +- **🔎 Semantic Search** - Index your codebase and search by meaning, not keywords +- **💰 Cost Optimization** - Use cheap models for simple tasks, reserve power for complex ones + +## File Structure + +``` +tools/multi-model/ +├── bin/ +│ ├── review.js # mm-review CLI +│ ├── index-codebase.js # mm-index CLI +│ └── search.js # mm-search CLI +├── lib/ +│ ├── clients.js # Unified API for all 3 providers +│ ├── code-review.js # Consensus review system +│ ├── model-router.js # Intelligent task routing +│ └── embeddings.js # Codebase indexing & search +├── examples/ +│ ├── pre-commit-hook.js # Git hook integration +│ └── agent-integration.js # Claude Code workflows +├── index.js # Main exports +├── package.json +└── README.md +``` + +## Quick Start + +```bash +# Install dependencies +cd tools/multi-model +pnpm install + +# Set up your API keys in .env (root of claude-code-sidekick) +OPENAI_API_KEY=sk-... +ANTHROPIC_API_KEY=sk-ant-... +GEMINI_API_KEY=... +``` + +## CLI Tools + +### Multi-Model Code Review + +```bash +# Quick review (Gemini Flash + GPT-4o-mini) +pnpm review -- src/app.js --quick + +# Deep review (GPT-4o + Claude Sonnet + Gemini Pro) +pnpm review -- src/app.js --deep + +# Custom models +pnpm review -- src/app.js --models "gpt-4o,claude-3-5-sonnet-20241022" + +# Output as JSON (for CI integration) +pnpm review -- src/app.js --json +``` + +### Codebase Indexing + +```bash +# Index current directory +pnpm index + +# Index specific directory +pnpm index -- /path/to/project + +# With options +pnpm index -- . --verbose --extensions ".ts,.tsx" +``` + +### Semantic Search + +```bash +# Search your codebase +pnpm search -- "authentication middleware" + +# More results, lower threshold +pnpm search -- "error handling" --top 20 --similarity 0.4 + +# JSON output +pnpm search -- "database connection" --json +``` + +## Programmatic Usage + +### Code Review + +```javascript +import { reviewCode, quickReview, deepReview } from '@claude-sidekick/multi-model'; + +// Basic review (3 models, consensus required) +const results = await reviewCode(code, { + filename: 'auth.js', + consensusThreshold: 2, // 2+ models must agree +}); + +console.log(results.confirmedIssues); // Issues multiple models found +console.log(results.possibleIssues); // Issues only one model found + +// Quick review for CI +const quick = await quickReview(code, 'app.js'); + +// Deep review for important changes +const deep = await deepReview(code, 'payment.js'); +``` + +### Intelligent Model Routing + +```javascript +import { createRouter, ModelRouter } from '@claude-sidekick/multi-model'; + +// Use a preset profile +const router = createRouter('balanced'); // 'cost', 'speed', 'quality', 'balanced' + +// Tasks are automatically routed to optimal models +const result = await router.route('Explain the architecture of this codebase...'); +console.log(result.model); // e.g., 'claude-3-5-sonnet-20241022' +console.log(result.taskType); // e.g., 'architecture' +console.log(result.routing); // 'Claude excels at complex reasoning...' + +// Estimate costs +const cost = router.estimateCost('documentation', 5000, 2000); +console.log(cost.formatted); // '$0.0215' +``` + +### Semantic Code Search + +```javascript +import { indexCodebase, searchCodebase, findSimilarCode } from '@claude-sidekick/multi-model'; + +// Index a codebase (do this once, or on changes) +await indexCodebase('/path/to/project', { + extensions: ['.js', '.ts', '.tsx'], + verbose: true, +}); + +// Search for code by meaning +const results = await searchCodebase('user authentication logic', { + indexPath: '/path/to/project/.code-index/index.json', + topK: 10, + minSimilarity: 0.5, +}); + +// Find duplicate/similar code +const similar = await findSimilarCode(myCode, { + indexPath: '/path/to/project/.code-index/index.json', + threshold: 0.85, +}); +``` + +## Model Selection Guide + +| Task | Best Model | Why | +|------|------------|-----| +| Long file analysis | Claude Sonnet | 200k context window | +| Code generation | GPT-4o | Mature function calling | +| Quick refactors | GPT-4o-mini | Fast, accurate | +| Documentation | Claude Sonnet | Nuanced, thorough | +| Image analysis | Gemini Pro | Native multimodal | +| Security review | Claude Sonnet | Careful reasoning | +| Linting/style | Gemini Flash | Cheapest | + +## Cost Comparison (per 1M tokens) + +| Model | Input | Output | +|-------|-------|--------| +| Gemini Flash | $0.075 | $0.30 | +| GPT-4o-mini | $0.15 | $0.60 | +| Claude Haiku | $0.25 | $1.25 | +| Claude Sonnet | $3.00 | $15.00 | +| Gemini Pro | $3.50 | $10.50 | +| GPT-4o | $5.00 | $15.00 | + +## CI/CD Integration + +```yaml +# GitHub Actions example +- name: Multi-Model Code Review + run: | + cd tools/multi-model + pnpm review -- ${{ github.event.pull_request.changed_files }} --json > review.json + +- name: Fail on Critical Issues + run: | + if jq -e '.confirmedIssues[] | select(.severity == "critical")' review.json; then + echo "Critical issues found!" + exit 1 + fi +``` + +## Environment Variables + +```bash +# Required (at least one) +OPENAI_API_KEY=sk-... +ANTHROPIC_API_KEY=sk-ant-... +GEMINI_API_KEY=... # or GEMENI_API_KEY (typo-tolerant) + +# Optional +DEBUG=true # Enable debug logging +``` + +## Examples + +### Pre-Commit Hook + +Block commits that have critical/high severity issues detected by multiple models. + +📄 **[examples/pre-commit-hook.js](examples/pre-commit-hook.js)** + +```javascript +// Install in .husky/pre-commit or run directly +import { quickReview } from '../lib/code-review.js'; + +// Reviews staged files, blocks on critical issues +const results = await quickReview(code, filename); +if (results.confirmedIssues.some(i => i.severity === 'critical')) { + process.exit(1); // Block commit +} +``` + +### Agent Integration + +Smart assistant that routes tasks to optimal models and uses semantic search for context. + +📄 **[examples/agent-integration.js](examples/agent-integration.js)** + +```javascript +import { createRouter, searchCodebase } from '../index.js'; + +const router = createRouter('balanced'); + +// Search for relevant code context +const context = await searchCodebase('authentication', { indexPath }); + +// Route to optimal model based on task type +const result = await router.route(userRequest, { context }); +// → Automatically picks Claude for architecture, GPT-4 for code gen, etc. +``` + +## Supported Models + +### OpenAI +- `gpt-4o` - Most capable, best for complex tasks +- `gpt-4o-mini` - Fast and cheap, good for simple tasks + +### Anthropic +- `claude-sonnet-4-20250514` - Best reasoning, 200k context +- `claude-3-5-haiku-20241022` - Fast and cheap + +### Google +- `gemini-1.5-pro` - Multimodal, good reasoning +- `gemini-2.0-flash` - Very fast, very cheap + +## Related Documentation + +- [Claude Code Sidekick README](../../README.md) +- [CLAUDE.md - AI Context](../../CLAUDE.md) +- [Agent Library](../../agent-library/README.md) + +--- + +## License + +Proprietary - © 2026 Dylan Burkey diff --git a/tools/multi-model/bin/index-codebase.js b/tools/multi-model/bin/index-codebase.js new file mode 100755 index 0000000..2aae258 --- /dev/null +++ b/tools/multi-model/bin/index-codebase.js @@ -0,0 +1,53 @@ +#!/usr/bin/env node + +/** + * Codebase Indexing CLI + * Usage: mm-index [directory] [options] + */ + +import { program } from 'commander'; +import { indexCodebase } from '../lib/embeddings.js'; +import chalk from 'chalk'; + +program + .name('mm-index') + .description('Index a codebase for semantic search') + .argument('[directory]', 'Directory to index', '.') + .option('-o, --output ', 'Output directory for index') + .option('-e, --extensions ', 'File extensions to include (comma-separated)') + .option('-i, --ignore ', 'Additional ignore patterns (comma-separated)') + .option('-v, --verbose', 'Show detailed output') + .action(async (directory, options) => { + try { + const indexOptions = { + verbose: options.verbose, + }; + + if (options.output) { + indexOptions.outputDir = options.output; + } + + if (options.extensions) { + indexOptions.extensions = options.extensions.split(',').map((e) => + e.trim().startsWith('.') ? e.trim() : `.${e.trim()}` + ); + } + + if (options.ignore) { + indexOptions.ignore = [ + ...indexOptions.ignore || [], + ...options.ignore.split(',').map((p) => p.trim()), + ]; + } + + const index = await indexCodebase(directory, indexOptions); + + console.log(chalk.green(`\n✅ Indexed ${index.totalFiles} files (${index.totalChunks} chunks)`)); + console.log(chalk.dim(` Index saved to: ${directory}/.code-index/index.json`)); + } catch (error) { + console.error(chalk.red(`Error: ${error.message}`)); + process.exit(1); + } + }); + +program.parse(); diff --git a/tools/multi-model/bin/review.js b/tools/multi-model/bin/review.js new file mode 100755 index 0000000..2b84676 --- /dev/null +++ b/tools/multi-model/bin/review.js @@ -0,0 +1,77 @@ +#!/usr/bin/env node + +/** + * Multi-Model Code Review CLI + * Usage: mm-review [options] + */ + +import { program } from 'commander'; +import { readFileSync } from 'fs'; +import chalk from 'chalk'; +import { reviewCode, quickReview, deepReview, formatReviewResults } from '../lib/code-review.js'; +import { MODELS } from '../lib/clients.js'; + +program + .name('mm-review') + .description('Multi-model consensus code review') + .argument('', 'File to review') + .option('-q, --quick', 'Quick review (fast models only)') + .option('-d, --deep', 'Deep review (most capable models)') + .option('-m, --models ', 'Comma-separated list of models') + .option('-t, --threshold ', 'Consensus threshold (default: 2)', parseInt) + .option('-v, --verbose', 'Show detailed output') + .option('--json', 'Output as JSON') + .action(async (file, options) => { + try { + const code = readFileSync(file, 'utf-8'); + + let results; + + if (options.quick) { + results = await quickReview(code, file); + } else if (options.deep) { + results = await deepReview(code, file); + } else { + const reviewOptions = { + filename: file, + verbose: options.verbose, + }; + + if (options.models) { + reviewOptions.models = options.models.split(',').map((m) => m.trim()); + } + + if (options.threshold) { + reviewOptions.consensusThreshold = options.threshold; + } + + results = await reviewCode(code, reviewOptions); + } + + if (options.json) { + // Remove embeddings from output for cleaner JSON + const output = { + ...results, + reviews: results.reviews.map(({ model, issues, summary }) => ({ + model, + issues, + summary, + })), + }; + console.log(JSON.stringify(output, null, 2)); + } else { + console.log(formatReviewResults(results)); + } + + // Exit with error code if critical/high issues found + const hasCritical = results.confirmedIssues.some( + (i) => i.severity === 'critical' || i.severity === 'high' + ); + process.exit(hasCritical ? 1 : 0); + } catch (error) { + console.error(chalk.red(`Error: ${error.message}`)); + process.exit(1); + } + }); + +program.parse(); diff --git a/tools/multi-model/bin/search.js b/tools/multi-model/bin/search.js new file mode 100755 index 0000000..92530dd --- /dev/null +++ b/tools/multi-model/bin/search.js @@ -0,0 +1,57 @@ +#!/usr/bin/env node + +/** + * Codebase Search CLI + * Usage: mm-search [options] + */ + +import { program } from 'commander'; +import { searchCodebase, formatSearchResults, loadIndex } from '../lib/embeddings.js'; +import { join } from 'path'; +import chalk from 'chalk'; + +program + .name('mm-search') + .description('Semantic search across your codebase') + .argument('', 'Search query') + .option('-d, --directory ', 'Directory with index', '.') + .option('-k, --top ', 'Number of results', parseInt, 10) + .option('-s, --similarity ', 'Minimum similarity (0-1)', parseFloat, 0.5) + .option('--json', 'Output as JSON') + .action(async (query, options) => { + try { + const indexPath = join(options.directory, '.code-index', 'index.json'); + + const results = await searchCodebase(query, { + indexPath, + topK: options.top, + minSimilarity: options.similarity, + }); + + if (results.length === 0) { + console.log(chalk.yellow('\nNo matching results found.\n')); + console.log(chalk.dim('Try:')); + console.log(chalk.dim(' - Using different keywords')); + console.log(chalk.dim(' - Lowering the similarity threshold with -s 0.3')); + process.exit(0); + } + + if (options.json) { + // Remove embeddings from output + const output = results.map(({ embedding, ...rest }) => rest); + console.log(JSON.stringify(output, null, 2)); + } else { + console.log(chalk.blue(`\n📊 Found ${results.length} results:\n`)); + console.log(formatSearchResults(results)); + } + } catch (error) { + if (error.message.includes('Index not found')) { + console.error(chalk.red('\nNo index found. Run `mm-index` first to index your codebase.\n')); + } else { + console.error(chalk.red(`Error: ${error.message}`)); + } + process.exit(1); + } + }); + +program.parse(); diff --git a/tools/multi-model/examples/agent-integration.js b/tools/multi-model/examples/agent-integration.js new file mode 100644 index 0000000..7dca760 --- /dev/null +++ b/tools/multi-model/examples/agent-integration.js @@ -0,0 +1,145 @@ +/** + * Agent Integration Example + * + * Shows how to integrate multi-model routing into a Claude Code workflow + */ + +import { createRouter, searchCodebase, reviewCode, MODELS } from '../index.js'; + +// Create a balanced router (switches between cost/quality as needed) +const router = createRouter('balanced'); + +/** + * Example: Smart code assistant that uses the right model for each task + */ +async function smartAssistant(userRequest, codeContext = {}) { + const { currentFile, projectRoot } = codeContext; + + // 1. Search for relevant code context + let relevantCode = []; + if (projectRoot) { + try { + relevantCode = await searchCodebase(userRequest, { + indexPath: `${projectRoot}/.code-index/index.json`, + topK: 5, + }); + } catch (e) { + // Index might not exist, that's okay + } + } + + // 2. Build context-aware prompt + const contextBlock = relevantCode.length > 0 + ? `\nRelevant code from the codebase:\n${relevantCode.map((r) => + `--- ${r.filename} (lines ${r.lineStart}-${r.lineEnd}) ---\n${r.content}` + ).join('\n\n')}\n` + : ''; + + const prompt = `${userRequest}${contextBlock}`; + + // 3. Route to optimal model based on task type + const result = await router.route(prompt, { + context: { + contentLength: prompt.length, + }, + systemPrompt: `You are a senior software engineer. Be concise and actionable. +Current file: ${currentFile || 'unknown'}`, + }); + + return { + response: result.content, + model: result.model, + taskType: result.taskType, + reasoning: result.routing, + }; +} + +/** + * Example: PR Review workflow + */ +async function reviewPullRequest(changedFiles) { + const results = { + summary: '', + fileReviews: [], + criticalCount: 0, + highCount: 0, + }; + + for (const file of changedFiles) { + // Use quick review for small files, deep for large/important ones + const isImportant = + file.path.includes('auth') || + file.path.includes('payment') || + file.path.includes('security'); + + const review = isImportant + ? await reviewCode(file.content, { + filename: file.path, + models: [MODELS.GPT4O, MODELS.CLAUDE_SONNET, MODELS.GEMINI_PRO], + }) + : await reviewCode(file.content, { + filename: file.path, + models: [MODELS.GEMINI_FLASH, MODELS.GPT4O_MINI], + }); + + results.fileReviews.push({ + file: file.path, + issues: review.confirmedIssues, + summary: review.summary, + }); + + results.criticalCount += review.confirmedIssues.filter( + (i) => i.severity === 'critical' + ).length; + results.highCount += review.confirmedIssues.filter( + (i) => i.severity === 'high' + ).length; + } + + // Generate overall summary using Claude (best at synthesis) + const summaryPrompt = `Summarize this PR review in 2-3 sentences: +${JSON.stringify(results.fileReviews, null, 2)}`; + + const summaryResult = await router.route(summaryPrompt, { + taskType: 'documentation', + }); + + results.summary = summaryResult.content; + + return results; +} + +/** + * Example: Cost-aware batch processing + */ +async function batchProcess(tasks, budget = 1.0) { + const costRouter = createRouter('cost'); + const qualityRouter = createRouter('quality'); + + let spent = 0; + const results = []; + + for (const task of tasks) { + // Estimate cost with cheap model + const estimate = costRouter.estimateCost(task.type, task.tokens); + + // Use quality model if we have budget, otherwise cheap + const useQuality = spent + estimate.total * 10 < budget; // 10x safety margin + const router = useQuality ? qualityRouter : costRouter; + + const result = await router.route(task.prompt, { + taskType: task.type, + }); + + spent += estimate.total; + results.push({ + ...result, + estimatedCost: estimate.formatted, + }); + } + + return { results, totalSpent: `$${spent.toFixed(4)}` }; +} + +// Export for use in other modules +export { smartAssistant, reviewPullRequest, batchProcess }; diff --git a/tools/multi-model/examples/pre-commit-hook.js b/tools/multi-model/examples/pre-commit-hook.js new file mode 100644 index 0000000..611bcc1 --- /dev/null +++ b/tools/multi-model/examples/pre-commit-hook.js @@ -0,0 +1,92 @@ +#!/usr/bin/env node + +/** + * Pre-Commit Hook Example + * + * Install: Add to .husky/pre-commit or package.json scripts + * + * This hook runs a quick multi-model review on staged files + * and blocks commits with critical issues. + */ + +import { execSync } from 'child_process'; +import { readFileSync } from 'fs'; +import { quickReview } from '../lib/code-review.js'; +import chalk from 'chalk'; + +const EXTENSIONS = ['.js', '.ts', '.jsx', '.tsx', '.py', '.go']; + +async function main() { + console.log(chalk.blue('\n🔍 Running multi-model code review...\n')); + + // Get staged files + const staged = execSync('git diff --cached --name-only --diff-filter=ACM', { + encoding: 'utf-8', + }) + .split('\n') + .filter((f) => f && EXTENSIONS.some((ext) => f.endsWith(ext))); + + if (staged.length === 0) { + console.log(chalk.dim('No code files staged, skipping review.\n')); + process.exit(0); + } + + console.log(chalk.dim(`Reviewing ${staged.length} file(s)...\n`)); + + let hasBlockingIssues = false; + const allIssues = []; + + for (const file of staged) { + try { + const code = readFileSync(file, 'utf-8'); + + // Skip small files + if (code.length < 50) continue; + + const results = await quickReview(code, file); + + // Check for critical/high severity issues + const blocking = results.confirmedIssues.filter( + (i) => i.severity === 'critical' || i.severity === 'high' + ); + + if (blocking.length > 0) { + hasBlockingIssues = true; + console.log(chalk.red(`\n❌ ${file}: ${blocking.length} blocking issue(s)`)); + + for (const issue of blocking) { + console.log(chalk.red(` [${issue.severity.toUpperCase()}] ${issue.description}`)); + console.log(chalk.yellow(` → ${issue.suggestion}`)); + } + + allIssues.push(...blocking.map((i) => ({ ...i, file }))); + } else if (results.confirmedIssues.length > 0) { + console.log( + chalk.yellow(`⚠️ ${file}: ${results.confirmedIssues.length} minor issue(s) (non-blocking)`) + ); + } else { + console.log(chalk.green(`✓ ${file}`)); + } + } catch (error) { + console.error(chalk.yellow(`⚠️ Could not review ${file}: ${error.message}`)); + } + } + + console.log(''); + + if (hasBlockingIssues) { + console.log(chalk.red('═══════════════════════════════════════════')); + console.log(chalk.red(' COMMIT BLOCKED: Fix critical/high issues ')); + console.log(chalk.red('═══════════════════════════════════════════\n')); + console.log(chalk.dim('To bypass: git commit --no-verify\n')); + process.exit(1); + } + + console.log(chalk.green('✅ All checks passed!\n')); + process.exit(0); +} + +main().catch((error) => { + console.error(chalk.red(`Hook error: ${error.message}`)); + process.exit(1); +}); diff --git a/tools/multi-model/index.js b/tools/multi-model/index.js new file mode 100644 index 0000000..fb6caaf --- /dev/null +++ b/tools/multi-model/index.js @@ -0,0 +1,59 @@ +/** + * Multi-Model AI Toolkit + * + * A comprehensive toolkit for leveraging multiple AI models: + * - OpenAI (GPT-4, GPT-4o, GPT-4o-mini) + * - Anthropic (Claude 3 Opus, Sonnet, Haiku) + * - Google (Gemini Pro, Flash) + * + * @example + * import { reviewCode, createRouter, searchCodebase } from '@claude-sidekick/multi-model'; + * + * // Multi-model code review + * const results = await reviewCode(code, { filename: 'app.js' }); + * + * // Intelligent routing + * const router = createRouter('balanced'); + * const response = await router.route('Explain this architecture...'); + * + * // Semantic search + * const matches = await searchCodebase('authentication logic'); + */ + +// Clients +export { + complete, + embed, + embedBatch, + getOpenAI, + getAnthropic, + getGemini, + MODELS, + MODEL_COSTS, +} from './lib/clients.js'; + +// Code Review +export { + reviewCode, + quickReview, + deepReview, + formatReviewResults, +} from './lib/code-review.js'; + +// Model Router +export { + ModelRouter, + createRouter, + detectTaskType, + getOptimalModel, + TASK_ROUTING, +} from './lib/model-router.js'; + +// Embeddings & Search +export { + indexCodebase, + loadIndex, + searchCodebase, + formatSearchResults, + findSimilarCode, +} from './lib/embeddings.js'; diff --git a/tools/multi-model/lib/clients.js b/tools/multi-model/lib/clients.js new file mode 100644 index 0000000..930ac18 --- /dev/null +++ b/tools/multi-model/lib/clients.js @@ -0,0 +1,160 @@ +/** + * Multi-Model AI Clients + * Unified interface for OpenAI, Anthropic, and Google Gemini + */ + +import OpenAI from 'openai'; +import Anthropic from '@anthropic-ai/sdk'; +import { GoogleGenerativeAI } from '@google/generative-ai'; +import { config } from 'dotenv'; + +config(); + +// Initialize clients lazily +let openaiClient = null; +let anthropicClient = null; +let geminiClient = null; + +export function getOpenAI() { + if (!openaiClient) { + if (!process.env.OPENAI_API_KEY) { + throw new Error('OPENAI_API_KEY not set in environment'); + } + openaiClient = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); + } + return openaiClient; +} + +export function getAnthropic() { + if (!anthropicClient) { + if (!process.env.ANTHROPIC_API_KEY) { + throw new Error('ANTHROPIC_API_KEY not set in environment'); + } + anthropicClient = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }); + } + return anthropicClient; +} + +export function getGemini() { + if (!geminiClient) { + const key = process.env.GEMINI_API_KEY || process.env.GEMENI_API_KEY; + if (!key) { + throw new Error('GEMINI_API_KEY not set in environment'); + } + geminiClient = new GoogleGenerativeAI(key); + } + return geminiClient; +} + +/** + * Unified completion interface + */ +export async function complete(model, prompt, options = {}) { + const { maxTokens = 4096, temperature = 0.3, systemPrompt } = options; + + // OpenAI models + if (model.startsWith('gpt-')) { + const client = getOpenAI(); + const messages = []; + if (systemPrompt) messages.push({ role: 'system', content: systemPrompt }); + messages.push({ role: 'user', content: prompt }); + + const response = await client.chat.completions.create({ + model, + messages, + max_tokens: maxTokens, + temperature, + }); + return { + content: response.choices[0].message.content, + model, + usage: response.usage, + }; + } + + // Anthropic models + if (model.startsWith('claude-')) { + const client = getAnthropic(); + const response = await client.messages.create({ + model, + max_tokens: maxTokens, + system: systemPrompt || undefined, + messages: [{ role: 'user', content: prompt }], + }); + return { + content: response.content[0].text, + model, + usage: { + prompt_tokens: response.usage.input_tokens, + completion_tokens: response.usage.output_tokens, + }, + }; + } + + // Gemini models + if (model.startsWith('gemini-')) { + const client = getGemini(); + const genModel = client.getGenerativeModel({ model }); + const fullPrompt = systemPrompt ? `${systemPrompt}\n\n${prompt}` : prompt; + const result = await genModel.generateContent(fullPrompt); + const response = await result.response; + return { + content: response.text(), + model, + usage: null, // Gemini doesn't return token counts the same way + }; + } + + throw new Error(`Unknown model: ${model}`); +} + +/** + * Get embeddings (OpenAI only for now) + */ +export async function embed(text, model = 'text-embedding-3-small') { + const client = getOpenAI(); + const response = await client.embeddings.create({ + model, + input: text, + }); + return response.data[0].embedding; +} + +/** + * Batch embeddings for efficiency + */ +export async function embedBatch(texts, model = 'text-embedding-3-small') { + const client = getOpenAI(); + const response = await client.embeddings.create({ + model, + input: texts, + }); + return response.data.map((d) => d.embedding); +} + +export const MODELS = { + // OpenAI + GPT4: 'gpt-4-turbo-preview', + GPT4O: 'gpt-4o', + GPT4O_MINI: 'gpt-4o-mini', + + // Anthropic + CLAUDE_OPUS: 'claude-sonnet-4-20250514', // Opus 4 not out yet, use Sonnet 4 + CLAUDE_SONNET: 'claude-sonnet-4-20250514', + CLAUDE_HAIKU: 'claude-3-5-haiku-20241022', + + // Google + GEMINI_PRO: 'gemini-1.5-pro', + GEMINI_FLASH: 'gemini-2.0-flash', +}; + +export const MODEL_COSTS = { + // Per 1M tokens [input, output] + 'gpt-4-turbo-preview': [10, 30], + 'gpt-4o': [5, 15], + 'gpt-4o-mini': [0.15, 0.6], + 'claude-sonnet-4-20250514': [3, 15], + 'claude-3-5-haiku-20241022': [0.8, 4], + 'gemini-1.5-pro': [3.5, 10.5], + 'gemini-2.0-flash': [0.075, 0.3], +}; diff --git a/tools/multi-model/lib/code-review.js b/tools/multi-model/lib/code-review.js new file mode 100644 index 0000000..a60a92b --- /dev/null +++ b/tools/multi-model/lib/code-review.js @@ -0,0 +1,231 @@ +/** + * Multi-Model Code Review System + * Run code through multiple AI models and find consensus issues + */ + +import { complete, MODELS } from './clients.js'; +import chalk from 'chalk'; + +const REVIEW_PROMPT = `You are an expert code reviewer. Analyze the following code and identify issues. + +For each issue found, respond in this JSON format: +{ + "issues": [ + { + "severity": "critical|high|medium|low", + "type": "security|performance|logic|style|maintainability", + "line": , + "description": "Brief description of the issue", + "suggestion": "How to fix it" + } + ], + "summary": "Overall assessment in 1-2 sentences" +} + +If no issues found, return: { "issues": [], "summary": "Code looks good" } + +CODE TO REVIEW: +\`\`\` +{{CODE}} +\`\`\` + +Respond ONLY with valid JSON, no markdown.`; + +/** + * Review code with a single model + */ +async function reviewWithModel(code, model, filename = 'unknown') { + const prompt = REVIEW_PROMPT.replace('{{CODE}}', code); + + try { + const result = await complete(model, prompt, { + temperature: 0.2, + systemPrompt: + 'You are a senior software engineer conducting a thorough code review. Be specific and actionable.', + }); + + // Parse JSON response + const content = result.content.trim(); + const jsonMatch = content.match(/\{[\s\S]*\}/); + if (!jsonMatch) { + console.warn(`${model}: Could not parse JSON response`); + return { model, issues: [], summary: 'Parse error', raw: content }; + } + + const parsed = JSON.parse(jsonMatch[0]); + return { + model, + issues: parsed.issues || [], + summary: parsed.summary || '', + usage: result.usage, + }; + } catch (error) { + console.error(`${model} error:`, error.message); + return { model, issues: [], summary: `Error: ${error.message}`, error: true }; + } +} + +/** + * Find consensus issues across multiple model reviews + */ +function findConsensus(reviews) { + const issueMap = new Map(); + + for (const review of reviews) { + for (const issue of review.issues) { + // Create a key based on issue characteristics + const key = `${issue.type}-${issue.line || 'general'}-${issue.severity}`; + const existing = issueMap.get(key); + + if (existing) { + existing.models.push(review.model); + existing.count++; + // Keep the most detailed description + if (issue.description.length > existing.description.length) { + existing.description = issue.description; + existing.suggestion = issue.suggestion; + } + } else { + issueMap.set(key, { + ...issue, + models: [review.model], + count: 1, + }); + } + } + } + + // Sort by consensus count and severity + const severityOrder = { critical: 4, high: 3, medium: 2, low: 1 }; + return Array.from(issueMap.values()).sort((a, b) => { + if (b.count !== a.count) return b.count - a.count; + return severityOrder[b.severity] - severityOrder[a.severity]; + }); +} + +/** + * Multi-model code review with consensus + */ +export async function reviewCode(code, options = {}) { + const { + filename = 'code', + models = [MODELS.GEMINI_FLASH, MODELS.GPT4O_MINI, MODELS.CLAUDE_HAIKU], + consensusThreshold = 2, // How many models must agree + verbose = false, + } = options; + + console.log(chalk.blue(`\n🔍 Reviewing ${filename} with ${models.length} models...\n`)); + + // Run reviews in parallel + const startTime = Date.now(); + const reviews = await Promise.all(models.map((model) => reviewWithModel(code, model, filename))); + const elapsed = ((Date.now() - startTime) / 1000).toFixed(1); + + if (verbose) { + console.log(chalk.dim(`\n⏱️ Completed in ${elapsed}s\n`)); + for (const review of reviews) { + console.log( + chalk.dim(`${review.model}: ${review.issues.length} issues - "${review.summary}"`) + ); + } + } + + // Find consensus + const consensusIssues = findConsensus(reviews); + const confirmedIssues = consensusIssues.filter((i) => i.count >= consensusThreshold); + const possibleIssues = consensusIssues.filter( + (i) => i.count < consensusThreshold && i.count > 0 + ); + + return { + filename, + models, + reviews, + confirmedIssues, + possibleIssues, + elapsed, + summary: generateSummary(confirmedIssues, possibleIssues), + }; +} + +/** + * Generate a human-readable summary + */ +function generateSummary(confirmed, possible) { + if (confirmed.length === 0 && possible.length === 0) { + return '✅ No issues found - all models agree the code looks good!'; + } + + const parts = []; + if (confirmed.length > 0) { + const critical = confirmed.filter((i) => i.severity === 'critical').length; + const high = confirmed.filter((i) => i.severity === 'high').length; + parts.push(`⚠️ ${confirmed.length} confirmed issue(s)`); + if (critical > 0) parts.push(`🚨 ${critical} critical`); + if (high > 0) parts.push(`🔴 ${high} high`); + } + if (possible.length > 0) { + parts.push(`❓ ${possible.length} possible issue(s) (single model)`); + } + return parts.join(' | '); +} + +/** + * Format review results for display + */ +export function formatReviewResults(results) { + const lines = []; + lines.push(chalk.bold(`\n📋 Code Review Results: ${results.filename}`)); + lines.push(chalk.dim(`Models: ${results.models.join(', ')}`)); + lines.push(chalk.dim(`Time: ${results.elapsed}s\n`)); + lines.push(results.summary); + + if (results.confirmedIssues.length > 0) { + lines.push(chalk.bold('\n🔴 Confirmed Issues (multiple models agree):')); + for (const issue of results.confirmedIssues) { + const severityColor = + { critical: 'red', high: 'yellow', medium: 'cyan', low: 'dim' }[issue.severity] || 'white'; + lines.push( + chalk[severityColor]( + ` [${issue.severity.toUpperCase()}] ${issue.type}${issue.line ? ` (line ${issue.line})` : ''}` + ) + ); + lines.push(` ${issue.description}`); + lines.push(chalk.green(` → ${issue.suggestion}`)); + lines.push(chalk.dim(` Flagged by: ${issue.models.join(', ')}\n`)); + } + } + + if (results.possibleIssues.length > 0) { + lines.push(chalk.bold('\n🟡 Possible Issues (single model):')); + for (const issue of results.possibleIssues) { + lines.push(chalk.dim(` [${issue.severity}] ${issue.type}: ${issue.description}`)); + lines.push(chalk.dim(` Flagged by: ${issue.models[0]}`)); + } + } + + return lines.join('\n'); +} + +/** + * Quick review with fastest/cheapest models + */ +export async function quickReview(code, filename = 'code') { + return reviewCode(code, { + filename, + models: [MODELS.GEMINI_FLASH, MODELS.GPT4O_MINI], + consensusThreshold: 2, + }); +} + +/** + * Deep review with most capable models + */ +export async function deepReview(code, filename = 'code') { + return reviewCode(code, { + filename, + models: [MODELS.GPT4O, MODELS.CLAUDE_SONNET, MODELS.GEMINI_PRO], + consensusThreshold: 2, + verbose: true, + }); +} diff --git a/tools/multi-model/lib/embeddings.js b/tools/multi-model/lib/embeddings.js new file mode 100644 index 0000000..6cce908 --- /dev/null +++ b/tools/multi-model/lib/embeddings.js @@ -0,0 +1,310 @@ +/** + * Codebase Indexing & Semantic Search + * Index your codebase with embeddings for semantic code search + */ + +import { embed, embedBatch } from './clients.js'; +import { glob } from 'glob'; +import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs'; +import { join, relative, extname } from 'path'; +import chalk from 'chalk'; + +const DEFAULT_EXTENSIONS = [ + '.js', '.ts', '.jsx', '.tsx', '.py', '.go', '.rs', + '.java', '.rb', '.php', '.vue', '.svelte', '.astro', + '.css', '.scss', '.html', '.json', '.md', '.yaml', '.yml', +]; + +const DEFAULT_IGNORE = [ + '**/node_modules/**', + '**/dist/**', + '**/build/**', + '**/.git/**', + '**/coverage/**', + '**/*.min.js', + '**/package-lock.json', + '**/pnpm-lock.yaml', + '**/yarn.lock', +]; + +/** + * Chunk code into meaningful segments + */ +function chunkCode(content, filename, options = {}) { + const { maxChunkSize = 1500, overlap = 200 } = options; + const chunks = []; + const ext = extname(filename); + + // For code files, try to chunk by functions/classes + if (['.js', '.ts', '.jsx', '.tsx', '.py', '.go', '.rs', '.java'].includes(ext)) { + // Simple heuristic: split on function/class definitions + const patterns = [ + /^(export\s+)?(async\s+)?function\s+\w+/gm, + /^(export\s+)?(const|let|var)\s+\w+\s*=\s*(async\s+)?\(/gm, + /^(export\s+)?class\s+\w+/gm, + /^def\s+\w+/gm, // Python + /^func\s+\w+/gm, // Go + ]; + + let lastIndex = 0; + const boundaries = [0]; + + for (const pattern of patterns) { + let match; + while ((match = pattern.exec(content)) !== null) { + boundaries.push(match.index); + } + } + + boundaries.push(content.length); + boundaries.sort((a, b) => a - b); + + // Merge small chunks, split large ones + let currentChunk = ''; + let currentStart = 0; + + for (let i = 1; i < boundaries.length; i++) { + const segment = content.slice(boundaries[i - 1], boundaries[i]); + + if (currentChunk.length + segment.length < maxChunkSize) { + currentChunk += segment; + } else { + if (currentChunk.length > 0) { + chunks.push({ + content: currentChunk, + start: currentStart, + end: boundaries[i - 1], + }); + } + currentChunk = segment; + currentStart = boundaries[i - 1]; + } + } + + if (currentChunk.length > 0) { + chunks.push({ + content: currentChunk, + start: currentStart, + end: content.length, + }); + } + } + + // Fallback: simple sliding window + if (chunks.length === 0) { + for (let i = 0; i < content.length; i += maxChunkSize - overlap) { + chunks.push({ + content: content.slice(i, i + maxChunkSize), + start: i, + end: Math.min(i + maxChunkSize, content.length), + }); + } + } + + return chunks.map((chunk, index) => ({ + ...chunk, + filename, + index, + lineStart: content.slice(0, chunk.start).split('\n').length, + lineEnd: content.slice(0, chunk.end).split('\n').length, + })); +} + +/** + * Index a codebase + */ +export async function indexCodebase(rootDir, options = {}) { + const { + extensions = DEFAULT_EXTENSIONS, + ignore = DEFAULT_IGNORE, + outputDir = join(rootDir, '.code-index'), + batchSize = 100, + verbose = false, + } = options; + + console.log(chalk.blue(`\n📦 Indexing codebase: ${rootDir}\n`)); + + // Find all files + const pattern = `**/*{${extensions.join(',')}}`; + const files = await glob(pattern, { + cwd: rootDir, + ignore, + nodir: true, + }); + + console.log(chalk.dim(`Found ${files.length} files to index\n`)); + + // Process files and create chunks + const allChunks = []; + + for (const file of files) { + const fullPath = join(rootDir, file); + try { + const content = readFileSync(fullPath, 'utf-8'); + if (content.length < 10) continue; // Skip tiny files + + const chunks = chunkCode(content, file); + allChunks.push(...chunks); + + if (verbose) { + console.log(chalk.dim(` ${file}: ${chunks.length} chunks`)); + } + } catch (error) { + console.warn(chalk.yellow(` Skipping ${file}: ${error.message}`)); + } + } + + console.log(chalk.blue(`\n🧮 Creating embeddings for ${allChunks.length} chunks...\n`)); + + // Generate embeddings in batches + const embeddings = []; + for (let i = 0; i < allChunks.length; i += batchSize) { + const batch = allChunks.slice(i, i + batchSize); + const texts = batch.map((c) => `File: ${c.filename}\n\n${c.content}`); + + try { + const batchEmbeddings = await embedBatch(texts); + embeddings.push(...batchEmbeddings); + + const progress = Math.min(100, Math.round(((i + batch.length) / allChunks.length) * 100)); + process.stdout.write(`\r Progress: ${progress}%`); + } catch (error) { + console.error(`\nBatch ${i / batchSize} failed:`, error.message); + // Fill with null embeddings for failed batch + embeddings.push(...new Array(batch.length).fill(null)); + } + } + + console.log('\n'); + + // Build index + const index = { + version: '1.0', + createdAt: new Date().toISOString(), + rootDir, + totalFiles: files.length, + totalChunks: allChunks.length, + chunks: allChunks.map((chunk, i) => ({ + ...chunk, + embedding: embeddings[i], + })).filter((c) => c.embedding !== null), + }; + + // Save index + if (!existsSync(outputDir)) { + mkdirSync(outputDir, { recursive: true }); + } + + const indexPath = join(outputDir, 'index.json'); + writeFileSync(indexPath, JSON.stringify(index, null, 2)); + + console.log(chalk.green(`✅ Index saved to ${indexPath}`)); + console.log(chalk.dim(` ${index.chunks.length} chunks indexed`)); + + return index; +} + +/** + * Load an existing index + */ +export function loadIndex(indexPath) { + if (!existsSync(indexPath)) { + throw new Error(`Index not found: ${indexPath}`); + } + return JSON.parse(readFileSync(indexPath, 'utf-8')); +} + +/** + * Cosine similarity between two vectors + */ +function cosineSimilarity(a, b) { + let dotProduct = 0; + let normA = 0; + let normB = 0; + + for (let i = 0; i < a.length; i++) { + dotProduct += a[i] * b[i]; + normA += a[i] * a[i]; + normB += b[i] * b[i]; + } + + return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB)); +} + +/** + * Search the codebase + */ +export async function searchCodebase(query, options = {}) { + const { + indexPath, + index: providedIndex, + topK = 10, + minSimilarity = 0.5, + } = options; + + // Load or use provided index + const index = providedIndex || loadIndex(indexPath); + + console.log(chalk.blue(`\n🔍 Searching: "${query}"\n`)); + + // Generate query embedding + const queryEmbedding = await embed(query); + + // Calculate similarities + const results = index.chunks + .map((chunk) => ({ + ...chunk, + similarity: cosineSimilarity(queryEmbedding, chunk.embedding), + })) + .filter((r) => r.similarity >= minSimilarity) + .sort((a, b) => b.similarity - a.similarity) + .slice(0, topK); + + return results; +} + +/** + * Format search results for display + */ +export function formatSearchResults(results) { + const lines = []; + + for (const result of results) { + const similarity = (result.similarity * 100).toFixed(1); + lines.push(chalk.bold(`\n📄 ${result.filename} (${similarity}% match)`)); + lines.push(chalk.dim(` Lines ${result.lineStart}-${result.lineEnd}`)); + lines.push(''); + + // Show preview (first 300 chars) + const preview = result.content.slice(0, 300).trim(); + const previewLines = preview.split('\n').map((l) => chalk.dim(` ${l}`)); + lines.push(...previewLines); + + if (result.content.length > 300) { + lines.push(chalk.dim(' ...')); + } + } + + return lines.join('\n'); +} + +/** + * Find similar code (duplicate detection) + */ +export async function findSimilarCode(code, options = {}) { + const { indexPath, index: providedIndex, threshold = 0.85, topK = 5 } = options; + + const index = providedIndex || loadIndex(indexPath); + const codeEmbedding = await embed(code); + + const similar = index.chunks + .map((chunk) => ({ + ...chunk, + similarity: cosineSimilarity(codeEmbedding, chunk.embedding), + })) + .filter((r) => r.similarity >= threshold) + .sort((a, b) => b.similarity - a.similarity) + .slice(0, topK); + + return similar; +} diff --git a/tools/multi-model/lib/model-router.js b/tools/multi-model/lib/model-router.js new file mode 100644 index 0000000..1c7a29b --- /dev/null +++ b/tools/multi-model/lib/model-router.js @@ -0,0 +1,260 @@ +/** + * Intelligent Model Router + * Routes tasks to the optimal AI model based on task characteristics + */ + +import { complete, MODELS, MODEL_COSTS } from './clients.js'; + +/** + * Task type definitions with optimal models + */ +const TASK_ROUTING = { + // Long context tasks → Claude (200k context) + 'long-context': { + primary: MODELS.CLAUDE_SONNET, + fallback: MODELS.GPT4O, + reason: 'Claude has 200k context window, best for large files', + }, + + // Code generation → GPT-4 (mature function calling) + 'code-generation': { + primary: MODELS.GPT4O, + fallback: MODELS.CLAUDE_SONNET, + reason: 'GPT-4 has mature function calling and code generation', + }, + + // Quick refactors → Fast models + refactor: { + primary: MODELS.GPT4O_MINI, + fallback: MODELS.GEMINI_FLASH, + reason: 'Fast and accurate for straightforward refactors', + }, + + // Documentation → Claude (nuanced, thorough) + documentation: { + primary: MODELS.CLAUDE_SONNET, + fallback: MODELS.GPT4O, + reason: 'Claude excels at nuanced, comprehensive documentation', + }, + + // Image/diagram analysis → Gemini (native multimodal) + multimodal: { + primary: MODELS.GEMINI_PRO, + fallback: MODELS.GPT4O, + reason: 'Gemini has native multimodal support', + }, + + // Research/synthesis → Gemini + research: { + primary: MODELS.GEMINI_PRO, + fallback: MODELS.CLAUDE_SONNET, + reason: 'Gemini good at information synthesis', + }, + + // Security review → Claude (careful reasoning) + security: { + primary: MODELS.CLAUDE_SONNET, + fallback: MODELS.GPT4O, + reason: 'Claude better at nuanced security analysis', + }, + + // Architecture decisions → Claude + architecture: { + primary: MODELS.CLAUDE_SONNET, + fallback: MODELS.GPT4O, + reason: 'Claude excels at complex reasoning and trade-offs', + }, + + // Linting/style → Cheap and fast + lint: { + primary: MODELS.GEMINI_FLASH, + fallback: MODELS.GPT4O_MINI, + reason: 'Simple checks, optimize for cost', + }, + + // Test generation → GPT-4 + testing: { + primary: MODELS.GPT4O, + fallback: MODELS.CLAUDE_SONNET, + reason: 'GPT-4 good at structured test generation', + }, + + // Explanation/teaching → Claude + explain: { + primary: MODELS.CLAUDE_SONNET, + fallback: MODELS.GPT4O, + reason: 'Claude provides clear, thorough explanations', + }, + + // Default/general + general: { + primary: MODELS.GPT4O_MINI, + fallback: MODELS.GEMINI_FLASH, + reason: 'Good balance of capability and cost', + }, +}; + +/** + * Detect task type from prompt characteristics + */ +export function detectTaskType(prompt, context = {}) { + const promptLower = prompt.toLowerCase(); + const { contentLength = 0, hasImage = false } = context; + + // Check for multimodal + if (hasImage) return 'multimodal'; + + // Check for long context + if (contentLength > 50000) return 'long-context'; + + // Keyword matching (in priority order) + const patterns = [ + { type: 'security', keywords: ['security', 'vulnerability', 'exploit', 'injection', 'xss', 'csrf'] }, + { type: 'documentation', keywords: ['document', 'readme', 'jsdoc', 'explain the code', 'write docs'] }, + { type: 'testing', keywords: ['test', 'spec', 'unittest', 'jest', 'vitest', 'coverage'] }, + { type: 'architecture', keywords: ['architect', 'design pattern', 'structure', 'scalab'] }, + { type: 'refactor', keywords: ['refactor', 'clean up', 'simplify', 'optimize'] }, + { type: 'code-generation', keywords: ['generate', 'create a function', 'implement', 'build a'] }, + { type: 'lint', keywords: ['lint', 'format', 'style', 'prettier', 'eslint'] }, + { type: 'explain', keywords: ['explain', 'what does', 'how does', 'why does', 'teach me'] }, + { type: 'research', keywords: ['research', 'compare', 'alternatives', 'best practice'] }, + ]; + + for (const { type, keywords } of patterns) { + if (keywords.some((kw) => promptLower.includes(kw))) { + return type; + } + } + + return 'general'; +} + +/** + * Get the optimal model for a task + */ +export function getOptimalModel(taskType, options = {}) { + const { preferCost = false, preferSpeed = false, preferQuality = false } = options; + + const routing = TASK_ROUTING[taskType] || TASK_ROUTING.general; + + if (preferCost) { + // Return cheapest model that can handle the task + return MODELS.GEMINI_FLASH; + } + + if (preferSpeed) { + // Return fastest model + const fastModels = [MODELS.GEMINI_FLASH, MODELS.GPT4O_MINI, MODELS.CLAUDE_HAIKU]; + return fastModels.includes(routing.primary) ? routing.primary : MODELS.GEMINI_FLASH; + } + + if (preferQuality) { + // Return most capable model for the task + const qualityModels = [MODELS.GPT4O, MODELS.CLAUDE_SONNET, MODELS.GEMINI_PRO]; + return qualityModels.includes(routing.primary) ? routing.primary : MODELS.CLAUDE_SONNET; + } + + return routing.primary; +} + +/** + * Router class for stateful routing with fallbacks + */ +export class ModelRouter { + constructor(options = {}) { + this.preferCost = options.preferCost || false; + this.preferSpeed = options.preferSpeed || false; + this.preferQuality = options.preferQuality || false; + this.verbose = options.verbose || false; + this.failedModels = new Set(); + } + + /** + * Route a task to the optimal model and execute + */ + async route(prompt, options = {}) { + const { context = {}, systemPrompt, maxTokens } = options; + + // Detect task type + const taskType = options.taskType || detectTaskType(prompt, context); + const routing = TASK_ROUTING[taskType] || TASK_ROUTING.general; + + if (this.verbose) { + console.log(`\n🎯 Task type: ${taskType}`); + console.log(`📋 Reason: ${routing.reason}`); + } + + // Get model (considering preferences and failures) + let model = this.getModel(taskType); + + // Try primary, then fallback + const modelsToTry = [model, routing.fallback].filter( + (m) => m && !this.failedModels.has(m) + ); + + for (const tryModel of modelsToTry) { + try { + if (this.verbose) { + console.log(`🤖 Using model: ${tryModel}`); + } + + const result = await complete(tryModel, prompt, { + systemPrompt, + maxTokens, + }); + + return { + ...result, + taskType, + routing: routing.reason, + }; + } catch (error) { + console.error(`Model ${tryModel} failed:`, error.message); + this.failedModels.add(tryModel); + } + } + + throw new Error(`All models failed for task type: ${taskType}`); + } + + getModel(taskType) { + return getOptimalModel(taskType, { + preferCost: this.preferCost, + preferSpeed: this.preferSpeed, + preferQuality: this.preferQuality, + }); + } + + /** + * Estimate cost for a task + */ + estimateCost(taskType, inputTokens, outputTokens = 1000) { + const model = this.getModel(taskType); + const costs = MODEL_COSTS[model] || [1, 3]; + const inputCost = (inputTokens / 1_000_000) * costs[0]; + const outputCost = (outputTokens / 1_000_000) * costs[1]; + return { + model, + inputCost, + outputCost, + total: inputCost + outputCost, + formatted: `$${(inputCost + outputCost).toFixed(4)}`, + }; + } +} + +/** + * Create a pre-configured router + */ +export function createRouter(profile = 'balanced') { + const profiles = { + cost: { preferCost: true }, + speed: { preferSpeed: true }, + quality: { preferQuality: true }, + balanced: {}, + }; + + return new ModelRouter(profiles[profile] || profiles.balanced); +} + +export { TASK_ROUTING }; diff --git a/tools/multi-model/package.json b/tools/multi-model/package.json new file mode 100644 index 0000000..77e0948 --- /dev/null +++ b/tools/multi-model/package.json @@ -0,0 +1,35 @@ +{ + "name": "@claude-sidekick/multi-model", + "version": "1.0.0", + "description": "Multi-model AI toolkit for code review, routing, and semantic search", + "type": "module", + "main": "index.js", + "bin": { + "mm-review": "./bin/review.js", + "mm-index": "./bin/index-codebase.js", + "mm-search": "./bin/search.js" + }, + "scripts": { + "review": "node bin/review.js", + "index": "node bin/index-codebase.js", + "search": "node bin/search.js", + "test": "vitest run" + }, + "dependencies": { + "@anthropic-ai/sdk": "^0.18.0", + "@google/generative-ai": "^0.24.1", + "chalk": "^5.3.0", + "commander": "^12.0.0", + "dotenv": "^16.4.0", + "glob": "^10.3.0", + "openai": "^4.28.0", + "ora": "^8.0.1", + "tiktoken": "^1.0.0" + }, + "devDependencies": { + "vitest": "^2.0.0" + }, + "engines": { + "node": ">=18.0.0" + } +} diff --git a/tools/multi-model/pnpm-lock.yaml b/tools/multi-model/pnpm-lock.yaml new file mode 100644 index 0000000..4a8bf8b --- /dev/null +++ b/tools/multi-model/pnpm-lock.yaml @@ -0,0 +1,1657 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@anthropic-ai/sdk': + specifier: ^0.18.0 + version: 0.18.0 + '@google/generative-ai': + specifier: ^0.24.1 + version: 0.24.1 + chalk: + specifier: ^5.3.0 + version: 5.6.2 + commander: + specifier: ^12.0.0 + version: 12.1.0 + dotenv: + specifier: ^16.4.0 + version: 16.6.1 + glob: + specifier: ^10.3.0 + version: 10.5.0 + openai: + specifier: ^4.28.0 + version: 4.104.0 + ora: + specifier: ^8.0.1 + version: 8.2.0 + tiktoken: + specifier: ^1.0.0 + version: 1.0.22 + devDependencies: + vitest: + specifier: ^2.0.0 + version: 2.1.9(@types/node@18.19.130) + +packages: + + '@anthropic-ai/sdk@0.18.0': + resolution: {integrity: sha512-3XsWEn/4nPGRd4AdSguugbSDFy6Z2AWTNOeI3iK+aV22+w23+vY9CEb3Hiy0kvKIQuxSmZz/+5WKC8nPWy8gVg==} + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@google/generative-ai@0.24.1': + resolution: {integrity: sha512-MqO+MLfM6kjxcKoy0p1wRzG3b4ZZXtPI+z2IE26UogS2Cm/XHO+7gGRBh6gcJsOiIVoH93UwKvW4HdgiOZCy9Q==} + engines: {node: '>=18.0.0'} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@rollup/rollup-android-arm-eabi@4.59.0': + resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.59.0': + resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.59.0': + resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.59.0': + resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.59.0': + resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.59.0': + resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': + resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.59.0': + resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.59.0': + resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.59.0': + resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.59.0': + resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.59.0': + resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.59.0': + resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.59.0': + resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.59.0': + resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.59.0': + resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.59.0': + resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.59.0': + resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.59.0': + resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openbsd-x64@4.59.0': + resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.59.0': + resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.59.0': + resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.59.0': + resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.59.0': + resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.59.0': + resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==} + cpu: [x64] + os: [win32] + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/node-fetch@2.6.13': + resolution: {integrity: sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==} + + '@types/node@18.19.130': + resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} + + '@vitest/expect@2.1.9': + resolution: {integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==} + + '@vitest/mocker@2.1.9': + resolution: {integrity: sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@2.1.9': + resolution: {integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==} + + '@vitest/runner@2.1.9': + resolution: {integrity: sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==} + + '@vitest/snapshot@2.1.9': + resolution: {integrity: sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==} + + '@vitest/spy@2.1.9': + resolution: {integrity: sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==} + + '@vitest/utils@2.1.9': + resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + agentkeepalive@4.6.0: + resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} + engines: {node: '>= 8.0.0'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + base-64@0.1.0: + resolution: {integrity: sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==} + + brace-expansion@5.0.3: + resolution: {integrity: sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==} + engines: {node: 18 || 20 || >=22} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + chai@5.3.3: + resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + engines: {node: '>=18'} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + charenc@0.0.2: + resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + + check-error@2.1.3: + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} + engines: {node: '>= 16'} + + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + crypt@0.0.2: + resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + digest-fetch@1.3.0: + resolution: {integrity: sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA==} + + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} + engines: {node: '>=12'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + form-data-encoder@1.7.2: + resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + formdata-node@4.4.1: + resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} + engines: {node: '>= 12.20'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-east-asian-width@1.5.0: + resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + engines: {node: '>=18'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + + is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + + is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + log-symbols@6.0.0: + resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} + engines: {node: '>=18'} + + loupe@3.2.1: + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + md5@2.3.0: + resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + minimatch@9.0.6: + resolution: {integrity: sha512-kQAVowdR33euIqeA0+VZTDqU+qo1IeVY+hrKYtZMio3Pg0P0vuh/kwRylLUddJhB6pf3q/botcOvRtx4IN1wqQ==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + openai@4.104.0: + resolution: {integrity: sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==} + hasBin: true + peerDependencies: + ws: ^8.18.0 + zod: ^3.23.8 + peerDependenciesMeta: + ws: + optional: true + zod: + optional: true + + ora@8.2.0: + resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} + engines: {node: '>=18'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathval@2.0.1: + resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} + engines: {node: '>= 14.16'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + + rollup@4.59.0: + resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + + stdin-discarder@0.2.2: + resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} + engines: {node: '>=18'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.2: + resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} + engines: {node: '>=12'} + + tiktoken@1.0.22: + resolution: {integrity: sha512-PKvy1rVF1RibfF3JlXBSP0Jrcw2uq3yXdgcEXtKTYn3QJ/cBRBHDnrJ5jHky+MENZ6DIPwNUGWpkVx+7joCpNA==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@1.2.0: + resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} + engines: {node: '>=14.0.0'} + + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + engines: {node: '>=14.0.0'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + vite-node@2.1.9: + resolution: {integrity: sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + + vite@5.4.21: + resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vitest@2.1.9: + resolution: {integrity: sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 2.1.9 + '@vitest/ui': 2.1.9 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + + web-streams-polyfill@4.0.0-beta.3: + resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} + engines: {node: '>= 14'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + +snapshots: + + '@anthropic-ai/sdk@0.18.0': + dependencies: + '@types/node': 18.19.130 + '@types/node-fetch': 2.6.13 + abort-controller: 3.0.0 + agentkeepalive: 4.6.0 + digest-fetch: 1.3.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + web-streams-polyfill: 3.3.3 + transitivePeerDependencies: + - encoding + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@google/generative-ai@0.24.1': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.2 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@rollup/rollup-android-arm-eabi@4.59.0': + optional: true + + '@rollup/rollup-android-arm64@4.59.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.59.0': + optional: true + + '@rollup/rollup-darwin-x64@4.59.0': + optional: true + + '@rollup/rollup-freebsd-arm64@4.59.0': + optional: true + + '@rollup/rollup-freebsd-x64@4.59.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.59.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.59.0': + optional: true + + '@rollup/rollup-openbsd-x64@4.59.0': + optional: true + + '@rollup/rollup-openharmony-arm64@4.59.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.59.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.59.0': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.59.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.59.0': + optional: true + + '@types/estree@1.0.8': {} + + '@types/node-fetch@2.6.13': + dependencies: + '@types/node': 18.19.130 + form-data: 4.0.5 + + '@types/node@18.19.130': + dependencies: + undici-types: 5.26.5 + + '@vitest/expect@2.1.9': + dependencies: + '@vitest/spy': 2.1.9 + '@vitest/utils': 2.1.9 + chai: 5.3.3 + tinyrainbow: 1.2.0 + + '@vitest/mocker@2.1.9(vite@5.4.21(@types/node@18.19.130))': + dependencies: + '@vitest/spy': 2.1.9 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 5.4.21(@types/node@18.19.130) + + '@vitest/pretty-format@2.1.9': + dependencies: + tinyrainbow: 1.2.0 + + '@vitest/runner@2.1.9': + dependencies: + '@vitest/utils': 2.1.9 + pathe: 1.1.2 + + '@vitest/snapshot@2.1.9': + dependencies: + '@vitest/pretty-format': 2.1.9 + magic-string: 0.30.21 + pathe: 1.1.2 + + '@vitest/spy@2.1.9': + dependencies: + tinyspy: 3.0.2 + + '@vitest/utils@2.1.9': + dependencies: + '@vitest/pretty-format': 2.1.9 + loupe: 3.2.1 + tinyrainbow: 1.2.0 + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + agentkeepalive@4.6.0: + dependencies: + humanize-ms: 1.2.1 + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.3: {} + + assertion-error@2.0.1: {} + + asynckit@0.4.0: {} + + balanced-match@4.0.4: {} + + base-64@0.1.0: {} + + brace-expansion@5.0.3: + dependencies: + balanced-match: 4.0.4 + + cac@6.7.14: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + chai@5.3.3: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.3 + deep-eql: 5.0.2 + loupe: 3.2.1 + pathval: 2.0.1 + + chalk@5.6.2: {} + + charenc@0.0.2: {} + + check-error@2.1.3: {} + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-spinners@2.9.2: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@12.1.0: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crypt@0.0.2: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + deep-eql@5.0.2: {} + + delayed-stream@1.0.0: {} + + digest-fetch@1.3.0: + dependencies: + base-64: 0.1.0 + md5: 2.3.0 + + dotenv@16.6.1: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + eastasianwidth@0.2.0: {} + + emoji-regex@10.6.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-module-lexer@1.7.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + + event-target-shim@5.0.1: {} + + expect-type@1.3.0: {} + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + form-data-encoder@1.7.2: {} + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + formdata-node@4.4.1: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 4.0.0-beta.3 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + get-east-asian-width@1.5.0: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.6 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + gopd@1.2.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + humanize-ms@1.2.1: + dependencies: + ms: 2.1.3 + + is-buffer@1.1.6: {} + + is-fullwidth-code-point@3.0.0: {} + + is-interactive@2.0.0: {} + + is-unicode-supported@1.3.0: {} + + is-unicode-supported@2.1.0: {} + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + log-symbols@6.0.0: + dependencies: + chalk: 5.6.2 + is-unicode-supported: 1.3.0 + + loupe@3.2.1: {} + + lru-cache@10.4.3: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + math-intrinsics@1.1.0: {} + + md5@2.3.0: + dependencies: + charenc: 0.0.2 + crypt: 0.0.2 + is-buffer: 1.1.6 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mimic-function@5.0.1: {} + + minimatch@9.0.6: + dependencies: + brace-expansion: 5.0.3 + + minipass@7.1.3: {} + + ms@2.1.3: {} + + nanoid@3.3.11: {} + + node-domexception@1.0.0: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + openai@4.104.0: + dependencies: + '@types/node': 18.19.130 + '@types/node-fetch': 2.6.13 + abort-controller: 3.0.0 + agentkeepalive: 4.6.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + ora@8.2.0: + dependencies: + chalk: 5.6.2 + cli-cursor: 5.0.0 + cli-spinners: 2.9.2 + is-interactive: 2.0.0 + is-unicode-supported: 2.1.0 + log-symbols: 6.0.0 + stdin-discarder: 0.2.2 + string-width: 7.2.0 + strip-ansi: 7.1.2 + + package-json-from-dist@1.0.1: {} + + path-key@3.1.1: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.3 + + pathe@1.1.2: {} + + pathval@2.0.1: {} + + picocolors@1.1.1: {} + + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + + rollup@4.59.0: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.59.0 + '@rollup/rollup-android-arm64': 4.59.0 + '@rollup/rollup-darwin-arm64': 4.59.0 + '@rollup/rollup-darwin-x64': 4.59.0 + '@rollup/rollup-freebsd-arm64': 4.59.0 + '@rollup/rollup-freebsd-x64': 4.59.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.59.0 + '@rollup/rollup-linux-arm-musleabihf': 4.59.0 + '@rollup/rollup-linux-arm64-gnu': 4.59.0 + '@rollup/rollup-linux-arm64-musl': 4.59.0 + '@rollup/rollup-linux-loong64-gnu': 4.59.0 + '@rollup/rollup-linux-loong64-musl': 4.59.0 + '@rollup/rollup-linux-ppc64-gnu': 4.59.0 + '@rollup/rollup-linux-ppc64-musl': 4.59.0 + '@rollup/rollup-linux-riscv64-gnu': 4.59.0 + '@rollup/rollup-linux-riscv64-musl': 4.59.0 + '@rollup/rollup-linux-s390x-gnu': 4.59.0 + '@rollup/rollup-linux-x64-gnu': 4.59.0 + '@rollup/rollup-linux-x64-musl': 4.59.0 + '@rollup/rollup-openbsd-x64': 4.59.0 + '@rollup/rollup-openharmony-arm64': 4.59.0 + '@rollup/rollup-win32-arm64-msvc': 4.59.0 + '@rollup/rollup-win32-ia32-msvc': 4.59.0 + '@rollup/rollup-win32-x64-gnu': 4.59.0 + '@rollup/rollup-win32-x64-msvc': 4.59.0 + fsevents: 2.3.3 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + siginfo@2.0.0: {} + + signal-exit@4.1.0: {} + + source-map-js@1.2.1: {} + + stackback@0.0.2: {} + + std-env@3.10.0: {} + + stdin-discarder@0.2.2: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.2 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.5.0 + strip-ansi: 7.1.2 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.2: + dependencies: + ansi-regex: 6.2.2 + + tiktoken@1.0.22: {} + + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + + tinypool@1.1.1: {} + + tinyrainbow@1.2.0: {} + + tinyspy@3.0.2: {} + + tr46@0.0.3: {} + + undici-types@5.26.5: {} + + vite-node@2.1.9(@types/node@18.19.130): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + es-module-lexer: 1.7.0 + pathe: 1.1.2 + vite: 5.4.21(@types/node@18.19.130) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + vite@5.4.21(@types/node@18.19.130): + dependencies: + esbuild: 0.21.5 + postcss: 8.5.6 + rollup: 4.59.0 + optionalDependencies: + '@types/node': 18.19.130 + fsevents: 2.3.3 + + vitest@2.1.9(@types/node@18.19.130): + dependencies: + '@vitest/expect': 2.1.9 + '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@18.19.130)) + '@vitest/pretty-format': 2.1.9 + '@vitest/runner': 2.1.9 + '@vitest/snapshot': 2.1.9 + '@vitest/spy': 2.1.9 + '@vitest/utils': 2.1.9 + chai: 5.3.3 + debug: 4.4.3 + expect-type: 1.3.0 + magic-string: 0.30.21 + pathe: 1.1.2 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.1.1 + tinyrainbow: 1.2.0 + vite: 5.4.21(@types/node@18.19.130) + vite-node: 2.1.9(@types/node@18.19.130) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 18.19.130 + transitivePeerDependencies: + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + web-streams-polyfill@3.3.3: {} + + web-streams-polyfill@4.0.0-beta.3: {} + + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.1.2 From 48153dc3df876b310cbcfa71f15a8270caf6f1c8 Mon Sep 17 00:00:00 2001 From: Dylan Burkey Date: Mon, 23 Feb 2026 14:45:02 -0500 Subject: [PATCH 3/5] style: Format code with Prettier --- .claude/agents/dev-agent.md | 6 + .claude/agents/orchestrator-agent.md | 4 + .claude/agents/planner-agent.md | 11 +- .claude/agents/review-agent.md | 29 +- .claude/commands/phase-approve.md | 14 +- .claude/commands/status.md | 19 +- .claude/commands/task-runner.md | 2 + .claude/commands/worktree-disable.md | 8 + .claude/commands/worktree-enable.md | 10 +- .claude/config.yml | 26 +- .claude/config/models.yml | 60 +- .claude/mcp/default-servers.md | 48 +- .claude/skills/checkpoint-manager/SKILL.md | 23 +- .claude/skills/git-worktree/SKILL.md | 40 +- .claude/skills/phase-control/SKILL.md | 25 +- .claude/skills/scope-guard/SKILL.md | 29 +- CHANGELOG.md | 12 +- CLAUDE.md | 69 +- README.md | 38 +- docs/EXAMPLES.md | 131 +- docs/SCREENSHOTS.md | 30 +- docs/guides/getting-started-tutorial.md | 95 +- docs/guides/multi-model-setup.md | 99 +- docs/guides/real-world-example-ssg.md | 79 +- .../.claude/project-plan/phase_1.md | 21 +- .../.claude/tasks/phase-1-tasks.md | 50 +- examples/crypto-dashboard/CLAUDE.md | 36 +- examples/crypto-dashboard/PROJECT_STARTER.md | 29 +- examples/crypto-dashboard/README.md | 29 +- examples/crypto-dashboard/index.html | 11 +- examples/crypto-dashboard/src/App.tsx | 20 +- .../src/components/ActivityFeed.tsx | 20 +- .../src/components/Dashboard.tsx | 10 +- .../crypto-dashboard/src/components/Hero.tsx | 14 +- .../src/components/Navbar.tsx | 20 +- .../src/components/SignatureModal.tsx | 39 +- .../crypto-dashboard/src/styles/globals.css | 165 ++- .../.claude/project-plan/phase_1.md | 17 +- .../.claude/tasks/phase-1-tasks.md | 69 +- examples/ssg-starter/CLAUDE.md | 35 +- examples/ssg-starter/PROJECT_STARTER.md | 22 +- examples/ssg-starter/README.md | 33 +- examples/ssg-starter/astro.config.mjs | 4 +- examples/ssg-starter/public/styles.css | 107 +- examples/ssg-starter/src/content/config.ts | 2 +- .../src/content/posts/hello-world.md | 21 +- .../content/posts/modern-css-architecture.md | 13 +- tools/multi-model/README.md | 93 +- tools/multi-model/bin/index-codebase.js | 12 +- tools/multi-model/bin/search.js | 4 +- .../multi-model/examples/agent-integration.js | 31 +- tools/multi-model/examples/pre-commit-hook.js | 14 +- tools/multi-model/index.js | 17 +- tools/multi-model/lib/clients.js | 2 +- tools/multi-model/lib/code-review.js | 4 +- tools/multi-model/lib/embeddings.js | 40 +- tools/multi-model/lib/model-router.js | 19 +- tools/multi-model/pnpm-lock.yaml | 1169 ++++++++++++----- 58 files changed, 2103 insertions(+), 996 deletions(-) diff --git a/.claude/agents/dev-agent.md b/.claude/agents/dev-agent.md index 0dc5f38..95195ac 100644 --- a/.claude/agents/dev-agent.md +++ b/.claude/agents/dev-agent.md @@ -6,19 +6,24 @@ You are the **Development Agent**, responsible for implementing features, writing code, and following project patterns and best practices. ## Required Skills + Load before ANY implementation: + - `.claude/skills/scope-guard/SKILL.md` - Scope validation ## CRITICAL: Scope Awareness ### Before ANY Implementation + 1. Load scope-guard skill 2. Check current phase from `.claude/state/execution.json` 3. Verify ALL planned files are within phase scope 4. If ANY file belongs to future phase → **STOP IMMEDIATELY** ### Scope Violation Response + If out-of-scope work is detected: + ``` ⛔ SCOPE VIOLATION DETECTED @@ -34,6 +39,7 @@ RESOLUTION: This deliverable is scheduled for Phase {{N}}. ``` ### MCP Integration + - Use **Serena** for code analysis before implementation - Use **Chrome DevTools** for live testing - Use **Context7** for framework documentation lookup diff --git a/.claude/agents/orchestrator-agent.md b/.claude/agents/orchestrator-agent.md index ee14366..5652abd 100644 --- a/.claude/agents/orchestrator-agent.md +++ b/.claude/agents/orchestrator-agent.md @@ -6,7 +6,9 @@ Central coordination agent that manages workflow execution, agent delegation, and system-wide state across the project lifecycle. ## Required Skills + Before ANY execution, load these skills: + - `.claude/skills/phase-control/SKILL.md` - Phase boundary enforcement - `.claude/skills/scope-guard/SKILL.md` - Scope violation prevention - `.claude/skills/checkpoint-manager/SKILL.md` - Checkpoint management @@ -14,6 +16,7 @@ Before ANY execution, load these skills: ## CRITICAL: Scope Control Rules ### Phase Boundaries (MANDATORY - NO EXCEPTIONS) + 1. **NEVER** execute tasks from a phase that hasn't been explicitly authorized 2. **NEVER** auto-generate Phase N+1 plans after completing Phase N 3. **NEVER** continue past a phase boundary without explicit user command @@ -22,6 +25,7 @@ Before ANY execution, load these skills: 6. **ALWAYS** load phase-control skill before task execution ### Before EVERY Task + ``` 1. Check current authorized phase from .claude/state/execution.json 2. Verify task belongs to authorized phase diff --git a/.claude/agents/planner-agent.md b/.claude/agents/planner-agent.md index 4175930..95cea9e 100644 --- a/.claude/agents/planner-agent.md +++ b/.claude/agents/planner-agent.md @@ -171,7 +171,8 @@ Brief description of phase goals ## Multi-Model Support -The planner agent supports cross-validation with secondary models to get different perspectives on architecture decisions. +The planner agent supports cross-validation with secondary models to get +different perspectives on architecture decisions. ### Configuration @@ -180,8 +181,8 @@ See `.claude/config/models.yml`: ```yaml agent_overrides: planner: - primary: "claude-sonnet-4-20250514" - secondary: "gemini-2.5-pro" + primary: 'claude-sonnet-4-20250514' + secondary: 'gemini-2.5-pro' cross_validate: true ``` @@ -197,12 +198,14 @@ When cross-validation is enabled: ### When to Use Cross-Validation **Recommended for:** + - Major architecture decisions - Database schema design - API structure planning - Security-sensitive features **Optional for:** + - Simple feature planning - Bug fix planning - Documentation tasks @@ -210,11 +213,13 @@ When cross-validation is enabled: ### Disabling Cross-Validation For a single run: + ``` /project-planner --no-cross-validate ``` Permanently: + ```yaml # .claude/config/models.yml agent_overrides: diff --git a/.claude/agents/review-agent.md b/.claude/agents/review-agent.md index 4ae2365..6d57adf 100644 --- a/.claude/agents/review-agent.md +++ b/.claude/agents/review-agent.md @@ -254,7 +254,8 @@ When complete, report: ## Multi-Model Cross-Validation -The review agent supports cross-validation where a secondary model independently reviews the same code, catching issues that a single model might miss. +The review agent supports cross-validation where a secondary model independently +reviews the same code, catching issues that a single model might miss. ### Configuration @@ -263,8 +264,8 @@ See `.claude/config/models.yml`: ```yaml agent_overrides: review: - primary: "claude-sonnet-4-20250514" - secondary: "gpt-4o" + primary: 'claude-sonnet-4-20250514' + secondary: 'gpt-4o' cross_validate: true ``` @@ -283,32 +284,36 @@ When enabled: ## Cross-Validated Review ### Primary (Claude Sonnet 4) + - Found 3 issues - Security: ✅ Passed - Accessibility: ⚠️ 1 issue ### Secondary (GPT-4o) -- Found 4 issues + +- Found 4 issues - Security: ⚠️ 1 issue (XSS risk) - Accessibility: ⚠️ 2 issues ### Merged Findings (deduplicated) -| # | Issue | Found By | Severity | -|---|-------|----------|----------| -| 1 | XSS vulnerability | GPT-4 | Critical | -| 2 | Missing ARIA label | Both | Major | -| 3 | Focus trap missing | GPT-4 | Major | -| 4 | Consider memoization | Claude | Minor | + +| # | Issue | Found By | Severity | +| --- | -------------------- | -------- | -------- | +| 1 | XSS vulnerability | GPT-4 | Critical | +| 2 | Missing ARIA label | Both | Major | +| 3 | Focus trap missing | GPT-4 | Major | +| 4 | Consider memoization | Claude | Minor | ### Disagreements + - Claude: Security passed -- GPT-4: Found potential XSS -→ Human review recommended for security concern +- GPT-4: Found potential XSS → Human review recommended for security concern ``` ### When Cross-Validation Triggers By default: + - **Security-sensitive code** - Always - **High complexity** - When cyclomatic complexity > 10 - **On request** - When `--cross-validate` flag used diff --git a/.claude/commands/phase-approve.md b/.claude/commands/phase-approve.md index b6d9647..3287f3f 100644 --- a/.claude/commands/phase-approve.md +++ b/.claude/commands/phase-approve.md @@ -1,24 +1,30 @@ # /phase-approve - Authorize Next Phase ## Purpose -Explicitly authorizes execution of the next phase. This is the ONLY way to advance beyond the current phase. + +Explicitly authorizes execution of the next phase. This is the ONLY way to +advance beyond the current phase. ## Trigger + ``` /phase-approve ``` ## Arguments + - `phase_number` (required): The phase number to authorize (e.g., 2) ## Process ### Step 1: Validate Request + 1. Check that previous phase is complete 2. Check that requested phase is next in sequence 3. Verify no unresolved scope violations ### Step 2: Confirm with User + ``` ╔══════════════════════════════════════════════════════════════╗ ║ 📋 PHASE AUTHORIZATION REQUEST ║ @@ -46,7 +52,9 @@ Type "APPROVE" to authorize Phase {{N}}, or "CANCEL" to abort. ``` ### Step 3: Update State + If approved, update `.claude/state/execution.json`: + ```json { "authorized_phases": [1, 2], @@ -56,6 +64,7 @@ If approved, update `.claude/state/execution.json`: ``` ### Step 4: Confirm Authorization + ``` ╔══════════════════════════════════════════════════════════════╗ ║ ✓ PHASE {{N}} AUTHORIZED ║ @@ -71,12 +80,14 @@ If approved, update `.claude/state/execution.json`: ## Validation Rules ### Cannot Approve If: + - Previous phase is not complete - Unresolved scope violations exist - Pending checkpoints require approval - Skipping phases (e.g., approving Phase 3 when Phase 2 not done) ### Error Messages + ``` ⛔ CANNOT AUTHORIZE PHASE {{N}} @@ -87,6 +98,7 @@ Complete Phase {{N-1}} first, then try again. ``` ## Example Usage + ```bash # After completing Phase 1 /phase-approve 2 diff --git a/.claude/commands/status.md b/.claude/commands/status.md index 6fac360..de93329 100644 --- a/.claude/commands/status.md +++ b/.claude/commands/status.md @@ -1,9 +1,11 @@ # /status - Execution Status Command ## Purpose + Displays current execution state, phase progress, and next steps. ## Trigger + Run `/status` at any time to see project state. ## Output Format @@ -50,6 +52,7 @@ Run `/status` at any time to see project state. ## Data Sources Read from: + 1. `.claude/state/execution.json` - Execution state 2. `.claude/tasks/phase-{{N}}-tasks.md` - Task progress 3. `.claude/config.yml` - Configuration @@ -57,14 +60,14 @@ Read from: ## Status Values -| Status | Meaning | -|--------|---------| -| `not_started` | Phase planning not yet run | -| `planning` | Running /project-planner or /task-planner | -| `in_progress` | Tasks being executed | -| `awaiting_approval` | At checkpoint, waiting for user | -| `complete` | Phase finished | -| `blocked` | Execution halted due to error/violation | +| Status | Meaning | +| ------------------- | ----------------------------------------- | +| `not_started` | Phase planning not yet run | +| `planning` | Running /project-planner or /task-planner | +| `in_progress` | Tasks being executed | +| `awaiting_approval` | At checkpoint, waiting for user | +| `complete` | Phase finished | +| `blocked` | Execution halted due to error/violation | ## Next Steps Logic diff --git a/.claude/commands/task-runner.md b/.claude/commands/task-runner.md index 9235ec8..9dd4f06 100644 --- a/.claude/commands/task-runner.md +++ b/.claude/commands/task-runner.md @@ -40,6 +40,7 @@ Before ANY execution, output: ### Step 0.5: Load Required Skills Before execution, load: + 1. `.claude/skills/phase-control/SKILL.md` 2. `.claude/skills/scope-guard/SKILL.md` 3. `.claude/skills/checkpoint-manager/SKILL.md` @@ -203,6 +204,7 @@ Output exactly this completion message: ``` **CRITICAL RULES:** + - **NEVER** automatically invoke task-planner for next phase - **NEVER** automatically invoke task-runner for next phase - **NEVER** generate Phase N+1 plans without explicit user command diff --git a/.claude/commands/worktree-disable.md b/.claude/commands/worktree-disable.md index 5a04b9f..e43a059 100644 --- a/.claude/commands/worktree-disable.md +++ b/.claude/commands/worktree-disable.md @@ -1,9 +1,11 @@ # /worktree-disable - Disable Git Worktree Mode ## Purpose + Returns to sequential task execution. Cleans up existing worktrees. ## Trigger + ``` /worktree-disable ``` @@ -11,7 +13,9 @@ Returns to sequential task execution. Cleans up existing worktrees. ## Process ### Step 1: Check for Active Worktrees + If worktrees exist with uncommitted work: + ``` ⚠️ ACTIVE WORKTREES DETECTED @@ -26,6 +30,7 @@ Options: ``` ### Step 2: Clean Up Worktrees + ```bash # Remove all worktrees git worktree list | grep ".worktrees" | while read wt; do @@ -37,7 +42,9 @@ git branch | grep "task/" | xargs git branch -D ``` ### Step 3: Update Config + Sets in `.claude/config.yml`: + ```yaml git: worktrees: @@ -45,6 +52,7 @@ git: ``` ### Step 4: Confirm + ``` ╔══════════════════════════════════════════════════════════════╗ ║ ✓ GIT WORKTREE MODE DISABLED ║ diff --git a/.claude/commands/worktree-enable.md b/.claude/commands/worktree-enable.md index 3d5d230..94bf553 100644 --- a/.claude/commands/worktree-enable.md +++ b/.claude/commands/worktree-enable.md @@ -1,9 +1,11 @@ # /worktree-enable - Enable Git Worktree Mode ## Purpose + Enables parallel task execution using git worktrees. Simple one-command opt-in. ## Trigger + ``` /worktree-enable ``` @@ -11,6 +13,7 @@ Enables parallel task execution using git worktrees. Simple one-command opt-in. ## What It Does ### Step 1: Check Prerequisites + ```bash # Verify git version supports worktrees git --version # Requires 2.5+ @@ -20,23 +23,27 @@ git rev-parse --git-dir ``` ### Step 2: Create Worktree Directory + ```bash mkdir -p .worktrees echo ".worktrees/" >> .gitignore ``` ### Step 3: Update Config + Adds to `.claude/config.yml`: + ```yaml git: worktrees: enabled: true - base_dir: ".worktrees" + base_dir: '.worktrees' auto_cleanup: true max_concurrent: 3 ``` ### Step 4: Confirm + ``` ╔══════════════════════════════════════════════════════════════╗ ║ ✓ GIT WORKTREE MODE ENABLED ║ @@ -87,6 +94,7 @@ git: ``` ## Reverting + ``` /worktree-disable ``` diff --git a/.claude/config.yml b/.claude/config.yml index 2f0c1a2..7fcb270 100644 --- a/.claude/config.yml +++ b/.claude/config.yml @@ -88,10 +88,10 @@ workflow: # Phase execution control (CRITICAL for scope management) execution: - phase_limit: 1 # Only execute up to this phase - auto_advance: false # NEVER auto-advance to next phase - require_confirmation: true # Require explicit user command for each phase - hard_stop_on_completion: true # Stop execution at phase boundary + phase_limit: 1 # Only execute up to this phase + auto_advance: false # NEVER auto-advance to next phase + require_confirmation: true # Require explicit user command for each phase + hard_stop_on_completion: true # Stop execution at phase boundary # Skills configuration skills: @@ -108,13 +108,13 @@ skills: # Enable with: /worktree-enable git: worktrees: - enabled: false # Set to true or run /worktree-enable - base_dir: ".worktrees" # Where worktrees are created - auto_cleanup: true # Remove worktrees after task completion - max_concurrent: 3 # Max parallel worktrees - branch_prefix: "task/" # Prefix for worktree branches - merge_strategy: "auto" # auto | manual | squash - require_review: false # Require review-agent before merge + enabled: false # Set to true or run /worktree-enable + base_dir: ".worktrees" # Where worktrees are created + auto_cleanup: true # Remove worktrees after task completion + max_concurrent: 3 # Max parallel worktrees + branch_prefix: "task/" # Prefix for worktree branches + merge_strategy: "auto" # auto | manual | squash + require_review: false # Require review-agent before merge # Multi-model configuration # Supports Claude, OpenAI, and Gemini for cross-validation and specialization @@ -123,8 +123,8 @@ models: config_file: ".claude/config/models.yml" cross_validation: enabled: true - tasks: ["planning", "review"] # Tasks that get second opinions - + tasks: ["planning", "review"] # Tasks that get second opinions + # Default MCP servers (always enabled) mcp: required: diff --git a/.claude/config/models.yml b/.claude/config/models.yml index 9b63ec1..7e7776c 100644 --- a/.claude/config/models.yml +++ b/.claude/config/models.yml @@ -25,7 +25,7 @@ providers: cost_tier: "high" openai: - enabled: true # Set to true if OPENAI_API_KEY is available + enabled: true # Set to true if OPENAI_API_KEY is available env_key: "OPENAI_API_KEY" models: - id: "gpt-4o" @@ -45,7 +45,7 @@ providers: cost_tier: "high" google: - enabled: true # Set to true if GOOGLE_API_KEY is available + enabled: true # Set to true if GOOGLE_API_KEY is available env_key: "GOOGLE_API_KEY" models: - id: "gemini-2.0-flash" @@ -72,41 +72,41 @@ defaults: # Secondary model for cross-validation (optional) # Set to null to disable cross-validation secondary: - planning: "gemini-2.5-pro" # Different perspective on architecture - review: "gpt-4o" # Independent code review - testing: null # No cross-validation for tests - documentation: null # No cross-validation for docs + planning: "gemini-2.5-pro" # Different perspective on architecture + review: "gpt-4o" # Independent code review + testing: null # No cross-validation for tests + documentation: null # No cross-validation for docs # Cross-validation configuration cross_validation: enabled: true - + # When to use cross-validation triggers: planning: - always: true # Always get second opinion on plans + always: true # Always get second opinion on plans description: "Architecture decisions benefit from multiple perspectives" - + review: - on_complexity: "high" # Only for complex code reviews - on_security: true # Always for security-sensitive code - on_request: true # When explicitly requested + on_complexity: "high" # Only for complex code reviews + on_security: true # Always for security-sensitive code + on_request: true # When explicitly requested description: "Critical code benefits from independent review" - + development: - on_request: true # Only when explicitly requested + on_request: true # Only when explicitly requested description: "Optional second opinion on implementation" # How to handle disagreements conflict_resolution: - strategy: "human" # human | primary | vote | merge - notify: true # Notify user of disagreements - + strategy: "human" # human | primary | vote | merge + notify: true # Notify user of disagreements + # Output format for cross-validation output: - show_both: true # Show both model responses - highlight_differences: true # Highlight where models disagree - summary: true # Generate summary of consensus/conflicts + show_both: true # Show both model responses + highlight_differences: true # Highlight where models disagree + summary: true # Generate summary of consensus/conflicts # Agent-specific model overrides # Override the default model for specific agents @@ -115,47 +115,47 @@ agent_overrides: primary: "claude-sonnet-4-20250514" secondary: "gemini-2.5-pro" cross_validate: true - + review: primary: "claude-sonnet-4-20250514" secondary: "gpt-4o" cross_validate: true - + dev: primary: "claude-sonnet-4-20250514" secondary: null cross_validate: false - + test: primary: "claude-sonnet-4-20250514" secondary: null cross_validate: false docs: - primary: "gemini-2.0-flash" # Fast model for docs + primary: "gemini-2.0-flash" # Fast model for docs secondary: null cross_validate: false # Cost optimization settings cost_optimization: enabled: true - + # Use cheaper models for these tasks use_budget_model: - "simple-refactoring" - "documentation-updates" - "code-formatting" - "simple-tests" - + budget_model: "gemini-2.0-flash" - + # Always use premium model for these tasks use_premium_model: - "architecture-decisions" - "security-reviews" - "complex-algorithms" - "api-design" - + premium_model: "claude-opus-4-20250514" # Fallback chain if primary model fails @@ -174,12 +174,12 @@ prompt_adjustments: # OpenAI models prefer explicit JSON formatting prefer_json_mode: true system_prompt_style: "concise" - + google: # Gemini handles large contexts well include_full_context: true system_prompt_style: "detailed" - + anthropic: # Claude excels with examples include_examples: true diff --git a/.claude/mcp/default-servers.md b/.claude/mcp/default-servers.md index d49673e..e8a863c 100644 --- a/.claude/mcp/default-servers.md +++ b/.claude/mcp/default-servers.md @@ -1,26 +1,31 @@ # Default MCP Servers -These MCP servers are recommended for all projects using Claude Code Sidekick. They provide essential capabilities for structured development. +These MCP servers are recommended for all projects using Claude Code Sidekick. +They provide essential capabilities for structured development. ## Required MCPs ### 1. Serena (Structured Reasoning) -**Purpose:** Provides structured reasoning, code analysis, and semantic understanding of your codebase. +**Purpose:** Provides structured reasoning, code analysis, and semantic +understanding of your codebase. **Installation:** + ```bash claude mcp add serena -- uvx --from git+https://github.com/oraios/serena \ serena start-mcp-server --project "$(pwd)" ``` **When Used:** + - During project analysis (`/project-planner`) - Code review and quality checks - Architecture decisions - Complex refactoring tasks **Integration with Sidekick:** + - Planner agent uses Serena for requirement analysis - Review agent uses Serena for code quality assessment - Orchestrator consults Serena for task dependency resolution @@ -30,17 +35,20 @@ claude mcp add serena -- uvx --from git+https://github.com/oraios/serena \ **Purpose:** Browser automation, testing, and debugging capabilities. **Installation:** + ```bash claude mcp add chrome-devtools -- npx @anthropic/mcp-chrome-devtools ``` **When Used:** + - Frontend testing and validation - Accessibility audits (WCAG compliance) - Performance profiling - Visual regression testing **Integration with Sidekick:** + - Test agent uses for browser-based tests - Dev agent uses for live preview during development - Review agent uses for accessibility validation @@ -50,17 +58,20 @@ claude mcp add chrome-devtools -- npx @anthropic/mcp-chrome-devtools **Purpose:** Documentation lookup and context enrichment from external sources. **Installation:** + ```bash claude mcp add context7 -- npx @anthropic/mcp-context7 ``` **When Used:** + - Looking up framework documentation - API reference queries - Best practices lookup - Integration guidance **Integration with Sidekick:** + - All agents can query for relevant documentation - Reduces hallucination by grounding in real docs @@ -73,7 +84,14 @@ Add to your Claude Code settings (`~/.claude/settings.json`): "mcpServers": { "serena": { "command": "uvx", - "args": ["--from", "git+https://github.com/oraios/serena", "serena", "start-mcp-server", "--project", "."], + "args": [ + "--from", + "git+https://github.com/oraios/serena", + "serena", + "start-mcp-server", + "--project", + "." + ], "env": {} }, "chrome-devtools": { @@ -82,7 +100,7 @@ Add to your Claude Code settings (`~/.claude/settings.json`): "env": {} }, "context7": { - "command": "npx", + "command": "npx", "args": ["@anthropic/mcp-context7"], "env": {} } @@ -92,35 +110,37 @@ Add to your Claude Code settings (`~/.claude/settings.json`): ## Quick Setup Command -Run `/mcp-setup` after filling out PROJECT_STARTER.md to automatically configure all required MCPs based on your project type. +Run `/mcp-setup` after filling out PROJECT_STARTER.md to automatically configure +all required MCPs based on your project type. ## MCP Usage in Agents ### Planner Agent + Serena + ```yaml When analyzing PROJECT_STARTER.md: - 1. Use Serena to parse requirements - 2. Use Serena to identify code patterns - 3. Use Context7 to lookup framework best practices + 1. Use Serena to parse requirements 2. Use Serena to identify code patterns 3. + Use Context7 to lookup framework best practices ``` ### Dev Agent + Chrome DevTools + ```yaml During implementation: - 1. Use Chrome DevTools for live preview - 2. Run accessibility checks after each component - 3. Profile performance of new features + 1. Use Chrome DevTools for live preview 2. Run accessibility checks after each + component 3. Profile performance of new features ``` ### Test Agent + Chrome DevTools + ```yaml During testing: - 1. Run automated browser tests - 2. Capture screenshots for visual regression - 3. Validate responsive behavior + 1. Run automated browser tests 2. Capture screenshots for visual regression 3. + Validate responsive behavior ``` ### Review Agent + All MCPs + ```yaml During review: 1. Serena: Code quality analysis diff --git a/.claude/skills/checkpoint-manager/SKILL.md b/.claude/skills/checkpoint-manager/SKILL.md index e034e5f..5fbcc3c 100644 --- a/.claude/skills/checkpoint-manager/SKILL.md +++ b/.claude/skills/checkpoint-manager/SKILL.md @@ -1,9 +1,13 @@ # Checkpoint Manager Skill ## Purpose -Manages execution checkpoints to ensure proper stopping points and enable safe resumption of work. Creates explicit gates that require user approval before continuing. + +Manages execution checkpoints to ensure proper stopping points and enable safe +resumption of work. Creates explicit gates that require user approval before +continuing. ## When to Use + - At phase boundaries - After critical task completion - Before any deployment action @@ -12,6 +16,7 @@ Manages execution checkpoints to ensure proper stopping points and enable safe r ## Checkpoint Types ### 1. Phase Checkpoint (MANDATORY) + Triggered when all tasks in a phase complete. ``` @@ -37,6 +42,7 @@ Triggered when all tasks in a phase complete. ``` ### 2. Critical Task Checkpoint + Triggered after high-risk tasks (database changes, auth setup, etc.) ``` @@ -53,6 +59,7 @@ Review before continuing: /checkpoint-review PHASE1-005 ``` ### 3. Decision Checkpoint + Triggered when agent encounters ambiguity. ``` @@ -70,6 +77,7 @@ Waiting for input: /decide A or /decide B ## Checkpoint State Stored in `.claude/state/checkpoints.json`: + ```json { "checkpoints": [ @@ -94,48 +102,59 @@ Stored in `.claude/state/checkpoints.json`: ## Commands ### View Current Checkpoint + ``` /checkpoint-status ``` ### Approve and Continue + ``` /checkpoint-continue ``` + Marks checkpoint as approved, allows execution to continue. ### Rollback + ``` /checkpoint-rollback ``` + Reverts to state before checkpoint (requires git). ### Review Specific Checkpoint + ``` /checkpoint-review ``` + Shows detailed diff of changes. ## Integration with Git Each checkpoint creates a git tag: + ```bash git tag -a "checkpoint/phase-1-complete" -m "Phase 1 checkpoint" ``` Rollback uses: + ```bash git reset --hard "checkpoint/phase-1-start" ``` ## Enforcement Rules -1. **No auto-continue**: Checkpoints MUST wait for explicit `/checkpoint-continue` +1. **No auto-continue**: Checkpoints MUST wait for explicit + `/checkpoint-continue` 2. **Logged approval**: Record who approved and when 3. **Reversible**: Always maintain ability to rollback 4. **Visible**: Checkpoints must output clear terminal messages ## Configuration + ```yaml # .claude/config.yml checkpoints: diff --git a/.claude/skills/git-worktree/SKILL.md b/.claude/skills/git-worktree/SKILL.md index da62dd0..f09cadf 100644 --- a/.claude/skills/git-worktree/SKILL.md +++ b/.claude/skills/git-worktree/SKILL.md @@ -1,21 +1,25 @@ # Git Worktree Skill ## Purpose -Enables parallel task execution using git worktrees. Each task runs in an isolated worktree, preventing conflicts and allowing concurrent development. + +Enables parallel task execution using git worktrees. Each task runs in an +isolated worktree, preventing conflicts and allowing concurrent development. ## Opt-In Add to `.claude/config.yml`: + ```yaml git: worktrees: enabled: true - base_dir: ".worktrees" # Where worktrees are created - auto_cleanup: true # Remove worktrees after task completion - max_concurrent: 3 # Max parallel worktrees + base_dir: '.worktrees' # Where worktrees are created + auto_cleanup: true # Remove worktrees after task completion + max_concurrent: 3 # Max parallel worktrees ``` Or run: + ``` /worktree-enable ``` @@ -23,6 +27,7 @@ Or run: ## How It Works ### Without Worktrees (Default) + ``` main branch ↓ @@ -30,6 +35,7 @@ Task 1 → Task 2 → Task 3 (sequential) ``` ### With Worktrees (Opt-In) + ``` main branch ↓ @@ -43,27 +49,35 @@ Merge all back to main ## Commands ### Enable Worktrees + ``` /worktree-enable ``` + Enables worktree mode for current project. ### Disable Worktrees + ``` /worktree-disable ``` + Returns to sequential mode. ### List Active Worktrees + ``` /worktree-list ``` + Shows all active worktrees and their status. ### Clean Up Worktrees + ``` /worktree-cleanup ``` + Removes completed/merged worktrees. ## Task Runner Integration @@ -71,17 +85,20 @@ Removes completed/merged worktrees. When worktrees are enabled, task-runner changes behavior: ### Step 1: Create Worktree for Task + ```bash git worktree add .worktrees/PHASE1-001 -b task/PHASE1-001 ``` ### Step 2: Execute Task in Worktree + ```bash cd .worktrees/PHASE1-001 # Agent executes task here ``` ### Step 3: Merge on Completion + ```bash git checkout main git merge task/PHASE1-001 @@ -112,13 +129,17 @@ With worktrees, independent tasks run in parallel: ## Merge Strategy ### Auto-Merge (default) + Tasks auto-merge to main when: + - All tests pass - No conflicts detected - Review agent approves ### Manual Merge + If conflicts or review needed: + ``` ⚠️ MERGE REQUIRED @@ -138,18 +159,19 @@ To resolve: git: worktrees: enabled: true - base_dir: ".worktrees" + base_dir: '.worktrees' auto_cleanup: true max_concurrent: 3 - branch_prefix: "task/" - merge_strategy: "auto" # auto | manual | squash - require_review: false # Require review-agent before merge - preserve_on_failure: true # Keep worktree if task fails + branch_prefix: 'task/' + merge_strategy: 'auto' # auto | manual | squash + require_review: false # Require review-agent before merge + preserve_on_failure: true # Keep worktree if task fails ``` ## .gitignore When enabled, adds to `.gitignore`: + ``` .worktrees/ ``` diff --git a/.claude/skills/phase-control/SKILL.md b/.claude/skills/phase-control/SKILL.md index f23ce63..a895e52 100644 --- a/.claude/skills/phase-control/SKILL.md +++ b/.claude/skills/phase-control/SKILL.md @@ -1,9 +1,12 @@ # Phase Control Skill ## Purpose -Enforces strict phase boundaries during project execution. Prevents scope creep by ensuring work stays within the authorized phase. + +Enforces strict phase boundaries during project execution. Prevents scope creep +by ensuring work stays within the authorized phase. ## When to Use + - Before executing any task - When task-runner completes a phase - When any agent attempts to create deliverables @@ -12,25 +15,32 @@ Enforces strict phase boundaries during project execution. Prevents scope creep ## Core Rules ### 1. Phase Authorization + ```yaml -current_phase: 1 # Read from .claude/state/execution.json -authorized_phases: [1] # Only phases explicitly approved +current_phase: 1 # Read from .claude/state/execution.json +authorized_phases: [1] # Only phases explicitly approved ``` ### 2. Pre-Task Validation + Before executing ANY task: + 1. Check task ID prefix matches current phase (e.g., PHASE1-xxx) 2. Verify deliverables are within phase scope 3. Confirm no dependencies on future-phase tasks ### 3. Scope Violation Detection + Flag as SCOPE VIOLATION if: + - Task creates files listed in Phase N+1 deliverables - Task references components from future phases - Task implements features marked "Phase 2+" in PROJECT_STARTER.md ### 4. Hard Stop Protocol + When phase completes: + ``` ┌─────────────────────────────────────────────────────────────┐ │ ⛔ PHASE BOUNDARY - EXECUTION HALTED │ @@ -47,7 +57,9 @@ When phase completes: ``` ## State File + Maintain execution state in `.claude/state/execution.json`: + ```json { "current_phase": 1, @@ -62,24 +74,31 @@ Maintain execution state in `.claude/state/execution.json`: ## Commands ### Check Phase Status + ``` /phase-status ``` + Output: Current phase, completion %, next steps ### Authorize Next Phase + ``` /phase-approve 2 ``` + Explicitly authorizes Phase 2 execution ### Lock to Phase + ``` /phase-lock 1 ``` + Prevents any work beyond Phase 1 ## Integration Points + - task-runner.md: Calls phase-control before each task - orchestrator-agent.md: Respects phase boundaries - dev-agent.md: Checks scope before creating files diff --git a/.claude/skills/scope-guard/SKILL.md b/.claude/skills/scope-guard/SKILL.md index 44c70ef..bf14342 100644 --- a/.claude/skills/scope-guard/SKILL.md +++ b/.claude/skills/scope-guard/SKILL.md @@ -1,9 +1,13 @@ # Scope Guard Skill ## Purpose -Monitors all agent actions to prevent out-of-scope work. Acts as a watchdog that validates every file creation, modification, and task execution against the current phase scope. + +Monitors all agent actions to prevent out-of-scope work. Acts as a watchdog that +validates every file creation, modification, and task execution against the +current phase scope. ## When to Use + - Automatically invoked before any file operation - Called by dev-agent before implementation - Called by orchestrator before task delegation @@ -11,6 +15,7 @@ Monitors all agent actions to prevent out-of-scope work. Acts as a watchdog that ## Scope Validation Rules ### 1. File-Level Scope Check + Before creating/modifying ANY file: ```javascript @@ -18,21 +23,23 @@ Before creating/modifying ANY file: function validateScope(filePath, currentPhase) { const phaseDeliverables = loadPhaseDeliverables(currentPhase); const futureDeliverables = loadFuturePhaseDeliverables(currentPhase); - + if (futureDeliverables.includes(filePath)) { return { allowed: false, reason: `File "${filePath}" is a Phase ${futurePhase} deliverable`, - action: "STOP" + action: 'STOP', }; } - + return { allowed: true }; } ``` ### 2. Task-Level Scope Check + Before executing ANY task: + ```yaml validation: - task_id_matches_phase: true @@ -42,7 +49,9 @@ validation: ``` ### 3. Code-Level Scope Check + During implementation, flag: + - Imports from future-phase modules - References to future-phase components - API calls to future-phase endpoints @@ -50,6 +59,7 @@ During implementation, flag: ## Violation Handling ### Level 1: Warning + ``` ⚠️ SCOPE WARNING Creating file that may belong to future phase. @@ -60,6 +70,7 @@ Continue? (Requires explicit confirmation) ``` ### Level 2: Block + ``` ⛔ SCOPE VIOLATION - BLOCKED Cannot create Phase 2 deliverable while in Phase 1. @@ -72,6 +83,7 @@ Resolution: Run /task-planner phase=2 first ``` ### Level 3: Emergency Stop + ``` 🚨 CRITICAL SCOPE VIOLATION Multiple out-of-scope operations detected. @@ -86,7 +98,9 @@ Manual review required before continuing. ``` ## Scope Definition Sources + Read scope from (in priority order): + 1. `.claude/tasks/phase-N-tasks.md` - Task deliverables 2. `.claude/project-plan/phase_N.md` - Phase scope 3. `PROJECT_STARTER.md` - Overall phase definitions @@ -94,6 +108,7 @@ Read scope from (in priority order): ## Integration ### With Dev Agent + ```markdown ## Before Any Implementation @@ -104,6 +119,7 @@ Read scope from (in priority order): ``` ### With Orchestrator + ```markdown ## Before Task Delegation @@ -114,11 +130,12 @@ Read scope from (in priority order): ``` ## Configuration + ```yaml # .claude/config.yml scope_guard: enabled: true - strictness: "strict" # strict | moderate | relaxed - on_violation: "block" # block | warn | log + strictness: 'strict' # strict | moderate | relaxed + on_violation: 'block' # block | warn | log allow_override: false ``` diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d5b2ad..9c40052 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,14 +6,18 @@ All notable changes to Claude Code Sidekick will be documented in this file. ### Added -- **Git Worktree Support** - Opt-in parallel task execution for concurrent development workflows +- **Git Worktree Support** - Opt-in parallel task execution for concurrent + development workflows - **Phase Control System** - Structured development phases with scope guards - **MCP Integration** - 35+ pre-configured Model Context Protocol integrations -- **Shopify Development Support** - Complete Shopify theme and app development templates +- **Shopify Development Support** - Complete Shopify theme and app development + templates - **WordPress Development Support** - WordPress plugin and theme scaffolding - **Vitest Testing Framework** - Complete test suite with coverage reporting -- **GitHub Actions CI/CD** - Automated linting, formatting, and testing workflows -- **Comprehensive Agent Library** - 50+ specialized agents for every development task +- **GitHub Actions CI/CD** - Automated linting, formatting, and testing + workflows +- **Comprehensive Agent Library** - 50+ specialized agents for every development + task - **Hooks Configuration System** - 32+ automated hooks with TRUE/FALSE toggles - **Quick Start Presets** - Master toggles for simplified configuration - **Python FastAPI Walkthrough** - Complete backend development guide diff --git a/CLAUDE.md b/CLAUDE.md index fe76de7..baf095f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -43,6 +43,7 @@ tasks/phase-N-tasks.md **The system WILL NOT auto-advance to the next phase.** After completing Phase N: + 1. Execution STOPS completely 2. User must review completed work 3. User must explicitly run `/task-planner phase=N+1` @@ -54,21 +55,24 @@ This prevents scope creep and ensures controlled, phased delivery. These skills are loaded automatically and enforce development discipline: -| Skill | Purpose | -|-------|---------| -| `phase-control` | Enforces phase boundaries, prevents auto-advance | -| `scope-guard` | Validates all file operations against current phase | -| `checkpoint-manager` | Creates explicit approval gates | -| `git-worktree` | Parallel task execution (opt-in) | +| Skill | Purpose | +| -------------------- | --------------------------------------------------- | +| `phase-control` | Enforces phase boundaries, prevents auto-advance | +| `scope-guard` | Validates all file operations against current phase | +| `checkpoint-manager` | Creates explicit approval gates | +| `git-worktree` | Parallel task execution (opt-in) | ## Git Worktree Mode (Opt-In) Enable parallel task execution with: + ``` /worktree-enable ``` -This creates isolated worktrees for each task, allowing independent tasks to run simultaneously: +This creates isolated worktrees for each task, allowing independent tasks to run +simultaneously: + ``` main branch ├── .worktrees/task-001/ → Task 1 @@ -82,23 +86,24 @@ Disable with `/worktree-disable`. These MCP servers are enabled by default: -| MCP | Purpose | -|-----|---------| -| `serena` | Structured reasoning, code analysis | +| MCP | Purpose | +| ----------------- | ------------------------------------- | +| `serena` | Structured reasoning, code analysis | | `chrome-devtools` | Browser testing, accessibility audits | -| `context7` | Documentation lookup, best practices | +| `context7` | Documentation lookup, best practices | ## Multi-Model AI Toolkit -The project includes a powerful multi-model toolkit at `tools/multi-model/` that leverages OpenAI, Anthropic, and Google Gemini together. +The project includes a powerful multi-model toolkit at `tools/multi-model/` that +leverages OpenAI, Anthropic, and Google Gemini together. ### Available Tools -| CLI Command | Purpose | Documentation | -|-------------|---------|---------------| +| CLI Command | Purpose | Documentation | +| ----------- | --------------------------------------- | ----------------------------------------------------------- | | `mm-review` | Consensus code review (multiple models) | [View](tools/multi-model/README.md#multi-model-code-review) | -| `mm-index` | Index codebase for semantic search | [View](tools/multi-model/README.md#codebase-indexing) | -| `mm-search` | Search code by meaning, not keywords | [View](tools/multi-model/README.md#semantic-search) | +| `mm-index` | Index codebase for semantic search | [View](tools/multi-model/README.md#codebase-indexing) | +| `mm-search` | Search code by meaning, not keywords | [View](tools/multi-model/README.md#semantic-search) | ### Quick Start @@ -119,11 +124,15 @@ pnpm search -- "project scaffolding" ### Programmatic Usage ```javascript -import { reviewCode, createRouter, searchCodebase } from './tools/multi-model/index.js'; +import { + reviewCode, + createRouter, + searchCodebase, +} from './tools/multi-model/index.js'; // Consensus code review const results = await reviewCode(code, { filename: 'app.js' }); -console.log(results.confirmedIssues); // Issues 2+ models agree on +console.log(results.confirmedIssues); // Issues 2+ models agree on // Intelligent routing (auto-selects best model per task) const router = createRouter('balanced'); @@ -131,7 +140,7 @@ const response = await router.route('Explain this architecture...'); // Semantic search const matches = await searchCodebase('authentication logic', { - indexPath: '.code-index/index.json' + indexPath: '.code-index/index.json', }); ``` @@ -139,19 +148,21 @@ const matches = await searchCodebase('authentication logic', { The router automatically selects the optimal model based on task type: -| Task Type | Optimal Model | Reason | -|-----------|---------------|--------| -| Long context (>50k chars) | Claude Sonnet | 200k context window | -| Code generation | GPT-4o | Mature function calling | -| Documentation | Claude Sonnet | Nuanced, thorough | -| Security review | Claude Sonnet | Careful reasoning | -| Quick refactors | GPT-4o-mini | Fast, accurate | -| Linting/style | Gemini Flash | Cheapest | +| Task Type | Optimal Model | Reason | +| ------------------------- | ------------- | ----------------------- | +| Long context (>50k chars) | Claude Sonnet | 200k context window | +| Code generation | GPT-4o | Mature function calling | +| Documentation | Claude Sonnet | Nuanced, thorough | +| Security review | Claude Sonnet | Careful reasoning | +| Quick refactors | GPT-4o-mini | Fast, accurate | +| Linting/style | Gemini Flash | Cheapest | ### Examples -- [Pre-Commit Hook](tools/multi-model/examples/pre-commit-hook.js) - Block commits with critical issues -- [Agent Integration](tools/multi-model/examples/agent-integration.js) - Smart assistant workflows +- [Pre-Commit Hook](tools/multi-model/examples/pre-commit-hook.js) - Block + commits with critical issues +- [Agent Integration](tools/multi-model/examples/agent-integration.js) - Smart + assistant workflows ### Required Environment Variables diff --git a/README.md b/README.md index d35345a..26f5d6a 100644 --- a/README.md +++ b/README.md @@ -195,8 +195,8 @@ roadmap. ### 6. Multi-Model AI Toolkit -**Others:** Locked into a single AI provider -**Sidekick:** Use Claude, GPT-4, and Gemini together with intelligent routing +**Others:** Locked into a single AI provider **Sidekick:** Use Claude, GPT-4, +and Gemini together with intelligent routing ```bash # Consensus code review (multiple models must agree) @@ -210,16 +210,17 @@ pnpm search -- "authentication middleware" **Built-in Multi-Model Tools:** -| Tool | Purpose | Models Used | -|------|---------|-------------| -| `mm-review` | Consensus code review | GPT-4o + Claude + Gemini | -| `mm-index` | Codebase indexing | OpenAI Embeddings | -| `mm-search` | Semantic search | OpenAI Embeddings | +| Tool | Purpose | Models Used | +| ------------- | ------------------------ | -------------------------- | +| `mm-review` | Consensus code review | GPT-4o + Claude + Gemini | +| `mm-index` | Codebase indexing | OpenAI Embeddings | +| `mm-search` | Semantic search | OpenAI Embeddings | | `ModelRouter` | Intelligent task routing | Auto-selects optimal model | **Cross-Validation Benefits:** + - Different models catch different issues -- Architecture decisions get multiple perspectives +- Architecture decisions get multiple perspectives - Security reviews are more thorough - Cost optimization (use cheaper models for simple tasks) @@ -375,7 +376,8 @@ tools/multi-model/ ### Comprehensive Guides - [**Real-World SSG Example**](docs/guides/real-world-example-ssg.md) - Build a - production static site with blog, SEO, and modern CSS (with terminal screenshots) + production static site with blog, SEO, and modern CSS (with terminal + screenshots) - [Nuxt Full-Stack Walkthrough](docs/guides/nuxt-fullstack-walkthrough.md) - Build complete Nuxt app - [Python FastAPI Walkthrough](docs/guides/python-fastapi-walkthrough.md) - @@ -393,12 +395,18 @@ tools/multi-model/ ### Multi-Model AI Tools -- [Multi-Model Toolkit Overview](tools/multi-model/README.md) - Full documentation -- [Consensus Code Review](tools/multi-model/README.md#multi-model-code-review) - Run code through multiple AI models -- [Intelligent Model Routing](tools/multi-model/README.md#intelligent-model-routing) - Auto-select optimal model per task -- [Semantic Code Search](tools/multi-model/README.md#semantic-code-search) - Index and search codebase by meaning -- [Pre-Commit Hook Example](tools/multi-model/examples/pre-commit-hook.js) - CI/CD integration -- [Agent Integration Example](tools/multi-model/examples/agent-integration.js) - Claude Code workflows +- [Multi-Model Toolkit Overview](tools/multi-model/README.md) - Full + documentation +- [Consensus Code Review](tools/multi-model/README.md#multi-model-code-review) - + Run code through multiple AI models +- [Intelligent Model Routing](tools/multi-model/README.md#intelligent-model-routing) - + Auto-select optimal model per task +- [Semantic Code Search](tools/multi-model/README.md#semantic-code-search) - + Index and search codebase by meaning +- [Pre-Commit Hook Example](tools/multi-model/examples/pre-commit-hook.js) - + CI/CD integration +- [Agent Integration Example](tools/multi-model/examples/agent-integration.js) - + Claude Code workflows ### Advanced diff --git a/docs/EXAMPLES.md b/docs/EXAMPLES.md index 53df3ad..9dc88e5 100644 --- a/docs/EXAMPLES.md +++ b/docs/EXAMPLES.md @@ -6,7 +6,8 @@ ## Quick Overview -Claude Code Sidekick transforms project development from "figure it out" to "follow the system." +Claude Code Sidekick transforms project development from "figure it out" to +"follow the system." ``` ┌─────────────────────────────────────────────────────────────────────┐ @@ -43,7 +44,7 @@ $ npx create-claude-project ╰──────────────────────────────────────────╯ ? Project name: › my-saas-app -? Select a preset: › +? Select a preset: › ○ Static Website - Landing pages, marketing sites ○ Astro Site - Content-heavy sites, blogs ● Next.js App - Full-stack React framework @@ -104,7 +105,8 @@ my-saas-app/ ## Example 2: The PROJECT_STARTER.md File -This is where you define what you're building. The AI reads this to understand your project. +This is where you define what you're building. The AI reads this to understand +your project. ```markdown # Project Starter Template @@ -112,13 +114,16 @@ This is where you define what you're building. The AI reads this to understand y ## Project Information ### Project Name + TaskFlow - Team Task Management ### Project Description -A Kanban-style task management app for small teams. Users can create boards, -add tasks, assign team members, and track progress with drag-and-drop. + +A Kanban-style task management app for small teams. Users can create boards, add +tasks, assign team members, and track progress with drag-and-drop. ### Project Type + web-app --- @@ -126,10 +131,12 @@ web-app ## Goals & Objectives ### Primary Goal -Create a fast, accessible task management tool that works offline-first -and syncs when connected. + +Create a fast, accessible task management tool that works offline-first and +syncs when connected. ### Success Criteria + - Sub-100ms interactions - Works offline (PWA) - WCAG 2.1 AA compliant @@ -197,16 +204,17 @@ Next: Run /task-planner to generate implementation tasks ```markdown # Phase 1: Foundation -Generated: 2026-02-21T14:30:00Z -Source: PROJECT_STARTER.md +Generated: 2026-02-21T14:30:00Z Source: PROJECT_STARTER.md ## Project Summary ### Overview + TaskFlow is a Kanban-style task management application targeting small teams. The app prioritizes performance, accessibility, and offline-first architecture. ### Goals + - Fast, responsive drag-and-drop interface - Offline-first with background sync - Real-time collaboration between team members @@ -215,6 +223,7 @@ The app prioritizes performance, accessibility, and offline-first architecture. ## Analysis ### Complexity Assessment + - **Overall Complexity:** Medium-High - **Key Challenges:** - Real-time sync with offline support requires careful state management @@ -222,12 +231,14 @@ The app prioritizes performance, accessibility, and offline-first architecture. - Conflict resolution needs clear, non-disruptive UI ### Dependencies + - **External:** Supabase (auth + realtime), Service Worker API - **Internal:** State → UI → Sync pipeline ## Phase 1 Scope ### Objectives + 1. Set up project structure with Next.js 15 2. Configure Supabase connection 3. Create base component library @@ -235,6 +246,7 @@ The app prioritizes performance, accessibility, and offline-first architecture. 5. Set up testing framework ### Deliverables + - [ ] Working dev environment - [ ] Base layout components - [ ] Design system foundation @@ -245,16 +257,12 @@ The app prioritizes performance, accessibility, and offline-first architecture. ### Architecture ``` -┌─────────────┐ ┌─────────────┐ ┌─────────────┐ -│ Next.js │────▶│ Supabase │────▶│ Postgres │ -│ (React) │ │ (Realtime) │ │ (D1) │ -└─────────────┘ └─────────────┘ └─────────────┘ - │ - ▼ -┌─────────────┐ -│ Service │ -│ Worker │ + +┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ Next.js │────▶│ Supabase +│────▶│ Postgres │ │ (React) │ │ (Realtime) │ │ (D1) │ └─────────────┘ +└─────────────┘ └─────────────┘ │ ▼ ┌─────────────┐ │ Service │ │ Worker │ └─────────────┘ + ``` ### Technology Stack @@ -327,46 +335,48 @@ Next: Run /task-runner to execute tasks ### Output: tasks/phase-1-tasks.md -```markdown +````markdown # Phase 1 Tasks -Generated: 2026-02-21T14:35:00Z -Source: project-plan/phase_1.md +Generated: 2026-02-21T14:35:00Z Source: project-plan/phase_1.md ## Task Overview -| ID | Agent | Task | Est. Time | Dependencies | -|----------|-------|---------------------|-----------|--------------| -| TASK-001 | init | Project Setup | 30 min | None | -| TASK-002 | init | Database Setup | 45 min | TASK-001 | -| TASK-003 | dev | Design System | 60 min | TASK-001 | -| TASK-004 | dev | Layout Components | 45 min | TASK-003 | -| TASK-005 | test | Testing Setup | 30 min | TASK-001 | +| ID | Agent | Task | Est. Time | Dependencies | +| -------- | ----- | ----------------- | --------- | ------------ | +| TASK-001 | init | Project Setup | 30 min | None | +| TASK-002 | init | Database Setup | 45 min | TASK-001 | +| TASK-003 | dev | Design System | 60 min | TASK-001 | +| TASK-004 | dev | Layout Components | 45 min | TASK-003 | +| TASK-005 | test | Testing Setup | 30 min | TASK-001 | --- ## TASK-001: Project Setup -**Agent:** init -**Priority:** Critical -**Estimated Time:** 30 minutes +**Agent:** init **Priority:** Critical **Estimated Time:** 30 minutes ### Description -Initialize the Next.js 15 project with TypeScript and establish -the foundational folder structure. + +Initialize the Next.js 15 project with TypeScript and establish the foundational +folder structure. ### Acceptance Criteria + - [ ] Next.js 15 project created with App Router - [ ] TypeScript configured in strict mode - [ ] ESLint and Prettier configured - [ ] Folder structure matches steering/structure.md ### Implementation Notes + ```bash npx create-next-app@latest taskflow --typescript --app --tailwind=false ``` +```` ### Files to Create + - `src/app/layout.tsx` - `src/app/page.tsx` - `src/lib/utils.ts` @@ -375,8 +385,10 @@ npx create-next-app@latest taskflow --typescript --app --tailwind=false --- ## TASK-002: Database Setup + ... -``` + +```` --- @@ -430,7 +442,7 @@ npx create-next-app@latest taskflow --typescript --app --tailwind=false ... (TASK-004, TASK-005) ... ═══════════════════════════════════════════════════════════════════ - ⛔ PHASE 1 COMPLETE + ⛔ PHASE 1 COMPLETE ═══════════════════════════════════════════════════════════════════ Summary: @@ -445,7 +457,7 @@ To continue to Phase 2: 3. Run: /task-runner phase=2 The system will NOT auto-advance. You control the pace. -``` +```` --- @@ -456,27 +468,27 @@ The system will NOT auto-advance. You control the pace. ```yaml # Controls the entire system project: - name: "TaskFlow" - version: "1.0.0" + name: 'TaskFlow' + version: '1.0.0' # Agent system agents: enabled: true - directory: ".claude/agents" + directory: '.claude/agents' # Phase execution control (CRITICAL) execution: - phase_limit: 1 # Only execute this phase - auto_advance: false # NEVER auto-advance - require_confirmation: true # User must approve each phase + phase_limit: 1 # Only execute this phase + auto_advance: false # NEVER auto-advance + require_confirmation: true # User must approve each phase # MCP servers mcp: required: - - name: "serena" - description: "Code analysis" - - name: "context7" - description: "Documentation lookup" + - name: 'serena' + description: 'Code analysis' + - name: 'context7' + description: 'Documentation lookup' ``` ### .claude/agents/dev-agent.yml - Agent Definition @@ -511,17 +523,20 @@ tools: # Code Style Rules ## HTML + - Semantic elements over divs - ARIA labels on interactive elements - No inline styles ## CSS + - Custom properties for theming - CSS layers for organization - Mobile-first responsive design - No utility-first frameworks ## JavaScript + - TypeScript in strict mode - Native APIs over libraries - Progressive enhancement @@ -599,20 +614,20 @@ tools: ## Summary -| Component | Purpose | Location | -|-----------|---------|----------| -| **CLI** | Creates new projects | `npx create-claude-project` | -| **PROJECT_STARTER.md** | Your requirements | Project root | -| **CLAUDE.md** | AI context | Project root | -| **.claude/config.yml** | System configuration | `.claude/` | -| **.claude/commands/** | Slash commands | `.claude/commands/` | -| **.claude/agents/** | Specialized AI agents | `.claude/agents/` | -| **.claude/hooks/** | Automation triggers | `.claude/hooks/` | -| **.claude/mcp/** | MCP integrations | `.claude/mcp/` | -| **.claude/rules/** | Code standards | `.claude/rules/` | +| Component | Purpose | Location | +| ---------------------- | --------------------- | --------------------------- | +| **CLI** | Creates new projects | `npx create-claude-project` | +| **PROJECT_STARTER.md** | Your requirements | Project root | +| **CLAUDE.md** | AI context | Project root | +| **.claude/config.yml** | System configuration | `.claude/` | +| **.claude/commands/** | Slash commands | `.claude/commands/` | +| **.claude/agents/** | Specialized AI agents | `.claude/agents/` | +| **.claude/hooks/** | Automation triggers | `.claude/hooks/` | +| **.claude/mcp/** | MCP integrations | `.claude/mcp/` | +| **.claude/rules/** | Code standards | `.claude/rules/` | **Start here:** `npx create-claude-project` --- -*Built for developers who want more than autocomplete.* +_Built for developers who want more than autocomplete._ diff --git a/docs/SCREENSHOTS.md b/docs/SCREENSHOTS.md index fb71d52..7a42ebd 100644 --- a/docs/SCREENSHOTS.md +++ b/docs/SCREENSHOTS.md @@ -13,12 +13,14 @@ npx create-claude-project my-app ``` **Capture:** + - The interactive prompts - Preset selection menu - Feature checkboxes - Success message -**Tool:** [asciinema](https://asciinema.org/) or [terminalizer](https://terminalizer.com/) +**Tool:** [asciinema](https://asciinema.org/) or +[terminalizer](https://terminalizer.com/) --- @@ -29,6 +31,7 @@ tree -L 2 -a --dirsfirst my-app ``` **Shows:** + - `.claude/` directory - Key configuration files - Clean, organized structure @@ -38,6 +41,7 @@ tree -L 2 -a --dirsfirst my-app ### 3. Workflow Commands **Screenshot 1: /project-planner** + ``` 📋 Reading PROJECT_STARTER.md... ✓ Parsed project requirements @@ -47,6 +51,7 @@ tree -L 2 -a --dirsfirst my-app ``` **Screenshot 2: /task-planner** + ``` 📖 Reading project-plan/phase_1.md... 🔨 Generating tasks... @@ -60,6 +65,7 @@ tree -L 2 -a --dirsfirst my-app ``` **Screenshot 3: /task-runner** + ``` 🚀 Executing Phase 1... ┌──────────────────────────────────────┐ @@ -193,14 +199,14 @@ vhs demo.tape ## Color Palette for Graphics -| Element | Color | Hex | -|---------|-------|-----| -| Success | Green | `#10B981` | -| In Progress | Blue | `#3B82F6` | -| Warning | Yellow | `#F59E0B` | -| Error | Red | `#EF4444` | -| Background | Dark | `#1E1E2E` | -| Text | Light | `#CDD6F4` | +| Element | Color | Hex | +| ----------- | ------ | --------- | +| Success | Green | `#10B981` | +| In Progress | Blue | `#3B82F6` | +| Warning | Yellow | `#F59E0B` | +| Error | Red | `#EF4444` | +| Background | Dark | `#1E1E2E` | +| Text | Light | `#CDD6F4` | --- @@ -209,6 +215,7 @@ vhs demo.tape **Dimensions:** 1200 x 630px (2:1 ratio) **Existing cards:** + - `public/social-card.png` - Main - `public/social-card-v2.png` - Overview - `public/social-card-v3.png` - CLI @@ -227,4 +234,7 @@ vhs demo.tape Renders as: -![Claude Code](https://img.shields.io/badge/Claude-Code-blueviolet) ![Agents](https://img.shields.io/badge/Agents-50+-green) ![MCPs](https://img.shields.io/badge/MCPs-35+-blue) ![Hooks](https://img.shields.io/badge/Hooks-32+-orange) +![Claude Code](https://img.shields.io/badge/Claude-Code-blueviolet) +![Agents](https://img.shields.io/badge/Agents-50+-green) +![MCPs](https://img.shields.io/badge/MCPs-35+-blue) +![Hooks](https://img.shields.io/badge/Hooks-32+-orange) diff --git a/docs/guides/getting-started-tutorial.md b/docs/guides/getting-started-tutorial.md index b4ad151..338f6af 100644 --- a/docs/guides/getting-started-tutorial.md +++ b/docs/guides/getting-started-tutorial.md @@ -2,7 +2,9 @@ > A complete walkthrough of building a project with Claude Code Sidekick -This guide walks you through the entire Claude Code Sidekick workflow from start to finish. By the end, you'll understand how to use each command and agent to build production-ready projects. +This guide walks you through the entire Claude Code Sidekick workflow from start +to finish. By the end, you'll understand how to use each command and agent to +build production-ready projects. --- @@ -25,6 +27,7 @@ Claude Code Sidekick follows a structured, 4-step workflow: ``` Each step builds on the previous one. This structure ensures: + - Clear requirements before coding starts - Organized phases and milestones - Trackable tasks with progress @@ -34,7 +37,8 @@ Each step builds on the previous one. This structure ensures: ## Step 1: Fill Out PROJECT_STARTER.md -The `PROJECT_STARTER.md` file is your project's blueprint. It tells Claude exactly what you want to build. +The `PROJECT_STARTER.md` file is your project's blueprint. It tells Claude +exactly what you want to build. ### Open the File @@ -58,17 +62,21 @@ Here's what each section means: ## Project Information ### Project Name + My Awesome Blog -### Project Description -A personal blog with dark theme, SEO optimization, and a -content management system for markdown posts. +### Project Description + +A personal blog with dark theme, SEO optimization, and a content management +system for markdown posts. ### Project Type + web-app ``` **Tips:** + - Be specific in the description - Mention key features you want - Project type helps Claude choose the right tools @@ -79,22 +87,26 @@ web-app ## Goals & Objectives ### Primary Goal -Create a fast, SEO-optimized blog that ranks well in search -engines and provides an excellent reading experience. + +Create a fast, SEO-optimized blog that ranks well in search engines and provides +an excellent reading experience. ### Success Criteria + - Lighthouse score above 95 - All pages have meta tags and structured data - Mobile responsive design - Blog post pages with proper heading hierarchy ### Non-Goals + - User authentication (this is a static site) - Comments system (will add later) - E-commerce features ``` **Tips:** + - Non-goals are important! They prevent scope creep - Success criteria should be measurable @@ -106,29 +118,30 @@ EARS notation makes requirements clear and testable: ## Requirements ### Functional Requirements + 1. WHEN user visits homepage THE SYSTEM SHALL display recent posts 2. WHEN user clicks a post THE SYSTEM SHALL navigate to the post page 3. THE SYSTEM SHALL generate an RSS feed at /feed.xml 4. WHILE page is loading THE SYSTEM SHALL show a loading indicator ### Non-Functional Requirements + - Load time under 2 seconds on 3G - WCAG 2.1 AA accessible - Works without JavaScript enabled ``` -**EARS Keywords:** -| Keyword | Meaning | Example | -|---------|---------|---------| -| WHEN | Triggered by event | WHEN user clicks... | -| THE SYSTEM SHALL | Required behavior | ...SHALL show menu | -| WHILE | During a state | WHILE loading... | -| WHERE | Specific conditions | WHERE user is admin... | +**EARS Keywords:** | Keyword | Meaning | Example | +|---------|---------|---------| | WHEN | Triggered by event | WHEN user +clicks... | | THE SYSTEM SHALL | Required behavior | ...SHALL show menu | | +WHILE | During a state | WHILE loading... | | WHERE | Specific conditions | +WHERE user is admin... | #### Technical Stack ```markdown ## Technical Stack + - Framework: Astro 5 - Styling: Modern CSS (no framework) - Content: Markdown with frontmatter @@ -143,7 +156,8 @@ Once filled out, save the file. You're ready for step 2. ## Step 2: Run /project-planner -The `/project-planner` command reads your PROJECT_STARTER.md and generates a structured project plan. +The `/project-planner` command reads your PROJECT_STARTER.md and generates a +structured project plan. ### Run the Command @@ -156,6 +170,7 @@ In Claude Code (Terminal or VS Code), type: ### What Happens Claude will: + 1. Read your PROJECT_STARTER.md 2. Analyze the requirements 3. Break the project into phases @@ -164,6 +179,7 @@ Claude will: ### Output Location The plan is saved to: + ``` .claude/project-plan/phase_1.md ``` @@ -174,6 +190,7 @@ The plan is saved to: # Phase 1: Core Blog Setup ## Objectives + 1. Project scaffolding with Astro 2. Base layout and navigation 3. Blog post collection setup @@ -181,6 +198,7 @@ The plan is saved to: 5. Individual post pages ## Deliverables + - [ ] package.json with dependencies - [ ] src/layouts/BaseLayout.astro - [ ] src/components/Nav.astro @@ -189,6 +207,7 @@ The plan is saved to: - [ ] src/content/config.ts ## Technical Approach + - Use Astro content collections for posts - CSS custom properties for theming - Mobile-first responsive design @@ -197,6 +216,7 @@ The plan is saved to: ### Review the Plan Read through the generated plan. If something's wrong: + - Edit `.claude/project-plan/phase_1.md` directly - Or update PROJECT_STARTER.md and re-run @@ -215,6 +235,7 @@ The `/task-planner` command converts the project plan into actionable tasks. ### What Happens Claude will: + 1. Read the project plan (phase_1.md) 2. Break each objective into tasks 3. Estimate time for each task @@ -223,6 +244,7 @@ Claude will: ### Output Location Tasks are saved to: + ``` .claude/tasks/phase-1-tasks.md ``` @@ -233,7 +255,7 @@ Tasks are saved to: # Phase 1 Tasks | ID | Agent | Task | Est. | Status | -|----------|-------|--------------------------|--------|--------| +| -------- | ----- | ------------------------ | ------ | ------ | | TASK-001 | init | Project scaffolding | 5 min | ⬜ | | TASK-002 | dev | Create BaseLayout.astro | 15 min | ⬜ | | TASK-003 | dev | Create Nav component | 10 min | ⬜ | @@ -245,15 +267,16 @@ Tasks are saved to: ## TASK-001: Project Scaffolding -**Agent:** init -**Estimated Time:** 5 minutes +**Agent:** init **Estimated Time:** 5 minutes ### Instructions + 1. Initialize Astro project 2. Add TypeScript configuration 3. Create folder structure ### Acceptance Criteria + - [ ] package.json exists - [ ] tsconfig.json configured - [ ] src/ directory structure created @@ -263,19 +286,20 @@ Tasks are saved to: Each task is assigned an agent: -| Agent | Purpose | -|-------|---------| -| init | Project setup, dependencies | -| dev | Feature development, code | -| test | Testing, validation | -| docs | Documentation | -| review | Code review, refactoring | +| Agent | Purpose | +| ------ | --------------------------- | +| init | Project setup, dependencies | +| dev | Feature development, code | +| test | Testing, validation | +| docs | Documentation | +| review | Code review, refactoring | --- ## Step 4: Run /task-runner -The `/task-runner` command executes tasks one by one using the appropriate agent. +The `/task-runner` command executes tasks one by one using the appropriate +agent. ### Run the Command @@ -286,6 +310,7 @@ The `/task-runner` command executes tasks one by one using the appropriate agent ### What Happens Claude will: + 1. Find the first incomplete task 2. Load the assigned agent 3. Execute the task @@ -326,6 +351,7 @@ If a task produces broken code: ### Manual Fixes You can also: + - Edit files directly in your editor - Mark tasks complete manually in the tasks file - Skip tasks by marking them as "skipped" @@ -349,27 +375,33 @@ cd my-blog ## Project Information ### Project Name + Developer Blog ### Project Description -A technical blog for sharing programming tutorials. -Dark theme with syntax highlighting. + +A technical blog for sharing programming tutorials. Dark theme with syntax +highlighting. ### Project Type + static-site ## Goals & Objectives ### Primary Goal + Create a fast, beautiful blog with excellent SEO. ### Success Criteria + - Lighthouse 95+ on all pages - Blog posts with code syntax highlighting - RSS feed - Sitemap ### Non-Goals + - User accounts - Comments - Newsletter signup @@ -377,6 +409,7 @@ Create a fast, beautiful blog with excellent SEO. ## Requirements ### Functional + 1. WHEN user visits / THE SYSTEM SHALL show latest 5 posts 2. WHEN user visits /blog THE SYSTEM SHALL show all posts 3. WHEN user visits /blog/[slug] THE SYSTEM SHALL show post content @@ -384,6 +417,7 @@ Create a fast, beautiful blog with excellent SEO. 5. THE SYSTEM SHALL generate feed.xml ### Non-Functional + - Dark theme with purple accents - Mobile responsive - WCAG 2.1 AA compliant @@ -421,8 +455,8 @@ npm run dev ### 1. Be Specific in Requirements -❌ Bad: "Make it look good" -✅ Good: "Dark theme with #0a0a0f background, pink (#ec4899) accents" +❌ Bad: "Make it look good" ✅ Good: "Dark theme with #0a0a0f background, pink +(#ec4899) accents" ### 2. Include Non-Goals @@ -461,6 +495,7 @@ Ask Claude: "There are TypeScript errors. Can you fix them?" ```bash npm run build 2>&1 | head -50 ``` + Share the error output with Claude. --- diff --git a/docs/guides/multi-model-setup.md b/docs/guides/multi-model-setup.md index 0389a88..5032e7a 100644 --- a/docs/guides/multi-model-setup.md +++ b/docs/guides/multi-model-setup.md @@ -2,7 +2,9 @@ > Use Claude, GPT-4, and Gemini together for better results -Claude Code Sidekick supports multiple AI providers. This guide shows you how to configure and use them together for cross-validation, cost optimization, and specialized tasks. +Claude Code Sidekick supports multiple AI providers. This guide shows you how to +configure and use them together for cross-validation, cost optimization, and +specialized tasks. --- @@ -10,7 +12,8 @@ Claude Code Sidekick supports multiple AI providers. This guide shows you how to ### 1. Cross-Validation -Different models have different strengths. Getting a second opinion can catch issues: +Different models have different strengths. Getting a second opinion can catch +issues: ``` ┌─────────────────────────────────────────────────────────────────┐ @@ -38,12 +41,12 @@ Claude writes code → GPT-4 reviews it → Issues caught early Use cheaper/faster models for simple tasks: -| Task | Model | Why | -|------|-------|-----| -| Documentation | Gemini Flash | Fast, cheap, good enough | -| Architecture | Claude Opus | Complex reasoning needed | -| Code review | GPT-4o | Independent perspective | -| Simple refactoring | Gemini Flash | Cost-effective | +| Task | Model | Why | +| ------------------ | ------------ | ------------------------ | +| Documentation | Gemini Flash | Fast, cheap, good enough | +| Architecture | Claude Opus | Complex reasoning needed | +| Code review | GPT-4o | Independent perspective | +| Simple refactoring | Gemini Flash | Cost-effective | --- @@ -53,11 +56,11 @@ Use cheaper/faster models for simple tasks: You need API keys from the providers you want to use: -| Provider | Get Key From | Env Variable | -|----------|--------------|--------------| +| Provider | Get Key From | Env Variable | +| --------- | ------------------------------------------------------ | ------------------- | | Anthropic | [console.anthropic.com](https://console.anthropic.com) | `ANTHROPIC_API_KEY` | -| OpenAI | [platform.openai.com](https://platform.openai.com) | `OPENAI_API_KEY` | -| Google | [aistudio.google.com](https://aistudio.google.com) | `GOOGLE_API_KEY` | +| OpenAI | [platform.openai.com](https://platform.openai.com) | `OPENAI_API_KEY` | +| Google | [aistudio.google.com](https://aistudio.google.com) | `GOOGLE_API_KEY` | ### Step 2: Set Environment Variables @@ -77,9 +80,9 @@ providers: anthropic: enabled: true openai: - enabled: true # ← Enable if you have the key + enabled: true # ← Enable if you have the key google: - enabled: true # ← Enable if you have the key + enabled: true # ← Enable if you have the key ``` --- @@ -93,9 +96,9 @@ providers: defaults: primary: - planning: "claude-sonnet-4-20250514" - development: "claude-sonnet-4-20250514" - review: "claude-sonnet-4-20250514" + planning: 'claude-sonnet-4-20250514' + development: 'claude-sonnet-4-20250514' + review: 'claude-sonnet-4-20250514' ``` ### Cross-Validation: Second Opinion @@ -103,8 +106,8 @@ defaults: ```yaml defaults: secondary: - planning: "gemini-2.5-pro" # Gemini reviews Claude's plans - review: "gpt-4o" # GPT-4 reviews Claude's code + planning: 'gemini-2.5-pro' # Gemini reviews Claude's plans + review: 'gpt-4o' # GPT-4 reviews Claude's code ``` ### Per-Agent Configuration @@ -112,13 +115,13 @@ defaults: ```yaml agent_overrides: planner: - primary: "claude-sonnet-4-20250514" - secondary: "gemini-2.5-pro" - cross_validate: true # ← Enable cross-validation - + primary: 'claude-sonnet-4-20250514' + secondary: 'gemini-2.5-pro' + cross_validate: true # ← Enable cross-validation + review: - primary: "gpt-4o" # ← Use GPT-4 as primary reviewer - secondary: "claude-sonnet-4-20250514" + primary: 'gpt-4o' # ← Use GPT-4 as primary reviewer + secondary: 'claude-sonnet-4-20250514' cross_validate: true ``` @@ -206,46 +209,48 @@ When you run `/project-planner` with cross-validation enabled: ### 1. Use Cross-Validation for Important Decisions Enable for: + - Architecture planning - Security-sensitive code - API design - Database schema Skip for: + - Simple bug fixes - Documentation updates - Formatting changes ### 2. Match Model to Task -| Model | Best For | -|-------|----------| -| Claude Opus | Complex reasoning, nuanced decisions | -| Claude Sonnet | General development, balanced | -| GPT-4o | Fast iteration, multimodal | -| GPT-4 Turbo | Instruction following | -| o1 | Math, algorithms, complex logic | -| Gemini Flash | Speed, large contexts, docs | -| Gemini Pro | Balanced, large codebase analysis | +| Model | Best For | +| ------------- | ------------------------------------ | +| Claude Opus | Complex reasoning, nuanced decisions | +| Claude Sonnet | General development, balanced | +| GPT-4o | Fast iteration, multimodal | +| GPT-4 Turbo | Instruction following | +| o1 | Math, algorithms, complex logic | +| Gemini Flash | Speed, large contexts, docs | +| Gemini Pro | Balanced, large codebase analysis | ### 3. Cost-Conscious Configuration ```yaml cost_optimization: enabled: true - + # Cheap model for simple stuff use_budget_model: - - "documentation-updates" - - "code-formatting" - - "simple-tests" - budget_model: "gemini-2.0-flash" - + - 'documentation-updates' + - 'code-formatting' + - 'simple-tests' + budget_model: 'gemini-2.0-flash' + # Premium model only when needed use_premium_model: - - "architecture-decisions" - - "security-reviews" - premium_model: "claude-opus-4-20250514" + - 'architecture-decisions' + - 'security-reviews' + premium_model: 'claude-opus-4-20250514' ``` --- @@ -259,6 +264,7 @@ cost_optimization: ``` Output: + ``` Available Models: @@ -302,6 +308,7 @@ Available Models: ### "API key not found" Check your environment: + ```bash echo $OPENAI_API_KEY echo $GOOGLE_API_KEY @@ -311,17 +318,19 @@ If empty, set them and restart your terminal. ### "Model not available" -The model ID may have changed. Check provider documentation for current model IDs. +The model ID may have changed. Check provider documentation for current model +IDs. ### "Cross-validation taking too long" Disable for non-critical tasks: + ```yaml cross_validation: triggers: planning: always: false - on_request: true # Only when you ask + on_request: true # Only when you ask ``` --- diff --git a/docs/guides/real-world-example-ssg.md b/docs/guides/real-world-example-ssg.md index 7a10ddb..5485924 100644 --- a/docs/guides/real-world-example-ssg.md +++ b/docs/guides/real-world-example-ssg.md @@ -1,14 +1,16 @@ # Real-World Example: Building an SSG with Claude Code Sidekick -> A complete walkthrough of using Claude Code Sidekick to build a production static site generator project. +> A complete walkthrough of using Claude Code Sidekick to build a production +> static site generator project. --- ## The Project: Rise3 Recovery Platform We'll rebuild a live production site (rise3.org) as a proper SSG with: + - Blog support via markdown -- SEO meta tags and JSON-LD structured data +- SEO meta tags and JSON-LD structured data - Modern CSS (layers, custom properties, glass effects) - Content collections for easy updates @@ -64,14 +66,17 @@ Edit `PROJECT_STARTER.md` with your project specs: ## Project Information ### Project Name + Rise3 - Recovery Platform Website ### Project Description -A static site for Rise3, a blockchain-powered recovery incentives platform. -Must match the existing deployed site at rise3.org exactly, but rebuilt -as a proper SSG with blog support and content management. + +A static site for Rise3, a blockchain-powered recovery incentives platform. Must +match the existing deployed site at rise3.org exactly, but rebuilt as a proper +SSG with blog support and content management. ### Project Type + static-site --- @@ -79,13 +84,16 @@ static-site ## Goals & Objectives ### Primary Goal + Rebuild rise3.org as an Astro SSG with: + - Exact design match (dark theme, glass effects, pink/purple gradients) - Blog system using markdown content collections - SEO optimization (meta tags, JSON-LD structured data) - Modern CSS architecture (@layer, custom properties) ### Success Criteria + - Visual parity with production site - Lighthouse SEO score > 95 - Blog posts render from markdown @@ -100,12 +108,13 @@ Rebuild rise3.org as an Astro SSG with: 1. WHEN user visits /blog THE SYSTEM SHALL display list of posts 2. WHEN user visits /blog/[slug] THE SYSTEM SHALL render markdown content 3. THE SYSTEM SHALL include Open Graph and Twitter meta tags -4. THE SYSTEM SHALL include JSON-LD structured data for Organization and Articles +4. THE SYSTEM SHALL include JSON-LD structured data for Organization and + Articles ### Non-Functional Requirements - CSS: Use @layer for organization -- CSS: Use namespaced custom properties (--r3-*) +- CSS: Use namespaced custom properties (--r3-\*) - Accessibility: WCAG 2.1 AA compliant - Performance: Static HTML, minimal JavaScript ``` @@ -149,11 +158,10 @@ Rebuild rise3.org as an Astro SSG with: ### Generated Output: `.claude/project-plan/phase_1.md` -```markdown +````markdown # Phase 1: Foundation & Design System -Generated: 2026-02-21T16:00:00Z -Source: PROJECT_STARTER.md +Generated: 2026-02-21T16:00:00Z Source: PROJECT_STARTER.md ## Objectives @@ -173,6 +181,7 @@ Source: PROJECT_STARTER.md ## Technical Approach ### CSS Architecture + ```css @layer reset, base, tokens, layout, components, utilities; @@ -185,7 +194,9 @@ Source: PROJECT_STARTER.md } } ``` -``` +```` + +```` --- @@ -237,7 +248,7 @@ Source: PROJECT_STARTER.md 📁 Created tasks/phase-1-tasks.md ✅ 5 tasks generated -``` +```` --- @@ -282,8 +293,8 @@ export default defineConfig({ site: 'https://rise3.org', output: 'static', adapter: cloudflare({ - platformProxy: { enabled: true } - }) + platformProxy: { enabled: true }, + }), }); ``` @@ -454,16 +465,16 @@ export const collections = { posts }; ```markdown --- -title: "Welcome to Rise3" -description: "Introducing our blockchain-powered recovery platform" +title: 'Welcome to Rise3' +description: 'Introducing our blockchain-powered recovery platform' publishedAt: 2024-02-21 -tags: ["announcement", "recovery"] +tags: ['announcement', 'recovery'] --- # Welcome to Rise3 -We're excited to introduce Rise3, a revolutionary platform -designed to support and reward your recovery journey. +We're excited to introduce Rise3, a revolutionary platform designed to support +and reward your recovery journey. ## Why We Built Rise3 @@ -484,7 +495,7 @@ const posts = await getCollection('posts');

Rise3 Blog

- +
{posts.map(post => (
@@ -508,13 +519,13 @@ const posts = await getCollection('posts'); # Build static site $ pnpm build - prerendering static routes + prerendering static routes ▶ src/pages/blog/[slug].astro - └─ /blog/welcome/index.html (+7ms) + └─ /blog/welcome/index.html (+7ms) ▶ src/pages/blog/index.astro - └─ /blog/index.html (+5ms) + └─ /blog/index.html (+5ms) ▶ src/pages/index.astro - └─ /index.html (+12ms) + └─ /index.html (+12ms) ✓ Completed in 44ms. [build] Complete! @@ -530,14 +541,14 @@ $ pnpm deploy ## Key Sidekick Features Used -| Feature | How It Helped | -|---------|---------------| +| Feature | How It Helped | +| ---------------------- | ------------------------------------------- | | **PROJECT_STARTER.md** | Defined exact requirements in EARS notation | -| **/project-planner** | Analyzed requirements, created phased plan | -| **/task-planner** | Generated specific implementation tasks | -| **/task-runner** | Executed tasks with specialized agents | -| **CSS Rules** | Enforced modern CSS standards | -| **Hooks** | Auto-formatted on save, validated on commit | +| **/project-planner** | Analyzed requirements, created phased plan | +| **/task-planner** | Generated specific implementation tasks | +| **/task-runner** | Executed tasks with specialized agents | +| **CSS Rules** | Enforced modern CSS standards | +| **Hooks** | Auto-formatted on save, validated on commit | --- @@ -576,14 +587,16 @@ rise3-webapp/ ## Summary -Claude Code Sidekick transformed this from a vague request ("rebuild as SSG") into: +Claude Code Sidekick transformed this from a vague request ("rebuild as SSG") +into: 1. **Structured requirements** via PROJECT_STARTER.md 2. **Phased plan** via /project-planner 3. **Actionable tasks** via /task-planner 4. **Executed implementation** via /task-runner -The result: A production-ready static site with blog support, SEO optimization, and modern CSS architecture—built systematically instead of ad-hoc. +The result: A production-ready static site with blog support, SEO optimization, +and modern CSS architecture—built systematically instead of ad-hoc. --- diff --git a/examples/crypto-dashboard/.claude/project-plan/phase_1.md b/examples/crypto-dashboard/.claude/project-plan/phase_1.md index 14c53ff..d6e7cd3 100644 --- a/examples/crypto-dashboard/.claude/project-plan/phase_1.md +++ b/examples/crypto-dashboard/.claude/project-plan/phase_1.md @@ -1,16 +1,19 @@ # Phase 1: Core Web3 Dashboard -Generated: 2024-02-22T12:00:00Z -Source: PROJECT_STARTER.md +Generated: 2024-02-22T12:00:00Z Source: PROJECT_STARTER.md --- ## Project Summary ### Overview -Nexus Protocol Dashboard - A Web3 landing page with Privy wallet authentication, signature verification, and elaborate dashboard UI. Dark neon aesthetic inspired by GigaBrain and modern DeFi platforms. + +Nexus Protocol Dashboard - A Web3 landing page with Privy wallet authentication, +signature verification, and elaborate dashboard UI. Dark neon aesthetic inspired +by GigaBrain and modern DeFi platforms. ### Goals + - Privy wallet connection - Signature verification flow - Elaborate dashboard post-auth @@ -22,6 +25,7 @@ Nexus Protocol Dashboard - A Web3 landing page with Privy wallet authentication, ## Analysis ### Complexity Assessment + - **Overall:** Medium - **Challenges:** - Privy integration with signature flow @@ -29,6 +33,7 @@ Nexus Protocol Dashboard - A Web3 landing page with Privy wallet authentication, - Neon/glass CSS effects ### Dependencies + - **External:** Privy SDK, Google Fonts - **Internal:** Auth state flows through all components @@ -37,6 +42,7 @@ Nexus Protocol Dashboard - A Web3 landing page with Privy wallet authentication, ## Phase 1 Scope ### Objectives + 1. Project setup (Vite + React + TypeScript) 2. Privy provider configuration 3. Global CSS with neon dark theme @@ -46,6 +52,7 @@ Nexus Protocol Dashboard - A Web3 landing page with Privy wallet authentication, 7. Demo mode for testing ### Deliverables + - [ ] `package.json` with dependencies - [ ] `vite.config.ts` + TypeScript config - [ ] `src/styles/globals.css` - Complete theme @@ -92,11 +99,9 @@ Nexus Protocol Dashboard - A Web3 landing page with Privy wallet authentication, ### Color System ```css ---color-bg: #0a0a0f /* Deep dark */ ---color-cyan: #00f5ff /* Primary accent */ ---color-purple: #a855f7 /* Secondary */ ---color-pink: #ec4899 /* Tertiary */ ---gradient-hero: linear-gradient(135deg, cyan → purple → pink) +--color-bg: #0a0a0f /* Deep dark */ --color-cyan: #00f5ff /* Primary accent */ + --color-purple: #a855f7 /* Secondary */ --color-pink: #ec4899 /* Tertiary */ + --gradient-hero: linear-gradient(135deg, cyan → purple → pink); ``` --- diff --git a/examples/crypto-dashboard/.claude/tasks/phase-1-tasks.md b/examples/crypto-dashboard/.claude/tasks/phase-1-tasks.md index 4231d83..e000591 100644 --- a/examples/crypto-dashboard/.claude/tasks/phase-1-tasks.md +++ b/examples/crypto-dashboard/.claude/tasks/phase-1-tasks.md @@ -1,24 +1,23 @@ # Phase 1 Tasks -Generated: 2024-02-22T12:15:00Z -Source: .claude/project-plan/phase_1.md +Generated: 2024-02-22T12:15:00Z Source: .claude/project-plan/phase_1.md --- ## Task Overview -| ID | Agent | Task | Est. Time | Status | -|----------|-------|-------------------------|-----------|--------| -| TASK-001 | init | Project Setup | 10 min | ✅ | -| TASK-002 | dev | CSS Theme | 45 min | ✅ | -| TASK-003 | dev | Privy Integration | 20 min | ✅ | -| TASK-004 | dev | Navbar Component | 15 min | ✅ | -| TASK-005 | dev | Hero Component | 20 min | ✅ | -| TASK-006 | dev | Signature Modal | 25 min | ✅ | -| TASK-007 | dev | Dashboard Layout | 20 min | ✅ | -| TASK-008 | dev | Stats Cards | 15 min | ✅ | -| TASK-009 | dev | Token List | 15 min | ✅ | -| TASK-010 | dev | Activity Feed | 15 min | ✅ | +| ID | Agent | Task | Est. Time | Status | +| -------- | ----- | ----------------- | --------- | ------ | +| TASK-001 | init | Project Setup | 10 min | ✅ | +| TASK-002 | dev | CSS Theme | 45 min | ✅ | +| TASK-003 | dev | Privy Integration | 20 min | ✅ | +| TASK-004 | dev | Navbar Component | 15 min | ✅ | +| TASK-005 | dev | Hero Component | 20 min | ✅ | +| TASK-006 | dev | Signature Modal | 25 min | ✅ | +| TASK-007 | dev | Dashboard Layout | 20 min | ✅ | +| TASK-008 | dev | Stats Cards | 15 min | ✅ | +| TASK-009 | dev | Token List | 15 min | ✅ | +| TASK-010 | dev | Activity Feed | 15 min | ✅ | **Total Time:** ~3.5 hours @@ -29,6 +28,7 @@ Source: .claude/project-plan/phase_1.md **Status:** ✅ Complete ### Files Created + - `package.json` - React, Vite, Privy dependencies - `vite.config.ts` - Vite configuration - `tsconfig.json` - TypeScript strict mode @@ -42,7 +42,9 @@ Source: .claude/project-plan/phase_1.md **Status:** ✅ Complete ### Implementation + 13,000+ lines of modern CSS: + - CSS custom properties for colors, spacing, typography - Glassmorphism `.glass` class with backdrop-filter - Glow button `.btn--glow` with animated pseudo-element @@ -52,11 +54,10 @@ Source: .claude/project-plan/phase_1.md - Modal overlay with blur ### Key Tokens + ```css ---color-cyan: #00f5ff ---color-purple: #a855f7 ---color-pink: #ec4899 ---gradient-hero: linear-gradient(135deg, cyan, purple, pink) +--color-cyan: #00f5ff --color-purple: #a855f7 --color-pink: #ec4899 + --gradient-hero: linear-gradient(135deg, cyan, purple, pink); ``` --- @@ -66,6 +67,7 @@ Source: .claude/project-plan/phase_1.md **Status:** ✅ Complete ### Implementation + ```tsx Step-by-step walkthrough of building a Web3 dApp with Claude Code Sidekick -This example shows how to build a crypto landing page with wallet authentication using the Sidekick workflow. +This example shows how to build a crypto landing page with wallet authentication +using the Sidekick workflow. --- @@ -68,6 +69,7 @@ Open [PROJECT_STARTER.md](./PROJECT_STARTER.md) to see the requirements. See [.claude/project-plan/phase_1.md](./.claude/project-plan/phase_1.md) The plan identifies: + - Authentication flow (connect → sign → dashboard) - Component hierarchy - CSS architecture decisions @@ -88,15 +90,15 @@ See [.claude/tasks/phase-1-tasks.md](./.claude/tasks/phase-1-tasks.md) Tasks are broken down by component: -| ID | Agent | Task | Status | -|----|-------|------|--------| -| TASK-001 | init | Project setup | ✅ | -| TASK-002 | dev | CSS theme | ✅ | -| TASK-003 | dev | Privy integration | ✅ | -| TASK-004 | dev | Navbar | ✅ | -| TASK-005 | dev | Hero section | ✅ | -| TASK-006 | dev | Signature modal | ✅ | -| TASK-007 | dev | Dashboard | ✅ | +| ID | Agent | Task | Status | +| -------- | ----- | ----------------- | ------ | +| TASK-001 | init | Project setup | ✅ | +| TASK-002 | dev | CSS theme | ✅ | +| TASK-003 | dev | Privy integration | ✅ | +| TASK-004 | dev | Navbar | ✅ | +| TASK-005 | dev | Hero section | ✅ | +| TASK-006 | dev | Signature modal | ✅ | +| TASK-007 | dev | Dashboard | ✅ | --- @@ -168,6 +170,7 @@ npm run dev ``` Demo mode simulates: + - Wallet connection - Signature flow - Full dashboard @@ -234,7 +237,7 @@ const handleSign = async () => { const message = `Welcome to Nexus Protocol! Timestamp: ${Date.now()} Nonce: ${crypto.randomUUID()}`; - + // In real app: await signMessage(message) // Then verify signature onSuccess(); @@ -375,6 +378,7 @@ const tokens = [ ### Real Blockchain Data Replace mock data with: + - Alchemy/Infura for balances - CoinGecko for prices - The Graph for history @@ -392,6 +396,7 @@ Replace mock data with: ## Next Steps -- Read the [Getting Started Tutorial](../../docs/guides/getting-started-tutorial.md) +- Read the + [Getting Started Tutorial](../../docs/guides/getting-started-tutorial.md) - Try the [SSG Starter Example](../ssg-starter/) - Learn about [Available Agents](../../.claude/agents/) diff --git a/examples/crypto-dashboard/index.html b/examples/crypto-dashboard/index.html index 0e50f1d..42d957d 100644 --- a/examples/crypto-dashboard/index.html +++ b/examples/crypto-dashboard/index.html @@ -1,4 +1,4 @@ - + @@ -6,9 +6,12 @@ Nexus Protocol | Dashboard - - - + + +
diff --git a/examples/crypto-dashboard/src/App.tsx b/examples/crypto-dashboard/src/App.tsx index c1ce784..1f5a8f7 100644 --- a/examples/crypto-dashboard/src/App.tsx +++ b/examples/crypto-dashboard/src/App.tsx @@ -23,16 +23,13 @@ function AppContent() { return ( <> - + {!authenticated ? ( ) : needsSignature ? ( <> - setSignatureVerified(true)} - onClose={() => {}} - /> + setSignatureVerified(true)} onClose={() => {}} /> ) : ( @@ -76,13 +73,16 @@ function DemoApp() { return ( <> - setConnected(true)} - onDisconnect={() => { setConnected(false); setVerified(false); }} + onDisconnect={() => { + setConnected(false); + setVerified(false); + }} /> - + {!connected ? ( setConnected(true)} /> ) : !verified ? ( diff --git a/examples/crypto-dashboard/src/components/ActivityFeed.tsx b/examples/crypto-dashboard/src/components/ActivityFeed.tsx index 6c91b30..ed4faf1 100644 --- a/examples/crypto-dashboard/src/components/ActivityFeed.tsx +++ b/examples/crypto-dashboard/src/components/ActivityFeed.tsx @@ -1,33 +1,33 @@ const activities = [ - { + { type: 'stake', title: 'Staked 1,000 NEXUS', time: '2 hours ago', - icon: '🔒' + icon: '🔒', }, - { + { type: 'claim', title: 'Claimed 42.5 NEXUS rewards', time: '5 hours ago', - icon: '🎁' + icon: '🎁', }, - { + { type: 'swap', title: 'Swapped 0.5 ETH → 2,100 NEXUS', time: '1 day ago', - icon: '🔄' + icon: '🔄', }, - { + { type: 'vote', title: 'Voted on Proposal #47', time: '2 days ago', - icon: '🗳️' + icon: '🗳️', }, - { + { type: 'stake', title: 'Staked 5,000 NEXUS', time: '3 days ago', - icon: '🔒' + icon: '🔒', }, ]; diff --git a/examples/crypto-dashboard/src/components/Dashboard.tsx b/examples/crypto-dashboard/src/components/Dashboard.tsx index d946009..0b53066 100644 --- a/examples/crypto-dashboard/src/components/Dashboard.tsx +++ b/examples/crypto-dashboard/src/components/Dashboard.tsx @@ -53,13 +53,13 @@ export function Dashboard() { {/* Chart Placeholder */}

📈 Performance (30d)

-
diff --git a/examples/crypto-dashboard/src/components/Hero.tsx b/examples/crypto-dashboard/src/components/Hero.tsx index d2e1cda..6927bdb 100644 --- a/examples/crypto-dashboard/src/components/Hero.tsx +++ b/examples/crypto-dashboard/src/components/Hero.tsx @@ -12,21 +12,19 @@ export function Hero({ demoMode, onConnect }: HeroProps) { return (
- +
- - ⚡ Powered by Web3 - - + ⚡ Powered by Web3 +

NEXUS
PROTOCOL

- +

- The Future of Decentralized Intelligence. Stake, earn, and govern - the next generation of AI-powered DeFi infrastructure. + The Future of Decentralized Intelligence. Stake, earn, and govern the next generation of + AI-powered DeFi infrastructure.

+ + - -
diff --git a/examples/crypto-dashboard/src/styles/globals.css b/examples/crypto-dashboard/src/styles/globals.css index f32bfea..0426682 100644 --- a/examples/crypto-dashboard/src/styles/globals.css +++ b/examples/crypto-dashboard/src/styles/globals.css @@ -8,7 +8,9 @@ /* ============================================ Reset & Base ============================================ */ -*, *::before, *::after { +*, +*::before, +*::after { box-sizing: border-box; margin: 0; padding: 0; @@ -17,42 +19,48 @@ :root { /* Background */ --color-bg: #0a0a0f; - --color-bg-gradient: radial-gradient(ellipse at 50% 0%, rgba(0, 245, 255, 0.05) 0%, transparent 50%), - radial-gradient(ellipse at 80% 100%, rgba(168, 85, 247, 0.05) 0%, transparent 50%); + --color-bg-gradient: + radial-gradient(ellipse at 50% 0%, rgba(0, 245, 255, 0.05) 0%, transparent 50%), + radial-gradient(ellipse at 80% 100%, rgba(168, 85, 247, 0.05) 0%, transparent 50%); --color-surface: #12121a; --color-surface-elevated: #1a1a24; --color-card: rgba(18, 18, 26, 0.8); --color-border: rgba(255, 255, 255, 0.06); - + /* Accent Colors */ --color-cyan: #00f5ff; --color-purple: #a855f7; --color-pink: #ec4899; --color-blue: #3b82f6; - + /* Status */ --color-green: #10b981; --color-red: #ef4444; --color-yellow: #f59e0b; - + /* Text */ --color-text: #ffffff; --color-text-secondary: #a1a1aa; --color-text-muted: #52525b; - + /* Gradients */ - --gradient-hero: linear-gradient(135deg, var(--color-cyan) 0%, var(--color-purple) 50%, var(--color-pink) 100%); + --gradient-hero: linear-gradient( + 135deg, + var(--color-cyan) 0%, + var(--color-purple) 50%, + var(--color-pink) 100% + ); --gradient-card: linear-gradient(135deg, rgba(0, 245, 255, 0.1) 0%, rgba(168, 85, 247, 0.1) 100%); - + /* Glows */ --glow-cyan: 0 0 30px rgba(0, 245, 255, 0.4); --glow-purple: 0 0 30px rgba(168, 85, 247, 0.4); --glow-pink: 0 0 30px rgba(236, 72, 153, 0.4); - + /* Typography */ --font-sans: 'Inter', system-ui, -apple-system, sans-serif; --font-mono: 'JetBrains Mono', monospace; - + /* Spacing */ --space-xs: 0.25rem; --space-sm: 0.5rem; @@ -61,7 +69,7 @@ --space-xl: 2rem; --space-2xl: 3rem; --space-3xl: 4rem; - + /* Border Radius */ --radius-sm: 0.375rem; --radius-md: 0.75rem; @@ -89,16 +97,29 @@ body { /* ============================================ Typography ============================================ */ -h1, h2, h3, h4, h5, h6 { +h1, +h2, +h3, +h4, +h5, +h6 { font-weight: 700; line-height: 1.2; letter-spacing: -0.02em; } -h1 { font-size: 3rem; } -h2 { font-size: 2rem; } -h3 { font-size: 1.5rem; } -h4 { font-size: 1.25rem; } +h1 { + font-size: 3rem; +} +h2 { + font-size: 2rem; +} +h3 { + font-size: 1.5rem; +} +h4 { + font-size: 1.25rem; +} .text-gradient { background: var(--gradient-hero); @@ -119,9 +140,15 @@ h4 { font-size: 1.25rem; } color: var(--color-text-secondary); } -.text-green { color: var(--color-green); } -.text-red { color: var(--color-red); } -.text-cyan { color: var(--color-cyan); } +.text-green { + color: var(--color-green); +} +.text-red { + color: var(--color-red); +} +.text-cyan { + color: var(--color-cyan); +} /* ============================================ Layout @@ -167,12 +194,20 @@ h4 { font-size: 1.25rem; } } @media (max-width: 1024px) { - .grid-4 { grid-template-columns: repeat(2, 1fr); } - .grid-3 { grid-template-columns: repeat(2, 1fr); } + .grid-4 { + grid-template-columns: repeat(2, 1fr); + } + .grid-3 { + grid-template-columns: repeat(2, 1fr); + } } @media (max-width: 640px) { - .grid-4, .grid-3, .grid-2 { grid-template-columns: 1fr; } + .grid-4, + .grid-3, + .grid-2 { + grid-template-columns: 1fr; + } } /* ============================================ @@ -348,8 +383,13 @@ h4 { font-size: 1.25rem; } } @keyframes pulse { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.5; } + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } } /* ============================================ @@ -382,8 +422,15 @@ h4 { font-size: 1.25rem; } } @keyframes glow-pulse { - 0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.15; } - 50% { transform: translate(-50%, -50%) scale(1.1); opacity: 0.2; } + 0%, + 100% { + transform: translate(-50%, -50%) scale(1); + opacity: 0.15; + } + 50% { + transform: translate(-50%, -50%) scale(1.1); + opacity: 0.2; + } } .hero__tag { @@ -467,11 +514,15 @@ h4 { font-size: 1.25rem; } } @media (max-width: 1024px) { - .stats-row { grid-template-columns: repeat(2, 1fr); } + .stats-row { + grid-template-columns: repeat(2, 1fr); + } } @media (max-width: 640px) { - .stats-row { grid-template-columns: 1fr; } + .stats-row { + grid-template-columns: 1fr; + } } .stat-card { @@ -497,8 +548,12 @@ h4 { font-size: 1.25rem; } gap: var(--space-xs); } -.stat-card__change.positive { color: var(--color-green); } -.stat-card__change.negative { color: var(--color-red); } +.stat-card__change.positive { + color: var(--color-green); +} +.stat-card__change.negative { + color: var(--color-red); +} /* Token List */ .token-list { @@ -666,16 +721,38 @@ h4 { font-size: 1.25rem; } /* ============================================ Utilities ============================================ */ -.mt-sm { margin-top: var(--space-sm); } -.mt-md { margin-top: var(--space-md); } -.mt-lg { margin-top: var(--space-lg); } -.mt-xl { margin-top: var(--space-xl); } - -.mb-sm { margin-bottom: var(--space-sm); } -.mb-md { margin-bottom: var(--space-md); } -.mb-lg { margin-bottom: var(--space-lg); } -.mb-xl { margin-bottom: var(--space-xl); } - -.gap-sm { gap: var(--space-sm); } -.gap-md { gap: var(--space-md); } -.gap-lg { gap: var(--space-lg); } +.mt-sm { + margin-top: var(--space-sm); +} +.mt-md { + margin-top: var(--space-md); +} +.mt-lg { + margin-top: var(--space-lg); +} +.mt-xl { + margin-top: var(--space-xl); +} + +.mb-sm { + margin-bottom: var(--space-sm); +} +.mb-md { + margin-bottom: var(--space-md); +} +.mb-lg { + margin-bottom: var(--space-lg); +} +.mb-xl { + margin-bottom: var(--space-xl); +} + +.gap-sm { + gap: var(--space-sm); +} +.gap-md { + gap: var(--space-md); +} +.gap-lg { + gap: var(--space-lg); +} diff --git a/examples/ssg-starter/.claude/project-plan/phase_1.md b/examples/ssg-starter/.claude/project-plan/phase_1.md index b40a766..15f7473 100644 --- a/examples/ssg-starter/.claude/project-plan/phase_1.md +++ b/examples/ssg-starter/.claude/project-plan/phase_1.md @@ -1,16 +1,18 @@ # Phase 1: Foundation & Core Components -Generated: 2024-02-21T10:00:00Z -Source: PROJECT_STARTER.md +Generated: 2024-02-21T10:00:00Z Source: PROJECT_STARTER.md --- ## Project Summary ### Overview -SSG Starter is a production-ready static site template with blog support, SEO optimization, and modern CSS architecture. Built using Astro with static output. + +SSG Starter is a production-ready static site template with blog support, SEO +optimization, and modern CSS architecture. Built using Astro with static output. ### Goals + - Create reusable SSG template - Blog system with markdown content collections - Comprehensive SEO (meta tags, JSON-LD) @@ -18,6 +20,7 @@ SSG Starter is a production-ready static site template with blog support, SEO op - Dark theme with glass morphism effects ### Success Criteria + - Lighthouse SEO score > 95 - Lighthouse Accessibility score > 95 - Blog posts render from markdown @@ -28,6 +31,7 @@ SSG Starter is a production-ready static site template with blog support, SEO op ## Analysis ### Complexity Assessment + - **Overall Complexity:** Medium - **Key Challenges:** - CSS architecture with @layer requires careful organization @@ -35,10 +39,12 @@ SSG Starter is a production-ready static site template with blog support, SEO op - JSON-LD schemas must be valid ### Dependencies + - **External:** Astro 5, Google Fonts - **Internal:** SEO → BaseLayout → Pages ### Risks + - Browser support for backdrop-filter (mitigated with fallbacks) - Content collection type generation (handled by Astro) @@ -47,6 +53,7 @@ SSG Starter is a production-ready static site template with blog support, SEO op ## Phase 1 Scope ### Objectives + 1. Set up Astro project with static output 2. Create CSS design system with @layer 3. Build SEO component with meta tags @@ -56,6 +63,7 @@ SSG Starter is a production-ready static site template with blog support, SEO op 7. Create blog listing and post pages ### Deliverables + - [ ] `astro.config.mjs` - Static output configuration - [ ] `public/styles.css` - Complete CSS design system - [ ] `src/components/SEO.astro` - Meta tags component @@ -69,6 +77,7 @@ SSG Starter is a production-ready static site template with blog support, SEO op - [ ] `src/pages/blog/[slug].astro` - Post pages ### Out of Scope + - Server-side functionality - Database integration - Authentication @@ -115,6 +124,7 @@ SSG Starter is a production-ready static site template with blog support, SEO op ``` ### Technology Stack + - Astro 5 (static output) - Modern CSS (no preprocessors) - Markdown with frontmatter @@ -138,6 +148,7 @@ SSG Starter is a production-ready static site template with blog support, SEO op ## Next Steps After Phase 1 completion: + 1. Run Lighthouse audits 2. Test on multiple browsers 3. Add more blog posts diff --git a/examples/ssg-starter/.claude/tasks/phase-1-tasks.md b/examples/ssg-starter/.claude/tasks/phase-1-tasks.md index 14f6445..c484aed 100644 --- a/examples/ssg-starter/.claude/tasks/phase-1-tasks.md +++ b/examples/ssg-starter/.claude/tasks/phase-1-tasks.md @@ -1,27 +1,25 @@ # Phase 1 Tasks -Generated: 2024-02-21T10:15:00Z -Source: .claude/project-plan/phase_1.md +Generated: 2024-02-21T10:15:00Z Source: .claude/project-plan/phase_1.md --- ## Task Overview -| ID | Agent | Task | Est. Time | Status | -|----------|-------|-------------------------|-----------|--------| -| TASK-001 | init | Astro Configuration | 10 min | ✅ | -| TASK-002 | dev | CSS Design System | 30 min | ✅ | -| TASK-003 | dev | SEO Component | 20 min | ✅ | -| TASK-004 | dev | JSON-LD Component | 20 min | ✅ | -| TASK-005 | dev | Navigation Component | 15 min | ✅ | -| TASK-006 | dev | Footer Component | 10 min | ✅ | -| TASK-007 | dev | Base Layout | 15 min | ✅ | -| TASK-008 | dev | Content Collections | 15 min | ✅ | -| TASK-009 | dev | Homepage | 20 min | ✅ | -| TASK-010 | dev | Blog System | 30 min | ✅ | - -**Total Estimated Time:** ~3 hours -**Actual Time:** ~2.5 hours +| ID | Agent | Task | Est. Time | Status | +| -------- | ----- | -------------------- | --------- | ------ | +| TASK-001 | init | Astro Configuration | 10 min | ✅ | +| TASK-002 | dev | CSS Design System | 30 min | ✅ | +| TASK-003 | dev | SEO Component | 20 min | ✅ | +| TASK-004 | dev | JSON-LD Component | 20 min | ✅ | +| TASK-005 | dev | Navigation Component | 15 min | ✅ | +| TASK-006 | dev | Footer Component | 10 min | ✅ | +| TASK-007 | dev | Base Layout | 15 min | ✅ | +| TASK-008 | dev | Content Collections | 15 min | ✅ | +| TASK-009 | dev | Homepage | 20 min | ✅ | +| TASK-010 | dev | Blog System | 30 min | ✅ | + +**Total Estimated Time:** ~3 hours **Actual Time:** ~2.5 hours --- @@ -32,21 +30,24 @@ Source: .claude/project-plan/phase_1.md **Status:** ✅ Complete ### Description + Configure Astro for static site generation. ### Implementation + ```javascript // astro.config.mjs export default defineConfig({ site: 'https://example.com', output: 'static', build: { - inlineStylesheets: 'auto' - } + inlineStylesheets: 'auto', + }, }); ``` ### Files Created + - `astro.config.mjs` - `package.json` @@ -59,9 +60,11 @@ export default defineConfig({ **Status:** ✅ Complete ### Description + Create comprehensive CSS with @layer architecture. ### Implementation + ```css @layer reset, base, tokens, layout, components, utilities; @@ -77,9 +80,11 @@ Create comprehensive CSS with @layer architecture. ``` ### Files Created + - `public/styles.css` (400+ lines) ### Notes + - Used fluid typography with `clamp()` - Glass effect uses `backdrop-filter: blur(12px)` - Dark theme with pink/purple accent gradient @@ -93,9 +98,11 @@ Create comprehensive CSS with @layer architecture. **Status:** ✅ Complete ### Description + Create reusable SEO component with comprehensive meta tags. ### Implementation + ```astro --- interface Props { @@ -115,9 +122,11 @@ interface Props { ``` ### Files Created + - `src/components/SEO.astro` ### Meta Tags Included + - Primary (title, description, keywords) - Open Graph (og:title, og:image, etc.) - Twitter Cards @@ -134,9 +143,11 @@ interface Props { **Status:** ✅ Complete ### Description + Create JSON-LD structured data component. ### Implementation + ```astro --- const schema = { @@ -153,9 +164,11 @@ const schema = { ``` ### Files Created + - `src/components/JsonLD.astro` ### Schemas Included + - Organization - WebSite (with SearchAction) - Article (for blog posts) @@ -169,12 +182,15 @@ const schema = { **Status:** ✅ Complete ### Description + Create fixed navigation with glass effect on scroll. ### Files Created + - `src/components/Nav.astro` ### Features + - Fixed position - Glass effect on scroll (JavaScript) - Mobile-responsive @@ -188,6 +204,7 @@ Create fixed navigation with glass effect on scroll. **Status:** ✅ Complete ### Files Created + - `src/components/Footer.astro` --- @@ -199,12 +216,15 @@ Create fixed navigation with glass effect on scroll. **Status:** ✅ Complete ### Description + Create main layout that combines all components. ### Files Created + - `src/layouts/BaseLayout.astro` ### Structure + ``` BaseLayout ├── @@ -225,9 +245,11 @@ BaseLayout **Status:** ✅ Complete ### Description + Configure Astro content collections for blog posts. ### Implementation + ```typescript const posts = defineCollection({ schema: z.object({ @@ -240,6 +262,7 @@ const posts = defineCollection({ ``` ### Files Created + - `src/content/config.ts` - `src/content/posts/hello-world.md` - `src/content/posts/modern-css-architecture.md` @@ -253,12 +276,15 @@ const posts = defineCollection({ **Status:** ✅ Complete ### Description + Create homepage with hero and features sections. ### Files Created + - `src/pages/index.astro` ### Sections + - Hero (title, subtitle, CTAs) - Features (6 glass cards) - CTA section @@ -272,13 +298,16 @@ Create homepage with hero and features sections. **Status:** ✅ Complete ### Description + Create blog listing and individual post pages. ### Files Created + - `src/pages/blog/index.astro` - `src/pages/blog/[slug].astro` ### Features + - Sorted by date (newest first) - Draft support - Dynamic routes for posts @@ -290,7 +319,7 @@ Create blog listing and individual post pages. ``` ═══════════════════════════════════════════════════════════════════ - ⛔ PHASE 1 COMPLETE + ⛔ PHASE 1 COMPLETE ═══════════════════════════════════════════════════════════════════ Summary: diff --git a/examples/ssg-starter/CLAUDE.md b/examples/ssg-starter/CLAUDE.md index 8c78078..91bed52 100644 --- a/examples/ssg-starter/CLAUDE.md +++ b/examples/ssg-starter/CLAUDE.md @@ -4,9 +4,11 @@ ## Project Overview -**SSG Starter** is a production-ready static site template built with Astro. It demonstrates the Claude Code Sidekick workflow for building modern web projects. +**SSG Starter** is a production-ready static site template built with Astro. It +demonstrates the Claude Code Sidekick workflow for building modern web projects. ### Tech Stack + - **Framework:** Astro 5 (static output) - **Styling:** Modern CSS (@layer, custom properties) - **Content:** Markdown with frontmatter @@ -64,14 +66,14 @@ All design values are CSS custom properties: ### Key Classes -| Class | Purpose | -|-------|---------| -| `.glass` | Glass morphism card effect | -| `.container` | Max-width centered container | -| `.section` | Vertical padding for sections | -| `.grid` | CSS grid with responsive columns | -| `.btn` | Button base styles | -| `.prose` | Blog post content styling | +| Class | Purpose | +| ------------ | -------------------------------- | +| `.glass` | Glass morphism card effect | +| `.container` | Max-width centered container | +| `.section` | Vertical padding for sections | +| `.grid` | CSS grid with responsive columns | +| `.btn` | Button base styles | +| `.prose` | Blog post content styling | ## Content Collections @@ -94,10 +96,10 @@ Create `src/content/posts/my-post.md`: ```markdown --- -title: "My Post Title" -description: "Brief description" +title: 'My Post Title' +description: 'Brief description' publishedAt: 2024-02-21 -tags: ["tag1", "tag2"] +tags: ['tag1', 'tag2'] --- Content here... @@ -116,16 +118,19 @@ Every page includes: ## Coding Standards ### HTML + - Semantic elements (`
`, `
`, `