- name
- context-detection
- version
- 1.1.0
- description
- Use when detecting project technology stack from files/configs/directory structure, auto-loading framework-specific skills, or analyzing multi-stack fullstack projects (e.g., React + Go).
- keywords
- ["context detection","stack detection","technology stack","project analysis","auto-detection","framework detection","skill discovery"]
- plugin
- dev
- updated
- 2026-02-03T00:00:00.000Z
- used_by
- stack-detector agent, all dev commands
- allowed-tools
- Bash(node *)
# Context Detection Skill
## Quick Start: Skill Discovery Script
Run the helper script to discover ALL skills available to a project:
```bash
node "${CLAUDE_PLUGIN_ROOT}/skills/context-detection/scripts/discover-skills.js" "$(pwd)"
```
This searches all 7 official Claude Code skill locations:
1. Personal: `~/.claude/skills/`
2. Project: `.claude/skills/`
3. Nested (monorepos): `**/.claude/skills/`
4. Legacy commands: `.claude/commands/`
5. Marketplace plugins: `~/.claude/plugins/marketplaces/{m}/plugins/{p}/skills/`
6. Local plugins: `.claude-plugin/skills/`, `plugins/*/skills/`
7. Enterprise (managed settings)
**Output:** JSON with summary stats and full skill metadata.
For detailed documentation on the script, see [scripts/discover-skills.js](scripts/discover-skills.js).
---
## Overview
The context detection skill provides systematic patterns for analyzing any project to determine its technology stack(s). It enables the dev plugin to auto-load appropriate framework-specific skills based on what's actually in the project.
**Key Innovation:** Multi-stack detection for fullstack projects (e.g., React + Go).
---
## Detection Priority
Detection follows a priority order from most explicit to most inferred:
### 1. Explicit User Preference (Highest Priority)
**Source:** `.claude/settings.json`
```json
{
"pluginSettings": {
"dev": {
"stack": ["react-typescript", "golang"],
"features": {
"testing": "vitest",
"api": "rest"
}
}
}
}
```
**When to use:**
- User wants to override auto-detection
- Project has ambiguous structure
- Custom stack combinations
### 2. Current File Context
**Source:** File extension of current editing context
```yaml
extension_mappings:
".tsx": ["react-typescript", "testing-frontend"]
".vue": ["vue-typescript", "testing-frontend"]
".go": ["golang", "testing-strategies"]
".dingo": ["dingo", "golang", "testing-strategies"]
".rs": ["rust", "testing-strategies"]
".py": ["python", "testing-strategies"]
```
**When to use:**
- User is editing a specific file
- Immediate context for implementation
- Quick detection without full project scan
### 3. Configuration Files (Primary Detection)
**Source:** Project configuration files
```yaml
config_file_patterns:
package.json:
check: "dependencies.react exists"
skills: ["react-typescript", "state-management", "testing-frontend"]
mode: "frontend"
package.json:
check: "dependencies.vue exists"
skills: ["vue-typescript", "state-management", "testing-frontend"]
mode: "frontend"
go.mod:
check: "file exists"
skills: ["golang", "api-design", "database-patterns"]
mode: "backend"
go.mod + *.dingo:
check: "go.mod exists AND any .dingo files present"
skills: ["dingo", "golang", "api-design", "database-patterns"]
mode: "backend"
note: "Dingo projects always include golang skill since Dingo transpiles to Go"
Cargo.toml:
check: "file exists"
skills: ["rust", "api-design"]
mode: "backend"
pyproject.toml:
check: "file exists"
skills: ["python", "api-design"]
mode: "backend"
bun.lockb:
check: "file exists AND no react/vue in package.json"
skills: ["bunjs", "api-design"]
mode: "backend"
```
**When to use:**
- First time analyzing a project
- Most reliable detection method
- Determine versions and dependencies
### 4. Directory Structure Patterns (Supporting Evidence)
**Source:** Common directory layouts
```yaml
directory_patterns:
"src/routes/":
indicator: "React Router structure"
skills: ["react-typescript"]
"src/components/":
indicator: "Component-based frontend"
skills: ["react-typescript", "vue-typescript"]
"cmd/":
indicator: "Go standard project layout"
skills: ["golang"]
"src/main.rs":
indicator: "Rust binary crate"
skills: ["rust"]
"frontend/":
indicator: "Separate frontend directory (fullstack)"
note: "Check for backend/ as well"
"backend/":
indicator: "Separate backend directory (fullstack)"
note: "Check for frontend/ as well"
```
**When to use:**
- Confirming config file detection
- Identifying fullstack projects
- Disambiguating multi-purpose projects
---
## Multi-Stack Detection Algorithm
**CRITICAL:** Always check for MULTIPLE stacks. Projects can be fullstack.
```bash
# Step 1: Find ALL config files (not just first match)
find_all_configs() {
configs=()
[ -f "package.json" ] && configs+=("package.json")
[ -f "go.mod" ] && configs+=("go.mod")
[ -f "Cargo.toml" ] && configs+=("Cargo.toml")
[ -f "pyproject.toml" ] && configs+=("pyproject.toml")
[ -f "bun.lockb" ] && configs+=("bun.lockb")
# Check for Dingo files (go.mod must also exist)
# Note: "dingo" is a detection indicator, not an actual config file name
if [ -f "go.mod" ] && find . -name "*.dingo" -type f ! -path "./.git/*" ! -path "./node_modules/*" ! -path "./vendor/*" -print -quit | grep -q .; then
configs+=("dingo")
fi
echo "${configs[@]}"
}
# Step 2: Analyze EACH config file
analyze_all_configs() {
local detected_stacks=()
# Check package.json
if [ -f "package.json" ]; then
if grep -q '"react"' package.json; then
detected_stacks+=("react-typescript")
elif grep -q '"vue"' package.json; then
detected_stacks+=("vue-typescript")
fi
fi
# Check go.mod (and optionally Dingo)
if [ -f "go.mod" ]; then
# Check if this is a Dingo project
if find . -name "*.dingo" -type f ! -path "./.git/*" ! -path "./node_modules/*" ! -path "./vendor/*" -print -quit | grep -q .; then
detected_stacks+=("dingo")
# Dingo always co-loads golang
detected_stacks+=("golang")
else
detected_stacks+=("golang")
fi
fi
# Check Cargo.toml
if [ -f "Cargo.toml" ]; then
detected_stacks+=("rust")
fi
# Check pyproject.toml
if [ -f "pyproject.toml" ]; then
detected_stacks+=("python")
fi
# Check bun.lockb (only if NOT frontend)
if [ -f "bun.lockb" ] && ! grep -q '"react"\|"vue"' package.json 2>/dev/null; then
detected_stacks+=("bunjs")
fi
echo "${detected_stacks[@]}"
}
# Step 3: Determine mode
determine_mode() {
local stacks=("$@")
local has_frontend=false
local has_backend=false
for stack in "${stacks[@]}"; do
case "$stack" in
react-typescript|vue-typescript)
has_frontend=true
;;
golang|rust|python|bunjs|dingo)
has_backend=true
;;
esac
done
if [ "$has_frontend" = true ] && [ "$has_backend" = true ]; then
echo "fullstack"
elif [ "$has_frontend" = true ]; then
echo "frontend"
elif [ "$has_backend" = true ]; then
echo "backend"
else
echo "unknown"
fi
}
# Step 4: Map stacks to skills
map_stacks_to_skills() {
local stacks=("$@")
local skills=(
# Core skills (ALWAYS included)
"universal-patterns"
"testing-strategies"
"debugging-strategies"
)
for stack in "${stacks[@]}"; do
case "$stack" in
react-typescript)
skills+=("react-typescript" "state-management" "testing-frontend")
;;
vue-typescript)
skills+=("vue-typescript" "state-management" "testing-frontend")
;;
golang)
skills+=("golang" "api-design" "database-patterns")
;;
dingo)
skills+=("dingo" "golang" "api-design" "database-patterns")
;;
rust)
skills+=("rust" "api-design")
;;
python)
skills+=("python" "api-design")
;;
bunjs)
skills+=("bunjs" "api-design")
;;
esac
done
# Deduplicate
echo "${skills[@]}" | tr ' ' '\n' | sort -u
}
# Step 5: Complete detection
detect_project_stack() {
# Check explicit preference first
local explicit_stack=$(jq -r '.pluginSettings.dev.stack // empty' .claude/settings.json 2>/dev/null)
if [ -n "$explicit_stack" ]; then
echo "Using explicit stack from .claude/settings.json"
return
fi
# Auto-detect all stacks
local detected_stacks=($(analyze_all_configs))
if [ ${#detected_stacks[@]} -eq 0 ]; then
echo "ERROR: No stack detected"
return 1
fi
# Determine mode
local mode=$(determine_mode "${detected_stacks[@]}")
# Map to skills
local skills=($(map_stacks_to_skills "${detected_stacks[@]}"))
# Output result
echo "Detected: ${detected_stacks[*]}"
echo "Mode: $mode"
echo "Skills: ${skills[*]}"
}
```
---
## Framework-Specific Detection
### React Detection
```bash
detect_react() {
# Check package.json
if [ -f "package.json" ]; then
# React in dependencies or devDependencies
if jq -e '.dependencies.react // .devDependencies.react' package.json >/dev/null 2>&1; then
# Check for TypeScript
local has_typescript=false
if jq -e '.dependencies["@types/react"] // .devDependencies["@types/react"]' package.json >/dev/null 2>&1; then
has_typescript=true
fi
# Get version
local react_version=$(jq -r '.dependencies.react // .devDependencies.react' package.json | sed 's/[^0-9.]//g')
echo "react-typescript"
echo "version: $react_version"
echo "typescript: $has_typescript"
return 0
fi
fi
return 1
}
```
### Vue Detection
```bash
detect_vue() {
if [ -f "package.json" ]; then
if jq -e '.dependencies.vue' package.json >/dev/null 2>&1; then
local vue_version=$(jq -r '.dependencies.vue' package.json | sed 's/[^0-9.]//g')
echo "vue-typescript"
echo "version: $vue_version"
return 0
fi
fi
return 1
}
```
### Go Detection
```bash
detect_go() {
if [ -f "go.mod" ]; then
local go_version=$(grep '^go ' go.mod | awk '{print $2}')
local module_name=$(grep '^module ' go.mod | awk '{print $2}')
echo "golang"
echo "version: $go_version"
echo "module: $module_name"
return 0
fi
return 1
Voir sur GitHub