Skip to main content

PyPI version PyPI Downloads Tests codecov License Python Versions

claudelint

A configurable, rule-based linter for Claude Code plugins and plugin marketplaces.

Features

✨ Context-Aware - Automatically detects single plugin vs marketplace repositories
🎯 Rule-Based - Enable/disable individual rules with configurable severity levels
🔌 Extensible - Load custom rules from Python files
📋 Comprehensive - Validates plugin structure, metadata, command format, and more
🐳 Containerized - Run via Docker for consistent, isolated linting
⚡ Fast - Efficient validation with clear, actionable output

Installation

Via uvx (easiest - no install required)

# From git (works before PyPI release)
uvx --from 'git+https://github.com/stbenjam/claudelint' claudelint

# Once published to PyPI, simply:
uvx claudelint

# With specific path
uvx --from 'git+https://github.com/stbenjam/claudelint' claudelint /path/to/plugin
pip install claudelint

From source

git clone https://github.com/stbenjam/claudelint.git
cd claudelint
pip install -e .

Using Docker

docker pull ghcr.io/stbenjam/claudelint:latest

# Run on current directory
docker run -v $(pwd):/workspace ghcr.io/stbenjam/claudelint

Quick Start

# Lint current directory
claudelint

# Lint specific directory
claudelint /path/to/plugin

# Verbose output
claudelint -v

# Strict mode (warnings as errors)
claudelint --strict

# Generate default config
claudelint --init

# List all available rules
claudelint --list-rules

Repository Types

claudelint automatically detects your repository structure:

Single Plugin

my-plugin/
├── .claude-plugin/
│   └── plugin.json
├── commands/
│   └── my-command.md
└── README.md

Marketplace (Multiple Plugins)

claudelint supports multiple marketplace structures per the Claude Code specification:

Traditional Structure (plugins/ directory)

marketplace/
├── .claude-plugin/
│   └── marketplace.json
└── plugins/
    ├── plugin-one/
    │   ├── .claude-plugin/
    │   └── commands/
    └── plugin-two/
        ├── .claude-plugin/
        └── commands/

Flat Structure (root-level plugin)

marketplace/
├── .claude-plugin/
│   └── marketplace.json    # source: "./"
├── commands/                # Plugin components at root
│   └── my-command.md
└── skills/
    └── my-skill/

Custom Paths

marketplace/
├── .claude-plugin/
│   └── marketplace.json    # source: "./custom/my-plugin"
└── custom/
    └── my-plugin/
        ├── commands/
        └── skills/

Mixed Structures

Plugins from plugins/, custom paths, and remote sources can coexist in one marketplace. Only local sources are validated.

Marketplace Features

Flexible Plugin Sources

claudelint understands all plugin source types and validates any sources that resolve to local paths:

  • Relative paths: "source": "./" (flat structure), "source": "./custom/path"
  • GitHub repositories: "source": {"source": "github", "repo": "owner/repo"}
  • Git URLs: "source": {"source": "url", "url": "https://..."}

Remote sources (GitHub, git URLs) are logged and skipped during local validation. They are valid per spec but cannot be checked until the plugin is fetched locally.

Strict Mode

The strict field in marketplace entries controls validation behavior:

{
  "name": "my-plugin",
  "source": "./",
  "strict": false,    // plugin.json becomes optional
  "description": "Plugin description can be in marketplace.json"
}

When strict: false:

  • plugin.json is optional
  • Marketplace entry serves as the complete plugin manifest
  • Plugin metadata is validated from marketplace.json
  • Skills, commands, and other components work normally

When strict: true (default):

  • plugin.json is required
  • Marketplace entry supplements plugin.json metadata

Configuration

Create .claudelint.yaml in your repository root:

# Enable/disable rules
rules:
  plugin-json-required:
    enabled: true
    severity: error
  
  plugin-naming:
    enabled: true
    severity: warning
  
  command-sections:
    enabled: true
    severity: warning
  
  # 'auto' enables only for marketplace repos
  marketplace-registration:
    enabled: auto
    severity: error

# Load custom rules
custom-rules:
  - ./my-custom-rules.py

# Exclude patterns
exclude:
  - "**/node_modules/**"
  - "**/.git/**"

# Treat warnings as errors
strict: false

Generating Default Config

claudelint --init

This creates .claudelint.yaml with all builtin rules enabled.

Builtin Rules

Plugin Structure

Rule ID Description Default Severity Notes
plugin-json-required Plugin must have .claude-plugin/plugin.json error Skipped when strict: false in marketplace
plugin-json-valid Plugin.json must be valid with required fields error
plugin-naming Plugin names should use kebab-case warning
commands-dir-required Plugin should have a commands directory warning (disabled by default)
commands-exist Plugin should have at least one command file info (disabled by default)
plugin-readme Plugin should have a README.md file warning

Command Format

Rule ID Description Default Severity
command-naming Command files should use kebab-case warning
command-frontmatter Command files must have valid frontmatter error
command-sections Commands should have Name, Synopsis, Description, Implementation sections warning
command-name-format Command Name section should be plugin:command format warning

Marketplace

Rule ID Description Default Severity Notes
marketplace-json-valid Marketplace.json must be valid JSON error (auto)
marketplace-registration Plugins must be registered in marketplace.json error (auto) Supports flat structures, custom paths, and remote sources

Skills

Rule ID Description Default Severity
skill-frontmatter SKILL.md files should have frontmatter warning

Agents

Rule ID Description Default Severity
agent-frontmatter Agent files must have valid frontmatter with description and capabilities error

Hooks

Rule ID Description Default Severity
hooks-json-valid hooks.json must be valid JSON with proper hook configuration structure error

MCP (Model Context Protocol)

Rule ID Description Default Severity Notes
mcp-valid-json MCP configuration must be valid JSON with proper mcpServers structure error Validates both .mcp.json and mcpServers in plugin.json
mcp-prohibited Plugins should not enable MCP servers error (disabled by default) Security/policy rule - enable to prohibit MCP usage

Custom Rules

Create custom validation rules by extending the Rule base class:

# my_custom_rules.py
from pathlib import Path
from typing import List
from claudelint import Rule, RuleViolation, Severity, RepositoryContext

class NoTodoCommentsRule(Rule):
    @property
    def rule_id(self) -> str:
        return "no-todo-comments"
    
    @property
    def description(self) -> str:
        return "Command files should not contain TODO comments"
    
    def default_severity(self) -> Severity:
        return Severity.WARNING
    
    def check(self, context: RepositoryContext) -> List[RuleViolation]:
        violations = []
        
        for plugin_path in context.plugins:
            commands_dir = plugin_path / "commands"
            if not commands_dir.exists():
                continue
            
            for cmd_file in commands_dir.glob("*.md"):
                with open(cmd_file, 'r') as f:
                    content = f.read()
                    if 'TODO' in content:
                        violations.append(
                            self.violation(
                                "Found TODO comment in command file",
                                file_path=cmd_file
                            )
                        )
        
        return violations

Then reference it in .claudelint.yaml:

custom-rules:
  - ./my_custom_rules.py

rules:
  no-todo-comments:
    enabled: true
    severity: warning

CI/CD Integration

GitHub Actions

name: Lint Claude Plugins

on: [pull_request, push]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.x'
      
      - name: Install claudelint
        run: pip install claudelint
      
      - name: Run linter
        run: claudelint --strict

GitLab CI

lint-plugins:
  image: python:3.11
  script:
    - pip install claudelint
    - claudelint --strict

Docker

docker run -v $(pwd):/workspace -w /workspace ghcr.io/stbenjam/claudelint --strict

Exit Codes

  • 0 - Success (no errors, or warnings only in non-strict mode)
  • 1 - Failure (errors found, or warnings in strict mode)

Examples

Example Output

Linting Claude plugins in: /path/to/marketplace

Errors:
  ✗ ERROR [plugins/git/.claude-plugin/plugin.json]: Missing plugin.json
  ✗ ERROR [.claude-plugin/marketplace.json]: Plugin 'new-plugin' not registered

Warnings:
  ⚠ WARNING [plugins/utils]: Missing README.md (recommended)
  ⚠ WARNING [plugins/jira/commands/solve.md]: Missing recommended section '## Implementation'

Summary:
  Errors:   2
  Warnings: 2

Disabling Specific Rules

rules:
  plugin-readme:
    enabled: false  # Don't require README files
  
  command-sections:
    enabled: false  # Don't check for specific sections

Changing Severity

rules:
  plugin-naming:
    severity: error  # Make naming violations errors instead of warnings
  
  command-name-format:
    severity: info   # Downgrade to info level

Development

Running Tests

pytest tests/

Building Docker Image

docker build -t claudelint .

Project Structure

claudelint/
├── src/
│   ├── rule.py          # Base Rule class
│   ├── context.py       # Repository detection
│   ├── config.py        # Configuration management
│   └── linter.py        # Main linter orchestration
├── rules/
│   └── builtin/         # Builtin validation rules
├── tests/               # Test suite
├── examples/            # Example configs and custom rules
├── claudelint           # CLI entry point
├── Dockerfile           # Container image
└── pyproject.toml       # Package metadata

Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

License

Apache 2.0 - See LICENSE for details.

See Also

Support

Metadata

Release files for claudelint 0.3.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for claudelint 0.3.6
File Size Uploaded
claudelint-0.3.6.tar.gz 38.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for claudelint 0.3.6
File Interpreter ABI Platform
claudelint-0.3.6-py3-none-any.whl Python 3 none any Details

Total release size: 69.2 kB

Release files / claudelint-0.3.6.tar.gz

Download URL claudelint-0.3.6.tar.gz
Size 38.1 kB
Tags Source
SHA-256 checksum
How to use checksums
42d4c3364cc54f65d454834f3a0b8e68d2e1de8e1e0052f20ebf5bd8ebdca328
BLAKE2b-256 checksum
How to use checksums
2ce53efdb4c94579bf0aa4ef5fc39c879af342db15029e82988b2c98db2f2b0d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 25, 2026.

Transparency log

Release files / claudelint-0.3.6-py3-none-any.whl

Download URL claudelint-0.3.6-py3-none-any.whl
Size 31.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bfae5513876d9866c2ceab4613c3a53abcc01973fcc464145e9cbce12791f0d0
BLAKE2b-256 checksum
How to use checksums
60b9de653cac6b35533aab23b3f9723f79198e8ad9cae89e3b562fbe3ba41b37
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.6 This release

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page