AIgentic

Agentic Systems & LLM Tooling Daily

Skills

Claude Code skill anti-patterns to avoid

Skills that hijack unrelated prompts, repeat Claude's defaults, leak secrets, or assume unavailable tools break reliability. Follow structured patterns: narrow descriptions, explicit scopes, and declarative tool dependencies.


Claude Code skills are structured files that extend Claude’s capabilities by teaching it to recognize and execute specialized workflows. A skill lives in ~/.claude/skills/ (or in the .claude/skills/ directory of a project) and contains metadata (name, description, triggers) plus implementation logic. The skill file acts as a contract: when the user’s input matches the description, Claude activates the skill; when it doesn’t, the skill stays dormant. This routing mechanism is powerful but fragile. Common mistakes turn skills into noise that hijacks unrelated conversations, duplicates work Claude already does, leaks secrets, or fails silently when tools aren’t installed.

This post identifies the most frequent anti-patterns and shows concrete before/after fixes.

Anti-Pattern 1: Overbroad or vague descriptions that hijack unrelated prompts

The most common failure is a description that matches too many user requests. When Claude’s routing engine sees a loose description, it activates the skill even for tangential or unrelated tasks.

Bad example:

name: DataProcessor
description: Handles data processing and analysis tasks

This description will activate for “analyze my survey results,” “clean this spreadsheet,” “load a CSV,” and “find outliers in my dataset.” The skill becomes a catch-all that consumes the user’s real intent.

Better example:

name: CSVtoParquetConverter
description: Converts CSV files to Apache Parquet format, handling schema inference and compression
triggers:
  - "convert CSV to Parquet"
  - "export data to Parquet"

The tighter description reduces false activations. The triggers field (supported in Anthropic’s skill format) makes intent even more explicit. Claude will activate this skill only when the user explicitly asks for a CSV-to-Parquet conversion, not for every data task.

Anti-Pattern 2: Duplicating default Claude capabilities

Skills are most valuable when they teach Claude something it cannot do alone. If your skill merely wraps a task Claude handles natively, you waste a skill slot and add latency.

Bad example:

name: JSONParser
description: Parses and validates JSON
implementation: |
  Parse the provided JSON string and return the result

Claude can parse JSON without a skill. This duplicates built-in capability and adds nothing.

Better approach: First test your task against baseline Claude. If Claude solves it in 1-2 turns without the skill, don’t make a skill. If the task requires:

  • Integration with a local tool (e.g., kubectl, ffmpeg, a company CLI)
  • Fetching data from a private API or database
  • Applying a company-specific schema or workflow
  • Repeating the same multi-step process across many conversations

Then a skill is justified. Example:

name: DeploymentHelper
description: Deploys Docker images to your Kubernetes cluster using kubectl, with rollback on failure
triggers:
  - "deploy to production"
  - "roll back deployment"
dependencies:
  - kubectl
  - docker
implementation: |
  Execute kubectl apply, monitor rollout status, and rollback if the deployment fails health checks.

This skill teaches Claude your deployment workflow and integrates with tools not available to baseline Claude.

Anti-Pattern 3: Embedding secrets, API keys, or private paths in skill files

Skills are often committed to version control, shared with teammates, or visible in logs. Hardcoding secrets is a critical security error.

Bad example:

name: DatabaseQuery
description: Queries the production database
implementation: |
  Connect to postgresql://user:password123@prod-db.company.com:5432/main
  Execute the following SQL query...

Any teammate with access to the repo, or any log aggregation system, now sees the credentials.

Better example:

name: DatabaseQuery
description: Queries the company PostgreSQL database using credentials from environment
implementation: |
  Retrieve the DB_HOST, DB_USER, and DB_PASSWORD from environment variables.
  If any are missing, instruct the user to run: export DB_HOST=... export DB_USER=... export DB_PASSWORD=...
  Connect to $DB_HOST and execute the query.
security_note: |
  Never hardcode credentials. Use environment variables or a secrets manager.

Alternatively, document that the user must configure secrets via their system’s credential store (.aws/credentials, ~/.kube/config, KUBECONFIG, etc.) before invoking the skill.

Anti-Pattern 4: Assuming tools or dependencies are installed

Skills often invoke external binaries (kubectl, Node.js, Python packages, custom CLIs). If the user’s environment lacks these tools, the skill fails cryptically or hangs.

Bad example:

name: KubernetesDeployer
description: Deploys applications to Kubernetes
implementation: |
  Run: kubectl apply -f deployment.yaml
  Check rollout: kubectl rollout status deployment/app

If the user doesn’t have kubectl installed, Claude attempts the command and fails. The skill provides no guidance on fixing the environment.

Better example:

name: KubernetesDeployer
description: Deploys applications to Kubernetes
dependencies:
  - kubectl (v1.20+)
  - kubeconfig configured
implementation: |
  Before proceeding, verify that kubectl is installed and kubeconfig is set.
  If kubectl is not found or kubeconfig is not readable, provide the user with:
    - Installation instructions: https://kubernetes.io/docs/tasks/tools/
    - Configuration guide: https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/
  Then execute: kubectl apply -f deployment.yaml
  Check rollout: kubectl rollout status deployment/app

Explicitly declaring dependencies in metadata and adding fallback instructions (check, inform, guide) makes the skill resilient.

Comparison of skill design patterns

Design aspectAnti-patternBest practice
Description”Handles all data work” (5+ possible intents)“Converts CSV to Parquet format” (1 intent)
ScopeCovers a broad tool (e.g., “SQL”)Covers a narrow, specific workflow (e.g., “Query production DB with schema validation”)
DuplicationRepeats Claude’s native JSON parsingTeaches Claude a custom company schema or a tool integration Claude cannot do alone
SecretsHardcoded API keys in implementationEnvironment variables or documented secure credential sources
DependenciesAssumes kubectl is installedDeclares dependencies, checks for them, provides install/config guidance
TriggersNone; relies on description matchingExplicit list of phrases the user is likely to say

How to audit and fix existing skills

Review each skill in your ~/.claude/skills/ directory:

  1. Test description narrowness: Ask yourself, “How many different user requests would trigger this skill?” If the answer is more than 2-3, narrow the description.
  2. Check for duplication: Run the skill’s core task through baseline Claude. If Claude solves it without the skill, consider removing the skill or narrowing its scope.
  3. Search for secrets: Grep the skill file for password, key, secret, token. If any exist, move them to environment variables.
  4. List dependencies: Note every external tool (kubectl, Node.js, ffmpeg, custom CLI) and add a check in the implementation that verifies each one before use.
  5. Document triggers explicitly: Add a triggers field listing the exact phrases that should activate the skill.

Takeaways

Effective Claude Code skills are narrow, single-purpose, and teach Claude something it cannot do alone. Overbroad descriptions and duplicate capabilities waste skill slots and confuse the routing system. Hardcoded secrets and missing dependency checks create security and reliability debt. Audit your skills against these patterns: explicit descriptions, single intent per skill, no embedded credentials, and declarative dependencies with fallback guidance.

Further reading

Frequently asked

What is a Claude Code skill and how does it differ from a prompt instruction?

A skill is a structured YAML or JSON file in ~/.claude/skills/ that tells Claude Code when and how to trigger specific capabilities. Unlike inline instructions, skills use a frontmatter pattern with name, description, and file paths, and they integrate with Claude's routing system to activate only when relevant. This prevents token waste and scope creep.

Why does an overbroad skill description break unrelated conversations?

Claude Code uses skill descriptions to route user input. A description like 'handles all data work' matches nearly every request, causing the skill to activate when the user asks about unrelated tasks. Narrow descriptions (e.g., 'converts CSV to Parquet') reduce false activations and preserve context for other tools.

How do I avoid duplicating Claude's built-in capabilities in a skill?

Check Anthropic's Claude capabilities docs and test your skill against baseline Claude first. If Claude solves the task without the skill, either remove the skill or make it narrowly specialized (e.g., a company-specific data schema instead of generic JSON parsing). Duplication wastes skill slots and slows activation.

What should I do if a skill needs a tool that might not be installed?

Declare tool dependencies explicitly in the skill metadata or frontmatter, and add a fallback instruction in the skill body that tells Claude to check installation and provide setup steps if needed. Never assume kubectl, Node.js, or custom CLIs exist without verification.

Why shouldn't I store API keys or credentials in skill files?

Skill files are often version-controlled or shared across teams. Hardcoding secrets risks exposure and violates security policy. Use environment variables, a secure secrets manager, or refer users to set credentials via Claude's context or authenticated configuration instead.

← All posts