Claude-skill-registry detect-project-type

Detect project type and configuration for generic application releases

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/detect-project-type" ~/.claude/skills/majiayu000-claude-skill-registry-detect-project-type && rm -rf "$T"
manifest: skills/data/detect-project-type/SKILL.md
source content

Detect Project Type

Purpose

Analyzes the project directory to determine the project type (Node.js, Python, Rust, Go, Java, generic, Claude Code plugin, or monorepo) and loads or generates appropriate release configuration. This is the foundation for generic release automation that works with any application.

Input Context

The skill expects to be invoked in a project root directory. It examines:

  • Configuration files (
    .release-config.json
    ,
    .releaserc.json
    )
  • Project markers (package.json, Cargo.toml, pyproject.toml, etc.)
  • Directory structure (monorepo patterns)
  • Version file locations

Workflow

1. Check for Explicit Configuration

First, check if user has provided explicit configuration:

# Check for config files in order of precedence
if [ -f ".release-config.json" ]; then
  config_file=".release-config.json"
elif [ -f ".releaserc.json" ]; then
  config_file=".releaserc.json"
elif [ -f ".releaserc" ]; then
  config_file=".releaserc"
else
  config_file=""
fi

If config file exists:

  • Parse JSON to extract configuration
  • Validate configuration (required fields, file paths exist)
  • Return configuration with
    config_source: "explicit"

See Configuration Reference for schema details.

2. Auto-Detect Project Type

If no configuration file, detect project type from filesystem markers:

# Detection logic (in priority order)
project_type="unknown"

# Check for monorepo first (multiple package.json or project files in subdirs)
if [ $(find packages -name "package.json" 2>/dev/null | wc -l) -gt 1 ] || \
   [ $(find apps -name "package.json" 2>/dev/null | wc -l) -gt 1 ]; then
  project_type="monorepo"

# Node.js project
elif [ -f "package.json" ]; then
  project_type="nodejs"

# Python project
elif [ -f "pyproject.toml" ]; then
  project_type="python"

# Rust project
elif [ -f "Cargo.toml" ]; then
  project_type="rust"

# Go project
elif [ -f "go.mod" ]; then
  project_type="go"

# Java/Gradle project
elif [ -f "build.gradle" ] || [ -f "gradle.properties" ]; then
  project_type="java"

# Maven project
elif [ -f "pom.xml" ]; then
  project_type="java"

# Claude Code plugin
elif [ -f ".claude-plugin/plugin.json" ]; then
  project_type="claude-plugin"

# Claude Code marketplace
elif [ -f ".claude-plugin/marketplace.json" ]; then
  project_type="claude-marketplace"

# Generic project with VERSION file
elif [ -f "VERSION" ] || [ -f "version.txt" ] || [ -f ".version" ]; then
  project_type="generic"

# Legacy Python (setup.py)
elif [ -f "setup.py" ]; then
  project_type="python"

else
  project_type="unknown"
fi

3. Determine Version Files

Based on detected project type, determine version file locations:

Node.js:

version_files=("package.json")
adapter="json"
field="version"

Python:

# Check for multiple version sources
version_files=()

if [ -f "pyproject.toml" ]; then
  version_files+=("pyproject.toml")
fi

# Look for __version__.py files
if [ -d "src" ]; then
  # Find __version__.py in src directory
  version_file=$(find src -name "__version__.py" | head -1)
  if [ -n "$version_file" ]; then
    version_files+=("$version_file")
  fi
fi

# Legacy setup.py
if [ -f "setup.py" ]; then
  version_files+=("setup.py")
fi

Rust:

version_files=("Cargo.toml")

Go:

# Go uses git tags for versions, no version file
version_files=()
version_via_tags=true

Java/Gradle:

if [ -f "gradle.properties" ]; then
  version_files=("gradle.properties")
elif [ -f "build.gradle" ]; then
  version_files=("build.gradle")
fi

Maven:

version_files=("pom.xml")

Claude Code Plugin:

version_files=(".claude-plugin/plugin.json")

Generic:

# Find version file by name
if [ -f "VERSION" ]; then
  version_files=("VERSION")
elif [ -f "version.txt" ]; then
  version_files=("version.txt")
elif [ -f ".version" ]; then
  version_files=(".version")
fi

4. Determine Changelog File

# Check for existing changelog in common formats
if [ -f "CHANGELOG.md" ]; then
  changelog_file="CHANGELOG.md"
elif [ -f "HISTORY.md" ]; then
  changelog_file="HISTORY.md"
elif [ -f "CHANGES.md" ]; then
  changelog_file="CHANGES.md"
elif [ -f "NEWS.md" ]; then
  changelog_file="NEWS.md"
elif [ -f "CHANGES.rst" ]; then
  changelog_file="CHANGES.rst"
else
  # Will be created
  changelog_file="CHANGELOG.md"
fi

5. Determine Tag Pattern

# Project-specific tag patterns
case "$project_type" in
  "nodejs"|"python"|"rust"|"generic")
    tag_pattern="v{version}"
    ;;
  "go")
    tag_pattern="v{version}"  # Go convention
    ;;
  "java")
    tag_pattern="v{version}"
    ;;
  "claude-plugin")
    # Use plugin name from plugin.json
    plugin_name=$(jq -r '.name' .claude-plugin/plugin.json)
    tag_pattern="${plugin_name}-v{version}"
    ;;
  "claude-marketplace")
    tag_pattern="marketplace-v{version}"
    ;;
  "monorepo")
    tag_pattern="{package}-v{version}"
    ;;
esac

6. Detect Monorepo Packages

For monorepo projects, scan for packages:

monorepo_packages=()

# Check common monorepo patterns
for pattern in "packages/*" "apps/*" "libs/*"; do
  for dir in $pattern; do
    if [ -d "$dir" ]; then
      # Check if directory contains a project marker
      if [ -f "$dir/package.json" ] || \
         [ -f "$dir/Cargo.toml" ] || \
         [ -f "$dir/pyproject.toml" ]; then
        monorepo_packages+=("$dir")
      fi
    fi
  done
done

7. Determine Documentation Files

documentation_files=("README.md")

# Add common doc patterns
if [ -d "docs" ]; then
  documentation_files+=("docs/**/*.md")
fi

if [ -d "website/docs" ]; then
  documentation_files+=("website/docs/**/*.md")
fi

8. Validation

Validate the detected configuration:

Required validations:

  • At least one version file exists (unless Go project)
  • Version files are readable
  • Project type is not "unknown"

Warnings:

  • No changelog file exists (will be created)
  • No README.md exists

Output Format

Return structured configuration:

{
  "project_type": "nodejs",
  "config_source": "auto-detected",
  "version_files": [
    {
      "path": "package.json",
      "adapter": "json",
      "field": "version",
      "exists": true
    }
  ],
  "changelog_file": "CHANGELOG.md",
  "changelog_format": "keep-a-changelog",
  "tag_pattern": "v{version}",
  "tag_message": "Release v{version}",
  "conventional_commits": true,
  "documentation_files": [
    "README.md",
    "docs/**/*.md"
  ],
  "monorepo": {
    "enabled": false,
    "packages": []
  },
  "validations": {
    "errors": [],
    "warnings": [
      "No CHANGELOG.md found, will be created"
    ]
  }
}

Examples

Example 1: Node.js Project

Project structure:

/
├── package.json
├── README.md
└── src/

Detection result:

{
  "project_type": "nodejs",
  "config_source": "auto-detected",
  "version_files": [
    {
      "path": "package.json",
      "adapter": "json",
      "field": "version"
    }
  ],
  "changelog_file": "CHANGELOG.md",
  "tag_pattern": "v{version}",
  "conventional_commits": true
}

Example 2: Python Package

Project structure:

/
├── pyproject.toml
├── src/
│   └── mypackage/
│       └── __version__.py
└── README.md

Detection result:

{
  "project_type": "python",
  "config_source": "auto-detected",
  "version_files": [
    {
      "path": "pyproject.toml",
      "adapter": "toml",
      "section": "project"
    },
    {
      "path": "src/mypackage/__version__.py",
      "adapter": "python-file"
    }
  ],
  "changelog_file": "CHANGELOG.md",
  "tag_pattern": "v{version}"
}

Example 3: Rust Crate

Project structure:

/
├── Cargo.toml
├── src/
└── README.md

Detection result:

{
  "project_type": "rust",
  "config_source": "auto-detected",
  "version_files": [
    {
      "path": "Cargo.toml",
      "adapter": "toml",
      "section": "package"
    }
  ],
  "changelog_file": "CHANGELOG.md",
  "tag_pattern": "v{version}"
}

Example 4: Go Module

Project structure:

/
├── go.mod
├── main.go
└── README.md

Detection result:

{
  "project_type": "go",
  "config_source": "auto-detected",
  "version_files": [],
  "version_via_tags": true,
  "changelog_file": "CHANGELOG.md",
  "tag_pattern": "v{version}"
}

Example 5: Monorepo

Project structure:

/
├── packages/
│   ├── lib-a/
│   │   └── package.json
│   └── lib-b/
│       └── package.json
└── README.md

Detection result:

{
  "project_type": "monorepo",
  "config_source": "auto-detected",
  "monorepo": {
    "enabled": true,
    "packages": [
      "packages/lib-a",
      "packages/lib-b"
    ]
  },
  "tag_pattern": "{package}-v{version}",
  "changelog_file": "{package}/CHANGELOG.md"
}

Example 6: Claude Code Plugin

Project structure:

/
├── .claude-plugin/
│   └── plugin.json
├── skills/
└── README.md

Detection result:

{
  "project_type": "claude-plugin",
  "config_source": "auto-detected",
  "version_files": [
    {
      "path": ".claude-plugin/plugin.json",
      "adapter": "json",
      "field": "version"
    }
  ],
  "tag_pattern": "my-plugin-v{version}",
  "changelog_file": "CHANGELOG.md"
}

Example 7: Explicit Configuration

Project structure:

/
├── .release-config.json
├── VERSION
└── README.md

.release-config.json:

{
  "projectType": "generic",
  "versionFiles": ["VERSION"],
  "tagPattern": "release-{version}"
}

Detection result:

{
  "project_type": "generic",
  "config_source": "explicit",
  "version_files": [
    {
      "path": "VERSION",
      "adapter": "text"
    }
  ],
  "tag_pattern": "release-{version}",
  "changelog_file": "CHANGELOG.md"
}

Error Handling

Unknown project type:

{
  "project_type": "unknown",
  "validations": {
    "errors": [
      "Could not detect project type. Please create .release-config.json with explicit configuration."
    ]
  }
}

Invalid configuration:

{
  "config_source": "explicit",
  "validations": {
    "errors": [
      "Configuration file .release-config.json contains invalid JSON",
      "versionFiles[0]: 'missing.json' does not exist"
    ]
  }
}

No version files found:

{
  "project_type": "generic",
  "validations": {
    "errors": [
      "No version files found. Expected one of: VERSION, version.txt, package.json"
    ]
  }
}

Integration Notes

This skill is invoked by the

/release
command in Phase 1. The command will:

  1. Use the detected configuration for all subsequent phases
  2. Display project type and configuration to user
  3. Allow user to override with
    --config
    argument if needed
  4. Proceed with release workflow using detected/configured settings

Reference Documentation