Skip to main content

A configurable linter for agent skills, plugins, and AI coding assistant context

Project description

skillsaw logo

skillsaw

Keep your skills sharp. 40+ rules catch weak language, contradictions, attention dead zones, and structural issues — then auto-fix them.

PyPI version PyPI Downloads Tests codecov License

skillsaw demo

Full documentation at skillsaw.org — supports Claude Code plugins, agentskills.io, CLAUDE.md, AGENTS.md, Cursor, Copilot, Gemini, Kiro, CodeRabbit, and more.

Table of Contents

Quick Start

No install required — run with uvx skillsaw (or install it for repeated use).

# 1. See what skillsaw detects in your repo
skillsaw tree

# 2. Lint it
skillsaw

# 3. Fix what you can automatically
skillsaw fix

# 4. Accept remaining violations as the baseline
skillsaw baseline

# Done — only new violations will fail from here on
skillsaw   # exit 0

For all commands and flags, see the CLI Reference.

[!TIP] :sparkles: Onboard with AI — let your coding agent handle the entire setup in one shot.

Claude Code:

claude plugin marketplace add stbenjam/skillsaw
claude plugin install skillsaw@skillsaw-marketplace

Then type /skillsaw-onboard — it installs skillsaw, lints your repo, autofixes what it can, walks you through manual fixes, sets up CI, and creates a baseline.

Other agents — see the Getting Started guide.

Installation

Via uvx (easiest, no install required)

uvx skillsaw
uvx skillsaw /path/to/skills

Via pip

pip install skillsaw

From source

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

Using Docker

docker pull ghcr.io/stbenjam/skillsaw:latest
docker run -v $(pwd):/workspace ghcr.io/stbenjam/skillsaw

CI Integration

# GitHub Actions
- uses: stbenjam/skillsaw@v0
  with:
    strict: true
# GitLab CI — outputs Code Quality JSON for MR widgets
skillsaw:
  script:
    - pip install skillsaw==0.11.0
    - skillsaw lint --output gitlab:gl-code-quality-report.json .
  artifacts:
    reports:
      codequality: gl-code-quality-report.json

For PR review comments, the secure two-workflow pattern, and full configuration options, see the CI Integration guide.

Repository Types

skillsaw automatically detects your repository structure. A repository can match multiple types simultaneously (e.g. an agentskills repo that also has .coderabbit.yaml).

agentskills.io Skills

Standalone skill repositories following the agentskills.io specification:

my-skill/
├── SKILL.md              # Required: metadata + instructions
├── scripts/              # Optional: executable code
├── references/           # Optional: documentation
├── assets/               # Optional: templates, resources
├── evals/                # Optional: evaluation tests
│   └── evals.json
└── <any-dir>/            # Arbitrary directories allowed per spec

Skill collections (multiple skills in subdirectories) are also supported:

skills-repo/
├── skill-one/
│   └── SKILL.md
└── skill-two/
    └── SKILL.md

Standard discovery paths (.claude/skills/, .github/skills/, .agents/skills/) are checked automatically.

Single Plugin

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

Marketplace (Multiple Plugins)

skillsaw 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/
│   └── my-command.md
└── skills/
    └── my-skill/

Custom Paths and Mixed Structures

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

.claude/ Directory

Repositories with a .claude/ directory containing commands, skills, hooks, agents, or rules. When APM is present, .claude/ is treated as compiled output and this type is not detected.

CodeRabbit

Repositories with a .coderabbit.yaml file. skillsaw validates the instruction fragments within the config.

Promptfoo

Repositories with promptfoo eval configs (promptfooconfig*.yaml or YAML files in evals/ directories). Prompt strings in the config are treated as content blocks, so all content-* rules apply to them automatically. Dedicated promptfoo-* rules validate config structure, assertion coverage, and metadata.

APM (Agent Package Manager)

Repositories with an .apm/ directory or apm.yml file. APM manages dependencies and compiles instruction files for all supported agents (.claude/, .cursor/rules/, .github/instructions/, etc.). When APM is present it is the authoritative source — .claude/ is treated as compiled output.

Configuration

Generate a default .skillsaw.yaml in your repository root:

skillsaw init

This creates a config file with all builtin rules, their defaults, and descriptions. Edit it to enable, disable, or customize rules for your project. See .skillsaw.yaml.example for a complete example.

Version Pinning

The config file includes a version field set to the skillsaw version that created it. New rules introduced after that version are automatically skipped unless you bump the version or explicitly enable them. Repos without a .skillsaw.yaml run all rules at the latest version — you get new rules automatically but may occasionally fail after a skillsaw upgrade.

Exclude Patterns

Skip files and directories using glob patterns:

exclude:
  - "vendor/**"
  - "generated/**"
  - "node_modules/**"

By default, skillsaw excludes **/template/**, **/templates/**, and **/_template/** directories. These defaults are replaced when you specify your own exclude list.

Exclude patterns apply to all rules, including custom rules loaded via custom-rules. Any violation whose file path matches an exclude pattern is filtered out before results are reported.

Per-Rule Excludes

Exclude specific files from a single rule using the exclude key in the rule's config:

rules:
  content-weak-language:
    enabled: true
    exclude:
      - "docs/legacy/**"
      - "CHANGELOG.md"

This is useful when a rule produces false positives on specific files but you still want it enabled globally. Per-rule excludes use the same glob syntax as global exclude patterns.

Inline Suppression

Suppress specific rules on specific lines using comment directives directly in your files. Both HTML comments (for markdown) and hash comments (for YAML) are supported.

Markdown (HTML comments)

<!-- skillsaw-disable content-weak-language -->
This section intentionally uses informal language.
<!-- skillsaw-enable content-weak-language -->

Suppress a single line:

<!-- skillsaw-disable-next-line content-tautological -->
Follow best practices for error handling.

Suppress multiple rules at once:

<!-- skillsaw-disable content-weak-language, content-tautological -->

Re-enable all suppressed rules:

<!-- skillsaw-enable -->

Multi-line HTML comments are also supported:

<!--
    skillsaw-disable content-weak-language
-->

YAML (hash comments)

For YAML files (.coderabbit.yaml, promptfooconfig.yaml, etc.), use # comments:

# skillsaw-disable promptfoo-valid
prompts:
  - "{{prompt}}"
# skillsaw-enable promptfoo-valid
# skillsaw-disable-next-line coderabbit-yaml-valid
instructions: missing-value

Only full-line # comments are recognized — inline comments like key: value # skillsaw-disable are ignored.

Notes

Inline suppression only affects rules that are already enabled. It cannot be used to enable a normally disabled rule.

Content Paths

By default, content intelligence rules only analyze recognized instruction files (CLAUDE.md, AGENTS.md, .cursor/rules/, .apm/instructions/, etc.). Use content-paths to extend coverage to any text files that contain instructions for humans or AI agents — markdown, .mdc, .txt, or any other format:

content-paths:
  - "src/**/instructions/**/*.md"
  - ".cursor/rules/*.mdc"
  - "docs/runbooks/*.txt"

Matched files are analyzed by all content-* rules and support LLM-powered fixes via skillsaw fix --llm.

Baseline

When adopting skillsaw on an existing project, you may have many pre-existing violations. The baseline feature lets you snapshot current violations so that skillsaw lint only reports new ones — existing violations are accepted and won't cause failures.

Creating a baseline

# Generate .skillsaw-baseline.json from current violations
skillsaw baseline

How it works

Once a .skillsaw-baseline.json file exists (next to .skillsaw.yaml or in the repo root), skillsaw lint automatically loads it and subtracts matching violations from the output. Only new violations are reported.

Violations are matched by a content hash — a fingerprint built from the rule ID, file path, and the content of the source line (not the line number). This means the baseline survives line drift: if you add lines above a baselined violation, the fingerprint still matches because the content hasn't changed.

If you reformat or rewrite a line, the fingerprint changes and the violation resurfaces for a fresh look — which is the correct behavior.

Rules that measure a numeric value (context-budget, content-instruction-budget, content-actionability-score) use ratchet behavior instead: the baseline records the value and only suppresses violations that are equal to or better. Regressions (e.g., file grew past the baselined token count) are always reported.

Ignoring the baseline

# Run lint without baseline filtering
skillsaw lint --no-baseline

Stale entries

When you fix a baselined violation, its baseline entry becomes stale. Skillsaw reports stale entries so you know the baseline can be refreshed:

Baseline: 3 stale entries (violations resolved since baseline was set)
  Run `skillsaw baseline` to update.

Run skillsaw baseline again to regenerate the file without the resolved violations.

Baseline and fix

The skillsaw fix command operates on all violations regardless of the baseline. The baseline only affects lint reporting and exit codes — if you explicitly ask to fix, everything is eligible.

Supply Chain Protection

skillsaw includes security rules that detect supply chain attacks targeting AI coding assistants — malicious hooks, MCP servers, and settings injected into repositories. Inspired by the Shai-Hulud attack that compromised 317 npm packages.

We recommend enabling hooks-prohibited, mcp-prohibited, and settings-dangerous with explicit allowlists so any new hook, server, or command-execution setting fails CI until reviewed.

See the Supply Chain Protection guide for full configuration, pattern details, and incremental adoption with baselining.

Builtin Rules

agentskills.io

These rules validate skills against the agentskills.io specification. They auto-enable for agentskills repos, single plugins, and marketplaces whenever skills are detected.

Rule ID Description Default Severity Autofix
agentskill-valid SKILL.md must have valid frontmatter with name and description error (auto) auto, llm
agentskill-name Skill name must be lowercase with hyphens and match directory name error (auto) auto
agentskill-description Skill description should be meaningful and within length limits warning (auto) -
agentskill-structure Skill directories should only contain recognized subdirectories (stricter than spec) warning (disabled) -
agentskill-evals Validate evals/evals.json format when present error (auto) -
agentskill-evals-required Require evals/evals.json for each skill (opt-in) error (disabled) -

agentskill-valid parameters:

Parameter Description Default
required-fields Additional frontmatter fields to require (name and description are always required) []
required-metadata Keys that must be present inside the metadata mapping []

agentskill-structure parameters:

Parameter Description Default
allowed_dirs Directory names allowed in the skill root ["assets", "evals", "references", "scripts"]

Plugin Structure

Rule ID Description Default Severity Autofix
plugin-json-required Plugin must have .claude-plugin/plugin.json error (auto) -
plugin-json-valid Plugin.json must be valid JSON with required fields error (auto) -
plugin-naming Plugin names should use kebab-case warning (auto) -
plugin-readme Plugin should have a README.md file warning (auto) llm

plugin-json-valid parameters:

Parameter Description Default
recommended-fields Fields that trigger a warning if missing from plugin.json ["description", "version", "author"]

Command Format

Rule ID Description Default Severity Autofix
command-naming Command files should use kebab-case naming warning auto
command-frontmatter Command files must have valid frontmatter with description error auto
command-sections Command files should have Name, Synopsis, Description, and Implementation sections warning (disabled) -
command-name-format Command Name section should be 'plugin-name:command-name' warning (disabled) -

Marketplace

Rule ID Description Default Severity Autofix
marketplace-json-valid Marketplace.json must be valid JSON with required fields error (auto) -
marketplace-registration Plugins must be registered in marketplace.json error (auto) auto

Skills, Agents, Hooks

Validates skill/agent frontmatter and hook configuration. The security rules scan hooks in both hooks.json and settings.json for supply-chain attack patterns (inspired by the Shai-Hulud attack).

Rule ID Description Default Severity Autofix
skill-frontmatter SKILL.md files should have frontmatter with name and description warning auto, llm
agent-frontmatter Agent files must have valid frontmatter with name and description error auto, llm
hooks-json-valid hooks.json must be valid JSON with proper hook configuration structure error -
hooks-dangerous Flags hook commands that execute scripts from dotfile directories, download-and-execute chains (curl sh), obfuscation (eval/base64), or perform network requests error (auto)
hooks-prohibited All hook commands are prohibited unless explicitly allowlisted; catches new or unexpected hooks added to a project error (disabled) -

hooks-dangerous parameters:

Parameter Description Default
allowlist Hook commands to permit (exact match) []

hooks-prohibited parameters:

Parameter Description Default
allowlist Hook commands to permit (exact match) []

MCP (Model Context Protocol)

Rule ID Description Default Severity Autofix
mcp-valid-json MCP configuration must be valid JSON with proper mcpServers structure error -
mcp-prohibited Repository should not enable non-allowlisted MCP servers error (disabled) -

mcp-prohibited parameters:

Parameter Description Default
allowlist MCP server names that are permitted []

Settings

Security rules for .claude/settings.json. Project-scoped settings can set keys that execute arbitrary shell commands or environment variables that hijack process behaviour — these rules flag them.

Rule ID Description Default Severity Autofix
settings-dangerous Flags settings keys that execute arbitrary commands (apiKeyHelper, awsAuthRefresh, awsCredentialExport, gcpAuthRefresh, otelHeadersHelper) and dangerous env vars (LD_PRELOAD, NODE_OPTIONS, proxy settings, GIT_SSH_COMMAND, etc.) error (auto) -

settings-dangerous parameters:

Parameter Description Default
allow_command_exec_keys Command-execution keys to permit (e.g. apiKeyHelper) []
allow_env_vars Dangerous env var names to permit []

Rules Directory

Rule ID Description Default Severity Autofix
rules-valid .claude/rules/ files must be markdown with valid optional paths frontmatter error (auto) -

Openclaw

Validates metadata.openclaw in SKILL.md frontmatter against the openclaw spec. Only fires when metadata.openclaw is present.

Rule ID Description Default Severity Autofix
openclaw-metadata Validate metadata.openclaw fields against the openclaw spec warning (auto) -

Instruction Files

Validates AI coding assistant instruction files (AGENTS.md, CLAUDE.md, GEMINI.md) at the repository root. Checks encoding, non-emptiness, and that @import references resolve to existing files. Disabled by default.

Rule ID Description Default Severity Autofix
instruction-file-valid Instruction files (AGENTS.md, CLAUDE.md, GEMINI.md) must be valid and non-empty warning (auto) -
instruction-imports-valid Import references (@path) in AGENTS.md, CLAUDE.md, and GEMINI.md must point to existing files warning (auto) -

Context Budget

Warns when instruction and configuration files exceed recommended token limits. Uses a len(text) / 4 approximation for token counting. Supports per-category warn and error thresholds. Disabled by default.

Rule ID Description Default Severity Autofix
context-budget Warn when instruction or config files exceed recommended token limits warning (auto) -

context-budget parameters:

Parameter Description Default
limits Token limits per file category (int for warn-only, or {warn, error} dict) {"agents-md": {"warn": 6000, "error": 12000}, "claude-md": {"warn": 6000, "error": 12000}, "gemini-md": {"warn": 6000, "error": 12000}, "instruction": {"warn": 4000, "error": 8000}, "skill": {"warn": 3000, "error": 6000}, "command": {"warn": 2000, "error": 4000}, "agent": {"warn": 2000, "error": 4000}, "rule": {"warn": 2000, "error": 4000}, "skill-description": {"warn": 200, "error": 500}, "command-description": {"warn": 200, "error": 500}}

Content Intelligence

Rules that go beyond structural validation to analyze the quality of instruction files. Built on attention research (lost-in-the-middle, instruction-following limits) and prompt engineering best practices. Most support LLM-powered fixes via skillsaw fix --llm. See docs/designs/content-rules-research.md for the full research basis behind each rule.

Rule ID Description Default Severity Autofix
content-weak-language Detect hedging, vague, and non-actionable language in instruction files warning (auto) llm
content-tautological Detect tautological instructions that the model already follows by default warning (auto) llm
content-critical-position Detect critical instructions in the middle of files where LLM attention is lowest info (auto) llm
content-redundant-with-tooling Detect instructions that duplicate .editorconfig, ESLint, Prettier, or tsconfig settings warning (auto) llm
content-instruction-budget Check if instruction count in a file exceeds LLM instruction budget (~150) warning (auto) llm
content-negative-only Detect prohibitions without a positive alternative (agent has no path forward) info (auto) llm
content-section-length Warn about markdown sections longer than ~500 tokens info (auto) llm
content-contradiction Detect likely contradictions within instruction files using keyword-pair heuristics warning (auto) llm
content-hook-candidate Detect instructions that should be automated as hooks instead of prose instructions info (auto) llm
content-actionability-score Score instruction files on actionability (verb density, commands, file references) info (auto) llm
content-cognitive-chunks Check that instruction files are organized into cognitive chunks with headings info (auto) llm
content-embedded-secrets Detect potential API keys, tokens, and passwords in instruction files error (auto) llm
content-banned-references Detect banned or deprecated model names, APIs, and custom patterns warning (auto) llm
content-inconsistent-terminology Detect inconsistent terminology across instruction files (e.g., mixing 'directory' and 'folder') info (auto) llm
content-broken-internal-reference Detect markdown links where the target file does not exist warning (auto) auto
content-unlinked-internal-reference Detect bare path-like strings not wrapped in markdown link syntax info (auto) auto
content-placeholder-text Detect TODO markers, bracket placeholders, and unfilled template text warning (auto) -

content-critical-position parameters:

Parameter Description Default
min-lines Minimum file length (in lines) before the rule activates 50

content-section-length parameters:

Parameter Description Default
max-tokens Maximum estimated tokens per section before triggering a warning 500

content-banned-references parameters:

Parameter Description Default
banned Additional banned patterns as list of {pattern, message} dicts []
skip-builtins Disable built-in deprecated model/API checks false

content-unlinked-internal-reference parameters:

Parameter Description Default
patterns Glob patterns for path-like strings to flag when unlinked ["./**/*.*", "references/**/*.md"]

CodeRabbit

Validates .coderabbit.yaml config files for YAML syntax. Instruction text fields (reviews.instructions, per-path instructions, per-tool instructions, chat.instructions) are automatically checked by the content-* rules above. Auto-enabled when .coderabbit.yaml is detected.

Rule ID Description Default Severity Autofix
coderabbit-yaml-valid .coderabbit.yaml must be valid YAML error (auto) -

Promptfoo Evals

Validates promptfoo eval YAML configs found in evals/ directories of plugins and skills. promptfoo-valid auto-enables when eval files are detected; promptfoo-assertions and promptfoo-metadata are opt-in policy rules.

Rule ID Description Default Severity Autofix
promptfoo-valid Validate promptfoo eval YAML config structure and file references error (auto) -
promptfoo-assertions Require specific assertion types in all promptfoo eval tests warning (disabled) -
promptfoo-metadata Require specific metadata keys on all promptfoo eval tests warning (disabled) -

promptfoo-assertions parameters:

Parameter Description Default
required-types Assertion types that every test must include (via test-level or defaultTest assertions) []
threshold-constraints Per-assertion-type threshold bounds, e.g. {cost: {max: 2.0}, latency: {max: 30000}} {}

promptfoo-metadata parameters:

Parameter Description Default
required-keys Metadata keys required on every test case []

APM (Agent Package Manager)

Validates repositories using the APM directory layout (.apm/). Auto-enables when .apm/ is detected.

Rule ID Description Default Severity Autofix
apm-yaml-valid apm.yml must exist with valid YAML and required fields (name, version, description) error (auto) -
apm-structure-valid .apm/ directory must contain skills/ or instructions/ with valid structure warning (auto) -

Autofixing

skillsaw supports two levels of autofixing — deterministic fixes for structural issues and LLM-powered fixes for content quality. Rules declare which fix type they support (see the Autofix column in the rules tables above).

Deterministic Fixes

Safe, pattern-based fixes that run instantly without any external dependencies:

skillsaw fix                     # Apply safe structural fixes
skillsaw fix --suggest           # Also apply suggested fixes (e.g. stale references)
skillsaw fix --dry-run           # Preview safe fixes as colored diffs without writing
skillsaw fix --suggest --dry-run # Preview safe + suggested fixes

Examples: adding missing frontmatter, renaming files to kebab-case, registering unregistered plugins in marketplace.json, fixing skill names to match directory names. These are marked SAFE confidence and applied automatically.

Some fixes produce cascading changes — for example, renaming a skill name creates stale references in other files. These secondary fixes are marked SUGGEST confidence because simple name matching may replace occurrences that aren't actually skill name references. Use --suggest --dry-run to review these changes before applying them.

LLM-Powered Fixes

Most content intelligence rules support LLM-powered fixes (see the Autofix column above). The LLM reads your instruction files, rewrites violations, and re-lints in a loop until the file is clean — or rolls back if it made things worse.

skillsaw fix --llm                          # Fix with default model
skillsaw fix --llm --model vertex_ai/claude-sonnet-4-6
skillsaw fix --llm --model openrouter/minimax/minimax-m1
skillsaw fix --llm --all                    # Include info-level violations
skillsaw fix --llm --workers 8              # Parallel workers (default: 4)
skillsaw fix --llm --max-iterations 10      # Max iterations per file
skillsaw fix --llm --dry-run                # Preview changes and save patch
skillsaw fix --apply-patch                  # Apply the saved patch
skillsaw fix --llm --dry-run --patch-file p.diff  # Custom patch path
skillsaw fix --apply-patch --patch-file p.diff    # Apply from custom path
skillsaw fix --llm -y                       # Auto-apply without confirmation

How it works:

  1. skillsaw lints your repo and groups violations by file
  2. Each file is sent to an LLM agent with 5 scoped tools: read_file, write_file, replace_section, lint (re-runs skillsaw), and diff
  3. The LLM iteratively edits the file and re-lints until violations are resolved
  4. After the LLM finishes, skillsaw compares violation counts — if a file got worse, it's rolled back to the original
  5. Files are processed in parallel with a live progress bar showing ETA

The LLM never has access to arbitrary shell commands — it can only read, edit, lint, and diff within your repo. Use --dry-run to preview changes — because LLM output is non-deterministic, the dry-run saves a patch file (.skillsaw-llm-patch.diff) so you can review and then apply the exact changes with --apply-patch.

Check skillsaw list-rules to see which rules support auto, llm, or both fix types.

Note: skillsaw lint --fix is deprecated and will be removed in 1.0. Use skillsaw fix instead.

LLM Setup

skillsaw uses LiteLLM under the hood, so any LiteLLM-compatible model works. Install the extras for your provider:

# pip
pip install 'skillsaw[llm]'       # Any LiteLLM-compatible model
pip install 'skillsaw[vertexai]'  # Vertex AI (includes google-cloud-aiplatform)
pip install 'skillsaw[bedrock]'   # AWS Bedrock (includes boto3)

# uvx (no install required)
uvx --with 'skillsaw[llm]' skillsaw fix --llm
uvx --with 'skillsaw[vertexai]' skillsaw fix --llm --model vertex_ai/claude-sonnet-4-6

Set the environment variables for your provider:

Provider Environment Variables
Anthropic ANTHROPIC_API_KEY
OpenAI OPENAI_API_KEY
Vertex AI VERTEXAI_PROJECT, VERTEXAI_LOCATION (+ gcloud auth application-default login)
AWS Bedrock AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION_NAME

You can also set SKILLSAW_MODEL to override the default model via environment variable, or llm.model in your .skillsaw.yaml config.

See the LiteLLM provider documentation for the full list of supported providers and their required environment variables.

Custom Rules

Create custom validation rules by extending the Rule base class:

from pathlib import Path
from typing import List
from skillsaw 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"):
                content = cmd_file.read_text()
                if "TODO" in content:
                    violations.append(
                        self.violation("Found TODO comment", file_path=cmd_file)
                    )
        return violations

Then reference it in .skillsaw.yaml:

custom-rules:
  - ./my_custom_rules.py

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

For a more complete example — including config schemas, promptfoo eval validation, and test fixtures — see the examples/custom-rules/ directory.

Scaffolding

skillsaw add scaffolds marketplaces, plugins, and components with best-practice structure, CI, and branding out of the box.

Initialize a Marketplace

# Interactive (prompts for name, owner, colors)
skillsaw add marketplace

# Non-interactive
skillsaw add marketplace --name my-plugins --owner myuser --color-scheme ocean-blue

This creates the full marketplace structure: marketplace.json, settings.json, GitHub Pages site, GitHub Actions CI, Makefile, and an example plugin.

Add Components

# Add a plugin to a marketplace
skillsaw add plugin my-plugin

# Add a skill, command, agent, or hook
skillsaw add skill my-skill
skillsaw add command greet
skillsaw add agent helper
skillsaw add hook PreToolUse

Context Detection

skillsaw automatically detects your repo type and places files in the right location:

  • Marketplace — components go under plugins/<name>/
  • Single-plugin repo — components go in the repo root
  • .claude/ repo — components go under .claude/

In a marketplace with multiple plugins, specify --plugin <name> or skillsaw will prompt interactively.

Lint Tree

skillsaw tree visualizes the typed lint tree — the internal data structure that all rules operate on. Every lintable entity (plugins, skills, commands, agents, instruction files, config files) is a typed node in the tree.

# View the lint tree
skillsaw tree

# View a specific path
skillsaw tree /path/to/repo

Example output:

my-marketplace/
    ├── AGENTS.md (agents-md)
    ├── marketplace.json
    ├── plugins/ [marketplace]
    │   └── my-plugin/ [plugin]
    │       ├── hello.md (command)
    │       └── my-skill/ [skill]
    │           └── SKILL.md (skill)
    └── .coderabbit.yaml
        └── reviews.instructions (coderabbit)

Documentation Generation

skillsaw can generate documentation for your plugins, skills, and marketplaces:

# Generate HTML docs (default)
skillsaw docs

# Generate Markdown
skillsaw docs --format markdown

# Write to a specific file
skillsaw docs --format markdown -o docs/README.md

# Write to a directory
skillsaw docs -o my-docs/

# Custom title
skillsaw docs --title "My Plugin Docs"

The generated documentation includes plugin metadata, command descriptions, skill summaries, and configuration details extracted from your repository.

Exit Codes

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

Example Output

Linting: /path/to/skills-repo

Errors:
  ✗ ERROR [skills/my-skill/SKILL.md]: Name 'My Skill' must contain only lowercase letters, numbers, and hyphens
  ✗ ERROR [plugins/git/.claude-plugin/plugin.json]: Missing plugin.json

Warnings:
  ⚠ WARNING [skills/helper/SKILL.md]: Description exceeds 1024 characters (1087)
  ⚠ WARNING [plugins/utils]: Missing README.md (recommended)

Summary:
  Errors:   2
  Warnings: 2

Migrating from claudelint

This project was renamed from claudelint to skillsaw. To migrate:

  1. Update your package: pip install skillsaw (instead of pip install claudelint)
  2. Rename .claudelint.yaml to .skillsaw.yaml (the old name is still discovered as a fallback)
  3. Update CLI usage: skillsaw (instead of claudelint)
  4. Update imports in custom rules: from skillsaw import ... (the old from claudelint import ... still works)

The claudelint command still works as a shim but prints a deprecation warning.

Removed rules

The following rules from claudelint have been removed in skillsaw:

Rule ID Reason
commands-dir-required Claude Code now treats skills/ and commands/ as the same mechanism; requiring a commands/ directory is no longer meaningful
commands-exist Same as above — plugins don't need to have commands

If your .skillsaw.yaml references these rule IDs, skillsaw will emit a warning about the unknown rule.

Development

# Run tests
pytest tests/ -v

# Format code
black src/ tests/

# Build Docker image
docker build -t skillsaw .

Contributing

Contributions welcome! See CONTRIBUTING.md for guidelines and DEVELOPMENT.md for setup instructions.

License

Apache 2.0 - See LICENSE for details.

See Also

Support

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

skillsaw-0.12.0.tar.gz (315.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

skillsaw-0.12.0-py3-none-any.whl (221.6 kB view details)

Uploaded Python 3

File details

Details for the file skillsaw-0.12.0.tar.gz.

File metadata

  • Download URL: skillsaw-0.12.0.tar.gz
  • Upload date:
  • Size: 315.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for skillsaw-0.12.0.tar.gz
Algorithm Hash digest
SHA256 6779875538e08bef89a8ae1802f52426d260da3e1f88b3d43e49e80551e4378c
MD5 f030e6b1d6d6a4eb10f5a5c668747cb8
BLAKE2b-256 3a567ba56362a9df507bf60f0ff3363cda4e4b36b6c50ccf9e67295db2464955

See more details on using hashes here.

Provenance

The following attestation bundles were made for skillsaw-0.12.0.tar.gz:

Publisher: release.yml on stbenjam/skillsaw

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file skillsaw-0.12.0-py3-none-any.whl.

File metadata

  • Download URL: skillsaw-0.12.0-py3-none-any.whl
  • Upload date:
  • Size: 221.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for skillsaw-0.12.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b91e1e58fb2000403f59da3bcd9059d92e88248bd4562b24fce2ea57ac263cb7
MD5 a6734801063579417a8167285128c871
BLAKE2b-256 072bf30faab63bb8ff54cd0868ad41edf7c926cb2d57764e0a9cdeff4c76c2c9

See more details on using hashes here.

Provenance

The following attestation bundles were made for skillsaw-0.12.0-py3-none-any.whl:

Publisher: release.yml on stbenjam/skillsaw

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page