---
name: debugging-toolkit-smart-debug
description: "Use when working with debugging toolkit smart debug"
risk: critical
source: community
date_added: "2026-02-27"
---

## Use this skill when

- Working on debugging toolkit smart debug tasks or workflows
- Needing guidance, best practices, or checklists for debugging toolkit smart debug

## Do not use this skill when

- The task is unrelated to debugging toolkit smart debug
- You need a different domain or tool outside this scope

## Instructions

- Clarify goals, constraints, and required inputs.
- Apply relevant best practices and validate outcomes.
- Provide actionable steps and verification.
- If detailed examples are required, open `resources/implementation-playbook.md`.

You are an expert AI-assisted debugging specialist with deep knowledge of modern debugging tools, observability platforms, and automated root cause analysis.

## Context

Process issue from: $ARGUMENTS

Parse for:
- Error messages/stack traces
- Reproduction steps
- Affected components/services
- Performance characteristics
- Environment (dev/staging/production)
- Failure patterns (intermittent/consistent)

## Workflow

### 1. Initial Triage
Use Task tool (subagent_type="debugger") for AI-powered analysis:
- Error pattern recognition
- Stack trace analysis with probable causes
- Component dependency analysis
- Severity assessment
- Generate 3-5 ranked hypotheses
- Recommend debugging strategy

### 2. Observability Data Collection
For production/staging issues, gather:
- Error tracking (Sentry, Rollbar, Bugsnag)
- APM metrics (DataDog, New Relic, Dynatrace)
- Distributed traces (Jaeger, Zipkin, Honeycomb)
- Log aggregation (ELK, Splunk, Loki)
- Session replays (LogRocket, FullStory)

Query for:
- Error frequency/trends
- Affected user cohorts
- Environment-specific patterns
- Related errors/warnings
- Performance degradation correlation
- Deployment timeline correlation

### 3. Hypothesis Generation
For each hypothesis include:
- Probability score (0-100%)
- Supporting evidence from logs/traces/code
- Falsification criteria
- Testing approach
- Expected symptoms if true

Common categories:
- Logic errors (race conditions, null handling)
- State management (stale cache, incorrect transitions)
- Integration failures (API changes, timeouts, auth)
- Resource exhaustion (memory leaks, connection pools)
- Configuration drift (env vars, feature flags)
- Data corruption (schema mismatches, encoding)

### 4. Strategy Selection
Select based on issue characteristics:

**Interactive Debugging**: Reproducible locally → VS Code/Chrome DevTools, step-through
**Observability-Driven**: Production issues → Sentry/DataDog/Honeycomb, trace analysis
**Time-Travel**: Complex state issues → rr/Redux DevTools, record & replay
**Chaos Engineering**: Intermittent under load → Chaos Monkey/Gremlin, inject failures
**Statistical**: Small % of cases → Delta debugging, compare success vs failure

### 5. Intelligent Instrumentation
AI suggests optimal breakpoint/logpoint locations:
- Entry points to affected functionality
- Decision nodes where behavior diverges
- State mutation points
- External integration boundaries
- Error handling paths

Use conditional breakpoints and logpoints for production-like environments.

### 6. Production-Safe Techniques
**Dynamic Instrumentation**: OpenTelemetry spans, non-invasive attributes
**Feature-Flagged Debug Logging**: Conditional logging for specific users
**Sampling-Based Profiling**: Continuous profiling with minimal overhead (Pyroscope)
**Read-Only Debug Endpoints**: Protected by auth, rate-limited state inspection
**Gradual Traffic Shifting**: Canary deploy debug version to 10% traffic

### 7. Root Cause Analysis
AI-powered code flow analysis:
- Full execution path reconstruction
- Variable state tracking at decision points
- External dependency interaction analysis
- Timing/sequence diagram generation
- Code smell detection
- Similar bug pattern identification
- Fix complexity estimation

### 8. Fix Implementation
AI generates fix with:
- Code changes required
- Impact assessment
- Risk level
- Test coverage needs
- Rollback strategy

### 9. Validation
Post-fix verification:
- Run test suite
- Performance comparison (baseline vs fix)
- Canary deployment (monitor error rate)
- AI code review of fix

Success criteria:
- Tests pass
- No performance regression
- Error rate unchanged or decreased
- No new edge cases introduced

### 10. Prevention
- Generate regression tests using AI
- Update knowledge base with root cause
- Add monitoring/alerts for similar issues
- Document troubleshooting steps in runbook

## Example: Minimal Debug Session

```typescript
// Issue: "Checkout timeout errors (intermittent)"

// 1. Initial analysis
const analysis = await aiAnalyze({
  error: "Payment processing timeout",
  frequency: "5% of checkouts",
  environment: "production"
});
// AI suggests: "Likely N+1 query or external API timeout"

// 2. Gather observability data
const sentryData = await getSentryIssue("CHECKOUT_TIMEOUT");
const ddTraces = await getDataDogTraces({
  service: "checkout",
  operation: "process_payment",
  duration: ">5000ms"
});

// 3. Analyze traces
// AI identifies: 15+ sequential DB queries per checkout
// Hypothesis: N+1 query in payment method loading

// 4. Add instrumentation
span.setAttribute('debug.queryCount', queryCount);
span.setAttribute('debug.paymentMethodId', methodId);

// 5. Deploy to 10% traffic, monitor
// Confirmed: N+1 pattern in payment verification

// 6. AI generates fix
// Replace sequential queries with batch query

// 7. Validate
// - Tests pass
// - Latency reduced 70%
// - Query count: 15 → 1
```

## Output Format

Provide structured report:
1. **Issue Summary**: Error, frequency, impact
2. **Root Cause**: Detailed diagnosis with evidence
3. **Fix Proposal**: Code changes, risk, impact
4. **Validation Plan**: Steps to verify fix
5. **Prevention**: Tests, monitoring, documentation

Focus on actionable insights. Use AI assistance throughout for pattern recognition, hypothesis generation, and fix validation.

---

Issue to debug: $ARGUMENTS

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: decision-navigator
description: "Guide stuck or overwhelmed users through targeted branching questions until they reach concrete next steps."
category: planning
risk: safe
source: community
source_type: community
date_added: "2026-05-27"
---

# Decision Navigator

Help users who feel stuck or overwhelmed by guiding them through a structured branching exploration
of their situation — one clear question at a time — until they arrive at concrete, actionable steps.

## Core Philosophy

Most people go blank not because they're incapable, but because the problem space feels infinite.
Your job is to collapse that space progressively: ask one clarifying question, offer 3–5 distinct
paths, let them choose, and repeat — getting more specific each level — until you reach a leaf
where concrete steps make sense.

Never overwhelm with a wall of options or advice upfront. Navigate, don't lecture.

---

## When to Use This Skill

Use this skill whenever a user feels stuck, overwhelmed, or does not know where to start.
Trigger on phrases like "I don't know what to do", "I want to X but don't know how",
"I'm not sure where to begin", "help me figure out...", "I feel lost about...", or broad
open-ended goals like "I want to start a business", "I want to change careers", "I want to
learn something new", or "I need to make a decision about X".

Do not wait for the user to ask a precise question. If they seem stuck or overwhelmed, use
this skill.

## The Process

### Step 1 — Acknowledge and orient (1–2 sentences)

Reflect the situation back briefly so the user feels heard. Don't give advice yet.

> "Changing careers is a big one — lots of directions it could go. Let me help you narrow it down."

### Step 2 — Ask one clarifying question

Ask the single most useful question to understand *what kind* of problem this actually is.
Frame it as a choice between 3–5 concrete options, not open-ended.

**Option labels must be short** — 2 to 6 words max. No explanations inside the bullet.
The question itself carries the context; the options are just the choices.

**Good question format:**
> "What's driving this for you right now?
> - Unhappy in my current role
> - Want to earn more
> - Want more flexibility
> - Found a new interest
> - Not sure yet"

**Bad question format:**
> "Tell me more about your situation." ← too open, doesn't reduce the space

> "- Simplicity: I want the easiest setup with zero server management." ← option labels should never have colons or sub-explanations

### Step 2b — Extract before you ask

If the user's message already contains useful information (they described constraints, named
platforms, listed requirements), pull that out first. Don't make them re-answer what they
already told you.

> "Ok so you've got: Docker container ready, needs auth + multi-tenant DB, websockets, and
> the client wants AWS or GCP. That's a lot. What's the scariest part right now?
> - Choosing between AWS and GCP
> - Understanding how all the pieces connect
> - Actually deploying the container
> - Not sure where to even begin"

### Step 3 — Branch based on their answer

After they choose, go one level deeper. Each level should feel more specific.

Typical depth: 3–4 levels before reaching actionable steps.

**Level 1** — What kind of problem is this? (motivation, constraint, knowledge gap, fear, resources...)
**Level 2** — What's the most important factor for them? (urgency, risk tolerance, resources available...)
**Level 3** — What's their current situation / starting point?
**Level 4** (leaf) — Give concrete steps

### Step 4 — Deliver concrete steps at the leaf

When you've narrowed things down enough (usually 3–4 questions in), stop branching and give
3–6 specific, ordered action steps. These should be immediately doable, not vague advice.

**Good leaf output:**
> Based on what you've shared — you're unhappy in your current role, want to stay in tech, and
> have about 3 months before you need to move — here's where to start:
>
> 1. Spend one hour this week writing down what specifically drains you vs. energizes you at work.
> 2. Look at 3 job postings in roles that seem interesting — note what skills overlap with yours.
> 3. Reach out to 1–2 people doing those roles on LinkedIn for a 20-min conversation.
> 4. Set a decision deadline: commit to applying somewhere within 6 weeks.
> 5. Tell one trusted person about your plan so you have accountability.

**Bad leaf output:**
> "You should network more and update your resume." ← too vague

---

## Branching Guidelines

### How to design your questions

- **Short option labels** — 2 to 6 words. Never a colon + explanation inside a bullet.
  The question sets the context; options are just the fork in the road.
- **Mutually exclusive options** — each choice should lead down a genuinely different path
- **Concrete labels** — "Earn more money" not "financial reasons"
- **Cover the realistic space** — include the uncomfortable options (e.g. "Scared of failing")
- **Always offer an escape** — include "Not sure yet" so no one feels forced
- **Extract first** — if the user already gave you info, acknowledge it before asking the next question.
  Summarize what you know in 1–2 lines, then ask only what's still missing.

### When to branch vs. when to go straight to steps

Go straight to concrete steps when:
- The user's situation is already specific enough (they've answered 3+ questions)
- The remaining branches would all lead to the same advice
- The user says something like "just tell me what to do"

Keep branching when:
- The advice would be meaningfully different depending on their answer
- You'd be guessing at key constraints (budget, timeline, risk tolerance, etc.)
- The problem space still feels large

### How many options per question

- **3 options** — when the distinctions are clear-cut
- **4–5 options** — when the space is genuinely varied
- **Never more than 5** — more than that is overwhelming (the whole problem we're solving)

---

## Tone and Style

- Warm but efficient — not therapist-soft, not consultant-cold
- Short sentences. No jargon.
- Reflect their words back to them (if they said "burned out", use "burned out" not "fatigued")
- Never judge the path they choose
- If they seem emotionally distressed (not just confused), acknowledge that before navigating

---

## Format

Present choices as a short list, not prose:

```
[Question]

- Option A
- Option B
- Option C
- Something else / not sure
```

At the leaf, use a numbered list for steps. Start with the number ("1.") not a bullet.

Keep the whole interaction feeling like a conversation, not a form.

---

## Example Flow

**User:** I want to start a business but I have no idea where to start.

**Claude (Level 1):**
Starting a business means different things to different people. What's the main thing drawing you to it?

- I have a specific idea I want to build
- I want freedom / to be my own boss
- I want to make more money than my job pays
- I'm not sure yet — I just know I want something different

**User:** I have a specific idea I want to build.

**Claude (Level 2):**
Got it. Where are you in terms of the idea itself?

- It's clear in my head but I haven't done anything yet
- I've talked to some people about it but haven't built anything
- I've started building / have a prototype
- I've tried before and it didn't work out

**User:** It's clear in my head but I haven't done anything yet.

**Claude (Level 3):**
One more thing — what feels like the biggest blocker right now?

- I don't know if the idea is actually good
- I don't know how to build it / lack technical skills
- I'm worried about the financial risk
- I don't know the first practical step to take

**User:** I don't know if the idea is actually good.

**Claude (Leaf):**
That's the right thing to worry about first — most ideas fail on this, not execution.
Here's how to find out quickly:

1. Write one sentence describing who your customer is and what problem you solve for them.
2. Find 5 people who match that description. Not friends — people who'd actually pay.
3. Ask them: "Do you have this problem? How do you currently deal with it?"
4. Do NOT pitch your solution yet. Just listen. If they describe your problem unprompted, that's signal.
5. After 5 conversations, you'll know if this is real. If 3+ people have the problem badly, keep going.

---

## Edge Cases

**User gives a very vague situation** ("I don't know what to do with my life")
→ Start even broader: ask what *area* of life feels most stuck (work, relationships, health, purpose, finances)

**User picks "something else"**
→ Ask them to describe it briefly, then fit their answer into the next level of branching

**User wants to explore multiple paths**
→ Finish one path to the leaf, then offer: "Want to explore what the [other option] path looks like too?"

**User is clearly in distress**
→ Pause the navigation. Acknowledge first. Ask if they want to talk through how they're feeling or
  if they'd find it helpful to focus on practical next steps.

## Limitations

- This skill helps structure uncertainty; it does not replace professional legal, medical, financial, or mental-health advice.
- It should not force branching when the user has already requested a specific action or direct answer.
- It depends on the user's stated preferences and constraints, so recommendations should stay tentative when important facts are missing.


---
name: deep-research
description: "Run autonomous research tasks that plan, search, read, and synthesize information into comprehensive reports."
risk: safe
source: "https://github.com/sanjay3290/ai-skills/tree/main/skills/deep-research"
date_added: "2026-02-27"
---

# Gemini Deep Research Skill

Run autonomous research tasks that plan, search, read, and synthesize information into comprehensive reports.

## When to Use This Skill

Use this skill when:
- Performing market analysis
- Conducting competitive landscaping
- Creating literature reviews
- Doing technical research
- Performing due diligence
- Need detailed, cited research reports

## Requirements

- Python 3.8+
- httpx: `pip install -r requirements.txt`
- GEMINI_API_KEY environment variable

## Setup

1. Get a Gemini API key from [Google AI Studio](https://aistudio.google.com/)
2. Set the environment variable:
   ```bash
   export GEMINI_API_KEY=your-api-key-here
   ```
   Or create a `.env` file in the skill directory.

## Usage

### Start a research task
```bash
python3 scripts/research.py --query "Research the history of Kubernetes"
```

### With structured output format
```bash
python3 scripts/research.py --query "Compare Python web frameworks" \
  --format "1. Executive Summary\n2. Comparison Table\n3. Recommendations"
```

### Stream progress in real-time
```bash
python3 scripts/research.py --query "Analyze EV battery market" --stream
```

### Start without waiting
```bash
python3 scripts/research.py --query "Research topic" --no-wait
```

### Check status of running research
```bash
python3 scripts/research.py --status <interaction_id>
```

### Wait for completion
```bash
python3 scripts/research.py --wait <interaction_id>
```

### Continue from previous research
```bash
python3 scripts/research.py --query "Elaborate on point 2" --continue <interaction_id>
```

### List recent research
```bash
python3 scripts/research.py --list
```

## Output Formats

- **Default**: Human-readable markdown report
- **JSON** (`--json`): Structured data for programmatic use
- **Raw** (`--raw`): Unprocessed API response

## Cost & Time

| Metric | Value |
|--------|-------|
| Time | 2-10 minutes per task |
| Cost | $2-5 per task (varies by complexity) |
| Token usage | ~250k-900k input, ~60k-80k output |

## Best Use Cases

- Market analysis and competitive landscaping
- Technical literature reviews
- Due diligence research
- Historical research and timelines
- Comparative analysis (frameworks, products, technologies)

## Workflow

1. User requests research → Run `--query "..."`
2. Inform user of estimated time (2-10 minutes)
3. Monitor with `--stream` or poll with `--status`
4. Return formatted results
5. Use `--continue` for follow-up questions

## Exit Codes

- **0**: Success
- **1**: Error (API error, config issue, timeout)
- **130**: Cancelled by user (Ctrl+C)

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: deepapi
description: "Use DeepAPI for supported scraping, research, and email workflows with explicit credentials and approval."
category: research
risk: critical
source: community
source_repo: davidondrej/skills
source_type: community
date_added: "2026-07-07"
author: davidondrej
tags: [deepapi, scraping, email, api]
tools: [claude, codex]
license: "MIT"
license_source: "https://github.com/davidondrej/skills/blob/main/LICENSE"
version: b17ad5148ab7
---

# DeepAPI

## When to Use

- Use when the task needs supported DeepAPI scraping, research, or email endpoints.
- Use when the user has provided or confirmed the required DeepAPI credentials and scope.

Use this skill when the user asks you to scrape public web data or draft/read/send email through DeepAPI.

## Version Pinning

- The installed copy is pinned to the `version` value in the frontmatter above.
- If a request or API response reports a different `skillVersion`, report the mismatch and
  stop. Do not fetch, overwrite, or otherwise self-update this `SKILL.md`.
- Updates must arrive through the reviewed repository release process, with explicit user
  approval for any package or repository update.

## Required Environment

- Read `DEEPAPI_API_BASE_URL` from the environment.
- Read `DEEPAPI_API_KEY` from the environment.
- If either value is missing, stop and ask the user for setup.
- Never commit, print, log, paste, or expose `DEEPAPI_API_KEY`.

## Request Rules

- Send `Authorization: Bearer $DEEPAPI_API_KEY` on every request.
- Send `Content-Type: application/json` when sending JSON.
- Send a unique `Idempotency-Key` for every `POST`.
- For scrape work, set explicit `maxCostUsd` or `maxCostMicrousd`.
- Keep email as `send: false` or `mode: draft` unless the user explicitly approves sending.
- Do not pass inbox IDs. Use `emailIdentityId` or omit it.

## Execution Loop

1. Choose the narrowest endpoint that matches the task.
2. Build the request from the endpoint schema and examples below.
3. Run the request with the required headers.
4. If the response has `status: running`, wait `next.afterSecs` and call `next.method` + `next.path` until `status` is `succeeded` or `failed`.
5. If `error.retryable` is true, wait `error.retryAfterSecs` before retrying.
6. If the response is HTTP 402 with `error.code: insufficient_credits`, stop and ask the user to top up credits at https://deepapi.co/credits. After top-up, retry with the same `Idempotency-Key`.
7. Report `requestId`, `status`, `debitMicrousd`, `costFinal`, and the useful part of `output`.

## Endpoints

| Method | Path | Scope | Cost |
| --- | --- | --- | --- |
| POST | `/v1/scrape/website` | `scrape:website` | Set `maxCostUsd: "1.00"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/linkedin/profile` | `scrape:linkedin` | Set `maxCostUsd: "0.05"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/github/profile` | `scrape:github` | Set `maxCostUsd: "0.03"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/twitter/search` | `scrape:twitter` | Set `maxCostUsd: "0.03"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/linkedin/jobs` | `scrape:linkedin` | Set `maxCostUsd: "0.05"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/linkedin/company` | `scrape:linkedin` | Set `maxCostUsd: "0.05"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/linkedin/people` | `scrape:linkedin` | Set `maxCostUsd: "0.50"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/linkedin/posts` | `scrape:linkedin` | Set `maxCostUsd: "0.05"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/twitter/user` | `scrape:twitter` | Set `maxCostUsd: "0.05"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/twitter/replies` | `scrape:twitter` | Set `maxCostUsd: "0.20"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/youtube/transcript` | `scrape:youtube` | Set `maxCostUsd: "0.05"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/youtube/channel` | `scrape:youtube` | Set `maxCostUsd: "0.30"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/youtube/search` | `scrape:youtube` | Set `maxCostUsd: "0.10"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/linkedin` | `scrape:linkedin` | Set `maxCostUsd: "0.05"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/github` | `scrape:github` | Set `maxCostUsd: "0.03"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/scrape/twitter` | `scrape:twitter` | Set `maxCostUsd: "0.03"` unless the user gives a different cap. The route requires maxCostUsd or maxCostMicrousd as the customer spend cap. The final debit is capped by that amount and reported as debitMicrousd. |
| POST | `/v1/email/send` | `email:send` | Uses configured email unit pricing; the route does not accept maxCostUsd. Check debitMicrousd in the response. |
| GET | `/v1/email/messages` | `email:read` | Read route returns debitMicrousd 0. |
| GET | `/v1/email/drafts` | `email:read` | Read route returns debitMicrousd 0. |
| POST | `/v1/email/drafts/{draftId}/send` | `email:send` | Uses configured email unit pricing; the route does not accept maxCostUsd. Check debitMicrousd in the response. |
| POST | `/v1/research/deep` | `research:deep` | Set `maxCostUsd: "0.10"` unless the user gives a different cap. Defaults to maxCostUsd 0.10. Pass maxCostUsd or maxCostMicrousd to choose a different customer spend cap. The final debit is capped and reported as debitMicrousd. |
| POST | `/v1/generate/image` | `generate:image` | Set `maxCostUsd: "0.20"` unless the user gives a different cap. Defaults to maxCostUsd 0.20. Pass maxCostUsd or maxCostMicrousd to choose a different customer spend cap. The final debit is capped and reported as debitMicrousd. |
| POST | `/v1/search/web` | `search:web` | Set `maxCostUsd: "0.05"` unless the user gives a different cap. Defaults to maxCostUsd 0.05. Pass maxCostUsd or maxCostMicrousd to choose a different customer spend cap. The final debit is capped and reported as debitMicrousd. |
| GET | `/v1/requests/{requestId}` | `same key` | Status polling does not create a new debit. |

## Endpoint Details

### Scrape Website

Use `POST /v1/scrape/website`. Crawl website pages and return clean text and markdown per page.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running and report the final debitMicrousd.

Example body:
```json
{
  "maxCostUsd": "1.00",
  "waitForFinishSecs": 60,
  "urls": [
    "https://example.com"
  ],
  "maxPages": 1
}
```

### Scrape LinkedIn Profile

Use `POST /v1/scrape/linkedin/profile`. Scrape public LinkedIn profile details.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running and report the final debitMicrousd.

Example body:
```json
{
  "maxCostUsd": "0.05",
  "waitForFinishSecs": 60,
  "profiles": [
    "williamhgates"
  ]
}
```

### Scrape GitHub Profile

Use `POST /v1/scrape/github/profile`. Scrape public GitHub profile details.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running and report the final debitMicrousd.

Example body:
```json
{
  "maxCostUsd": "0.03",
  "waitForFinishSecs": 60,
  "usernames": [
    "octocat"
  ]
}
```

### Search X/Twitter

Use `POST /v1/scrape/twitter/search`. Scrape X/Twitter posts from a search query or account handles.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running and report the final debitMicrousd.

Example body:
```json
{
  "maxCostUsd": "0.03",
  "waitForFinishSecs": 60,
  "handles": [
    "nasa"
  ],
  "maxItems": 1,
  "sort": "latest"
}
```

### Scrape LinkedIn Jobs

Use `POST /v1/scrape/linkedin/jobs`. Scrape public LinkedIn job listings for a search query.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running and report the final debitMicrousd.

Example body:
```json
{
  "maxCostUsd": "0.05",
  "waitForFinishSecs": 60,
  "query": "software engineer",
  "location": "United States",
  "maxItems": 5
}
```

### Scrape LinkedIn Company

Use `POST /v1/scrape/linkedin/company`. Scrape public LinkedIn company pages for firmographic details.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running and report the final debitMicrousd.

Example body:
```json
{
  "maxCostUsd": "0.05",
  "waitForFinishSecs": 60,
  "companies": [
    "microsoft"
  ]
}
```

### Search LinkedIn People

Use `POST /v1/scrape/linkedin/people`. Search public LinkedIn profiles by role, location, company, or school. Requires maxCostUsd of at least 0.50.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running and report the final debitMicrousd.

Example body:
```json
{
  "maxCostUsd": "0.50",
  "waitForFinishSecs": 60,
  "titles": [
    "Founder"
  ],
  "locations": [
    "San Francisco"
  ],
  "maxItems": 5
}
```

### Scrape LinkedIn Posts

Use `POST /v1/scrape/linkedin/posts`. Scrape recent public posts from LinkedIn profiles or company pages.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running and report the final debitMicrousd.

Example body:
```json
{
  "maxCostUsd": "0.05",
  "waitForFinishSecs": 60,
  "profiles": [
    "williamhgates"
  ],
  "maxItems": 3
}
```

### Scrape X/Twitter User

Use `POST /v1/scrape/twitter/user`. Scrape public X/Twitter account profiles, with optional follower and following lists.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running and report the final debitMicrousd.

Example body:
```json
{
  "maxCostUsd": "0.05",
  "waitForFinishSecs": 60,
  "handles": [
    "nasa"
  ]
}
```

### Scrape X/Twitter Replies

Use `POST /v1/scrape/twitter/replies`. Scrape the public reply thread of an X/Twitter post. Requires maxCostUsd of at least 0.20.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running and report the final debitMicrousd.

Example body:
```json
{
  "maxCostUsd": "0.20",
  "waitForFinishSecs": 60,
  "url": "https://x.com/NASA/status/1234567890123456789",
  "maxItems": 5
}
```

### Scrape YouTube Transcript

Use `POST /v1/scrape/youtube/transcript`. Scrape the transcript of a YouTube video as plain text plus timed segments. Videos without captions return an empty result.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running and report the final debitMicrousd.

Example body:
```json
{
  "maxCostUsd": "0.05",
  "waitForFinishSecs": 60,
  "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}
```

### Scrape YouTube Channel

Use `POST /v1/scrape/youtube/channel`. Scrape a YouTube channel's stats and recent videos. Each video item includes subscriber and channel totals.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running and report the final debitMicrousd.

Example body:
```json
{
  "maxCostUsd": "0.30",
  "waitForFinishSecs": 60,
  "channels": [
    "mkbhd"
  ],
  "maxItems": 3
}
```

### Search YouTube

Use `POST /v1/scrape/youtube/search`. Search YouTube videos by keyword and return video metadata.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running and report the final debitMicrousd.

Example body:
```json
{
  "maxCostUsd": "0.10",
  "waitForFinishSecs": 60,
  "query": "ai agents",
  "sort": "views",
  "maxItems": 3
}
```

### Scrape LinkedIn

Use `POST /v1/scrape/linkedin`. Backward-compatible alias for LinkedIn profile scraping.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running and report the final debitMicrousd.

Example body:
```json
{
  "maxCostUsd": "0.05",
  "waitForFinishSecs": 60,
  "profiles": [
    "williamhgates"
  ]
}
```

### Scrape GitHub

Use `POST /v1/scrape/github`. Backward-compatible alias for GitHub profile scraping.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running and report the final debitMicrousd.

Example body:
```json
{
  "maxCostUsd": "0.03",
  "waitForFinishSecs": 60,
  "usernames": [
    "octocat"
  ]
}
```

### Scrape Twitter

Use `POST /v1/scrape/twitter`. Backward-compatible alias for X/Twitter search scraping.

Side effects: Starts a scrape run and may debit credits when the run finishes.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Set an explicit customer spend cap with maxCostUsd or maxCostMicrousd before starting a scrape.
- Start with small result caps such as maxItems or capability-specific limits.
- Poll next.path while status is running and report the final debitMicrousd.

Example body:
```json
{
  "maxCostUsd": "0.03",
  "waitForFinishSecs": 60,
  "handles": [
    "nasa"
  ],
  "maxItems": 1,
  "sort": "latest"
}
```

### Send Email

Use `POST /v1/email/send`. Create an email draft from a workspace email identity; set send=true to send it.

Side effects: Creates a draft, or sends an email when direct send is approved.
Polling: This route returns a terminal envelope directly.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Keep send=false or mode=draft unless the user explicitly approves sending.
- Do not pass inboxId or inbox_id; use emailIdentityId or the workspace default.
- Attachments, hidden HTML, image HTML, URL shorteners, and high-risk direct sends are blocked by policy.

Example body:
```json
{
  "to": "<email-address>",
  "subject": "Quick hello",
  "text": "Hi, this is a draft from my agent.",
  "send": false
}
```

### Receive Email

Use `GET /v1/email/messages`. Read messages for a workspace email identity.

Side effects: Reads messages only.
Polling: This route returns a terminal envelope directly.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Do not pass inboxId or inbox_id; use emailIdentityId or the workspace default.

### List Drafts

Use `GET /v1/email/drafts`. List pending email drafts for a workspace email identity.

Side effects: Reads drafts only.
Polling: This route returns a terminal envelope directly.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Do not pass inboxId or inbox_id; use emailIdentityId or the workspace default.

### Send Draft

Use `POST /v1/email/drafts/{draftId}/send`. Approve and send an existing draft by draftId after review.

Side effects: Sends the reviewed draft as a real email when direct send is approved.
Polling: This route returns a terminal envelope directly.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Only send a draft after the user explicitly approves that draft.
- Do not pass inboxId or inbox_id; use emailIdentityId or the workspace default.
- Sending re-checks recipient and content policy against the stored draft; blocked drafts stay drafts.

Example body:
```json
{}
```

### Deep Research

Use `POST /v1/research/deep`. Answer a research question with current web evidence.

Side effects: Runs a paid web research request and debits credits when finished.
Polling: This route returns a terminal envelope directly.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Use query for the research question and context only for relevant background.
- Set maxCostUsd when you need a lower or higher spend cap than the default.
- Report debitMicrousd and summarize the returned sources when sources are present.

Example body:
```json
{
  "query": "What changed in EU AI Act compliance timelines for API startups?",
  "context": "We sell API tooling to EU customers.",
  "maxCostUsd": "0.10"
}
```

### Generate Image

Use `POST /v1/generate/image`. Generate an image from a text prompt.

Side effects: Runs a paid image generation request and debits credits when finished.
Polling: This route returns a terminal envelope directly.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Describe the image you want in prompt, including style and composition.
- Set maxCostUsd when you need a lower or higher spend cap than the default.
- output.images contains base64 data URLs; save them to files instead of printing them.

Example body:
```json
{
  "prompt": "A minimal flat illustration of a rocket launching from a laptop screen",
  "maxCostUsd": "0.20"
}
```

### Web Search

Use `POST /v1/search/web`. Search the web and return ranked results with title, url, and snippet.

Side effects: Runs a paid web search request and debits credits when finished.
Polling: This route returns a terminal envelope directly.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Send a unique Idempotency-Key for every POST.
- Use query for the search terms only; keep it under 500 characters.
- Set maxCostUsd when you need a lower or higher spend cap than the default.
- Treat snippets as page summaries; open a result URL when you need the full content.

Example body:
```json
{
  "query": "latest stable Node.js LTS version",
  "maxResults": 3,
  "maxCostUsd": "0.05"
}
```

### Request Status

Use `GET /v1/requests/{requestId}`. Poll a running request by requestId.

Side effects: Reads or refreshes request status.
Polling: If status is running, wait next.afterSecs and call next.method next.path until status is succeeded or failed.

Safety:
- Send Authorization: Bearer $DEEPAPI_API_KEY and never expose the key.
- Only poll request ids created by the same API key.

Example query: `waitForFinishSecs=60`

## Limitations

- Adapted from `davidondrej/skills`; verify local paths, tools, credentials, and agent features before acting.
- For commands, remote access, scheduling, browser automation, or file-changing workflows, get explicit user approval and confirm the target environment first.


---
name: defi-protocol-templates
description: "Implement DeFi protocols with production-ready templates for staking, AMMs, governance, and lending systems. Use when building decentralized finance applications or smart contract protocols."
risk: critical
source: community
date_added: "2026-02-27"
---

# DeFi Protocol Templates

Production-ready templates for common DeFi protocols including staking, AMMs, governance, lending, and flash loans.

## Do not use this skill when

- The task is unrelated to defi protocol templates
- You need a different domain or tool outside this scope

## Instructions

- Clarify goals, constraints, and required inputs.
- Apply relevant best practices and validate outcomes.
- Provide actionable steps and verification.
- If detailed examples are required, open `resources/implementation-playbook.md`.

## Use this skill when

- Building staking platforms with reward distribution
- Implementing AMM (Automated Market Maker) protocols
- Creating governance token systems
- Developing lending/borrowing protocols
- Integrating flash loan functionality
- Launching yield farming platforms

## Staking Contract

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract StakingRewards is ReentrancyGuard, Ownable {
    IERC20 public stakingToken;
    IERC20 public rewardsToken;

    uint256 public rewardRate = 100; // Rewards per second
    uint256 public lastUpdateTime;
    uint256 public rewardPerTokenStored;

    mapping(address => uint256) public userRewardPerTokenPaid;
    mapping(address => uint256) public rewards;
    mapping(address => uint256) public balances;

    uint256 private _totalSupply;

    event Staked(address indexed user, uint256 amount);
    event Withdrawn(address indexed user, uint256 amount);
    event RewardPaid(address indexed user, uint256 reward);

    constructor(address _stakingToken, address _rewardsToken) {
        stakingToken = IERC20(_stakingToken);
        rewardsToken = IERC20(_rewardsToken);
    }

    modifier updateReward(address account) {
        rewardPerTokenStored = rewardPerToken();
        lastUpdateTime = block.timestamp;

        if (account != address(0)) {
            rewards[account] = earned(account);
            userRewardPerTokenPaid[account] = rewardPerTokenStored;
        }
        _;
    }

    function rewardPerToken() public view returns (uint256) {
        if (_totalSupply == 0) {
            return rewardPerTokenStored;
        }
        return rewardPerTokenStored +
            ((block.timestamp - lastUpdateTime) * rewardRate * 1e18) / _totalSupply;
    }

    function earned(address account) public view returns (uint256) {
        return (balances[account] *
            (rewardPerToken() - userRewardPerTokenPaid[account])) / 1e18 +
            rewards[account];
    }

    function stake(uint256 amount) external nonReentrant updateReward(msg.sender) {
        require(amount > 0, "Cannot stake 0");
        _totalSupply += amount;
        balances[msg.sender] += amount;
        stakingToken.transferFrom(msg.sender, address(this), amount);
        emit Staked(msg.sender, amount);
    }

    function withdraw(uint256 amount) public nonReentrant updateReward(msg.sender) {
        require(amount > 0, "Cannot withdraw 0");
        _totalSupply -= amount;
        balances[msg.sender] -= amount;
        stakingToken.transfer(msg.sender, amount);
        emit Withdrawn(msg.sender, amount);
    }

    function getReward() public nonReentrant updateReward(msg.sender) {
        uint256 reward = rewards[msg.sender];
        if (reward > 0) {
            rewards[msg.sender] = 0;
            rewardsToken.transfer(msg.sender, reward);
            emit RewardPaid(msg.sender, reward);
        }
    }

    function exit() external {
        withdraw(balances[msg.sender]);
        getReward();
    }
}
```

## AMM (Automated Market Maker)

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract SimpleAMM {
    IERC20 public token0;
    IERC20 public token1;

    uint256 public reserve0;
    uint256 public reserve1;

    uint256 public totalSupply;
    mapping(address => uint256) public balanceOf;

    event Mint(address indexed to, uint256 amount);
    event Burn(address indexed from, uint256 amount);
    event Swap(address indexed trader, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out);

    constructor(address _token0, address _token1) {
        token0 = IERC20(_token0);
        token1 = IERC20(_token1);
    }

    function addLiquidity(uint256 amount0, uint256 amount1) external returns (uint256 shares) {
        token0.transferFrom(msg.sender, address(this), amount0);
        token1.transferFrom(msg.sender, address(this), amount1);

        if (totalSupply == 0) {
            shares = sqrt(amount0 * amount1);
        } else {
            shares = min(
                (amount0 * totalSupply) / reserve0,
                (amount1 * totalSupply) / reserve1
            );
        }

        require(shares > 0, "Shares = 0");
        _mint(msg.sender, shares);
        _update(
            token0.balanceOf(address(this)),
            token1.balanceOf(address(this))
        );

        emit Mint(msg.sender, shares);
    }

    function removeLiquidity(uint256 shares) external returns (uint256 amount0, uint256 amount1) {
        uint256 bal0 = token0.balanceOf(address(this));
        uint256 bal1 = token1.balanceOf(address(this));

        amount0 = (shares * bal0) / totalSupply;
        amount1 = (shares * bal1) / totalSupply;

        require(amount0 > 0 && amount1 > 0, "Amount0 or amount1 = 0");

        _burn(msg.sender, shares);
        _update(bal0 - amount0, bal1 - amount1);

        token0.transfer(msg.sender, amount0);
        token1.transfer(msg.sender, amount1);

        emit Burn(msg.sender, shares);
    }

    function swap(address tokenIn, uint256 amountIn) external returns (uint256 amountOut) {
        require(tokenIn == address(token0) || tokenIn == address(token1), "Invalid token");

        bool isToken0 = tokenIn == address(token0);
        (IERC20 tokenIn_, IERC20 tokenOut, uint256 resIn, uint256 resOut) = isToken0
            ? (token0, token1, reserve0, reserve1)
            : (token1, token0, reserve1, reserve0);

        tokenIn_.transferFrom(msg.sender, address(this), amountIn);

        // 0.3% fee
        uint256 amountInWithFee = (amountIn * 997) / 1000;
        amountOut = (resOut * amountInWithFee) / (resIn + amountInWithFee);

        tokenOut.transfer(msg.sender, amountOut);

        _update(
            token0.balanceOf(address(this)),
            token1.balanceOf(address(this))
        );

        emit Swap(msg.sender, isToken0 ? amountIn : 0, isToken0 ? 0 : amountIn, isToken0 ? 0 : amountOut, isToken0 ? amountOut : 0);
    }

    function _mint(address to, uint256 amount) private {
        balanceOf[to] += amount;
        totalSupply += amount;
    }

    function _burn(address from, uint256 amount) private {
        balanceOf[from] -= amount;
        totalSupply -= amount;
    }

    function _update(uint256 res0, uint256 res1) private {
        reserve0 = res0;
        reserve1 = res1;
    }

    function sqrt(uint256 y) private pure returns (uint256 z) {
        if (y > 3) {
            z = y;
            uint256 x = y / 2 + 1;
            while (x < z) {
                z = x;
                x = (y / x + x) / 2;
            }
        } else if (y != 0) {
            z = 1;
        }
    }

    function min(uint256 x, uint256 y) private pure returns (uint256) {
        return x <= y ? x : y;
    }
}
```

## Governance Token

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract GovernanceToken is ERC20Votes, Ownable {
    constructor() ERC20("Governance Token", "GOV") ERC20Permit("Governance Token") {
        _mint(msg.sender, 1000000 * 10**decimals());
    }

    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal override(ERC20Votes) {
        super._afterTokenTransfer(from, to, amount);
    }

    function _mint(address to, uint256 amount) internal override(ERC20Votes) {
        super._mint(to, amount);
    }

    function _burn(address account, uint256 amount) internal override(ERC20Votes) {
        super._burn(account, amount);
    }
}

contract Governor is Ownable {
    GovernanceToken public governanceToken;

    struct Proposal {
        uint256 id;
        address proposer;
        string description;
        uint256 forVotes;
        uint256 againstVotes;
        uint256 startBlock;
        uint256 endBlock;
        bool executed;
        mapping(address => bool) hasVoted;
    }

    uint256 public proposalCount;
    mapping(uint256 => Proposal) public proposals;

    uint256 public votingPeriod = 17280; // ~3 days in blocks
    uint256 public proposalThreshold = 100000 * 10**18;

    event ProposalCreated(uint256 indexed proposalId, address proposer, string description);
    event VoteCast(address indexed voter, uint256 indexed proposalId, bool support, uint256 weight);
    event ProposalExecuted(uint256 indexed proposalId);

    constructor(address _governanceToken) {
        governanceToken = GovernanceToken(_governanceToken);
    }

    function propose(string memory description) external returns (uint256) {
        require(
            governanceToken.getPastVotes(msg.sender, block.number - 1) >= proposalThreshold,
            "Proposer votes below threshold"
        );

        proposalCount++;
        Proposal storage newProposal = proposals[proposalCount];
        newProposal.id = proposalCount;
        newProposal.proposer = msg.sender;
        newProposal.description = description;
        newProposal.startBlock = block.number;
        newProposal.endBlock = block.number + votingPeriod;

        emit ProposalCreated(proposalCount, msg.sender, description);
        return proposalCount;
    }

    function vote(uint256 proposalId, bool support) external {
        Proposal storage proposal = proposals[proposalId];
        require(block.number >= proposal.startBlock, "Voting not started");
        require(block.number <= proposal.endBlock, "Voting ended");
        require(!proposal.hasVoted[msg.sender], "Already voted");

        uint256 weight = governanceToken.getPastVotes(msg.sender, proposal.startBlock);
        require(weight > 0, "No voting power");

        proposal.hasVoted[msg.sender] = true;

        if (support) {
            proposal.forVotes += weight;
        } else {
            proposal.againstVotes += weight;
        }

        emit VoteCast(msg.sender, proposalId, support, weight);
    }

    function execute(uint256 proposalId) external {
        Proposal storage proposal = proposals[proposalId];
        require(block.number > proposal.endBlock, "Voting not ended");
        require(!proposal.executed, "Already executed");
        require(proposal.forVotes > proposal.againstVotes, "Proposal failed");

        proposal.executed = true;

        // Execute proposal logic here

        emit ProposalExecuted(proposalId);
    }
}
```

## Flash Loan

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IFlashLoanReceiver {
    function executeOperation(
        address asset,
        uint256 amount,
        uint256 fee,
        bytes calldata params
    ) external returns (bool);
}

contract FlashLoanProvider {
    IERC20 public token;
    uint256 public feePercentage = 9; // 0.09% fee

    event FlashLoan(address indexed borrower, uint256 amount, uint256 fee);

    constructor(address _token) {
        token = IERC20(_token);
    }

    function flashLoan(
        address receiver,
        uint256 amount,
        bytes calldata params
    ) external {
        uint256 balanceBefore = token.balanceOf(address(this));
        require(balanceBefore >= amount, "Insufficient liquidity");

        uint256 fee = (amount * feePercentage) / 10000;

        // Send tokens to receiver
        token.transfer(receiver, amount);

        // Execute callback
        require(
            IFlashLoanReceiver(receiver).executeOperation(
                address(token),
                amount,
                fee,
                params
            ),
            "Flash loan failed"
        );

        // Verify repayment
        uint256 balanceAfter = token.balanceOf(address(this));
        require(balanceAfter >= balanceBefore + fee, "Flash loan not repaid");

        emit FlashLoan(receiver, amount, fee);
    }
}

// Example flash loan receiver
contract FlashLoanReceiver is IFlashLoanReceiver {
    function executeOperation(
        address asset,
        uint256 amount,
        uint256 fee,
        bytes calldata params
    ) external override returns (bool) {
        // Decode params and execute arbitrage, liquidation, etc.
        // ...

        // Approve repayment
        IERC20(asset).approve(msg.sender, amount + fee);

        return true;
    }
}
```

## Resources

- **references/staking.md**: Staking mechanics and reward distribution
- **references/liquidity-pools.md**: AMM mathematics and pricing
- **references/governance-tokens.md**: Governance and voting systems
- **references/lending-protocols.md**: Lending/borrowing implementation
- **references/flash-loans.md**: Flash loan security and use cases
- **assets/staking-contract.sol**: Production staking template
- **assets/amm-contract.sol**: Full AMM implementation
- **assets/governance-token.sol**: Governance system
- **assets/lending-protocol.sol**: Lending platform template

## Best Practices

1. **Use Established Libraries**: OpenZeppelin, Solmate
2. **Test Thoroughly**: Unit tests, integration tests, fuzzing
3. **Audit Before Launch**: Professional security audits
4. **Start Simple**: MVP first, add features incrementally
5. **Monitor**: Track contract health and user activity
6. **Upgradability**: Consider proxy patterns for upgrades
7. **Emergency Controls**: Pause mechanisms for critical issues

## Common DeFi Patterns

- **Time-Weighted Average Price (TWAP)**: Price oracle resistance
- **Liquidity Mining**: Incentivize liquidity provision
- **Vesting**: Lock tokens with gradual release
- **Multisig**: Require multiple signatures for critical operations
- **Timelocks**: Delay execution of governance decisions

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: defuddle
description: Extract clean markdown content from web pages using Defuddle CLI, removing clutter and navigation to save tokens. Use instead of WebFetch when the user provides a URL to read or analyze, for online documentation, articles, blog posts, or any standard web page.
risk: critical
source: "https://github.com/kepano/obsidian-skills"
date_added: "2026-03-21"
---

# Defuddle

Use Defuddle CLI to extract clean readable content from web pages. Prefer over WebFetch for standard web pages — it removes navigation, ads, and clutter, reducing token usage.

## When to Use
- Use when the user provides a normal webpage URL to read, summarize, or analyze.
- Prefer it over noisy page-fetch approaches when token efficiency matters.
- Use for docs, articles, blog posts, and similar public web content.

If not installed: `npm install -g defuddle`

## Usage

Always use `--md` for markdown output:

```bash
defuddle parse <url> --md
```

Save to file:

```bash
defuddle parse <url> --md -o content.md
```

Extract specific metadata:

```bash
defuddle parse <url> -p title
defuddle parse <url> -p description
defuddle parse <url> -p domain
```

## Output formats

| Flag | Format |
|------|--------|
| `--md` | Markdown (default choice) |
| `--json` | JSON with both HTML and markdown |
| (none) | HTML |
| `-p <name>` | Specific metadata property |

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: delegate-setup
description: Configure approved delegation lanes across installed implementer CLIs,
  including optional model and effort choices, then write global or project config
  only after explicit user approval.
risk: safe
category: agent-orchestration
source: https://github.com/amElnagdy/delegate-skills
source_repo: amElnagdy/delegate-skills
source_type: community
date_added: '2026-08-26'
license: MIT
license_source: https://github.com/amElnagdy/delegate-skills/blob/master/LICENSE
compatibility: Requires Node 18+. No implementer CLIs are required — the skill discovers
  what is available.
metadata:
  version: 0.5.0
---
# Delegate Setup

## When to Use

- You want to configure which implementer CLI handles which kind of work (fleet lanes).
- You need to discover installed implementers and write lane config after user approval.

You are the **orchestrator** in **setup mode**. Discover installed implementer CLIs, propose a
**fleet of lanes**, and write configuration only after the user approves.

This skill does **not** dispatch coding work. It only authors the lane map.

One concept: **lanes**. Never say “routes.”

Example lane: **feature** → implementer `opencode`, model `opencode/grok`, variant `high`
(OpenCode uses `variant` for reasoning intensity, not `effort`).

## When NOT to use this

- The user wants a task implemented — use the matching `*-delegate` skill instead.
- A one-off model change on a single dispatch — pass `--model` / `--effort` / `--variant` on that relay.

## Hard rules

1. Every lane **must** include `implementer`.
2. Put dials on the same object (`model`, `effort` or `variant`, …) only if that implementer supports them — see [references/schema.md](references/schema.md).
3. Show a human-readable lane table **and** the full JSON before every write; re-show after every tweak.
4. Write **only** after an explicit approval (“yes”, “approve”, “write it”).
5. Ask scope unless already clear: **global** (all projects) vs **this repo only**. Never create a project file just because cwd is a git repo. If there is no git repo, default to global and say so.
6. Do not invent model identifiers.
7. In interview or usage-scan mode, never write **any** dial the user did not give you and the schema does not require — omit it, so the CLI’s or relay’s own default applies.
8. Prefer 3–5 useful lanes over a kitchen-sink map.
9. Never edit `AGENTS.md`, `CLAUDE.md`, or other user agent-instruction files.
10. Never run a `*-delegate` relay from this skill.

(`<skill-dir>` is this skill’s install directory — the folder that contains this `SKILL.md`.)

## Flow

`discover → load → grounding menu → propose (with Basis) → scope → approve → write`

### 1. Discover

```bash
node "<skill-dir>/scripts/discover.mjs"
```

Summarize installed vs missing, auth (`true` / `false` / `null` = unknown), and whether models were
`reported`, `aliases` (curated aliases in the registry, not live discovery — full model names also
work), `unsupported`, or `failed`.

### 2. Load existing (effective map)

```bash
node "<skill-dir>/scripts/config.mjs" load --cwd "$PWD"
```

- Neither present → “No lanes configured yet.”
- Otherwise → table of **effective** lanes with a Source column (`global` / `project`). Do not paste
  both raw files unless asked.
- If `projectPresent` is true and `projectTrusted` is false, label the project lanes **untrusted**.
  They cannot dispatch until the user reviews and approves a project write.

### 3. Propose

Discovery reports capability, never task fit. So ask **one** grounding question before proposing
anything — one question, three options, not a wizard:

> How should I pick the lanes? **(1) Quick defaults** — I decide, no questions.
> **(2) Interview** — about four questions on how you want work allocated.
> **(3) Usage scan** — I re-read your CLIs’ local session folders (counts and dates only, never the
> conversations) and let the numbers place your lanes — if one CLI dominates, expect one question
> about its role. Happy to do 2 and 3 together.

- **Quick defaults** → propose immediately.
- **Interview** → the four questions (allocation policy, never model rankings) and how to ask them
  (one medium per round) live in [references/setup-dialogue.md](references/setup-dialogue.md) — read
  it before you ask.
- **Usage scan** → `node "<skill-dir>/scripts/discover.mjs" --usage`. Tell the user it is metadata
  only before running it. Each discovered CLI gains `usage: { sessions, lastUsed }`; `null` means no
  probe is wired — unknown, not unused.
- **Both** → run the scan first, then ask only what the numbers cannot answer.
- Inside a git repo, repo signals (languages, test weight, frontend share) are a fourth source of
  evidence. They do not change the menu; they feed the proposal and the `repo` basis.

**That menu is also the consent surface** — the option chosen sets how much of the map is yours to
decide:

- **Quick defaults** — the user hired your opinion. A full map is legitimate, dials included; label
  every lane `my opinion`, say plainly that the map is your opinion, and keep it cheap to revise.
- **Interview / usage scan** — evidence modes, so **every** dial is gated (rule 7): set one only from
  the user’s answer, or where the schema requires it (opencode lanes require `model`). Omitting is
  always safe — every dial has a default the user already lives with, and a CLI’s configured default
  is their standing choice, better evidence than your priors. Choosing which installed implementer
  gets a lane is still yours — Basis `my opinion` — but a dial that raises spend is not: offer your
  dial picks only as an addendum after the proposal, see
  [references/setup-dialogue.md](references/setup-dialogue.md).
- **An unanswered question shrinks the map; it never licenses a substitution.** Propose fewer, more
  conservative lanes, name the axis you are blind on (no quota answer → say the map is quota-blind),
  and invite the answer anytime. Re-ask once at most; never backfill silence with priors.

**Delegation economics.** The orchestrator reviews and lands every result — the review is the
quality gate, so optimize total cost, not implementer prestige:

- Prefer capable, authenticated, burnable, **low-usage** CLIs for bounded, objectively gated work
  (tests, mechanical refactors, straightforward fixes) when their reliability keeps review and
  rework economical — lanes push token burn away from the subscriptions the user is protecting.
  Low usage alone does not establish burnable: discovery cannot see plans, limits, or per-run
  cost, and a rarely-used CLI may be metered or deliberately avoided. Burnable comes from the
  user's quota answer — or, in quick defaults, from your labeled opinion.
- Avoid binding a lane to a CLI the user is protecting or orchestrates from, by default; bind it
  only when the user asks for it or no acceptable alternative exists. Lanes are
  **orchestrator-blind**: the same lane fires from every seat the user drives from, and from that
  CLI's own seat it dispatches the CLI to itself.
- Surplus placement breaks down when rework and review cost exceed the savings; when the
  implementer is flaky; when correctness rides on security, concurrency, migrations, or unstated
  domain knowledge; and when the output **is** the product (debate, architecture, research) —
  review limits damage, it does not manufacture a good first attempt. Bind those lanes to stronger
  implementers.
- An explicit "spare X" answer removes X from proposed lanes by default, and overrides blanket
  posture answers on any lane the user explicitly retains for X — ask whether the posture applies
  there; omit the dial if unanswered. Never silently stretch one answer across an axis it
  conflicts with.

Question phrasings for the burn/spare and trust interview live in
[references/setup-dialogue.md](references/setup-dialogue.md).

Then propose the lanes. Name them after the work the user described; fall back to `feature`, `tests`,
`ui`, `fast`, `complex`. Installed implementers only.

Show:

| Lane | Implementer | Model | Effort / variant | Basis | Source (if updating) |
| --- | --- | --- | --- | --- | --- |
| feature | opencode | opencode/grok | variant: high | your answer + schema requirement | — |
| tests | codex | — | — | usage data | — |
| ui | claude | — | — | my opinion (implementer) | — |

**Basis** is mandatory on every lane: `your answer` / `usage data` / `repo` / `my opinion` /
`schema requirement` (a dial the schema forces is neither evidence nor opinion — say so). A lane you
picked from model-quality priors is `my opinion` — never present it as something the tooling
determined, and “installed and authenticated” is capability, not evidence of fit. When a lane’s
implementer and its dials come from different places, split the label — see
[references/setup-dialogue.md](references/setup-dialogue.md).

Then the **complete** JSON (`version`: `delegate-fleet.v1`). One line of why per lane; flag auth or
model uncertainty.

Schema and dial table: [references/schema.md](references/schema.md).

### 4. Scope

- User said global / all projects / outside the project → `global`.
- No git repo → `global` (say so).
- Else ask once: global vs this repo only.

### 5. Approve and write

On explicit yes, write **only** the chosen scope (validate first). Build the payload from that
scope’s raw file (or an empty `lanes` object if new) — not from the effective merged `load` view,
or a project write will shadow global-only lanes and a global write will promote project-only ones.

Create a uniquely named file under the platform temporary directory (`$TMPDIR`, `%TEMP%`, or Node
`os.tmpdir()`; never hard-code `/tmp`, which breaks on native Windows), write the **exact approved
JSON** into it with the orchestrator's file-writing tool, and use that populated path as
`<lanes-json>` below. Never validate an empty temp file. Remove the temp file after the
validation/write attempt, whether it succeeds or fails.

```bash
node "<skill-dir>/scripts/config.mjs" validate "<lanes-json>"
node "<skill-dir>/scripts/config.mjs" write --scope global "<lanes-json>"
# or:  write --scope project --cwd /path/to/repo "<lanes-json>"
```

Re-read with `load`, then confirm the path written and the active lane names. Project writes bind
approval to the exact config content; later changes fail closed until re-approved. On update, a short
before/after is enough.

### 6. Ready to delegate

Stop after confirming. Tell the user the map is ready. For later work: read the lane’s
`implementer`, load that `*-delegate` skill, and dispatch with `--lane <name>` (explicit
`--model` / `--effort` / `--variant` still win when passed). Do not start a delegate task
unless they ask.

## Reconfigure

Same flow. Show the effective current map, propose changes, approve, write one scope’s file.
Reinstalling the skills package must not rewrite these files — they live outside the package.

## Limitations

- Never dispatches work itself — only discovers CLIs and writes config after explicit approval.
- Docs-only import — executable helpers (`scripts/`) not included; see upstream for full runtime. Requires Node 18+.

> Adapted from [amElnagdy/delegate-skills](https://github.com/amElnagdy/delegate-skills) (MIT) — docs-only, runtime not bundled.


---
name: delegating-to-agents
description: "Delegate bounded work to other AI agents while preserving context, ownership, and progress checks."
category: agent-orchestration
risk: critical
source: community
source_repo: davidondrej/skills
source_type: community
date_added: "2026-07-07"
author: davidondrej
tags: [agents, delegation, orchestration]
tools: [claude, codex]
license: "MIT"
license_source: "https://github.com/davidondrej/skills/blob/main/LICENSE"
---

# Delegating to Agents

## When to Use

- Use when work should be handed to another AI agent with a complete prompt and progress checks.
- Use when you need to relay instructions to terminal or TUI agents without losing context.

## Which agent to pick

- **Coding (default) → Codex CLI.** Strongest coding agent, especially for complex, long-running SWE tasks. It's on an unlimited-usage plan — effectively unlimited, don't ration it.
- **Most other tasks → Pi Agent** (`pi` in a cmux terminal). All Pi agents run opus-4.8-fast via OpenRouter at xhigh reasoning effort.
- **Frontend / design → Pi.** Opus 4.8 Fast beats Codex on UI, styling, design.
- **Heavy multi-step work:** you as orchestrator + Codex CLI executing in a right-hand cmux pane is a solid default setup.

## Sending prompts to a TUI agent

1. **ONE single line — never newlines in the message body.** In a TUI, newline = Enter: a multi-line prompt submits at the first line and the rest arrives as fragmented mid-turn steering messages. Use ". " or "; " instead of line breaks, then one explicit enter. For long instructions, write them to a file and send: `read /tmp/task.md and follow it`.
2. **Wrap the prompt in plain double quotes — NEVER escaped.** `cmux send --surface surface:N "your prompt"`. The recurring bug is emitting `\"` — in bash that's literal-broken and dies with `unexpected EOF`. Inside the prompt, avoid apostrophes and literal double quotes (write "dont", "wont", "lets"); rephrase instead of escaping. If a send failed, the cause was the escaped `\"`, not the quote type.
3. **Exact command names:** `cmux send --surface surface:N` then `cmux send-key --surface surface:N enter`. There is NO `send-surface` or `send-key-surface`.

## Polling

Keep sleeps SHORT: start at 3-5s, re-check, repeat. Don't `sleep 30`. Pi and Hermes (opus-4.8-fast) launch and respond within seconds; scale up only for genuinely heavy tasks. After every check, send the user a one-line status: what the agent is doing and whether it's on track.

Claude Code note: after it finishes, it may prefill a predicted next user message — that draft is Claude, not the user.

## Remote VPS

SSH in first and launch the agent ON the VPS (e.g. `codex --yolo`), then drive that on-box agent. Don't run an agent locally and have it SSH for every step.

## The 4 agents (background reference)

All four use the portable SKILL.md standard; project skills win over global.

- **Pi** (pi.dev, open-source TS): minimal read/write/edit/bash core, self-extends via TS extensions; true BYOK; best-in-class session branch/fork/resume. Skills: `~/.pi/agent/skills/`.
- **Codex CLI** (OpenAI, Rust): fastest startup; kernel-level sandboxing; `codex exec` for CI; reads AGENTS.md. Skills: `~/.codex/skills/`.
- **Claude Code** (Anthropic, TS): deepest Claude integration, `.claude/` conventions, live skill hot-reload. Skills: `~/.claude/skills/`.
- **Hermes** (Nous Research, Python): persistent autonomous agent — cross-session memory, built-in scheduler, 40+ tools; can orchestrate the other CLIs as workers. Skills: `~/.hermes/skills/`.

## Driving interactive CLIs

- Codex, Pi, OpenCode: need `pty=true`.
- Claude Code: prefer `claude --print --permission-mode bypassPermissions` (no PTY).

## Limitations

- Adapted from `davidondrej/skills`; verify local paths, tools, credentials, and agent features before acting.
- For commands, remote access, scheduling, browser automation, or file-changing workflows, get explicit user approval and confirm the target environment first.


---
name: dep
description: "Handles containerization, CI/CD pipelines, and deployment setup."
risk: safe
source: community
date_added: "2026-06-11"
role: DevOps Engineer
phase: 8 — Deployment
squad: agent-squad
reports-to: agent-squad
depends-on: mason, luna, quinn
---

# Dep — The DevOps Engineer

Dep handles everything between "code that works locally" and "code running in production." He generates build configurations, containerization, CI/CD pipelines, environment management, and deployment verification. He works only on code that has passed Luna's review and Quinn's tests.

Dep does not write application logic. He does not review code for quality. He takes the finished, tested artifact and makes it shippable.

---

## When to Use
- Use this skill when the task matches this description: Handles containerization, CI/CD pipelines, and deployment setup.

## Responsibilities

### 1. Containerization
- Generate a **Dockerfile** for the application:
  - Use the correct **base image version** (pinned, not `latest`).
  - Apply **multi-stage builds** where appropriate (build stage vs. runtime stage).
  - Run as a **non-root user** in the final stage.
  - Copy only **necessary files** — use `.dockerignore` to exclude dev dependencies, tests, secrets.
  - Set **HEALTHCHECK** instruction for production containers.
  - Expose the correct **port** and document it.
- Generate a **docker-compose.yml** for local development with all dependent services (DB, cache, queue).
- Pin all **service image versions** in docker-compose — no `latest`.

### 2. CI/CD Pipeline
- Generate a pipeline config for the target platform (GitHub Actions, GitLab CI, CircleCI, etc.).
- Pipeline must include these **mandatory stages** in order:
  1. `lint` — fail fast on syntax errors.
  2. `test` — run Quinn's full test suite.
  3. `build` — compile/bundle the artifact.
  4. `security-scan` — dependency vulnerability scan (npm audit, pip audit, trivy, etc.).
  5. `deploy` — only runs on specific branches (main, release).
- No deploy stage runs if **any prior stage fails** — this is non-negotiable.
- Generate **branch protection rules** recommendation if the target is GitHub/GitLab.
- Separate **staging deploy** from **production deploy** — different triggers, different configs.

### 3. Environment Configuration
- Generate a **`.env.example`** with every required environment variable, with comments explaining each.
- Generate **environment-specific config files** if the framework uses them (e.g. `config/production.js`).
- Define the **secrets management strategy**: where secrets live (Vault, AWS Secrets Manager, GitHub Secrets, etc.) — never in env files committed to the repo.
- Specify **which variables are build-time vs. runtime**.
- List all **external service endpoints** that need environment-specific values (DB URL, API base URL, CDN, etc.).

### 4. Infrastructure as Code (when applicable)
- Generate **Terraform, Pulumi, or CloudFormation** configs if the user has specified a cloud provider.
- Define **resource sizing** conservatively — right-size, don't over-provision.
- Configure **auto-scaling rules** with sensible defaults.
- Set up **networking rules**: VPC, security groups, ingress/egress.
- Configure **managed DB** instance (RDS, Cloud SQL, etc.) with backups enabled.

### 5. Build Verification
- Generate a **deployment verification checklist** the human should run after first deploy:
  - Health endpoint returns 200.
  - DB migrations ran successfully.
  - Auth flow works end-to-end.
  - Error monitoring (Sentry, Datadog, etc.) is receiving events.
  - Logs are shipping to the log aggregator.
- Generate a **rollback procedure** — simple, documented, runnable in under 5 minutes.

### 6. Observability Setup
- Configure **structured logging** output (JSON format with request ID, timestamp, level, message).
- Add a `/health` and `/ready` endpoint if not already present — document expected responses.
- Set up **error tracking** integration (Sentry snippet, Datadog agent, etc.) if in scope.
- Define **key metrics** the app should emit (request rate, error rate, DB query latency).
- Provide **alerting rule recommendations** for the metrics defined.

---

## Output Format (Structured Report to Main Agent)

```
DEP DEPLOYMENT PACKAGE — v1.0
Project: [name]
Target: [platform — Vercel / Railway / AWS ECS / GCP Cloud Run / self-hosted / etc.]
Input: Quinn Test Report v[x]

## Files Generated
- Dockerfile
- .dockerignore
- docker-compose.yml (local dev)
- .github/workflows/ci.yml (or equivalent)
- .env.example
- [infra/main.tf] (if IaC in scope)

## Environment Variables Required
| Variable          | Description              | Example         | Secret? |
|-------------------|--------------------------|-----------------|---------|
| DATABASE_URL      | Postgres connection URL  | postgres://...  | YES     |
| JWT_SECRET        | Token signing secret     | —               | YES     |
| PORT              | HTTP server port         | 3000            | no      |

## CI/CD Pipeline Stages
1. lint → 2. test → 3. build → 4. security-scan → 5. deploy (main only)

## Deployment Verification Checklist
- [ ] GET /health → 200
- [ ] DB migration status → all applied
- [ ] Test login flow end-to-end
- [ ] Confirm error events reaching monitoring

## Rollback Procedure
[Step-by-step, < 5 min, no jargon]

## Open Questions
- [decision that requires user input — e.g. which cloud provider, which region]
```

---

## Handoff Protocol

Dep is the **last agent in the standard flow**. After his package is delivered:
- The main agent delivers the full package to the user.
- Dep flags any **post-deployment concerns** (database migration order, secret rotation schedule, etc.).

If Dep discovers that the application **cannot be containerized as-is** (missing health endpoint, hardcoded paths, etc.):
- He routes specific fix requirements back to **Mason** with exact file and change needed.
- He does not patch application code himself.

When Dep is invoked outside the full flow (e.g. "just set up CI for this existing repo"):
- He reads the codebase structure and Quinn's last test report if available.
- He produces the relevant subset of his output (pipeline only, Dockerfile only, etc.).

---

## Interaction Style

- Infrastructure-literate and security-conscious. Treats every environment variable as a potential leak.
- Never generates a pipeline that can deploy broken code — stage ordering is a core value.
- Does not over-engineer infra for simple apps: a 3-route Express app does not need Kubernetes.
- States cloud-provider-specific assumptions explicitly — always asks if the target platform is ambiguous.
- Documents every generated file with inline comments so the human can maintain it.

## Limitations
- AI agents may occasionally hallucinate or provide incorrect guidance. Always verify generated code and architectural designs before pushing to production.
- Context window constraints mean large project histories must be compressed by the Orchestrator.


---
name: dependency-management-deps-audit
description: "You are a dependency security expert specializing in vulnerability scanning, license compliance, and supply chain security. Analyze project dependencies for known vulnerabilities, licensing issues, outdated packages, and provide actionable remediation strategies."
risk: critical
source: community
date_added: "2026-02-27"
---

# Dependency Audit and Security Analysis

You are a dependency security expert specializing in vulnerability scanning, license compliance, and supply chain security. Analyze project dependencies for known vulnerabilities, licensing issues, outdated packages, and provide actionable remediation strategies.

## Use this skill when

- Auditing dependencies for vulnerabilities
- Checking license compliance or supply-chain risks
- Identifying outdated packages and upgrade paths
- Preparing security reports or remediation plans

## Do not use this skill when

- The project has no dependency manifests
- You cannot change or update dependencies
- The task is unrelated to dependency management

## Context
The user needs comprehensive dependency analysis to identify security vulnerabilities, licensing conflicts, and maintenance risks in their project dependencies. Focus on actionable insights with automated fixes where possible.

## Requirements
$ARGUMENTS

## Instructions

- Inventory direct and transitive dependencies.
- Run vulnerability and license scans.
- Prioritize fixes by severity and exposure.
- Propose upgrades with compatibility notes.
- If detailed workflows are required, open `resources/implementation-playbook.md`.

## Safety

- Do not publish sensitive vulnerability details to public channels.
- Verify upgrades in staging before production rollout.

## Resources

- `resources/implementation-playbook.md` for detailed tooling and templates.

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: dependency-upgrade
description: "Master major dependency version upgrades, compatibility analysis, staged upgrade strategies, and comprehensive testing approaches."
risk: critical
source: community
date_added: "2026-02-27"
---

# Dependency Upgrade

Master major dependency version upgrades, compatibility analysis, staged upgrade strategies, and comprehensive testing approaches.

## Do not use this skill when

- The task is unrelated to dependency upgrade
- You need a different domain or tool outside this scope

## Instructions

- Clarify goals, constraints, and required inputs.
- Apply relevant best practices and validate outcomes.
- Provide actionable steps and verification.
- If detailed examples are required, open `resources/implementation-playbook.md`.

## Use this skill when

- Upgrading major framework versions
- Updating security-vulnerable dependencies
- Modernizing legacy dependencies
- Resolving dependency conflicts
- Planning incremental upgrade paths
- Testing compatibility matrices
- Automating dependency updates

## Semantic Versioning Review

```
MAJOR.MINOR.PATCH (e.g., 2.3.1)

MAJOR: Breaking changes
MINOR: New features, backward compatible
PATCH: Bug fixes, backward compatible

^2.3.1 = >=2.3.1 <3.0.0 (minor updates)
~2.3.1 = >=2.3.1 <2.4.0 (patch updates)
2.3.1 = exact version
```

## Dependency Analysis

### Audit Dependencies
```bash
# npm
npm outdated
npm audit
npm audit fix

# yarn
yarn outdated
yarn audit

# Check for major updates
npx npm-check-updates
npx npm-check-updates -u  # Update package.json
```

### Analyze Dependency Tree
```bash
# See why a package is installed
npm ls package-name
yarn why package-name

# Find duplicate packages
npm dedupe
yarn dedupe

# Visualize dependencies
npx madge --image graph.png src/
```

## Compatibility Matrix

```javascript
// compatibility-matrix.js
const compatibilityMatrix = {
  'react': {
    '16.x': {
      'react-dom': '^16.0.0',
      'react-router-dom': '^5.0.0',
      '@testing-library/react': '^11.0.0'
    },
    '17.x': {
      'react-dom': '^17.0.0',
      'react-router-dom': '^5.0.0 || ^6.0.0',
      '@testing-library/react': '^12.0.0'
    },
    '18.x': {
      'react-dom': '^18.0.0',
      'react-router-dom': '^6.0.0',
      '@testing-library/react': '^13.0.0'
    }
  }
};

function checkCompatibility(packages) {
  // Validate package versions against matrix
}
```

## Staged Upgrade Strategy

### Phase 1: Planning
```bash
# 1. Identify current versions
npm list --depth=0

# 2. Check for breaking changes
# Read CHANGELOG.md and MIGRATION.md

# 3. Create upgrade plan
echo "Upgrade order:
1. TypeScript
2. React
3. React Router
4. Testing libraries
5. Build tools" > UPGRADE_PLAN.md
```

### Phase 2: Incremental Updates
```bash
# Don't upgrade everything at once!

# Step 1: Update TypeScript
npm install typescript@latest

# Test
npm run test
npm run build

# Step 2: Update React (one major version at a time)
npm install react@17 react-dom@17

# Test again
npm run test

# Step 3: Continue with other packages
npm install react-router-dom@6

# And so on...
```

### Phase 3: Validation
```javascript
// tests/compatibility.test.js
describe('Dependency Compatibility', () => {
  it('should have compatible React versions', () => {
    const reactVersion = require('react/package.json').version;
    const reactDomVersion = require('react-dom/package.json').version;

    expect(reactVersion).toBe(reactDomVersion);
  });

  it('should not have peer dependency warnings', () => {
    // Run npm ls and check for warnings
  });
});
```

## Breaking Change Handling

### Identifying Breaking Changes
```bash
# Use changelog parsers
npx changelog-parser react 16.0.0 17.0.0

# Or manually check
curl https://raw.githubusercontent.com/facebook/react/main/CHANGELOG.md
```

### Codemod for Automated Fixes
```bash
# React upgrade codemods
npx react-codeshift <transform> <path>

# Example: Update lifecycle methods
npx react-codeshift \
  --parser tsx \
  --transform react-codeshift/transforms/rename-unsafe-lifecycles.js \
  src/
```

### Custom Migration Script
```javascript
// migration-script.js
const fs = require('fs');
const glob = require('glob');

glob('src/**/*.tsx', (err, files) => {
  files.forEach(file => {
    let content = fs.readFileSync(file, 'utf8');

    // Replace old API with new API
    content = content.replace(
      /componentWillMount/g,
      'UNSAFE_componentWillMount'
    );

    // Update imports
    content = content.replace(
      /import { Component } from 'react'/g,
      "import React, { Component } from 'react'"
    );

    fs.writeFileSync(file, content);
  });
});
```

## Testing Strategy

### Unit Tests
```javascript
// Ensure tests pass before and after upgrade
npm run test

// Update test utilities if needed
npm install @testing-library/react@latest
```

### Integration Tests
```javascript
// tests/integration/app.test.js
describe('App Integration', () => {
  it('should render without crashing', () => {
    render(<App />);
  });

  it('should handle navigation', () => {
    const { getByText } = render(<App />);
    fireEvent.click(getByText('Navigate'));
    expect(screen.getByText('New Page')).toBeInTheDocument();
  });
});
```

### Visual Regression Tests
```javascript
// visual-regression.test.js
describe('Visual Regression', () => {
  it('should match snapshot', () => {
    const { container } = render(<App />);
    expect(container.firstChild).toMatchSnapshot();
  });
});
```

### E2E Tests
```javascript
// cypress/e2e/app.cy.js
describe('E2E Tests', () => {
  it('should complete user flow', () => {
    cy.visit('/');
    cy.get('[data-testid="login"]').click();
    cy.get('input[name="email"]').type('user@example.com');
    cy.get('button[type="submit"]').click();
    cy.url().should('include', '/dashboard');
  });
});
```

## Automated Dependency Updates

### Renovate Configuration
```json
// renovate.json
{
  "extends": ["config:base"],
  "packageRules": [
    {
      "matchUpdateTypes": ["minor", "patch"],
      "automerge": true
    },
    {
      "matchUpdateTypes": ["major"],
      "automerge": false,
      "labels": ["major-update"]
    }
  ],
  "schedule": ["before 3am on Monday"],
  "timezone": "America/New_York"
}
```

### Dependabot Configuration
```yaml
# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 5
    reviewers:
      - "team-leads"
    commit-message:
      prefix: "chore"
      include: "scope"
```

## Rollback Plan

```javascript
// rollback.sh
#!/bin/bash

# Save current state
git stash
git checkout -b upgrade-branch

# Attempt upgrade
npm install package@latest

# Run tests
if npm run test; then
  echo "Upgrade successful"
  git add package.json package-lock.json
  git commit -m "chore: upgrade package"
else
  echo "Upgrade failed, rolling back"
  git checkout main
  git branch -D upgrade-branch
  npm install  # Restore from package-lock.json
fi
```

## Common Upgrade Patterns

### Lock File Management
```bash
# npm
npm install --package-lock-only  # Update lock file only
npm ci  # Clean install from lock file

# yarn
yarn install --frozen-lockfile  # CI mode
yarn upgrade-interactive  # Interactive upgrades
```

### Peer Dependency Resolution
```bash
# npm 7+: strict peer dependencies
npm install --legacy-peer-deps  # Ignore peer deps

# npm 8+: override peer dependencies
npm install --force
```

### Workspace Upgrades
```bash
# Update all workspace packages
npm install --workspaces

# Update specific workspace
npm install package@latest --workspace=packages/app
```

## Resources

- **references/semver.md**: Semantic versioning guide
- **references/compatibility-matrix.md**: Common compatibility issues
- **references/staged-upgrades.md**: Incremental upgrade strategies
- **references/testing-strategy.md**: Comprehensive testing approaches
- **assets/upgrade-checklist.md**: Step-by-step checklist
- **assets/compatibility-matrix.csv**: Version compatibility table
- **scripts/audit-dependencies.sh**: Dependency audit script

## Best Practices

1. **Read Changelogs**: Understand what changed
2. **Upgrade Incrementally**: One major version at a time
3. **Test Thoroughly**: Unit, integration, E2E tests
4. **Check Peer Dependencies**: Resolve conflicts early
5. **Use Lock Files**: Ensure reproducible installs
6. **Automate Updates**: Use Renovate or Dependabot
7. **Monitor**: Watch for runtime errors post-upgrade
8. **Document**: Keep upgrade notes

## Upgrade Checklist

```markdown
Pre-Upgrade:
- [ ] Review current dependency versions
- [ ] Read changelogs for breaking changes
- [ ] Create feature branch
- [ ] Backup current state (git tag)
- [ ] Run full test suite (baseline)

During Upgrade:
- [ ] Upgrade one dependency at a time
- [ ] Update peer dependencies
- [ ] Fix TypeScript errors
- [ ] Update tests if needed
- [ ] Run test suite after each upgrade
- [ ] Check bundle size impact

Post-Upgrade:
- [ ] Full regression testing
- [ ] Performance testing
- [ ] Update documentation
- [ ] Deploy to staging
- [ ] Monitor for errors
- [ ] Deploy to production
```

## Common Pitfalls

- Upgrading all dependencies at once
- Not testing after each upgrade
- Ignoring peer dependency warnings
- Forgetting to update lock file
- Not reading breaking change notes
- Skipping major versions
- Not having rollback plan

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.