9.7 KiB
description
| description |
|---|
| List all configured CCPM projects |
List CCPM Projects
Display all projects configured in ~/.claude/ccpm-config.yaml with active project detection including subdirectory/subproject context.
Usage
/ccpm:project:list
Workflow
Step 1: Auto-Activate Skills
# Skills auto-activate for guidance
Skill(project-detection): Provides detection workflow
Skill(project-operations): Provides display format guidance
Step 2: Get Active Project Context
Use the project-context-manager agent to detect the active project:
const activeContext = Task(project-context-manager): `
Get active project context
Include detection method
Format: compact
`
// activeContext contains:
// - project_id (or null if not detected)
// - subproject (or null if not in subdirectory)
// - detection_method (git_remote, subdirectory, local_path, etc.)
Step 3: List All Projects
Use the project-config-loader agent to get all projects:
const allProjects = Task(project-config-loader): `
Load all project configurations
Return summary list with names and descriptions
Validate: false
`
if (allProjects.error?.code === 'CONFIG_NOT_FOUND') {
console.log("⚠️ No CCPM configuration found")
console.log("")
console.log("Create configuration:")
console.log(" /ccpm:project:add <project-id>")
exit(0)
}
if (Object.keys(allProjects.projects).length === 0) {
console.log("📋 No projects configured yet")
console.log("")
console.log("Add your first project:")
console.log(" /ccpm:project:add <project-id>")
exit(0)
}
Step 4: Display Project List
Sort projects with active first, then alphabetically:
const projects = allProjects.projects
const projectIds = Object.keys(projects)
// Sort: active first, then alphabetically
projectIds.sort((a, b) => {
if (activeContext?.project_id === a) return -1
if (activeContext?.project_id === b) return 1
return a.localeCompare(b)
})
console.log(`
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📋 CCPM Projects (${projectIds.length})
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
`)
for (const projectId of projectIds) {
const config = projects[projectId]
const isActive = activeContext?.project_id === projectId
const activeIndicator = isActive ? "⭐" : " "
// Build project title with subproject if applicable
let projectTitle = projectId
if (isActive && activeContext.subproject) {
projectTitle = `${projectId} › ${activeContext.subproject}`
}
console.log(`
${activeIndicator} ${projectTitle}
Name: ${config.name}
Description: ${config.description || "N/A"}
Linear: ${config.linear.team} / ${config.linear.project}
Repo Type: ${config.code_repository?.type || "N/A"}
External PM: ${config.external_pm?.enabled ? config.external_pm.type : "disabled"}`)
// Show subproject info for active project
if (isActive && activeContext.subproject) {
const subprojectConfig = config.code_repository?.subprojects?.find(
s => s.name === activeContext.subproject
)
if (subprojectConfig) {
console.log(` Subproject: 📁 ${subprojectConfig.path}`)
const techStack = subprojectConfig.tech_stack
if (techStack) {
const langs = techStack.languages?.join(", ") || ""
const frameworks = Object.values(techStack.frameworks || {}).flat().join(", ")
console.log(` Tech Stack: ${[langs, frameworks].filter(Boolean).join(", ")}`)
}
}
}
if (isActive) {
const detectionMethod = activeContext.detection_method || "unknown"
const methodDisplay = {
'manual': 'Manual setting',
'git_remote': 'Git remote match',
'subdirectory': 'Subdirectory match',
'local_path': 'Local path match',
'pattern': 'Custom pattern match'
}[detectionMethod] || detectionMethod
console.log(` Status: 🟢 Active (${methodDisplay})`)
}
console.log("")
console.log(" Commands:")
console.log(` View details: /ccpm:project:show ${projectId}`)
console.log(` Update config: /ccpm:project:update ${projectId}`)
console.log(` Delete: /ccpm:project:delete ${projectId}`)
console.log(` Set active: /ccpm:project:set ${projectId}`)
console.log("")
}
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
Step 4: Show Quick Actions
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🚀 Quick Actions
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Add new project: /ccpm:project:add <project-id>
Show project info: /ccpm:project:show <project-id>
Update project: /ccpm:project:update <project-id>
Delete project: /ccpm:project:delete <project-id>
Configuration file: ~/.claude/ccpm-config.yaml
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Output Format
Compact View (default)
Example 1: Simple Project (no subdirectories)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📋 CCPM Projects (3)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⭐ my-app
Name: My App
Description: Example application with full PM integration
Linear: Work / My App
Repo Type: github
External PM: jira
Status: 🟢 Active (Git remote match)
Commands:
View details: /ccpm:project:show my-app
Update config: /ccpm:project:update my-app
Delete: /ccpm:project:delete my-app
Set active: /ccpm:project:set my-app
my-project
Name: My Project
Description: Another example project
Linear: Work / My Project
Repo Type: bitbucket
External PM: jira
Commands:
View details: /ccpm:project:show my-project
Update config: /ccpm:project:update my-project
Delete: /ccpm:project:delete my-project
Set active: /ccpm:project:set my-project
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Example 2: Monorepo with Active Subproject
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📋 CCPM Projects (2)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⭐ repeat › jarvis
Name: Repeat
Description: Repeat.gg gaming platform - multi-project repository
Linear: Work / Repeat
Repo Type: bitbucket
External PM: jira
Subproject: 📁 jarvis
Tech Stack: typescript, nextjs, react, nestjs
Status: 🟢 Active (Subdirectory match)
Commands:
View details: /ccpm:project:show repeat
Update config: /ccpm:project:update repeat
Delete: /ccpm:project:delete repeat
Set active: /ccpm:project:set repeat
nv-internal
Name: NV Internal
Description: Task management application
Linear: Personal / NV Internal
Repo Type: github
External PM: disabled
Commands:
View details: /ccpm:project:show nv-internal
Update config: /ccpm:project:update nv-internal
Delete: /ccpm:project:delete nv-internal
Set active: /ccpm:project:set nv-internal
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Detailed View (with --detailed flag)
Shows complete configuration for each project including:
- All Linear settings
- External PM details (Jira, Confluence, Slack)
- Code repository configuration
- Tech stack
- Custom commands
- Quality gates
Active Project Detection
The command uses the project-context-manager agent to automatically detect the active project by:
Detection Priority Order:
- Manual override - User-set active project (highest priority)
- Git remote URL - Matches repository URL in config
- Subdirectory patterns - Matches working directory against configured patterns (NEW)
- Local path - Matches current directory path
- Custom patterns - User-defined glob patterns
Subdirectory Detection (NEW):
- For monorepos, detects which subproject you're currently in
- Displays as:
project-name › subproject-name - Shows subproject path and tech stack
- Detection method shown as "Subdirectory match"
Example:
# Working in /Users/dev/repeat/jarvis/src
# Detects: project="repeat", subproject="jarvis"
# Displays: ⭐ repeat › jarvis
The active project is marked with ⭐ and always appears first in the list.
Agent Integration
This command uses CCPM agents for efficient operation:
- project-context-manager: Detects active project and subproject
- project-config-loader: Loads all project configurations
- project-detection skill: Auto-activates for detection guidance
- project-operations skill: Provides display format guidance
Token usage: ~200 tokens (vs ~2000 with inline logic)
Notes
- Projects are listed with active first, then alphabetically
- Active project shows detection method (git remote, subdirectory, etc.)
- Subproject information shown only for active monorepo projects
- Use
/ccpm:project:show <id>for full details including all subprojects - Configuration file:
~/.claude/ccpm-config.yaml