9.8 KiB
9.8 KiB
description, argument-hint
| description | argument-hint |
|---|---|
| Add a subdirectory/subproject to a project for monorepo support | <project-id> <subproject-name> <path> [--pattern <pattern>] [--priority <priority>] |
Add Subdirectory to Project
Add subdirectory configuration to a project for automatic detection in monorepos.
Arguments
- $1 - Project ID (required)
- $2 - Subproject name (required)
- $3 - Subproject path (required, relative to repo root)
- --pattern - Match pattern (optional, default:
*/${path}/*) - --priority - Detection priority (optional, default: 10)
Usage
# Add with defaults
/ccpm:project:subdir:add repeat jarvis jarvis
# Add with custom pattern and priority
/ccpm:project:subdir:add repeat jarvis jarvis --pattern "*/jarvis/**" --priority 15
# Interactive mode (prompts for details)
/ccpm:project:subdir:add repeat
Workflow
Step 1: Auto-Activate Skills
Skill(project-operations): Provides configuration guidance
Step 2: Parse Arguments
const projectId = "$1"
const subprojectName = "$2"
const subprojectPath = "$3"
if (!projectId) {
console.log("❌ Error: Project ID required")
console.log("Usage: /ccpm:project:subdir:add <project-id> <name> <path>")
console.log("")
console.log("Available projects:")
console.log(" /ccpm:project:list")
exit(1)
}
// Check if interactive mode (only project ID provided)
const interactiveMode = !subprojectName
Step 3: Load Project Configuration
const projectConfig = Task(project-config-loader): `
Load configuration for project: ${projectId}
Validate: true
`
if (projectConfig.error) {
console.error(`❌ ${projectConfig.error.message}`)
exit(1)
}
console.log(`📋 Project: ${projectConfig.project_name}`)
console.log(`📁 Repository: ${projectConfig.repository.local_path || "Not configured"}`)
console.log("")
Step 4: Interactive Input (if needed)
If in interactive mode, use AskUserQuestion to gather details:
if (interactiveMode) {
const answers = AskUserQuestion({
questions: [
{
question: "What is the subproject name? (e.g., 'frontend', 'mobile-app')",
header: "Name",
multiSelect: false,
options: [
{
label: "Enter custom name",
description: "Provide a unique name for this subproject"
}
]
},
{
question: "What is the relative path to this subproject? (e.g., 'apps/frontend', 'packages/mobile')",
header: "Path",
multiSelect: false,
options: [
{
label: "apps/*",
description: "Subproject in apps directory"
},
{
label: "packages/*",
description: "Subproject in packages directory"
},
{
label: "services/*",
description: "Subproject in services directory"
}
]
}
]
})
subprojectName = answers["What is the subproject name?"]
subprojectPath = answers["What is the relative path to this subproject?"]
}
Step 5: Build Configuration
// Parse optional flags
const customPattern = getFlag("--pattern")
const customPriority = getFlag("--priority")
// Build subdirectory detection entry
const detectionEntry = {
subproject: subprojectName,
match_pattern: customPattern || `*/${subprojectPath}/*`,
priority: customPriority ? parseInt(customPriority) : 10
}
// Build subproject metadata entry
const metadataEntry = {
name: subprojectName,
path: subprojectPath,
description: "", // Will prompt user
tech_stack: {} // Can be filled later
}
console.log(`
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📁 New Subdirectory Configuration
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Subproject Name: ${detectionEntry.subproject}
Path: ${metadataEntry.path}
Match Pattern: ${detectionEntry.match_pattern}
Priority: ${detectionEntry.priority}
This will be added to project: ${projectId}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
`)
Step 6: Confirm and Update Configuration
const confirmation = AskUserQuestion({
questions: [{
question: "Add this subdirectory configuration?",
header: "Confirm",
multiSelect: false,
options: [
{
label: "Yes, add subdirectory",
description: "Update ccpm-config.yaml with this configuration"
},
{
label: "No, cancel",
description: "Don't make any changes"
}
]
}]
})
if (confirmation["Add this subdirectory configuration?"] === "No, cancel") {
console.log("❌ Cancelled")
exit(0)
}
Step 7: Update Configuration File
CONFIG_FILE="$HOME/.claude/ccpm-config.yaml"
# Read current configuration
current_config=$(cat "$CONFIG_FILE")
# Add to context.detection.subdirectories
# (This is pseudocode - actual implementation would use yq or python)
yq eval -i ".projects.${projectId}.context.detection.subdirectories += [{
\"subproject\": \"${subprojectName}\",
\"match_pattern\": \"${matchPattern}\",
\"priority\": ${priority}
}]" "$CONFIG_FILE"
# Add to code_repository.subprojects
yq eval -i ".projects.${projectId}.code_repository.subprojects += [{
\"name\": \"${subprojectName}\",
\"path\": \"${subprojectPath}\",
\"description\": \"\",
\"tech_stack\": {}
}]" "$CONFIG_FILE"
echo "✅ Subdirectory configuration added!"
Step 8: Validate and Display Results
// Reload configuration to validate
const updatedConfig = Task(project-config-loader): `
Load configuration for project: ${projectId}
Validate: true
`
if (updatedConfig.error) {
console.error("⚠️ Warning: Configuration validation failed")
console.error(updatedConfig.error.message)
console.log("")
console.log("Please check the configuration file:")
console.log(` ~/.claude/ccpm-config.yaml`)
exit(1)
}
console.log(`
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Subdirectory Added Successfully
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Project: ${projectId}
Subproject: ${subprojectName}
Path: ${subprojectPath}
Match Pattern: ${detectionEntry.match_pattern}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🧪 Test Detection
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
To test automatic detection:
cd ${projectConfig.repository.local_path}/${subprojectPath}
/ccpm:project:list
Expected result:
⭐ ${projectId} › ${subprojectName}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📝 Next Steps
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Update tech stack:
/ccpm:project:subdir:update ${projectId} ${subprojectName} --tech-stack
Add more subdirectories:
/ccpm:project:subdir:add ${projectId}
View all subdirectories:
/ccpm:project:subdir:list ${projectId}
View project details:
/ccpm:project:show ${projectId}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
`)
Examples
Example 1: Add Frontend Subproject
/ccpm:project:subdir:add my-monorepo frontend apps/frontend
Output:
📋 Project: My Monorepo
📁 Repository: /Users/dev/my-monorepo
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📁 New Subdirectory Configuration
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Subproject Name: frontend
Path: apps/frontend
Match Pattern: */apps/frontend/*
Priority: 10
✅ Subdirectory Added Successfully
Example 2: Add with Custom Pattern
/ccpm:project:subdir:add my-monorepo backend services/api --pattern "**/services/api/**" --priority 15
Example 3: Interactive Mode
/ccpm:project:subdir:add my-monorepo
Then answer prompts for name, path, tech stack, etc.
Pattern Matching
Glob Pattern Format:
*/path/*- Matches any nesting level with path in between**/path/**- Matches path at any depthapps/*/src- Matches specific structure
Priority Guidelines:
- 10 (default) - Standard subprojects
- 15-20 - More specific patterns (nested paths)
- 5 - Less specific, fallback patterns
Examples:
# Specific nested path (high priority)
- subproject: admin-panel
match_pattern: "*/apps/web/admin/*"
priority: 20
# General web app (standard priority)
- subproject: web-app
match_pattern: "*/apps/web/*"
priority: 10
Notes
- Subdirectory detection requires
repository.local_pathto be configured - Patterns are matched against the current working directory
- Higher priority patterns are matched first
- Use
/ccpm:project:show <project-id>to see all configured subdirectories - Tech stack can be added later with
/ccpm:project:subdir:update
Agent Integration
Uses these agents:
- project-config-loader: Loads and validates project configuration
- project-operations skill: Provides configuration guidance
Related Commands
/ccpm:project:subdir:list- List all subdirectories/ccpm:project:subdir:update- Update subdirectory details/ccpm:project:subdir:remove- Remove subdirectory/ccpm:project:show- View complete project configuration