prjct-cli 0.4.9 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +332 -0
  2. package/CLAUDE.md +109 -3
  3. package/README.md +231 -96
  4. package/core/agent-detector.js +55 -122
  5. package/core/agent-generator.js +516 -0
  6. package/core/command-installer.js +104 -890
  7. package/core/commands.js +74 -76
  8. package/core/editors-config.js +9 -57
  9. package/core/git-integration.js +401 -0
  10. package/package.json +12 -9
  11. package/scripts/install.sh +0 -1
  12. package/templates/agents/be.template.md +42 -0
  13. package/templates/agents/data.template.md +41 -0
  14. package/templates/agents/devops.template.md +41 -0
  15. package/templates/agents/fe.template.md +42 -0
  16. package/templates/agents/mobile.template.md +41 -0
  17. package/templates/agents/pm.template.md +84 -0
  18. package/templates/agents/qa.template.md +54 -0
  19. package/templates/agents/scribe.template.md +95 -0
  20. package/templates/agents/security.template.md +41 -0
  21. package/templates/agents/ux.template.md +49 -0
  22. package/templates/commands/analyze.md +137 -3
  23. package/templates/commands/done.md +154 -5
  24. package/templates/commands/init.md +61 -3
  25. package/templates/commands/ship.md +146 -6
  26. package/templates/commands/sync.md +220 -0
  27. package/templates/examples/natural-language-examples.md +234 -22
  28. package/core/agents/codex-agent.js +0 -256
  29. package/core/agents/terminal-agent.js +0 -465
  30. package/templates/workflows/analyze.md +0 -159
  31. package/templates/workflows/cleanup.md +0 -73
  32. package/templates/workflows/context.md +0 -72
  33. package/templates/workflows/design.md +0 -88
  34. package/templates/workflows/done.md +0 -20
  35. package/templates/workflows/fix.md +0 -201
  36. package/templates/workflows/git.md +0 -192
  37. package/templates/workflows/help.md +0 -13
  38. package/templates/workflows/idea.md +0 -22
  39. package/templates/workflows/init.md +0 -80
  40. package/templates/workflows/natural-language-handler.md +0 -183
  41. package/templates/workflows/next.md +0 -44
  42. package/templates/workflows/now.md +0 -19
  43. package/templates/workflows/progress.md +0 -113
  44. package/templates/workflows/recap.md +0 -66
  45. package/templates/workflows/roadmap.md +0 -95
  46. package/templates/workflows/ship.md +0 -18
  47. package/templates/workflows/stuck.md +0 -25
  48. package/templates/workflows/task.md +0 -109
  49. package/templates/workflows/test.md +0 -243
package/core/commands.js CHANGED
@@ -389,23 +389,9 @@ class PrjctCommands {
389
389
  const hasExistingCode = await this.detectExistingCode(projectPath)
390
390
 
391
391
  if (hasExistingCode) {
392
- try {
393
- console.log('šŸ” Analyzing existing codebase...')
394
- const analysisResult = await this.analyze({
395
- sync: true,
396
- silent: true,
397
- }, projectPath)
398
-
399
- if (analysisResult.success && analysisResult.syncResults) {
400
- const sync = analysisResult.syncResults
401
- analysisMessage = '\n\nšŸ“Š Analysis Complete:\n' +
402
- `āœ… Found ${analysisResult.analysis.commands.length} commands, ${analysisResult.analysis.features.length} features\n` +
403
- (sync.tasksMarkedComplete > 0 ? `āœ… Synced ${sync.tasksMarkedComplete} completed tasks\n` : '') +
404
- (sync.featuresAdded > 0 ? `āœ… Added ${sync.featuresAdded} features to shipped.md\n` : '')
405
- }
406
- } catch (error) {
407
- console.error('[prjct] Analysis warning:', error.message)
408
- }
392
+ // Instead of silently analyzing, prompt the AI agent to run /p:analyze workflow
393
+ analysisMessage = '\n\nšŸ“Š Existing codebase detected!\n' +
394
+ `\nšŸ’” Run ${this.agentInfo.config.commandPrefix}analyze to analyze your project and sync tasks`
409
395
  }
410
396
 
411
397
  const displayPath = pathManager.getDisplayPath(globalPath)
@@ -2224,7 +2210,6 @@ ${diagram}
2224
2210
  const chalk = require('chalk')
2225
2211
  console.log('')
2226
2212
  console.log('')
2227
- console.log(chalk.bold.magenta(' (ļ¾‰ā—•ćƒ®ā—•)ノ*:d゚✧'))
2228
2213
  console.log(chalk.bold.cyan(' ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—'))
2229
2214
  console.log(chalk.bold.cyan(' ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•—ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•— ā–ˆā–ˆā•‘ā–ˆā–ˆā•”ā•ā•ā•ā•ā•ā•šā•ā•ā–ˆā–ˆā•”ā•ā•ā•'))
2230
2215
  console.log(chalk.bold.blue(' ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•”ā•ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•”ā• ā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘'))
@@ -2239,54 +2224,55 @@ ${diagram}
2239
2224
  console.log(chalk.cyan(' šŸ¤– Perfect context for AI agents'))
2240
2225
  console.log('')
2241
2226
 
2242
- console.log(chalk.bold.magenta('šŸ“¦ Setup - Install Commands to AI Editors\n'))
2227
+ console.log(chalk.bold.magenta('šŸ“¦ Setup - Install Commands to Claude\n'))
2243
2228
 
2244
- // Detect editors
2229
+ // Detect Claude
2245
2230
  const commandInstaller = require('./command-installer')
2246
- const detection = await commandInstaller.detectEditors()
2247
- const detectedEditors = Object.entries(detection).filter(([_, info]) => info.detected)
2231
+ const claudeDetected = await commandInstaller.detectClaude()
2248
2232
 
2249
- if (detectedEditors.length === 0) {
2233
+ if (!claudeDetected) {
2250
2234
  return {
2251
2235
  success: false,
2252
2236
  message: this.agent.formatResponse(
2253
- 'No AI editors detected.\n\nSupported: Claude Code, Cursor, Windsurf',
2237
+ 'Claude not detected.\n\nPlease install Claude Code or Claude Desktop first.\n\nVisit: https://claude.ai/download',
2254
2238
  'error'
2255
2239
  ),
2256
2240
  }
2257
2241
  }
2258
2242
 
2259
- console.log(chalk.cyan('šŸ” Detected AI editors:'))
2260
- detectedEditors.forEach(([key, info]) => {
2261
- const editorName = commandInstaller.editors[key]?.name || key
2262
- console.log(chalk.green(` [āœ“] ${editorName} (${info.path})`))
2263
- })
2243
+ console.log(chalk.green('āœ“ Claude detected'))
2264
2244
  console.log('')
2265
2245
 
2266
- // Interactive selection (allow uninstall = true)
2267
- const installResult = await commandInstaller.interactiveInstall(true)
2246
+ // Install commands
2247
+ console.log(chalk.cyan('Installing /p:* commands...'))
2248
+ const installResult = await commandInstaller.installCommands()
2268
2249
 
2269
2250
  if (!installResult.success) {
2270
2251
  return {
2271
2252
  success: false,
2272
- message: this.agent.formatResponse(installResult.message || 'Setup failed', 'error'),
2253
+ message: this.agent.formatResponse(
2254
+ `Installation failed: ${installResult.error || 'Unknown error'}`,
2255
+ 'error'
2256
+ ),
2273
2257
  }
2274
2258
  }
2275
2259
 
2276
- // Install Context7 MCP
2277
- const mcpResult = await commandInstaller.installContext7MCP()
2278
-
2279
2260
  // Success message
2280
- let message = `āœ… Commands installed in: ${installResult.editors.join(', ')}\n`
2261
+ const installedCount = installResult.installed?.length || 0
2262
+ const errorCount = installResult.errors?.length || 0
2281
2263
 
2282
- if (mcpResult.success && mcpResult.editors.length > 0) {
2283
- message += `\nšŸ”Œ Context7 MCP enabled in: ${mcpResult.editors.join(', ')}`
2264
+ let message = `āœ… Successfully installed ${installedCount} commands to Claude\n`
2265
+ message += ` Location: ${installResult.path}\n`
2266
+
2267
+ if (errorCount > 0) {
2268
+ message += `\nāš ļø ${errorCount} command(s) had issues during installation`
2284
2269
  }
2285
2270
 
2286
2271
  message += '\n\n✨ prjct is ready to use!'
2287
2272
  message += '\n\nNext steps:'
2288
2273
  message += '\n cd your-project/'
2289
2274
  message += '\n prjct init'
2275
+ message += '\n\nā„¹ļø Context7 MCP is automatically available in Claude'
2290
2276
 
2291
2277
  return {
2292
2278
  success: true,
@@ -2311,60 +2297,72 @@ ${diagram}
2311
2297
  try {
2312
2298
  await this.initializeAgent()
2313
2299
 
2314
- const {
2315
- force = false,
2316
- editor = null,
2317
- createTemplates = false,
2318
- interactive = true,
2319
- } = options
2300
+ const { force = false } = options
2320
2301
 
2321
- if (createTemplates) {
2322
- const templateResult = await commandInstaller.createTemplates()
2323
- if (!templateResult.success) {
2324
- return {
2325
- success: false,
2326
- message: this.agent.formatResponse(templateResult.message, 'error'),
2327
- }
2302
+ // Detect Claude
2303
+ const commandInstaller = require('./command-installer')
2304
+ const claudeDetected = await commandInstaller.detectClaude()
2305
+
2306
+ if (!claudeDetected) {
2307
+ return {
2308
+ success: false,
2309
+ message: this.agent.formatResponse(
2310
+ 'Claude not detected. Please install Claude Code or Claude Desktop first.',
2311
+ 'error'
2312
+ ),
2328
2313
  }
2329
2314
  }
2330
2315
 
2331
- const detection = await commandInstaller.detectEditors(process.cwd())
2332
- const detectedEditors = Object.entries(detection)
2333
- .filter(([_, info]) => info.detected)
2316
+ // Check current installation status
2317
+ const status = await commandInstaller.checkInstallation()
2318
+
2319
+ if (status.installed && !force) {
2320
+ const chalk = require('chalk')
2321
+ let report = chalk.green('āœ“ Commands already installed\n')
2322
+ report += chalk.dim(` Location: ${status.path}\n`)
2323
+ report += chalk.dim(` Commands: ${status.commands.length}\n`)
2324
+ report += '\nUse --force to reinstall'
2334
2325
 
2335
- if (detectedEditors.length === 0) {
2336
2326
  return {
2337
- success: false,
2338
- message: this.agent.formatResponse('No AI editors detected on this system', 'error'),
2327
+ success: true,
2328
+ message: this.agent.formatResponse(report, 'info'),
2339
2329
  }
2340
2330
  }
2341
2331
 
2342
- let installResult
2332
+ // Install or reinstall commands
2333
+ const installResult = force
2334
+ ? await commandInstaller.updateCommands()
2335
+ : await commandInstaller.installCommands()
2343
2336
 
2344
- if (editor) {
2345
- // Install to specific editor
2346
- installResult = await commandInstaller.installToEditor(editor, force)
2347
- } else if (interactive) {
2348
- // Interactive mode: use new interactiveInstall method
2349
- installResult = await commandInstaller.interactiveInstall(force)
2350
- } else {
2351
- // Non-interactive mode: install to all detected editors
2352
- installResult = await commandInstaller.installToAll(force)
2337
+ if (!installResult.success) {
2338
+ return {
2339
+ success: false,
2340
+ message: this.agent.formatResponse(
2341
+ `Installation failed: ${installResult.error || 'Unknown error'}`,
2342
+ 'error'
2343
+ ),
2344
+ }
2353
2345
  }
2354
2346
 
2355
- // Always install Context7 MCP after commands installation
2356
- const mcpResult = await commandInstaller.installContext7MCP()
2347
+ // Generate report
2348
+ const installedCount = installResult.installed?.length || 0
2349
+ const errorCount = installResult.errors?.length || 0
2357
2350
 
2358
- let report = commandInstaller.generateReport(installResult)
2359
- if (mcpResult.success && mcpResult.editors.length > 0) {
2360
- report += '\n\nšŸ”Œ Context7 MCP Enabled\n'
2361
- report += ` Editors: ${mcpResult.editors.join(', ')}\n`
2362
- report += ' šŸ“š Library documentation now available automatically'
2351
+ let report = `āœ… Successfully ${force ? 'reinstalled' : 'installed'} ${installedCount} commands\n`
2352
+ report += ` Location: ${installResult.path}\n`
2353
+
2354
+ if (errorCount > 0) {
2355
+ report += `\nāš ļø ${errorCount} command(s) had issues\n`
2356
+ installResult.errors.forEach(err => {
2357
+ report += ` - ${err.file}: ${err.error}\n`
2358
+ })
2363
2359
  }
2364
2360
 
2361
+ report += '\nšŸ“š Context7 MCP is automatically available in Claude'
2362
+
2365
2363
  return {
2366
- success: installResult.success,
2367
- message: this.agent.formatResponse(report, installResult.success ? 'celebrate' : 'error'),
2364
+ success: true,
2365
+ message: this.agent.formatResponse(report, 'celebrate'),
2368
2366
  }
2369
2367
  } catch (error) {
2370
2368
  await this.initializeAgent()
@@ -3,14 +3,14 @@ const path = require('path')
3
3
  const os = require('os')
4
4
 
5
5
  /**
6
- * EditorsConfig - Manages installed editors tracking configuration
6
+ * EditorsConfig - Manages Claude installation tracking
7
7
  *
8
- * Tracks which AI editors user has installed prjct commands to,
8
+ * Tracks prjct commands installation in Claude (Code + Desktop),
9
9
  * enabling automatic updates when npm package is updated.
10
10
  *
11
11
  * Config location: ~/.prjct-cli/config/installed-editors.json
12
12
  *
13
- * @version 0.4.2
13
+ * @version 0.5.0
14
14
  */
15
15
  class EditorsConfig {
16
16
  constructor() {
@@ -31,7 +31,7 @@ class EditorsConfig {
31
31
  }
32
32
 
33
33
  /**
34
- * Load installed editors configuration
34
+ * Load installation configuration
35
35
  * @returns {Promise<Object|null>} Configuration object or null if not found
36
36
  */
37
37
  async loadConfig() {
@@ -48,21 +48,20 @@ class EditorsConfig {
48
48
  }
49
49
 
50
50
  /**
51
- * Save installed editors configuration
52
- * @param {string[]} editors - Array of editor keys (e.g., ['claude', 'cursor'])
53
- * @param {Object} paths - Object mapping editor keys to installation paths
51
+ * Save installation configuration
54
52
  * @param {string} version - Current prjct-cli version
53
+ * @param {string} claudePath - Path to Claude commands directory
55
54
  * @returns {Promise<boolean>} Success status
56
55
  */
57
- async saveConfig(editors, paths, version) {
56
+ async saveConfig(version, claudePath) {
58
57
  try {
59
58
  await this.ensureConfigDir()
60
59
 
61
60
  const config = {
62
61
  version,
63
- editors,
62
+ editor: 'claude',
64
63
  lastInstall: new Date().toISOString(),
65
- paths,
64
+ path: claudePath,
66
65
  }
67
66
 
68
67
  await fs.writeFile(
@@ -78,53 +77,6 @@ class EditorsConfig {
78
77
  }
79
78
  }
80
79
 
81
- /**
82
- * Get tracked editors from configuration
83
- * @returns {Promise<string[]>} Array of editor keys
84
- */
85
- async getTrackedEditors() {
86
- const config = await this.loadConfig()
87
- return config ? config.editors : []
88
- }
89
-
90
- /**
91
- * Remove an editor from tracked list
92
- * @param {string} editorKey - Editor key to remove
93
- * @returns {Promise<boolean>} Success status
94
- */
95
- async removeTrackedEditor(editorKey) {
96
- try {
97
- const config = await this.loadConfig()
98
- if (!config) return false
99
-
100
- // Remove from editors array
101
- config.editors = config.editors.filter(e => e !== editorKey)
102
-
103
- // Remove from paths object
104
- if (config.paths && config.paths[editorKey]) {
105
- delete config.paths[editorKey]
106
- }
107
-
108
- // Save updated config
109
- await fs.mkdir(this.configDir, { recursive: true })
110
- await fs.writeFile(this.configPath, JSON.stringify(config, null, 2), 'utf-8')
111
-
112
- return true
113
- } catch (error) {
114
- console.error('[editors-config] Error removing tracked editor:', error.message)
115
- return false
116
- }
117
- }
118
-
119
- /**
120
- * Get editor paths from configuration
121
- * @returns {Promise<Object>} Object mapping editor keys to paths
122
- */
123
- async getEditorPaths() {
124
- const config = await this.loadConfig()
125
- return config ? config.paths : {}
126
- }
127
-
128
80
  /**
129
81
  * Get last installed version
130
82
  * @returns {Promise<string|null>} Version string or null