---
name: claude-settings-audit
description: Analyze a repository to generate recommended Claude Code settings.json permissions. Use when setting up a new project, auditing existing settings, or determining which read-only bash commands to allow. Detects tech stack, build tools, and monorepo structure.
risk: critical
source: community
---

# Claude Settings Audit

Analyze this repository and generate recommended Claude Code `settings.json` permissions for read-only commands.

## When to Use
- You are setting up or auditing Claude Code `settings.json` permissions for a repository.
- You need to infer a safe read-only allow list from the repo's tech stack, tooling, and monorepo structure.
- You want to review or replace an existing Claude permissions baseline with something evidence-based.

## Phase 1: Detect Tech Stack

Run these commands to detect the repository structure:

```bash
ls -la
find . -maxdepth 2 \( -name "*.toml" -o -name "*.json" -o -name "*.lock" -o -name "*.yaml" -o -name "*.yml" -o -name "Makefile" -o -name "Dockerfile" -o -name "*.tf" \) 2>/dev/null | head -50
```

Check for these indicator files:

| Category     | Files to Check                                                                        |
| ------------ | ------------------------------------------------------------------------------------- |
| **Python**   | `pyproject.toml`, `setup.py`, `requirements.txt`, `Pipfile`, `poetry.lock`, `uv.lock` |
| **Node.js**  | `package.json`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`                    |
| **Go**       | `go.mod`, `go.sum`                                                                    |
| **Rust**     | `Cargo.toml`, `Cargo.lock`                                                            |
| **Ruby**     | `Gemfile`, `Gemfile.lock`                                                             |
| **Java**     | `pom.xml`, `build.gradle`, `build.gradle.kts`                                         |
| **Build**    | `Makefile`, `Dockerfile`, `docker-compose.yml`                                        |
| **Infra**    | `*.tf` files, `kubernetes/`, `helm/`                                                  |
| **Monorepo** | `lerna.json`, `nx.json`, `turbo.json`, `pnpm-workspace.yaml`                          |

## Phase 2: Detect Services

Check for service integrations:

| Service    | Detection                                                                       |
| ---------- | ------------------------------------------------------------------------------- |
| **Sentry** | `sentry-sdk` in deps, `@sentry/*` packages, `.sentryclirc`, `sentry.properties` |
| **Linear** | Linear config files, `.linear/` directory                                       |

Read dependency files to identify frameworks:

- `package.json` → check `dependencies` and `devDependencies`
- `pyproject.toml` → check `[project.dependencies]` or `[tool.poetry.dependencies]`
- `Gemfile` → check gem names
- `Cargo.toml` → check `[dependencies]`

## Phase 3: Check Existing Settings

```bash
cat .claude/settings.json 2>/dev/null || echo "No existing settings"
```

## Phase 4: Generate Recommendations

Build the allow list by combining:

### Baseline Commands (Always Include)

```json
[
  "Bash(ls:*)",
  "Bash(pwd:*)",
  "Bash(find:*)",
  "Bash(file:*)",
  "Bash(stat:*)",
  "Bash(wc:*)",
  "Bash(head:*)",
  "Bash(tail:*)",
  "Bash(cat:*)",
  "Bash(tree:*)",
  "Bash(git status:*)",
  "Bash(git log:*)",
  "Bash(git diff:*)",
  "Bash(git show:*)",
  "Bash(git branch:*)",
  "Bash(git remote:*)",
  "Bash(git tag:*)",
  "Bash(git stash list:*)",
  "Bash(git rev-parse:*)",
  "Bash(gh pr view:*)",
  "Bash(gh pr list:*)",
  "Bash(gh pr checks:*)",
  "Bash(gh pr diff:*)",
  "Bash(gh issue view:*)",
  "Bash(gh issue list:*)",
  "Bash(gh run view:*)",
  "Bash(gh run list:*)",
  "Bash(gh run logs:*)",
  "Bash(gh repo view:*)",
  "Bash(gh api:*)"
]
```

### Stack-Specific Commands

Only include commands for tools actually detected in the project.

#### Python (if any Python files or config detected)

| If Detected                        | Add These Commands                      |
| ---------------------------------- | --------------------------------------- |
| Any Python                         | `python --version`, `python3 --version` |
| `poetry.lock`                      | `poetry show`, `poetry env info`        |
| `uv.lock`                          | `uv pip list`, `uv tree`                |
| `Pipfile.lock`                     | `pipenv graph`                          |
| `requirements.txt` (no other lock) | `pip list`, `pip show`, `pip freeze`    |

#### Node.js (if package.json detected)

| If Detected                  | Add These Commands                     |
| ---------------------------- | -------------------------------------- |
| Any Node.js                  | `node --version`                       |
| `pnpm-lock.yaml`             | `pnpm list`, `pnpm why`                |
| `yarn.lock`                  | `yarn list`, `yarn info`, `yarn why`   |
| `package-lock.json`          | `npm list`, `npm view`, `npm outdated` |
| TypeScript (`tsconfig.json`) | `tsc --version`                        |

#### Other Languages

| If Detected    | Add These Commands                                                   |
| -------------- | -------------------------------------------------------------------- |
| `go.mod`       | `go version`, `go list`, `go mod graph`, `go env`                    |
| `Cargo.toml`   | `rustc --version`, `cargo --version`, `cargo tree`, `cargo metadata` |
| `Gemfile`      | `ruby --version`, `bundle list`, `bundle show`                       |
| `pom.xml`      | `java --version`, `mvn --version`, `mvn dependency:tree`             |
| `build.gradle` | `java --version`, `gradle --version`, `gradle dependencies`          |

#### Build Tools

| If Detected          | Add These Commands                                                   |
| -------------------- | -------------------------------------------------------------------- |
| `Dockerfile`         | `docker --version`, `docker ps`, `docker images`                     |
| `docker-compose.yml` | `docker-compose ps`, `docker-compose config`                         |
| `*.tf` files         | `terraform --version`, `terraform providers`, `terraform state list` |
| `Makefile`           | `make --version`, `make -n`                                          |

### Skills (for Sentry Projects)

If this is a Sentry project (or sentry-skills plugin is installed), include:

```json
[
  "Skill(sentry-skills:agents-md)",
  "Skill(sentry-skills:blog-writing-guide)",
  "Skill(sentry-skills:brand-guidelines)",
  "Skill(sentry-skills:claude-settings-audit)",
  "Skill(sentry-skills:code-review)",
  "Skill(sentry-skills:code-simplifier)",
  "Skill(sentry-skills:commit)",
  "Skill(sentry-skills:create-branch)",
  "Skill(sentry-skills:create-pr)",
  "Skill(sentry-skills:django-access-review)",
  "Skill(sentry-skills:django-perf-review)",
  "Skill(sentry-skills:doc-coauthoring)",
  "Skill(sentry-skills:find-bugs)",
  "Skill(sentry-skills:gh-review-requests)",
  "Skill(sentry-skills:gha-security-review)",
  "Skill(sentry-skills:iterate-pr)",
  "Skill(sentry-skills:pr-writer)",
  "Skill(sentry-skills:security-review)",
  "Skill(sentry-skills:skill-creator)",
  "Skill(sentry-skills:skill-scanner)",
  "Skill(sentry-skills:skill-writer)",
  "Skill(sentry-skills:sred-project-organizer)",
  "Skill(sentry-skills:sred-work-summary)"
]
```

### WebFetch Domains

#### Always Include (Sentry Projects)

```json
[
  "WebFetch(domain:docs.sentry.io)",
  "WebFetch(domain:develop.sentry.dev)",
  "WebFetch(domain:docs.github.com)",
  "WebFetch(domain:cli.github.com)"
]
```

#### Framework-Specific

| If Detected    | Add Domains                                     |
| -------------- | ----------------------------------------------- |
| **Django**     | `docs.djangoproject.com`                        |
| **Flask**      | `flask.palletsprojects.com`                     |
| **FastAPI**    | `fastapi.tiangolo.com`                          |
| **React**      | `react.dev`                                     |
| **Next.js**    | `nextjs.org`                                    |
| **Vue**        | `vuejs.org`                                     |
| **Express**    | `expressjs.com`                                 |
| **Rails**      | `guides.rubyonrails.org`, `api.rubyonrails.org` |
| **Go**         | `pkg.go.dev`                                    |
| **Rust**       | `docs.rs`, `doc.rust-lang.org`                  |
| **Docker**     | `docs.docker.com`                               |
| **Kubernetes** | `kubernetes.io`                                 |
| **Terraform**  | `registry.terraform.io`                         |

### MCP Server Suggestions

MCP servers are configured in `.mcp.json` (not `settings.json`). Check for existing config:

```bash
cat .mcp.json 2>/dev/null || echo "No existing .mcp.json"
```

#### Sentry MCP (if Sentry SDK detected)

Add to `.mcp.json` (replace `{org-slug}` and `{project-slug}` with your Sentry organization and project slugs):

```json
{
  "mcpServers": {
    "sentry": {
      "type": "http",
      "url": "https://mcp.sentry.dev/mcp/{org-slug}/{project-slug}"
    }
  }
}
```

#### Linear MCP (if Linear usage detected)

Add to `.mcp.json`:

```json
{
  "mcpServers": {
    "linear": {
      "command": "npx",
      "args": ["-y", "@linear/mcp-server"],
      "env": {
        "LINEAR_API_KEY": "${LINEAR_API_KEY}"
      }
    }
  }
}
```

**Note**: Never suggest GitHub MCP. Always use `gh` CLI commands for GitHub.

## Output Format

Present your findings as:

1. **Summary Table** - What was detected
2. **Recommended settings.json** - Complete JSON ready to copy
3. **MCP Suggestions** - If applicable
4. **Merge Instructions** - If existing settings found

Example output structure:

```markdown
## Detected Tech Stack

| Category        | Found          |
| --------------- | -------------- |
| Languages       | Python 3.x     |
| Package Manager | poetry         |
| Frameworks      | Django, Celery |
| Services        | Sentry         |
| Build Tools     | Docker, Make   |

## Recommended .claude/settings.json

\`\`\`json
{
"permissions": {
"allow": [
// ... grouped by category with comments
],
"deny": []
}
}
\`\`\`

## Recommended .mcp.json (if applicable)

If you use Sentry or Linear, add the MCP config to `.mcp.json`...
```

## Important Rules

### What to Include

- Only READ-ONLY commands that cannot modify state
- Only tools that are actually used by the project (detected via lock files)
- Standard system commands (ls, cat, find, etc.)
- The `:*` suffix allows any arguments to the base command

### What to NEVER Include

- **Absolute paths** - Never include user-specific paths like `/home/user/scripts/foo` or `/Users/name/bin/bar`
- **Custom scripts** - Never include project scripts that may have side effects (e.g., `./scripts/deploy.sh`)
- **Alternative package managers** - If the project uses pnpm, do NOT include npm/yarn commands
- **Commands that modify state** - No install, build, run, write, or delete commands

### Package Manager Rules

Only include the package manager actually used by the project:

| If Detected         | Include         | Do NOT Include                         |
| ------------------- | --------------- | -------------------------------------- |
| `pnpm-lock.yaml`    | pnpm commands   | npm, yarn                              |
| `yarn.lock`         | yarn commands   | npm, pnpm                              |
| `package-lock.json` | npm commands    | yarn, pnpm                             |
| `poetry.lock`       | poetry commands | pip (unless also has requirements.txt) |
| `uv.lock`           | uv commands     | pip, poetry                            |
| `Pipfile.lock`      | pipenv commands | pip, poetry                            |

If multiple lock files exist, include only the commands for each detected manager.

## 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: claude-speed-reader
description: "-Speed read Claude's responses at 600+ WPM using RSVP with Spritz-style ORP highlighting"
risk: safe
source: "https://github.com/SeanZoR/claude-speed-reader"
date_added: "2026-02-27"
---

# Claude Speed Reader

## Overview

-Speed read Claude's responses at 600+ WPM using RSVP with Spritz-style ORP highlighting

## When to Use This Skill

Use this skill when you need to work with -speed read claude's responses at 600+ wpm using rsvp with spritz-style orp highlighting.

## Instructions

This skill provides guidance and patterns for -speed read claude's responses at 600+ wpm using rsvp with spritz-style orp highlighting.

For more information, see the [source repository](https://github.com/SeanZoR/claude-speed-reader).

## 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: claude-win11-speckit-update-skill
description: "Windows 11 system management"
risk: safe
source: "https://github.com/NotMyself/claude-win11-speckit-update-skill"
date_added: "2026-02-27"
---

# Claude Win11 Speckit Update Skill

## Overview

Windows 11 system management

## When to Use This Skill

Use this skill when you need to work with windows 11 system management.

## Instructions

This skill provides guidance and patterns for windows 11 system management.

For more information, see the [source repository](https://github.com/NotMyself/claude-win11-speckit-update-skill).

## 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: claymorphism
description: Web and App implementation guide for Claymorphism. Trigger when user wants soft 3D elements, rounded shapes, and a playful, tactile appearance.
date_added: "2026-06-17"
risk: safe
source: self
source_type: self
---

# Claymorphism

> "Like interacting with a pristine, digital claymation set. Soft, bubbly, and incredibly approachable."

## When to Use
Use this sub-style when the user's request matches the aesthetic described above. This is a child reference of the `design-it` skill and is not meant to be triggered directly.

## Core Principles
1. **Fluffy 3D Volume**: Elements look like inflated balloons or soft clay blocks.
2. **Double Inner Shadows**: The signature of claymorphism is an inset light shadow on the top-left and an inset dark shadow on the bottom-right, giving 3D volume to a solid shape.
3. **Continuous Curves**: Maximum border-radius. No sharp edges exist in this universe.

## Visual DNA
- **Colors**: Thrives on pastels and bright, friendly hues. **Desert Mirage**, **Earth-Grounded Elegance**, or custom pastel palettes work best.
- **Typography**: Playful, thick, rounded fonts (e.g., `Sniglet`, `Fredoka One`, `Nunito`).
- **Shapes**: 'Squicles' (squares with heavily rounded, continuous corners) and perfect circles.

## Web Implementation
- Distinct from Neumorphism: Claymorphism elements detach from the background (they have drop shadows) and use inner shadows to create volume, often using colors that contrast with the background.
- **CSS Example**:
```css
.clay-card {
  background-color: #F8B4A6; /* Soft coral */
  border-radius: 32px;
  padding: 40px;

  /*
    1. Outer drop shadow (detaches from background)
    2. Inner top-left highlight (volume)
    3. Inner bottom-right shadow (volume)
  */
  box-shadow:
    8px 8px 24px rgba(0, 0, 0, 0.15),           /* Outer */
    inset -8px -8px 16px rgba(0, 0, 0, 0.1),    /* Inner dark */
    inset 8px 8px 16px rgba(255, 255, 255, 0.4); /* Inner light */

  transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1); /* Bouncy */
}

.clay-card:hover {
  transform: translateY(-5px) scale(1.02);
}
```

## App Implementation

### SwiftUI
```swift
struct ClayCard: View {
    @State private var isPressed = false

    var body: some View {
        VStack(spacing: 16) {
            Image(systemName: "cloud.sun.fill")
                .font(.system(size: 48))
                .foregroundColor(.white)
            Text("Claymorphic Card")
                .font(.system(size: 20, weight: .bold, design: .rounded))
                .foregroundColor(.white)
        }
        .padding(40)
        .background(Color(red: 0.97, green: 0.71, blue: 0.65)) // Soft coral
        .cornerRadius(32)
        // Outer shadow — detaches from background
        .shadow(color: .black.opacity(0.15), radius: 12, x: 8, y: 8)
        // Inner highlight (top-left) — faked with overlay
        .overlay(
            RoundedRectangle(cornerRadius: 32)
                .stroke(
                    LinearGradient(
                        colors: [.white.opacity(0.5), .clear, .black.opacity(0.1)],
                        startPoint: .topLeading,
                        endPoint: .bottomTrailing
                    ),
                    lineWidth: 3
                )
        )
        // Bouncy spring animation on tap
        .scaleEffect(isPressed ? 0.95 : 1.0)
        .animation(.interpolatingSpring(stiffness: 300, damping: 10), value: isPressed)
        .onTapGesture { }
        .simultaneousGesture(
            DragGesture(minimumDistance: 0)
                .onChanged { _ in isPressed = true }
                .onEnded { _ in isPressed = false }
        )
    }
}
```
- The "clay" volume comes from a gradient stroke overlay: white on top-left, dark on bottom-right.
- Use `.interpolatingSpring(stiffness: 300, damping: 10)` for the bouncy feel — critical for clay aesthetics.
- Background color should be pastel/bright but NOT the same as the parent (unlike neumorphism).

### Flutter
```dart
class ClayCard extends StatefulWidget {
  @override
  State<ClayCard> createState() => _ClayCardState();
}

class _ClayCardState extends State<ClayCard> with SingleTickerProviderStateMixin {
  double _scale = 1.0;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: (_) => setState(() => _scale = 0.95),
      onTapUp: (_) => setState(() => _scale = 1.0),
      onTapCancel: () => setState(() => _scale = 1.0),
      child: AnimatedScale(
        scale: _scale,
        duration: const Duration(milliseconds: 200),
        curve: Curves.elasticOut,  // Bouncy clay feel
        child: Container(
          padding: const EdgeInsets.all(40),
          decoration: BoxDecoration(
            color: const Color(0xFFF8B4A6), // Soft coral
            borderRadius: BorderRadius.circular(32),
            boxShadow: [
              // Outer shadow
              BoxShadow(
                color: Colors.black.withOpacity(0.15),
                offset: const Offset(8, 8),
                blurRadius: 24,
              ),
            ],
            // Gradient border for the clay volume effect
            border: GradientBorder(
              gradient: LinearGradient(
                colors: [
                  Colors.white.withOpacity(0.5),
                  Colors.transparent,
                  Colors.black.withOpacity(0.1),
                ],
                begin: Alignment.topLeft,
                end: Alignment.bottomRight,
              ),
              width: 3,
            ),
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              const Icon(Icons.wb_sunny, size: 48, color: Colors.white),
              const SizedBox(height: 16),
              const Text('Claymorphic Card',
                style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold,
                  color: Colors.white)),
            ],
          ),
        ),
      ),
    );
  }
}
```
- Use `Curves.elasticOut` or `Curves.bounceOut` for the spring animation — essential for the clay feeling.
- Gradient borders require a custom `ShapeDecoration` or a `Stack` with a gradient container behind the main container.
- Alternative for inner shadow: use `flutter_inset_box_shadow` package with light top-left and dark bottom-right insets.

### React Native
```jsx
const ClayCard = () => {
  const scale = useRef(new Animated.Value(1)).current;

  const pressIn = () => {
    Animated.spring(scale, {
      toValue: 0.95,
      friction: 3,      // Low friction = bouncy
      tension: 100,
      useNativeDriver: true,
    }).start();
  };

  const pressOut = () => {
    Animated.spring(scale, {
      toValue: 1,
      friction: 3,
      tension: 100,
      useNativeDriver: true,
    }).start();
  };

  return (
    <Pressable onPressIn={pressIn} onPressOut={pressOut}>
      <Animated.View style={{
        transform: [{ scale }],
        padding: 40,
        backgroundColor: '#F8B4A6',
        borderRadius: 32,
        alignItems: 'center',
        // Outer shadow
        shadowColor: '#000',
        shadowOffset: { width: 8, height: 8 },
        shadowOpacity: 0.15,
        shadowRadius: 12,
        elevation: 8,
        // Gradient border must be faked with a wrapper or SVG
        borderWidth: 3,
        borderColor: 'rgba(255,255,255,0.3)', // Simplified — top highlight
      }}>
        <Text style={{ fontSize: 48 }}>☀</Text>
        <Text style={{
          fontSize: 20, fontWeight: '700', color: '#FFF', marginTop: 16,
        }}>
          Claymorphic Card
        </Text>
      </Animated.View>
    </Pressable>
  );
};
```
- Use `Animated.spring` with low `friction` (3-5) for the signature bouncy clay behavior.
- Gradient borders aren't possible natively — use a solid white-tinted border as a simplified approximation, or wrap in an `expo-linear-gradient` View.

### Jetpack Compose
```kotlin
@Composable
fun ClayCard() {
    var isPressed by remember { mutableStateOf(false) }
    val scale by animateFloatAsState(
        targetValue = if (isPressed) 0.95f else 1f,
        animationSpec = spring(dampingRatio = 0.3f, stiffness = 300f),
    )

    Box(
        modifier = Modifier
            .graphicsLayer { scaleX = scale; scaleY = scale }
            .shadow(8.dp, RoundedCornerShape(32.dp))
            .clip(RoundedCornerShape(32.dp))
            .background(Color(0xFFF8B4A6))
            .border(
                3.dp,
                Brush.linearGradient(
                    colors = listOf(
                        Color.White.copy(alpha = 0.5f),
                        Color.Transparent,
                        Color.Black.copy(alpha = 0.1f),
                    ),
                    start = Offset.Zero,
                    end = Offset.Infinite,
                ),
                RoundedCornerShape(32.dp),
            )
            .padding(40.dp)
            .pointerInput(Unit) {
                detectTapGestures(
                    onPress = {
                        isPressed = true
                        tryAwaitRelease()
                        isPressed = false
                    },
                )
            },
        contentAlignment = Alignment.Center,
    ) {
        Column(horizontalAlignment = Alignment.CenterHorizontally) {
            Icon(Icons.Default.WbSunny, tint = Color.White,
                modifier = Modifier.size(48.dp))
            Spacer(Modifier.height(16.dp))
            Text("Claymorphic Card",
                fontSize = 20.sp, fontWeight = FontWeight.Bold, color = Color.White)
        }
    }
}
```
- Use `spring(dampingRatio = 0.3f)` — low damping = bouncy. This is the core of the clay feeling.
- Gradient borders work natively in Compose via `Modifier.border(width, Brush.linearGradient(...), shape)`.
- Use `Modifier.clip()` before `.background()` to ensure the rounded corners clip content properly.

## Do's and Don'ts
- **DO**: Use highly bouncy, spring-based animations to reinforce the soft, physical nature of the "clay."
- **DON'T**: Use thin, delicate fonts. They will get lost against the heavy, voluminous UI elements.

## Limitations
- This is a styling reference and does not replace environment-specific validation, accessibility testing, or expert review.
- Ensure appropriate contrast ratios and responsive behaviors are verified separately.


---
name: clean-code
description: "This skill embodies the principles of \"Clean Code\" by Robert C. Martin (Uncle Bob). Use it to transform \"code that works\" into \"code that is clean.\""
risk: safe
source: "ClawForge (https://github.com/jackjin1997/ClawForge)"
date_added: "2026-02-27"
---

# Clean Code Skill

This skill embodies the principles of "Clean Code" by Robert C. Martin (Uncle Bob). Use it to transform "code that works" into "code that is clean."

## 🧠 Core Philosophy
> "Code is clean if it can be read, and enhanced by a developer other than its original author." — Grady Booch

## When to Use
Use this skill when:
- **Writing new code**: To ensure high quality from the start.
- **Reviewing Pull Requests**: To provide constructive, principle-based feedback.
- **Refactoring legacy code**: To identify and remove code smells.
- **Improving team standards**: To align on industry-standard best practices.

## 1. Meaningful Names
- **Use Intention-Revealing Names**: `elapsedTimeInDays` instead of `d`.
- **Avoid Disinformation**: Don't use `accountList` if it's actually a `Map`.
- **Make Meaningful Distinctions**: Avoid `ProductData` vs `ProductInfo`.
- **Use Pronounceable/Searchable Names**: Avoid `genymdhms`.
- **Class Names**: Use nouns (`Customer`, `WikiPage`). Avoid `Manager`, `Data`.
- **Method Names**: Use verbs (`postPayment`, `deletePage`).

## 2. Functions
- **Small!**: Functions should be shorter than you think.
- **Do One Thing**: A function should do only one thing, and do it well.
- **One Level of Abstraction**: Don't mix high-level business logic with low-level details (like regex).
- **Descriptive Names**: `isPasswordValid` is better than `check`.
- **Arguments**: 0 is ideal, 1-2 is okay, 3+ requires a very strong justification.
- **No Side Effects**: Functions shouldn't secretly change global state.

## 3. Comments
- **Don't Comment Bad Code—Rewrite It**: Most comments are a sign of failure to express ourselves in code.
- **Explain Yourself in Code**:
  ```python
  # Check if employee is eligible for full benefits
  if employee.flags & HOURLY and employee.age > 65:
  ```
  vs
  ```python
  if employee.isEligibleForFullBenefits():
  ```
- **Good Comments**: Legal, Informative (regex intent), Clarification (external libraries), TODOs.
- **Bad Comments**: Mumbling, Redundant, Misleading, Mandated, Noise, Position Markers.

## 4. Formatting
- **The Newspaper Metaphor**: High-level concepts at the top, details at the bottom.
- **Vertical Density**: Related lines should be close to each other.
- **Distance**: Variables should be declared near their usage.
- **Indentation**: Essential for structural readability.

## 5. Objects and Data Structures
- **Data Abstraction**: Hide the implementation behind interfaces.
- **The Law of Demeter**: A module should not know about the innards of the objects it manipulates. Avoid `a.getB().getC().doSomething()`.
- **Data Transfer Objects (DTO)**: Classes with public variables and no functions.

## 6. Error Handling
- **Use Exceptions instead of Return Codes**: Keeps logic clean.
- **Write Try-Catch-Finally First**: Defines the scope of the operation.
- **Don't Return Null**: It forces the caller to check for null every time.
- **Don't Pass Null**: Leads to `NullPointerException`.

## 7. Unit Tests
- **The Three Laws of TDD**:
  1. Don't write production code until you have a failing unit test.
  2. Don't write more of a unit test than is sufficient to fail.
  3. Don't write more production code than is sufficient to pass the failing test.
- **F.I.R.S.T. Principles**: Fast, Independent, Repeatable, Self-Validating, Timely.

## 8. Classes
- **Small!**: Classes should have a single responsibility (SRP).
- **The Stepdown Rule**: We want the code to read like a top-down narrative.

## 9. Smells and Heuristics
- **Rigidity**: Hard to change.
- **Fragility**: Breaks in many places.
- **Immobility**: Hard to reuse.
- **Viscosity**: Hard to do the right thing.
- **Needless Complexity/Repetition**.

## 🛠 Implementation Checklist
- [ ] Is this function smaller than 20 lines?
- [ ] Does this function do exactly one thing?
- [ ] Are all names searchable and intention-revealing?
- [ ] Have I avoided comments by making the code clearer?
- [ ] Am I passing too many arguments?
- [ ] Is there a failing test for this change?

## 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: "clean-code-guard"
description: "Review generated or changed production code with Clean Code, SOLID, DRY, KISS, YAGNI, and LLM-specific failure-mode checks."
risk: "critical"
source: "community"
source_repo: "amElnagdy/guard-skills"
source_type: "community"
date_added: 2026-07-13
author: "community"
tags: []
tools: []
---

# clean-code-guard

You are reviewing generated or changed code before it ships. Apply the rules below as a guard pass after the first implementation pass — and once this skill is active, keep applying it to every later code change in the same session, re-running the self-check before delivery after each edit rather than reverting to unguarded output because the skill loaded earlier. If the user explicitly invokes this skill before writing code, use the same rules while writing and still run the self-check before delivery.

## When to Use

Use this skill when reviewing generated or changed code before it ships. Activate it reactively after an agent writes, edits, or refactors production code — especially after a first implementation pass. Re-run the guard pass before delivery after each edit.

## Compatibility

This is a portable instruction skill. It requires no MCP server, network access,
API key, shell command, local executable, or bundled script. It can be used in
any runtime that supports `SKILL.md` plus directly linked [references/](references/)
files; `agents/openai.yaml` is lightweight display metadata.

This skill does not replace project linters, formatters, type checkers, or test
runners. Use the project's own tools for mechanical verification; use this skill
for the judgement layer around code quality and review.

## How to use this skill

This skill has three modes — pick based on the user's request.

**Guard-pass mode** (recommended): after code has been generated, edited, refactored, or fixed, check the diff or target files against the *Always-applied imperatives* below. Fix violations before presenting, committing, or merging the work.

**Live mode** (explicit): when the user invokes this skill before a risky code edit, apply the same imperatives while writing, then run the *Self-check before delivery* checklist. If you violate any rule, fix it before showing the user.

**Review mode** (triggered when the user asks you to review, audit, critique, or rate code): walk [references/review-checklist.md](references/review-checklist.md) against the target file(s) and produce a structured findings report. Do not edit code in review mode unless asked.

Across all three modes, the rule bodies live in [references/](references/). Read the relevant reference file when:
- You hit a rule you don't fully remember the reasoning for.
- The user pushes back on a rule and you need the source citation.
- You're in review mode and need the full checklist.
- The code under review touches a specific principle (e.g., subclassing → [references/solid.md](references/solid.md); deduplication → [references/dry-kiss-yagni.md](references/dry-kiss-yagni.md)).

The reference files are:
- [references/naming-and-functions.md](references/naming-and-functions.md) — names, function size, parameters, command/query separation.
- [references/comments-and-formatting.md](references/comments-and-formatting.md) — when to comment, when to delete, matching neighbor style.
- [references/solid.md](references/solid.md) — SRP, OCP, LSP, ISP, DIP with the modern phrasings and detection smells.
- [references/dry-kiss-yagni.md](references/dry-kiss-yagni.md) — knowledge vs code duplication, Sandi Metz's re-inline rule, McCabe complexity, Fowler's YAGNI cost categories.
- [references/ai-failure-modes.md](references/ai-failure-modes.md) — the 14 systematic ways LLMs produce bad code. **Read this one first if you are an AI agent reading this skill.** It is the highest-leverage file in the skill.
- [references/review-checklist.md](references/review-checklist.md) — structured walk-through for review mode.
- [references/sources.md](references/sources.md) — central bibliography for source URLs. Read it only when you need to verify or cite an external source.

## Examples

- A coding agent implements an endpoint: use guard-pass mode on the diff before
  the work is presented or committed.
- User asks "review this PR" or "should I merge this?": use review mode and
  report findings from [references/review-checklist.md](references/review-checklist.md); do not edit unless
  asked.
- User asks "implement this endpoint using clean-code-guard": use live mode
  while writing, then run the self-check before delivery.
- User asks "refactor this function, same behavior": preserve observable
  behavior exactly and treat any bug fix as a separate change.

## Success criteria

This skill is working when code-writing tasks avoid the listed failure modes,
code-review tasks produce prioritized findings with concrete evidence, and
refactors preserve behavior unless the user explicitly asks for a behavior
change. It should stay silent for conceptual, CI, git workflow, prose, data
analysis, and test-running tasks covered by the frontmatter exclusions.

## Why this skill exists

LLM-generated code has measurable, systematic failure modes that generic "follow clean code" instructions do not catch. Examples backed by published research:

- **Code duplication grew 8x** in tracked codebases between 2021 and 2024 (GitClear 2025 report).
- **Package hallucination rate averages 19.6%** across 16 models (Spracklen et al., USENIX Security '25).
- LLMs often wrap risky operations in broad catch-all handlers that swallow errors (Karpathy).
- AI agents **"declare success despite failing tests"** by returning hardcoded fixture values (Fowler, Patterns for Reducing Friction).
- Function size grew from 142 to 267 LoC, cyclomatic complexity from 4.2 to 8.1 in AI-assisted commits (GitClear).

The classic principles (Clean Code, SOLID, DRY/KISS/YAGNI) are still the foundation — but this skill adds the *AI-specific* layer most rule packs miss.

## Always-applied imperatives

These are the rules to follow on every code change. They are imperative, not suggestions.

### Functions and names

1. **Names reveal intent.** Never use `data`, `data2`, `result`, `result_final`, `item`, `temp`, `value`, `obj`, `info`, `helper`, `manager`, `utils`, or `handle_*`/`process_*`/`do_*` without a qualifier. A name must answer *why it exists and what it does*. (Clean Code Ch. 2)
2. **Functions stay small.** Target ≤20 lines, one level of abstraction, one thing. If you can extract a function with a name that doesn't restate the body, the parent was doing more than one thing. (Clean Code Ch. 3)
3. **Four arguments is the hard ceiling.** At five, stop and introduce a request/config object (record, struct, DTO, or equivalent). Never use boolean flag arguments — split into two functions instead.
4. **No output arguments.** A function either returns a value (query) or has a side effect (command). Never both. Command names use verbs; query names use nouns or getter-style names. (CQS)

### Comments and structure

5. **Comments explain *why*, never *what*.** Delete any comment that paraphrases the line below it. Delete step-number scaffolding comments. Delete commented-out code — version control exists. (Clean Code Ch. 4)
6. **Match the file's existing style.** Read the file you're editing and at least one neighbor before writing. Mirror the casing, import order, error handling, logging, and HTTP/DB client choices. Do not introduce a second pattern.

### SOLID

7. **One actor per module.** A class should be answerable to one stakeholder group (Accounting, Auth, Reporting). If two unrelated subsystems both reach into the same class, split it. (SRP, Uncle Bob 2014)
8. **Extension via new code, not edits.** If adding a new variant requires another type-tag branch in an existing function, refactor to a registry, strategy, or polymorphic dispatch first. (OCP)
9. **No subclass refuses its parent's contract.** Never override a method to signal "not implemented" or "unsupported operation." Never strengthen preconditions or weaken postconditions in an override. If you need to do that, the inheritance is wrong. (LSP)
10. **Abstractions live with the client, not the implementation.** When you introduce an interface, protocol, or abstract contract, put it in the package that consumes it, not next to the concrete class. (DIP)

### DRY, KISS, YAGNI

11. **Delete duplicated *knowledge*, not duplicated *text*.** Two functions that look alike but encode different rules are not a DRY violation. One rule expressed in code + docs + schema is. (Pragmatic Programmer, "DRY")
12. **The wrong abstraction is worse than duplication.** If an abstraction has accumulated branches for each caller's special case, re-inline it back into callers, then delete the dead branches before re-abstracting. (Sandi Metz, "The Wrong Abstraction")
13. **Complexity ceiling: cyclomatic ≤10, nesting depth ≤5.** Refactor before exceeding. (McCabe 1976)
14. **No speculative anything.** No optional parameter, config flag, env var, feature toggle, interface, factory, or base class without a present-day caller. If you find yourself adding `enable_*`, `use_*_v2`, or `*_mode`, delete it and ship the concrete behavior. (Fowler, "Yagni")

### AI-specific guardrails — the highest-leverage section

15. **Never swallow errors with broad catch-all handling.** Catch only the specific error type you can recover from. If you cannot recover, let the error propagate. Returning null/none/empty success from a catch handler is forbidden unless the function contract documents that behavior. (Karpathy)
16. **Guard the boundary; trust the contract.** At a trust boundary — external input, request/API payloads, deserialized or cross-process data, anything from an untrusted source — validate, even when the happy path looks fine. *Inside* the boundary, do not add null checks or runtime type checks for values whose declared type or caller contract already excludes that case. The test for a guard is not "could this theoretically be wrong" but "can untrusted data reach here." (arXiv 2409.19182)
17. **Verify every import and external call.** Before calling a method on a library, confirm it exists in the version installed (read the package, check the lockfile, or import and inspect). Do not generate code based on what the API "should" look like. (USENIX Security '25)
18. **No hardcoded "success" returns or mock fixtures in production code.** Never return `{"status": "ok", ...}` or canned data from a function whose spec says it does real work. If you cannot implement, fail explicitly with the language's unimplemented or unsupported-operation mechanism and say so. Never disable, skip, or weaken a test to make it pass. (Fowler, Claude Code issue #6984)
19. **Re-derive, do not copy from similar.** When tempted to copy a function and modify it, stop. Re-derive from the spec. Off-by-one and wrong-null-semantic bugs almost always enter through copy-from-similar. (arXiv 2411.01414)
20. **Enumerate boundary cases before writing them.** For any range, off-by-one, null/empty/one/many, even/odd, or unicode/byte boundary, write the case list in a comment first. Cover each case in code before moving on.
21. **Strip dead code before delivery.** Run a linter or grep pass for unused imports, unused symbols, unreachable branches, and "just in case" exports. Remove them. A function that nothing calls today does not get to live for "someday."
22. **Read before write.** Before writing in an unfamiliar repo, read the file you'll edit, one neighbor, and any project rules file (CLAUDE.md, AGENTS.md, README's "conventions" section). Use the project's existing helpers, error types, and logging.
23. **No new dependency for what a few lines cover.** Before adding a package, check the standard library, the already-installed dependencies, and whether a few lines of local code do the job. A new dependency is permanent maintenance and supply-chain surface; add one only when it owns real complexity you should not re-implement (cryptography, parsing, time zones — illustrative, not exhaustive), never to save ten lines. See [references/dry-kiss-yagni.md](references/dry-kiss-yagni.md).

### The floor — never cut these for simplicity

Rule 16 trusts the contract *inside* the boundary; the items below stay even while you strip speculation (14), defensive guards (16), and dead code (21). Removing one of these is a behavior change, not a cleanup — keep it, or flag it and ask.

- **Validation and sanitization at every trust boundary** — external input, request/API payloads, deserialized or cross-process data.
- **Error handling that prevents data loss.**
- **Security measures** — authorization, output escaping, parameterized queries, secret handling.
- **Behavior the user explicitly requested.** Idly mentioned ≠ requested, but do not drop what was asked for.

### Refactoring discipline

24. **Preserve observable behavior when refactoring.** When the user asks you to clean up, simplify, or refactor existing code, do not change the contract — same inputs produce the same outputs, same exceptions raised, same side effects, same ordering guarantees. If you spot a bug while refactoring, flag it separately and ask before changing it. Refactoring is defined as *"a change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior"* (Fowler, *Refactoring*). Bug fixes and refactors are two operations — never bundle them in a single change.

## Self-check before delivery

Before you show the user the code you wrote or edited:

1. Walk imperatives 1–24 against your diff. Fix every violation.
2. For new functions, count: lines ≤ 20? params ≤ 4? complexity feels ≤ 10? names reveal intent?
3. For new comments, ask: does this explain *why*? If it explains *what*, delete it.
4. For new error handling: is the caught error type specific? Does the handler do something other than silently return?
5. For new abstractions (interface, factory, base class, registry): is there a second concrete user *today*? If no, inline it.
6. Did you read the file you edited and at least one neighbor? Did your style match?
7. Is there any hardcoded "ok" return or fixture data? If yes, replace with real implementation or an explicit unimplemented/unsupported-operation failure.
8. If this is a refactor: did you change observable behavior? If yes, you bundled a bug fix — split it out and ask the user.

If you cannot answer yes to every check, fix before shipping.

After the guard pass, surface it so the user can see it ran (guard-pass and live modes — review mode reports through its own findings format). List each fix as `<file>[:<line>] — <what changed>`, omitting the line number if it is unstable, then close with one line: `clean-code-guard: <N> fixed, <M> flagged for author` — or `clean-code-guard: clean` if nothing triggered. Report only changes you actually made; never estimate a quality score or percentage — no baseline exists, so such a number would be invented. This reports the pass; it does not block presenting or committing.

## When the user pushes back on a rule

Refer them to the source name in the relevant [references/](references/) file and use [references/sources.md](references/sources.md) only when the URL is needed. The rules are defensible — they come from primary sources (Uncle Bob, Fowler, Hunt & Thomas, McCabe, Metz) and from published 2024–2026 research on LLM code generation. If the user has a context-specific reason to override (e.g., a constructor genuinely needs 8 params for a config DTO), document the exception in a code comment that names the principle being overridden, the reason, and a revisit trigger — the condition under which it should be reconsidered. An exception comment with no revisit trigger is itself a finding on the next pass: a tradeoff with no exit is just deferred debt.

## Troubleshooting

- If the task is conceptual rather than code-producing, do not apply this skill;
  answer the concept directly.
- If review mode starts producing style-only feedback, use
  [references/review-checklist.md](references/review-checklist.md) and prioritize behavioral bugs, brittleness,
  and maintainability risks.
- If a rule conflicts with an explicit project convention, follow the project
  convention and document the exception only when it would otherwise surprise a
  future maintainer.
- If the skill feels too broad, use the frontmatter exclusions first; do not add
  runtime-specific rules to this general guard skill.

## What this skill does not do

- Run linters or static analysis. Those are tool-level concerns; this skill is about *what to write* and *what to look for*.
- Enforce language-specific formatter or linter preferences. Defer to the project's style tooling.
- Replace tests. Clean code passes tests; tests do not pass without clean code, but clean code without tests is also a defect.


---
name: clerk-auth
description: Expert patterns for Clerk auth implementation, middleware,
  organizations, webhooks, and user sync
risk: safe
source: vibeship-spawner-skills (Apache 2.0)
date_added: 2026-02-27
---

# Clerk Authentication

Expert patterns for Clerk auth implementation, middleware, organizations, webhooks, and user sync

## Patterns

### Next.js App Router Setup

Complete Clerk setup for Next.js 14/15 App Router.

Includes ClerkProvider, environment variables, and basic
sign-in/sign-up components.

Key components:
- ClerkProvider: Wraps app for auth context
- <SignIn />, <SignUp />: Pre-built auth forms
- <UserButton />: User menu with session management

### Code_example

# Environment variables (.env.local)
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/dashboard
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/onboarding

// app/layout.tsx
import { ClerkProvider } from '@clerk/nextjs';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <ClerkProvider>

        {children}

    </ClerkProvider>
  );
}

// app/sign-in/[[...sign-in]]/page.tsx
import { SignIn } from '@clerk/nextjs';

export default function SignInPage() {
  return (

      <SignIn />

  );
}

// app/sign-up/[[...sign-up]]/page.tsx
import { SignUp } from '@clerk/nextjs';

export default function SignUpPage() {
  return (

      <SignUp />

  );
}

// components/Header.tsx
import { SignedIn, SignedOut, SignInButton, UserButton } from '@clerk/nextjs';

export function Header() {
  return (

My App

      <SignedOut>
        <SignInButton />
      </SignedOut>
      <SignedIn>
        <UserButton afterSignOutUrl="/" />
      </SignedIn>

  );
}

### Anti_patterns

- Pattern: ClerkProvider inside page component | Why: Provider must wrap entire app in root layout | Fix: Move ClerkProvider to app/layout.tsx
- Pattern: Using auth() without middleware | Why: auth() requires clerkMiddleware to be configured | Fix: Set up middleware.ts with clerkMiddleware

### References

- https://clerk.com/docs/nextjs/getting-started/quickstart

### Middleware Route Protection

Protect routes using clerkMiddleware and createRouteMatcher.

Best practices:
- Single middleware.ts file at project root
- Use createRouteMatcher for route groups
- auth.protect() for explicit protection
- Centralize all auth logic in middleware

### Code_example

// middleware.ts
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';

// Define protected route patterns
const isProtectedRoute = createRouteMatcher([
  '/dashboard(.*)',
  '/settings(.*)',
  '/api/private(.*)',
]);

// Define public routes (optional, for clarity)
const isPublicRoute = createRouteMatcher([
  '/',
  '/sign-in(.*)',
  '/sign-up(.*)',
  '/api/webhooks(.*)',
]);

export default clerkMiddleware(async (auth, req) => {
  // Protect matched routes
  if (isProtectedRoute(req)) {
    await auth.protect();
  }
});

export const config = {
  matcher: [
    // Match all routes except static files
    '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
    // Always run for API routes
    '/(api|trpc)(.*)',
  ],
};

// Advanced: Role-based protection
export default clerkMiddleware(async (auth, req) => {
  if (isProtectedRoute(req)) {
    await auth.protect();
  }

  // Admin routes require admin role
  if (req.nextUrl.pathname.startsWith('/admin')) {
    await auth.protect({
      role: 'org:admin',
    });
  }

  // Premium routes require premium permission
  if (req.nextUrl.pathname.startsWith('/premium')) {
    await auth.protect({
      permission: 'org:premium:access',
    });
  }
});

### Anti_patterns

- Pattern: Multiple middleware.ts files | Why: Causes conflicts and redirect loops | Fix: Use single middleware.ts with route matchers
- Pattern: Manual redirects in components | Why: Double redirects, missed routes | Fix: Handle all redirects in middleware
- Pattern: Missing matcher config | Why: Middleware won't run on all routes | Fix: Add comprehensive matcher pattern

### References

- https://clerk.com/docs/reference/nextjs/clerk-middleware

### Server Component Authentication

Access auth state in Server Components using auth() and currentUser().

Key functions:
- auth(): Returns userId, sessionId, orgId, claims
- currentUser(): Returns full User object
- Both require clerkMiddleware to be configured

### Code_example

// app/dashboard/page.tsx (Server Component)
import { auth, currentUser } from '@clerk/nextjs/server';
import { redirect } from 'next/navigation';

export default async function DashboardPage() {
  const { userId } = await auth();

  if (!userId) {
    redirect('/sign-in');
  }

  // Full user data (counts toward rate limits)
  const user = await currentUser();

  return (

Welcome, {user?.firstName}!

Email: {user?.emailAddresses[0]?.emailAddress}

  );
}

// Using auth() for quick checks
export default async function ProtectedLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const { userId, orgId, orgRole } = await auth();

  if (!userId) {
    redirect('/sign-in');
  }

  // Check organization access
  if (!orgId) {
    redirect('/select-org');
  }

  return (

Organization Role: {orgRole}

      {children}

  );
}

// Server Action with auth check
// app/actions/posts.ts
'use server';
import { auth } from '@clerk/nextjs/server';

export async function createPost(formData: FormData) {
  const { userId } = await auth();

  if (!userId) {
    throw new Error('Unauthorized');
  }

  const title = formData.get('title') as string;

  // Create post with userId
  const post = await prisma.post.create({
    data: {
      title,
      authorId: userId,
    },
  });

  return post;
}

### Anti_patterns

- Pattern: Not awaiting auth() | Why: auth() is async in App Router | Fix: Use await auth() or const { userId } = await auth()
- Pattern: Using currentUser() for simple checks | Why: Counts toward rate limits, slower than auth() | Fix: Use auth() for userId checks, currentUser() for user data

### References

- https://clerk.com/docs/references/nextjs/auth

### Client Component Hooks

Access auth state in Client Components using hooks.

Key hooks:
- useUser(): User object and loading state
- useAuth(): Auth state, signOut, etc.
- useSession(): Session object
- useOrganization(): Current organization

### Code_example

// components/UserProfile.tsx
'use client';
import { useUser, useAuth } from '@clerk/nextjs';

export function UserProfile() {
  const { user, isLoaded, isSignedIn } = useUser();
  const { signOut } = useAuth();

  if (!isLoaded) {
    return
Loading...
;
  }

  if (!isSignedIn) {
    return
Not signed in
;
  }

  return (

{user.fullName}

{user.emailAddresses[0]?.emailAddress}

      <button onClick={() => signOut()}>Sign Out</button>

  );
}

// Organization context
'use client';
import { useOrganization, useOrganizationList } from '@clerk/nextjs';

export function OrgSwitcher() {
  const { organization, membership } = useOrganization();
  const { setActive, userMemberships } = useOrganizationList({
    userMemberships: { infinite: true },
  });

  if (!organization) {
    return
No organization selected
;
  }

  return (

Current: {organization.name}

Role: {membership?.role}

      <select
        onChange={(e) => setActive?.({ organization: e.target.value })}
        value={organization.id}
      >
        {userMemberships.data?.map((mem) => (
          <option key={mem.organization.id} value={mem.organization.id}>
            {mem.organization.name}
          </option>
        ))}
      </select>

  );
}

// Protected client component
'use client';
import { useAuth } from '@clerk/nextjs';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';

export function ProtectedContent() {
  const { isLoaded, userId } = useAuth();
  const router = useRouter();

  useEffect(() => {
    if (isLoaded && !userId) {
      router.push('/sign-in');
    }
  }, [isLoaded, userId, router]);

  if (!isLoaded || !userId) {
    return
Loading...
;
  }

  return
Protected content here
;
}

### Anti_patterns

- Pattern: Not checking isLoaded | Why: Auth state undefined during hydration | Fix: Always check isLoaded before accessing user/auth state
- Pattern: Using hooks in Server Components | Why: Hooks only work in Client Components | Fix: Use auth() and currentUser() in Server Components

### References

- https://clerk.com/docs/references/react/use-user

### Organizations and Multi-Tenancy

Implement B2B multi-tenancy with Clerk Organizations.

Features:
- Multiple orgs per user
- Roles and permissions
- Organization-scoped data
- Enterprise SSO per organization

### Code_example

// Organization creation UI
// app/create-org/page.tsx
import { CreateOrganization } from '@clerk/nextjs';

export default function CreateOrgPage() {
  return (

      <CreateOrganization afterCreateOrganizationUrl="/dashboard" />

  );
}

// Organization profile and management
// app/org-settings/page.tsx
import { OrganizationProfile } from '@clerk/nextjs';

export default function OrgSettingsPage() {
  return <OrganizationProfile />;
}

// Organization switcher in header
// components/Header.tsx
import { OrganizationSwitcher, UserButton } from '@clerk/nextjs';

export function Header() {
  return (

      <OrganizationSwitcher
        hidePersonal
        afterCreateOrganizationUrl="/dashboard"
        afterSelectOrganizationUrl="/dashboard"
      />
      <UserButton />

  );
}

// Org-scoped data access
// app/dashboard/page.tsx
import { auth } from '@clerk/nextjs/server';
import { prisma } from '@/lib/prisma';

export default async function DashboardPage() {
  const { orgId } = await auth();

  if (!orgId) {
    redirect('/select-org');
  }

  // Fetch org-scoped data
  const projects = await prisma.project.findMany({
    where: { organizationId: orgId },
  });

  return (

Projects

      {projects.map((p) => (

{p.name}

      ))}

  );
}

// Role-based UI
'use client';
import { useOrganization, Protect } from '@clerk/nextjs';

export function AdminPanel() {
  const { membership } = useOrganization();

  // Using Protect component
  return (
    <Protect role="org:admin" fallback={
Admin access required
}>

Admin content here

    </Protect>
  );

  // Or manual check
  if (membership?.role !== 'org:admin') {
    return
Admin access required
;
  }

  return
Admin content here
;
}

### Anti_patterns

- Pattern: Not scoping data by orgId | Why: Data leaks between organizations | Fix: Always filter queries by orgId from auth()
- Pattern: Hardcoding role strings | Why: Typos cause access issues | Fix: Define role constants or use TypeScript enums

### References

- https://clerk.com/docs/guides/organizations
- https://clerk.com/articles/multi-tenancy-in-react-applications-guide

### Webhook User Sync

Sync Clerk users to your database using webhooks.

Key webhooks:
- user.created: New user signed up
- user.updated: User profile changed
- user.deleted: User deleted account

Uses svix for signature verification.

### Code_example

// app/api/webhooks/clerk/route.ts
import { Webhook } from 'svix';
import { headers } from 'next/headers';
import { WebhookEvent } from '@clerk/nextjs/server';
import { prisma } from '@/lib/prisma';

export async function POST(req: Request) {
  const WEBHOOK_SECRET = process.env.CLERK_WEBHOOK_SECRET;

  if (!WEBHOOK_SECRET) {
    throw new Error('Missing CLERK_WEBHOOK_SECRET');
  }

  // Get headers
  const headerPayload = await headers();
  const svix_id = headerPayload.get('svix-id');
  const svix_timestamp = headerPayload.get('svix-timestamp');
  const svix_signature = headerPayload.get('svix-signature');

  if (!svix_id || !svix_timestamp || !svix_signature) {
    return new Response('Missing svix headers', { status: 400 });
  }

  // Get body
  const payload = await req.json();
  const body = JSON.stringify(payload);

  // Verify webhook
  const wh = new Webhook(WEBHOOK_SECRET);
  let evt: WebhookEvent;

  try {
    evt = wh.verify(body, {
      'svix-id': svix_id,
      'svix-timestamp': svix_timestamp,
      'svix-signature': svix_signature,
    }) as WebhookEvent;
  } catch (err) {
    console.error('Webhook verification failed:', err);
    return new Response('Verification failed', { status: 400 });
  }

  // Handle events
  const eventType = evt.type;

  if (eventType === 'user.created') {
    const { id, email_addresses, first_name, last_name, image_url } = evt.data;

    await prisma.user.create({
      data: {
        clerkId: id,
        email: email_addresses[0]?.email_address,
        firstName: first_name,
        lastName: last_name,
        imageUrl: image_url,
      },
    });
  }

  if (eventType === 'user.updated') {
    const { id, email_addresses, first_name, last_name, image_url } = evt.data;

    await prisma.user.update({
      where: { clerkId: id },
      data: {
        email: email_addresses[0]?.email_address,
        firstName: first_name,
        lastName: last_name,
        imageUrl: image_url,
      },
    });
  }

  if (eventType === 'user.deleted') {
    const { id } = evt.data;

    await prisma.user.delete({
      where: { clerkId: id! },
    });
  }

  return new Response('Webhook processed', { status: 200 });
}

// Prisma schema
// prisma/schema.prisma
model User {
  id        String   @id @default(cuid())
  clerkId   String   @unique
  email     String   @unique
  firstName String?
  lastName  String?
  imageUrl  String?
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  posts     Post[]
  @@index([clerkId])
}

### Anti_patterns

- Pattern: Not verifying webhook signature | Why: Anyone can hit your endpoint with fake data | Fix: Always verify with svix
- Pattern: Blocking middleware for webhook routes | Why: Webhooks come from Clerk, not authenticated users | Fix: Add /api/webhooks(.*)' to public routes
- Pattern: Not handling race conditions | Why: user.created might arrive after user.updated | Fix: Use upsert instead of create, handle missing records

### References

- https://clerk.com/docs/webhooks/sync-data
- https://clerk.com/articles/how-to-sync-clerk-user-data-to-your-database

### API Route Protection

Protect API routes using auth() from Clerk.

Route Handlers in App Router use auth() for authentication.
Middleware provides initial protection, auth() provides in-handler verification.

### Code_example

// app/api/projects/route.ts
import { auth } from '@clerk/nextjs/server';
import { prisma } from '@/lib/prisma';
import { NextResponse } from 'next/server';

export async function GET() {
  const { userId, orgId } = await auth();

  if (!userId) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  // User's personal projects or org projects
  const projects = await prisma.project.findMany({
    where: orgId
      ? { organizationId: orgId }
      : { userId, organizationId: null },
  });

  return NextResponse.json(projects);
}

export async function POST(req: Request) {
  const { userId, orgId } = await auth();

  if (!userId) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  const body = await req.json();

  const project = await prisma.project.create({
    data: {
      name: body.name,
      userId,
      organizationId: orgId ?? null,
    },
  });

  return NextResponse.json(project, { status: 201 });
}

// Protected with role check
// app/api/admin/users/route.ts
export async function GET() {
  const { userId, orgRole } = await auth();

  if (!userId) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  if (orgRole !== 'org:admin') {
    return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
  }

  // Admin-only logic
  const users = await prisma.user.findMany();
  return NextResponse.json(users);
}

// Using getAuth in older patterns (not recommended)
// For backwards compatibility only
import { getAuth } from '@clerk/nextjs/server';

export async function GET(req: Request) {
  const { userId } = getAuth(req);
  // ...
}

### Anti_patterns

- Pattern: Trusting middleware alone | Why: Middleware can be bypassed (CVE-2025-29927) | Fix: Always verify auth in route handler too
- Pattern: Not checking orgId for multi-tenant | Why: Users might access other org's data | Fix: Always filter by orgId from auth()

### References

- https://clerk.com/docs/guides/protecting-pages

## Sharp Edges

### CVE-2025-29927 Middleware Bypass Vulnerability

Severity: CRITICAL

### Multiple Middleware Files Cause Conflicts

Severity: HIGH

### 4KB Session Token Cookie Limit

Severity: HIGH

### auth() Requires clerkMiddleware Configuration

Severity: HIGH

### Webhook Race Conditions

Severity: MEDIUM

### auth() is Async in App Router

Severity: MEDIUM

### Middleware Blocks Webhook Endpoints

Severity: MEDIUM

### Accessing Auth State Before isLoaded

Severity: MEDIUM

### Manual Redirects Cause Double Redirects

Severity: MEDIUM

### Organization Data Not Scoped by orgId

Severity: HIGH

## Validation Checks

### Clerk Secret Key in Client Code

Severity: ERROR

CLERK_SECRET_KEY must only be used server-side

Message: Clerk secret key exposed to client. Use CLERK_SECRET_KEY without NEXT_PUBLIC prefix.

### Protected Route Without Middleware

Severity: ERROR

API routes should have middleware protection

Message: API route without auth check. Add middleware protection or auth() check.

### Hardcoded Clerk API Keys

Severity: ERROR

Clerk keys should use environment variables

Message: Hardcoded Clerk keys. Use environment variables.

### Missing Await on auth()

Severity: ERROR

auth() is async in App Router and must be awaited

Message: auth() not awaited. Use 'await auth()' in App Router.

### Multiple Middleware Files

Severity: WARNING

Only one middleware.ts file should exist

Message: Multiple middleware files detected. Use single middleware.ts.

### Webhook Route Not Excluded from Protection

Severity: WARNING

Webhook routes should be public

Message: Webhook route may be blocked by middleware. Add to public routes.

### Accessing Auth Without isLoaded Check

Severity: WARNING

Check isLoaded before accessing user state in client components

Message: Accessing user without isLoaded check. Check isLoaded first.

### Clerk Hooks in Server Component

Severity: ERROR

Clerk hooks only work in Client Components

Message: Clerk hooks in Server Component. Add 'use client' or use auth().

### Multi-Tenant Query Without orgId

Severity: WARNING

Organization data should be scoped by orgId

Message: Query without organization scope. Filter by orgId for multi-tenancy.

### Webhook Without Signature Verification

Severity: ERROR

Clerk webhooks must verify svix signature

Message: Webhook without signature verification. Use svix to verify.

## Collaboration

### Delegation Triggers

- user needs database -> postgres-wizard (User table with clerkId)
- user needs payments -> stripe-integration (Customer linked to Clerk user)
- user needs search -> algolia-search (Secured API keys per user)
- user needs analytics -> segment-cdp (User identification)
- user needs email -> resend-email (Transactional emails)

## When to Use
- User mentions or implies: adding authentication
- User mentions or implies: clerk auth
- User mentions or implies: user authentication
- User mentions or implies: sign in
- User mentions or implies: sign up
- User mentions or implies: user management
- User mentions or implies: multi-tenancy
- User mentions or implies: organizations
- User mentions or implies: sso
- User mentions or implies: single sign-on

## 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: clickup-automation
description: "Automate ClickUp project management including tasks, spaces, folders, lists, comments, and team operations via Rube MCP (Composio). Always search tools first for current schemas."
risk: critical
source: community
date_added: "2026-02-27"
---

# ClickUp Automation via Rube MCP

Automate ClickUp project management workflows including task creation and updates, workspace hierarchy navigation, comments, and team member management through Composio's ClickUp toolkit.

## Prerequisites

- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active ClickUp connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `clickup`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas

## Setup

**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.

1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `clickup`
3. If connection is not ACTIVE, follow the returned auth link to complete ClickUp OAuth
4. Confirm connection status shows ACTIVE before running any workflows

## Core Workflows

### 1. Create and Manage Tasks

**When to use**: User wants to create tasks, subtasks, update task properties, or list tasks in a ClickUp list.

**Tool sequence**:
1. `CLICKUP_GET_AUTHORIZED_TEAMS_WORKSPACES` - Get workspace/team IDs [Prerequisite]
2. `CLICKUP_GET_SPACES` - List spaces in the workspace [Prerequisite]
3. `CLICKUP_GET_FOLDERS` - List folders in a space [Prerequisite]
4. `CLICKUP_GET_FOLDERLESS_LISTS` - Get lists not inside folders [Optional]
5. `CLICKUP_GET_LIST` - Validate list and check available statuses [Prerequisite]
6. `CLICKUP_CREATE_TASK` - Create a task in the target list [Required]
7. `CLICKUP_CREATE_TASK` (with `parent`) - Create subtask under a parent task [Optional]
8. `CLICKUP_UPDATE_TASK` - Modify task status, assignees, dates, priority [Optional]
9. `CLICKUP_GET_TASK` - Retrieve full task details [Optional]
10. `CLICKUP_GET_TASKS` - List all tasks in a list with filters [Optional]
11. `CLICKUP_DELETE_TASK` - Permanently remove a task [Optional]

**Key parameters for CLICKUP_CREATE_TASK**:
- `list_id`: Target list ID (integer, required)
- `name`: Task name (string, required)
- `description`: Detailed task description
- `status`: Must exactly match (case-sensitive) a status name configured in the target list
- `priority`: 1 (Urgent), 2 (High), 3 (Normal), 4 (Low)
- `assignees`: Array of user IDs (integers)
- `due_date`: Unix timestamp in milliseconds
- `parent`: Parent task ID string for creating subtasks
- `tags`: Array of tag name strings
- `time_estimate`: Estimated time in milliseconds

**Pitfalls**:
- `status` is case-sensitive and must match an existing status in the list; use `CLICKUP_GET_LIST` to check available statuses
- `due_date` and `start_date` are Unix timestamps in **milliseconds**, not seconds
- Subtask `parent` must be a task (not another subtask) in the same list
- `notify_all` triggers watcher notifications; set to false for bulk operations
- Retries can create duplicates; track created task IDs to avoid re-creation
- `custom_item_id` for milestones (ID 1) is subject to workspace plan quotas

### 2. Navigate Workspace Hierarchy

**When to use**: User wants to browse or manage the ClickUp workspace structure (Workspaces > Spaces > Folders > Lists).

**Tool sequence**:
1. `CLICKUP_GET_AUTHORIZED_TEAMS_WORKSPACES` - List all accessible workspaces [Required]
2. `CLICKUP_GET_SPACES` - List spaces within a workspace [Required]
3. `CLICKUP_GET_SPACE` - Get details for a specific space [Optional]
4. `CLICKUP_GET_FOLDERS` - List folders in a space [Required]
5. `CLICKUP_GET_FOLDER` - Get details for a specific folder [Optional]
6. `CLICKUP_CREATE_FOLDER` - Create a new folder in a space [Optional]
7. `CLICKUP_GET_FOLDERLESS_LISTS` - List lists not inside any folder [Required]
8. `CLICKUP_GET_LIST` - Get list details including statuses and custom fields [Optional]

**Key parameters**:
- `team_id`: Workspace ID from GET_AUTHORIZED_TEAMS_WORKSPACES (required for spaces)
- `space_id`: Space ID (required for folders and folderless lists)
- `folder_id`: Folder ID (required for GET_FOLDER)
- `list_id`: List ID (required for GET_LIST)
- `archived`: Boolean filter for archived/active items

**Pitfalls**:
- ClickUp hierarchy is: Workspace (Team) > Space > Folder > List > Task
- Lists can exist directly under Spaces (folderless) or inside Folders
- Must use `CLICKUP_GET_FOLDERLESS_LISTS` to find lists not inside folders; `CLICKUP_GET_FOLDERS` only returns folders
- `team_id` in ClickUp API refers to the Workspace ID, not a user group

### 3. Add Comments to Tasks

**When to use**: User wants to add comments, review existing comments, or manage comment threads on tasks.

**Tool sequence**:
1. `CLICKUP_GET_TASK` - Verify task exists and get task_id [Prerequisite]
2. `CLICKUP_CREATE_TASK_COMMENT` - Add a new comment to the task [Required]
3. `CLICKUP_GET_TASK_COMMENTS` - List existing comments on the task [Optional]
4. `CLICKUP_UPDATE_COMMENT` - Edit comment text, assignee, or resolution status [Optional]

**Key parameters for CLICKUP_CREATE_TASK_COMMENT**:
- `task_id`: Task ID string (required)
- `comment_text`: Comment content with ClickUp formatting support (required)
- `assignee`: User ID to assign the comment to (required)
- `notify_all`: true/false for watcher notifications (required)

**Key parameters for CLICKUP_GET_TASK_COMMENTS**:
- `task_id`: Task ID string (required)
- `start` / `start_id`: Pagination for older comments (max 25 per page)

**Pitfalls**:
- `CLICKUP_CREATE_TASK_COMMENT` requires all four fields: `task_id`, `comment_text`, `assignee`, and `notify_all`
- `assignee` on a comment assigns the comment (not the task) to that user
- Comments are paginated at 25 per page; use `start` (Unix ms) and `start_id` for older pages
- `CLICKUP_UPDATE_COMMENT` requires all four fields: `comment_id`, `comment_text`, `assignee`, `resolved`

### 4. Manage Team Members and Assignments

**When to use**: User wants to view workspace members, check seat utilization, or look up user details.

**Tool sequence**:
1. `CLICKUP_GET_AUTHORIZED_TEAMS_WORKSPACES` - List workspaces and get team_id [Required]
2. `CLICKUP_GET_WORKSPACE_SEATS` - Check seat utilization (members vs guests) [Required]
3. `CLICKUP_GET_TEAMS` - List user groups within the workspace [Optional]
4. `CLICKUP_GET_USER` - Get details for a specific user (Enterprise only) [Optional]
5. `CLICKUP_GET_CUSTOM_ROLES` - List custom permission roles [Optional]

**Key parameters**:
- `team_id`: Workspace ID (required for all team operations)
- `user_id`: Specific user ID for GET_USER
- `group_ids`: Comma-separated group IDs to filter teams

**Pitfalls**:
- `CLICKUP_GET_WORKSPACE_SEATS` returns seat counts, not member details; distinguish members from guests
- `CLICKUP_GET_TEAMS` returns user groups, not workspace members; empty groups does not mean no members
- `CLICKUP_GET_USER` is only available on ClickUp Enterprise Plan
- Must repeat workspace seat queries for each workspace in multi-workspace setups

### 5. Filter and Query Tasks

**When to use**: User wants to find tasks with specific filters (status, assignee, dates, tags, custom fields).

**Tool sequence**:
1. `CLICKUP_GET_TASKS` - Filter tasks in a list with multiple criteria [Required]
2. `CLICKUP_GET_TASK` - Get full details for individual tasks [Optional]

**Key parameters for CLICKUP_GET_TASKS**:
- `list_id`: List ID (integer, required)
- `statuses`: Array of status strings to filter by
- `assignees`: Array of user ID strings
- `tags`: Array of tag name strings
- `due_date_gt` / `due_date_lt`: Unix timestamp in ms for date range
- `include_closed`: Boolean to include closed tasks
- `subtasks`: Boolean to include subtasks
- `order_by`: "id", "created", "updated", or "due_date"
- `page`: Page number starting at 0 (max 100 tasks per page)

**Pitfalls**:
- Only tasks whose home list matches `list_id` are returned; tasks in sublists are not included
- Date filters use Unix timestamps in milliseconds
- Status strings must match exactly; use URL encoding for spaces (e.g., "to%20do")
- Page numbering starts at 0; each page returns up to 100 tasks
- `custom_fields` filter accepts an array of JSON strings, not objects

## Common Patterns

### ID Resolution
Always resolve names to IDs through the hierarchy:
- **Workspace name -> team_id**: `CLICKUP_GET_AUTHORIZED_TEAMS_WORKSPACES` and match by name
- **Space name -> space_id**: `CLICKUP_GET_SPACES` with `team_id`
- **Folder name -> folder_id**: `CLICKUP_GET_FOLDERS` with `space_id`
- **List name -> list_id**: Navigate folders or use `CLICKUP_GET_FOLDERLESS_LISTS`
- **Task name -> task_id**: `CLICKUP_GET_TASKS` with `list_id` and match by name

### Pagination
- `CLICKUP_GET_TASKS`: Page-based with `page` starting at 0, max 100 tasks per page
- `CLICKUP_GET_TASK_COMMENTS`: Uses `start` (Unix ms) and `start_id` for cursor-based paging, max 25 per page
- Continue fetching until response returns fewer items than the page size

## Known Pitfalls

### ID Formats
- Workspace/Team IDs are large integers
- Space, folder, and list IDs are integers
- Task IDs are alphanumeric strings (e.g., "9hz", "abc123")
- User IDs are integers
- Comment IDs are integers

### Rate Limits
- ClickUp enforces rate limits; bulk task creation can trigger 429 responses
- Honor `Retry-After` header when present
- Set `notify_all=false` for bulk operations to reduce notification load

### Parameter Quirks
- `team_id` in the API means Workspace ID, not a user group
- `status` on tasks is case-sensitive and list-specific
- Dates are Unix timestamps in **milliseconds** (multiply seconds by 1000)
- `priority` is an integer 1-4 (1=Urgent, 4=Low), not a string
- `CLICKUP_CREATE_TASK_COMMENT` marks `assignee` and `notify_all` as required
- To clear a task description, pass a single space `" "` to `CLICKUP_UPDATE_TASK`

### Hierarchy Rules
- Subtask parent must not itself be a subtask
- Subtask parent must be in the same list
- Lists can be folderless (directly in a Space) or inside a Folder
- Subitem boards are not supported by CLICKUP_CREATE_TASK

## Quick Reference

| Task | Tool Slug | Key Params |
|------|-----------|------------|
| List workspaces | `CLICKUP_GET_AUTHORIZED_TEAMS_WORKSPACES` | (none) |
| List spaces | `CLICKUP_GET_SPACES` | `team_id` |
| Get space details | `CLICKUP_GET_SPACE` | `space_id` |
| List folders | `CLICKUP_GET_FOLDERS` | `space_id` |
| Get folder details | `CLICKUP_GET_FOLDER` | `folder_id` |
| Create folder | `CLICKUP_CREATE_FOLDER` | `space_id`, `name` |
| Folderless lists | `CLICKUP_GET_FOLDERLESS_LISTS` | `space_id` |
| Get list details | `CLICKUP_GET_LIST` | `list_id` |
| Create task | `CLICKUP_CREATE_TASK` | `list_id`, `name`, `status`, `assignees` |
| Update task | `CLICKUP_UPDATE_TASK` | `task_id`, `status`, `priority` |
| Get task | `CLICKUP_GET_TASK` | `task_id`, `include_subtasks` |
| List tasks | `CLICKUP_GET_TASKS` | `list_id`, `statuses`, `page` |
| Delete task | `CLICKUP_DELETE_TASK` | `task_id` |
| Add comment | `CLICKUP_CREATE_TASK_COMMENT` | `task_id`, `comment_text`, `assignee` |
| List comments | `CLICKUP_GET_TASK_COMMENTS` | `task_id`, `start`, `start_id` |
| Update comment | `CLICKUP_UPDATE_COMMENT` | `comment_id`, `comment_text`, `resolved` |
| Workspace seats | `CLICKUP_GET_WORKSPACE_SEATS` | `team_id` |
| List user groups | `CLICKUP_GET_TEAMS` | `team_id` |
| Get user details | `CLICKUP_GET_USER` | `team_id`, `user_id` |
| Custom roles | `CLICKUP_GET_CUSTOM_ROLES` | `team_id` |

## When to Use
This skill is applicable to execute the workflow or actions described in the overview.

## 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: cline-delegate
description: Delegate coding tasks to the Cline CLI (`cline`) only when the user explicitly
  requests it, while the orchestrator retains review and landing responsibility.
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 the `cline` CLI installed and authenticated with `cline auth`,
  Node 18+, and git. The orchestrator must be able to run shell commands and read
  files.
metadata:
  version: 0.5.0
---
# Cline Delegate

## When to Use

- You want to delegate a bounded coding task to a separate `cline` implementer (`Cline`) and then review its diff yourself.
- The user explicitly asked for delegation to this implementer.

You are the **orchestrator**. Delegate a bounded coding task to a separate **implementer** - the Cline
coding agent CLI - then review what it produced and land it yourself. You write the brief and own
the judgment; the implementer makes changes in its own session in a clean working tree; you verify
and commit.

The loop needs only a shell command and file access, so any comparable orchestrator can drive it.

## When NOT to use this

- The task is small enough to do inline; delegation overhead is not worth it.
- The `cline` CLI is not installed or authenticated.
- You require the relay to configure a sandbox. Cline exposes sandbox controls, but this relay
  leaves them to the CLI environment; use `--plan` when the run must be read-only.

## Prerequisites (check once)

1. Install `cline` (npm or bundled binary; the relay probes `cline --version`).
2. Authenticate: run `cline auth` (interactive sign-in), or configure
   `ANTHROPIC_API_KEY` / an OpenAI-compatible base URL.
3. Confirm `cline --version` succeeds.
4. Work in, or point `--cd` at, the target git repository.

## Choose the model (optional)

Cline picks a default model. To choose another, pass the separate `--model <id>` or `--provider <name>`
(e.g. `anthropic`, `openai-native`, `openrouter`). The relay accepts letters, digits,
and `. _ : / -` only (the value reaches a shell on Windows).

## The loop

Run these five steps per task. Steps 1, 4, and 5 require judgment; 2 and 3 are mechanical.

### 1. Write a brief

Cline sees only the text you send. It cannot read your conversation: the brief must stand alone
with the goal, current state, what to change, what to leave untouched, the project's **real**
gates, and a report contract. Keep each brief to a single task. Write it to a file and pass it as
the relay's `--brief`. See [references/writing-the-brief.md](references/writing-the-brief.md).

### 2. Dispatch

Use the bundled relay. It runs `cline --json -v`, streams the brief on stdin behind a fixed
positional instruction, captures the JSON event stream, and writes `result.json`.

```bash
node "<skill-dir>/scripts/relay.mjs" --brief brief.txt --cd /path/to/repo
# choose a model / provider:        add --model <id>  --provider <name>
# read-only planning pass:          add --plan   (forces --auto-approve false)
# deny approval-required tools:     add --auto-approve false
# hard time limit (watchdog):        add --timeout 2h   (the 30m default suits brief runs; most implementation briefs should be 1-2h)
# see all options:                   node .../relay.mjs --help
```

The child's cwd pins the workspace. The relay writes artifacts under the system temp dir by
default and never commits. See [references/dispatch-and-poll.md](references/dispatch-and-poll.md).

### 3. Wait for completion

The relay blocks until cline finishes. Run it with the orchestrator's background-command
facility, or background it in the shell and poll for `result.json`. A pre-run usage error exits 2
and writes no result; a missing `cline` exits 127 and writes `status: "cline_unavailable"`.

Completion means the process exited and `result.json` exists - trust process state and the
working tree, not the progress display. Cline's final message is the `finalMessage` field of
`result.json`.

### 4. Review - do not trust the self-report

- Re-run the project's gates yourself.
- Read the diff against the brief, starting with `touchedFiles`.
- Run relevant guard skills if installed.

See [references/review-and-land.md](references/review-and-land.md).

### 5. Land it

If the work is good, commit it. The relay never commits - the diff and `result.json` are the
record; run `git status` and `git diff` first to confirm exactly what changed. If the group has a
PR flow, make the commit and push a branch; let human review happen. If the diff is wrong or
incomplete, re-dispatch a corrected brief in a fresh run and review again.

## Autonomy and permissions

The relay explicitly passes Cline's `--auto-approve`, defaulting to `true` in act mode. Cline
plan mode can request a switch to act mode, so `--plan` forces `--auto-approve false`; the relay
rejects `--plan --auto-approve true`. That pair is the read-only gate. Cline also exposes sandbox
through `--data-dir` / `CLINE_SANDBOX`, but the relay does not configure or override it. Plan-first
for anything risky, then review the plan before a separate act-mode dispatch. Malformed or malicious
briefs remain dangerous in act mode because commands run as the current user.

## Authorization model

Delegation is something the human opts into. Once briefed, cline works as a tool you approved use
of. The boundary is: **do not accept conclusions from the self-report**; verify everything on
disk. For anything touching credentials, production data, or irreversible operations, stop and ask
the human first instead of encoding it in a brief.

## References

- [references/writing-the-brief.md](references/writing-the-brief.md) - structure, scope, gates,
  brief delivery.
- [references/dispatch-and-poll.md](references/dispatch-and-poll.md) - flags, artifacts,
  `result.json`, and failure recovery.
- [references/review-and-land.md](references/review-and-land.md) - what to verify before calling
  the diff done, at the end of a run.
- [references/multi-task-queues.md](references/multi-task-queues.md) - sequential queues,
  constraint carry-forward, progress tracking, and the final coherence pass.

## Limitations

- Docs-only import — executable `scripts/relay.mjs` not included; see upstream for full runtime. Requires `cline` CLI, Node 18+, git.
- Relay never commits — it only returns structured result JSON; you review and land the commit.

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


---
name: close-automation
description: "Automate Close CRM tasks via Rube MCP (Composio): create leads, manage calls/SMS, handle tasks, and track notes. Always search tools first for current schemas."
risk: critical
source: community
date_added: "2026-02-27"
---

# Close CRM Automation via Rube MCP

Automate Close CRM operations through Composio's Close toolkit via Rube MCP.

## Prerequisites

- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Close connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `close`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas

## Setup

**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.

1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `close`
3. If connection is not ACTIVE, follow the returned auth link to complete Close API authentication
4. Confirm connection status shows ACTIVE before running any workflows

## Core Workflows

### 1. Create and Manage Leads

**When to use**: User wants to create new leads or manage existing lead records

**Tool sequence**:
1. `CLOSE_CREATE_LEAD` - Create a new lead in Close [Required]

**Key parameters**:
- `name`: Lead/company name
- `contacts`: Array of contact objects associated with the lead
- `custom`: Custom field values as key-value pairs
- `status_id`: Lead status ID

**Pitfalls**:
- Leads in Close represent companies/organizations, not individual people
- Contacts are nested within leads; create the lead first, then contacts are included
- Custom field keys use the custom field ID (e.g., 'custom.cf_XXX'), not display names
- Duplicate lead detection is not automatic; check before creating

### 2. Log Calls

**When to use**: User wants to log a phone call activity against a lead

**Tool sequence**:
1. `CLOSE_CREATE_CALL` - Log a call activity [Required]

**Key parameters**:
- `lead_id`: ID of the associated lead
- `contact_id`: ID of the contact called
- `direction`: 'outbound' or 'inbound'
- `status`: Call status ('completed', 'no-answer', 'busy', etc.)
- `duration`: Call duration in seconds
- `note`: Call notes

**Pitfalls**:
- lead_id is required; calls must be associated with a lead
- Duration is in seconds, not minutes
- Call direction affects reporting and analytics
- contact_id is optional but recommended for tracking

### 3. Send SMS Messages

**When to use**: User wants to send or log SMS messages through Close

**Tool sequence**:
1. `CLOSE_CREATE_SMS` - Send or log an SMS message [Required]

**Key parameters**:
- `lead_id`: ID of the associated lead
- `contact_id`: ID of the contact
- `direction`: 'outbound' or 'inbound'
- `text`: SMS message content
- `status`: Message status

**Pitfalls**:
- SMS functionality requires Close phone/SMS integration to be configured
- lead_id is required for all SMS activities
- Outbound SMS may require a verified sending number
- Message length limits may apply depending on carrier

### 4. Manage Tasks

**When to use**: User wants to create or manage follow-up tasks

**Tool sequence**:
1. `CLOSE_CREATE_TASK` - Create a new task [Required]

**Key parameters**:
- `lead_id`: Associated lead ID
- `text`: Task description
- `date`: Due date for the task
- `assigned_to`: User ID of the assignee
- `is_complete`: Whether the task is completed

**Pitfalls**:
- Tasks are associated with leads, not contacts
- Date format should follow ISO 8601
- assigned_to requires the Close user ID, not email or name
- Tasks without a date appear in the 'no due date' section

### 5. Manage Notes

**When to use**: User wants to add or retrieve notes on leads

**Tool sequence**:
1. `CLOSE_GET_NOTE` - Retrieve a specific note [Required]

**Key parameters**:
- `note_id`: ID of the note to retrieve

**Pitfalls**:
- Notes are associated with leads
- Note IDs are required for retrieval; search leads first to find note references
- Notes support plain text and basic formatting

### 6. Delete Activities

**When to use**: User wants to remove call records or other activities

**Tool sequence**:
1. `CLOSE_DELETE_CALL` - Delete a call activity [Required]

**Key parameters**:
- `call_id`: ID of the call to delete

**Pitfalls**:
- Deletion is permanent and cannot be undone
- Only the call creator or admin can delete calls
- Deleting a call removes it from all reports and timelines

## Common Patterns

### Lead and Contact Relationship

```
Close data model:
- Lead = Company/Organization
  - Contact = Person (nested within Lead)
  - Activity = Call, SMS, Email, Note (linked to Lead)
  - Task = Follow-up item (linked to Lead)
  - Opportunity = Deal (linked to Lead)
```

### ID Resolution

**Lead ID**:
```
1. Search for leads using the Close search API
2. Extract lead_id from results (format: 'lead_XXXXXXXXXXXXX')
3. Use lead_id in all activity creation calls
```

**Contact ID**:
```
1. Retrieve lead details to get nested contacts
2. Extract contact_id (format: 'cont_XXXXXXXXXXXXX')
3. Use in call/SMS activities for accurate tracking
```

### Activity Logging Pattern

```
1. Identify the lead_id and optionally contact_id
2. Create the activity (call, SMS, note) with lead_id
3. Include relevant metadata (duration, direction, status)
4. Create follow-up tasks if needed
```

## Known Pitfalls

**ID Formats**:
- Lead IDs: 'lead_XXXXXXXXXXXXX'
- Contact IDs: 'cont_XXXXXXXXXXXXX'
- Activity IDs vary by type: 'acti_XXXXXXXXXXXXX', 'call_XXXXXXXXXXXXX'
- Custom field IDs: 'custom.cf_XXXXXXXXXXXXX'
- Always use the full ID string

**Rate Limits**:
- Close API has rate limits based on your plan
- Implement delays between bulk operations
- Monitor response headers for rate limit status
- 429 responses require backoff

**Custom Fields**:
- Custom fields are referenced by their API ID, not display name
- Different lead statuses may have different required custom fields
- Custom field types (text, number, date, dropdown) enforce value formats

**Data Integrity**:
- Leads are the primary entity; contacts and activities are linked to leads
- Deleting a lead may cascade to its contacts and activities
- Bulk operations should validate IDs before executing

## Quick Reference

| Task | Tool Slug | Key Params |
|------|-----------|------------|
| Create lead | CLOSE_CREATE_LEAD | name, contacts, custom |
| Log call | CLOSE_CREATE_CALL | lead_id, direction, status, duration |
| Send SMS | CLOSE_CREATE_SMS | lead_id, text, direction |
| Create task | CLOSE_CREATE_TASK | lead_id, text, date, assigned_to |
| Get note | CLOSE_GET_NOTE | note_id |
| Delete call | CLOSE_DELETE_CALL | call_id |

## When to Use
This skill is applicable to execute the workflow or actions described in the overview.

## 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: closed-loop-delivery
description: Use when a coding task must be completed against explicit acceptance criteria with minimal user re-intervention across implementation, review feedback, deployment, and runtime verification.
risk: safe
source: community
date_added: "2026-03-12"
---

# Closed-Loop Delivery

## Overview

Treat each task as incomplete until acceptance criteria are verified in evidence, not until code is merely changed.

Core rule: **deliver against DoD (Definition of Done), not against code diff size.**

## When to Use
Use this skill when:
- user gives a coding/fix task and expects end-to-end completion
- task spans code + tests + PR comments + dev deploy + runtime checks
- repeated manual prompts like "now test", "now deploy", "now re-check PR" should be avoided

Do not use this skill for:
- pure Q&A/explanations
- prod deploy requests without explicit human approval
- tasks blocked by missing secrets/account access that cannot be inferred

## Required Inputs

Before execution, define these once:
- task goal
- acceptance criteria (DoD)
- target environment (`dev` by default)
- max iteration rounds (default `2`)

If acceptance criteria are missing, request them once. If user does not provide, propose a concrete default and proceed.

## Issue Gate Dependency

Before execution, prefer using `create-issue-gate`.

- If issue status is `ready` and execution gate is `allowed`, continue.
- If issue status is `draft`, do not execute implementation/deploy/review loops.
- Require user-provided, testable acceptance criteria before starting execution.

## Default Workflow

1. **Define DoD**
   - Convert request into testable criteria.
   - Example: checkout task DoD = "checkout endpoint returns a valid, openable third-party payment URL in dev".

2. **Implement minimal change**
   - Keep scope tight to task goal.

3. **Verify locally**
   - Run focused tests first, then broader checks if needed.

4. **Review loop**
   - Fetch PR comments/reviews.
   - Classify valid vs non-actionable.
   - Fix valid items, re-run verification.

5. **Dev deploy + runtime verification**
   - Deploy to `dev` when runtime behavior matters.
   - Verify via real API/Lambda/log evidence against DoD.

6. **Completion decision**
   - Only report "done" when all DoD checks pass.
   - Otherwise continue loop until pass or stop condition.

## PR Comment Polling Policy

Avoid noisy short polling by default. Use batched windows:

- **Round 1:** wait `3m`, collect delta comments/reviews
- **Round 2:** wait `6m`, collect delta again
- **Final round:** wait `10m`, collect all remaining visible comments/reviews

At each round:
- process all new comments in one batch
- avoid immediate re-poll after each single comment
- after the `10m` round, stop waiting and proceed with all comments visible at that point

If CI is still running, align polling to check completion boundaries instead of fixed rapid polling.

## Human Gate Rules (Must Ask)

Require explicit user confirmation for:
- production/staging deploy beyond agreed scope
- destructive operations (history rewrite, force push, data-destructive ops)
- actions with billing/security posture changes
- secret values not available in repo/runtime
- ambiguous DoD that materially changes outcome

## Iteration/Stop Conditions

Stop and escalate with a concise blocker report when:
- DoD still fails after max rounds (`2` default)
- external dependency blocks progress (provider outage, missing creds, account permission)
- conflicting review instructions cannot both be satisfied

Escalation report must include:
- what passed
- what failed
- evidence (commands/logs/API result)
- smallest decision needed from user

## Output Contract

When claiming completion, always include:
- acceptance criteria checklist with pass/fail
- commands/tests run
- runtime evidence (endpoint/Lambda/log key lines)
- PR status (new actionable comments count)

Do not claim success without evidence.

## 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.