prjct-cli 0.8.1 → 0.8.3
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.
- package/CHANGELOG.md +59 -0
- package/README.md +15 -11
- package/core/command-registry.js +4 -4
- package/core/commands.js +64 -1
- package/core/infrastructure/command-installer.js +196 -2
- package/package.json +4 -1
- package/scripts/install.sh +32 -8
- package/scripts/postinstall.js +185 -0
- package/templates/commands/migrate-all.md +120 -0
- package/templates/commands/setup.md +74 -0
- package/templates/global/CLAUDE.md +214 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,65 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.2] - 2025-10-05
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **BREAKING: npm-only installation** - Simplified installation to npm-only
|
|
15
|
+
- ✅ Single command: `npm install -g prjct-cli`
|
|
16
|
+
- ✅ Automatic setup via postinstall hook
|
|
17
|
+
- ✅ Auto-migration of legacy projects
|
|
18
|
+
- ✅ Beautiful ASCII art on installation
|
|
19
|
+
- ⚠️ `curl -fsSL https://prjct.app/install.sh` now deprecated (shows migration message)
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- **Automatic Post-Install Setup** (`scripts/postinstall.js`)
|
|
24
|
+
- Runs automatically after `npm install -g prjct-cli`
|
|
25
|
+
- Detects global vs local installation
|
|
26
|
+
- Installs/syncs commands to `~/.claude/commands/p/`
|
|
27
|
+
- Migrates legacy projects automatically
|
|
28
|
+
- Shows beautiful ASCII art with quick start guide
|
|
29
|
+
|
|
30
|
+
- **Intelligent Command Sync** (`syncCommands()` in `command-installer.js`)
|
|
31
|
+
- Detects new commands and installs them
|
|
32
|
+
- Detects updated commands and refreshes them
|
|
33
|
+
- **Detects orphaned commands and removes them** (e.g., context.md, stuck.md)
|
|
34
|
+
- Reports: "✓ 2 nuevos, 5 actualizados, 2 eliminados"
|
|
35
|
+
|
|
36
|
+
- **Beautiful ASCII Art** (`showAsciiArt()` in `commands.js`)
|
|
37
|
+
- Displays after `prjct setup` completion
|
|
38
|
+
- Shows prjct logo with colors
|
|
39
|
+
- Includes quick start guide
|
|
40
|
+
- Links to documentation
|
|
41
|
+
|
|
42
|
+
- **Global Configuration** (`~/.claude/CLAUDE.md`)
|
|
43
|
+
- Automatically installs/updates global configuration for Claude Code
|
|
44
|
+
- Provides context for ALL `/p:*` commands across any prjct project
|
|
45
|
+
- Intelligent merge: preserves user content, updates only prjct section
|
|
46
|
+
- Includes path resolution rules, file structure, commit format, validation patterns
|
|
47
|
+
- Installed during `npm install -g prjct-cli` and `prjct setup`
|
|
48
|
+
- Single source of truth - no need to repeat in 25 command templates
|
|
49
|
+
|
|
50
|
+
### Fixed
|
|
51
|
+
|
|
52
|
+
- **Orphaned Commands Cleanup** - Removed deprecated commands
|
|
53
|
+
- Deleted `context.md` (replaced by context tracking in core)
|
|
54
|
+
- Deleted `stuck.md` (functionality merged into /p:ask)
|
|
55
|
+
- Total commands: 27 → 25 (cleaned up)
|
|
56
|
+
|
|
57
|
+
- **Context Preservation** - All projects now use global storage
|
|
58
|
+
- Legacy projects in `.prjct/` automatically migrated to `~/.prjct-cli/projects/{id}/`
|
|
59
|
+
- Only `prjct.config.json` (2KB) remains in project directory
|
|
60
|
+
- Prevents context loss on updates
|
|
61
|
+
|
|
62
|
+
### Documentation
|
|
63
|
+
|
|
64
|
+
- Updated README.md with new installation flow
|
|
65
|
+
- Added "Auto-Setup (NEW in v0.8.2)" section
|
|
66
|
+
- Simplified installation instructions
|
|
67
|
+
- Deprecated manual installation methods
|
|
68
|
+
|
|
10
69
|
## [0.8.1] - 2025-10-05
|
|
11
70
|
|
|
12
71
|
### Fixed
|
package/README.md
CHANGED
|
@@ -73,23 +73,27 @@ For easier installation from GitHub Packages, see [GitHub Packages Setup](docs/G
|
|
|
73
73
|
|
|
74
74
|
> **Note**: The CLI automatically detects updates and notifies you when a new version is available. Simply run `npm update -g prjct-cli` to upgrade.
|
|
75
75
|
|
|
76
|
-
###
|
|
76
|
+
### Auto-Setup (NEW in v0.8.2)
|
|
77
77
|
|
|
78
|
-
After
|
|
78
|
+
After `npm install -g prjct-cli`, setup runs automatically:
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
- ✅ Installs `/p:*` commands to `~/.claude`
|
|
81
|
+
- ✅ Migrates legacy projects to global storage
|
|
82
|
+
- ✅ Syncs commands (removes orphans, adds new ones)
|
|
83
|
+
- ✅ Shows beautiful ASCII art with quick start
|
|
83
84
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
**That's it!** No manual setup required.
|
|
86
|
+
|
|
87
|
+
If you need to reconfigure later:
|
|
87
88
|
|
|
88
|
-
|
|
89
|
+
```bash
|
|
90
|
+
prjct setup # Reconfigure and sync commands
|
|
91
|
+
prjct setup --force # Force reinstall all commands
|
|
92
|
+
```
|
|
89
93
|
|
|
90
|
-
|
|
94
|
+
**Installation Location**: `~/.claude/commands/p/`
|
|
91
95
|
|
|
92
|
-
All
|
|
96
|
+
All 25+ slash commands (`/p:*`) are automatically installed to Claude Code and Claude Desktop.
|
|
93
97
|
|
|
94
98
|
### Version Management
|
|
95
99
|
|
package/core/command-registry.js
CHANGED
|
@@ -460,12 +460,12 @@ const COMMANDS = [
|
|
|
460
460
|
category: 'setup',
|
|
461
461
|
description: 'Reconfigure editor installations',
|
|
462
462
|
usage: {
|
|
463
|
-
claude:
|
|
463
|
+
claude: '/p:setup',
|
|
464
464
|
terminal: 'prjct setup [--force] [--editor <name>]',
|
|
465
465
|
},
|
|
466
466
|
params: '[--force] [--editor <name>]',
|
|
467
467
|
implemented: true,
|
|
468
|
-
hasTemplate:
|
|
468
|
+
hasTemplate: true,
|
|
469
469
|
icon: 'Settings',
|
|
470
470
|
requiresInit: false,
|
|
471
471
|
blockingRules: null,
|
|
@@ -475,12 +475,12 @@ const COMMANDS = [
|
|
|
475
475
|
category: 'setup',
|
|
476
476
|
description: 'Migrate all legacy projects',
|
|
477
477
|
usage: {
|
|
478
|
-
claude:
|
|
478
|
+
claude: '/p:migrate-all',
|
|
479
479
|
terminal: 'prjct migrate-all [--deep-scan] [--remove-legacy] [--dry-run]',
|
|
480
480
|
},
|
|
481
481
|
params: '[--deep-scan] [--remove-legacy] [--dry-run]',
|
|
482
482
|
implemented: true,
|
|
483
|
-
hasTemplate:
|
|
483
|
+
hasTemplate: true,
|
|
484
484
|
icon: 'Database',
|
|
485
485
|
requiresInit: false,
|
|
486
486
|
blockingRules: null,
|
package/core/commands.js
CHANGED
|
@@ -2593,7 +2593,26 @@ Agent: ${agent}
|
|
|
2593
2593
|
result.errors.forEach((e) => console.log(` - ${e.file}: ${e.error}`))
|
|
2594
2594
|
}
|
|
2595
2595
|
|
|
2596
|
-
|
|
2596
|
+
// Install global configuration
|
|
2597
|
+
console.log('\n📝 Installing global configuration...')
|
|
2598
|
+
const configResult = await commandInstaller.installGlobalConfig()
|
|
2599
|
+
|
|
2600
|
+
if (configResult.success) {
|
|
2601
|
+
if (configResult.action === 'created') {
|
|
2602
|
+
console.log('✅ Created ~/.claude/CLAUDE.md')
|
|
2603
|
+
} else if (configResult.action === 'updated') {
|
|
2604
|
+
console.log('✅ Updated ~/.claude/CLAUDE.md')
|
|
2605
|
+
} else if (configResult.action === 'appended') {
|
|
2606
|
+
console.log('✅ Added prjct config to ~/.claude/CLAUDE.md')
|
|
2607
|
+
}
|
|
2608
|
+
} else {
|
|
2609
|
+
console.log(`⚠️ ${configResult.error}`)
|
|
2610
|
+
}
|
|
2611
|
+
|
|
2612
|
+
console.log('\n🎉 Setup complete!\n')
|
|
2613
|
+
|
|
2614
|
+
// Show beautiful ASCII art
|
|
2615
|
+
this.showAsciiArt()
|
|
2597
2616
|
|
|
2598
2617
|
return {
|
|
2599
2618
|
success: true,
|
|
@@ -2601,6 +2620,50 @@ Agent: ${agent}
|
|
|
2601
2620
|
}
|
|
2602
2621
|
}
|
|
2603
2622
|
|
|
2623
|
+
/**
|
|
2624
|
+
* Show beautiful ASCII art with quick start
|
|
2625
|
+
*/
|
|
2626
|
+
showAsciiArt() {
|
|
2627
|
+
const chalk = require('chalk')
|
|
2628
|
+
|
|
2629
|
+
console.log(chalk.cyan('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))
|
|
2630
|
+
console.log('')
|
|
2631
|
+
console.log(chalk.bold.cyan(' ██████╗ ██████╗ ██╗ ██████╗████████╗'))
|
|
2632
|
+
console.log(chalk.bold.cyan(' ██╔══██╗██╔══██╗ ██║██╔════╝╚══██╔══╝'))
|
|
2633
|
+
console.log(chalk.bold.cyan(' ██████╔╝██████╔╝ ██║██║ ██║'))
|
|
2634
|
+
console.log(chalk.bold.cyan(' ██╔═══╝ ██╔══██╗██ ██║██║ ██║'))
|
|
2635
|
+
console.log(chalk.bold.cyan(' ██║ ██║ ██║╚█████╔╝╚██████╗ ██║'))
|
|
2636
|
+
console.log(chalk.bold.cyan(' ╚═╝ ╚═╝ ╚═╝ ╚════╝ ╚═════╝ ╚═╝'))
|
|
2637
|
+
console.log('')
|
|
2638
|
+
console.log(` ${chalk.bold.cyan('prjct')}${chalk.magenta('/')}${chalk.green('cli')} ${chalk.dim.white('v' + VERSION + ' installed')}`)
|
|
2639
|
+
console.log('')
|
|
2640
|
+
console.log(` ${chalk.yellow('⚡')} Ship faster with zero friction`)
|
|
2641
|
+
console.log(` ${chalk.green('📝')} From idea to technical tasks in minutes`)
|
|
2642
|
+
console.log(` ${chalk.cyan('🤖')} Perfect context for AI agents`)
|
|
2643
|
+
console.log('')
|
|
2644
|
+
console.log(chalk.cyan('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))
|
|
2645
|
+
console.log('')
|
|
2646
|
+
console.log(chalk.bold.cyan('🚀 Quick Start'))
|
|
2647
|
+
console.log(chalk.dim('─────────────────────────────────────────────────'))
|
|
2648
|
+
console.log('')
|
|
2649
|
+
console.log(` ${chalk.bold('1.')} Initialize your project:`)
|
|
2650
|
+
console.log(` ${chalk.green('cd your-project && prjct init')}`)
|
|
2651
|
+
console.log('')
|
|
2652
|
+
console.log(` ${chalk.bold('2.')} Set your current focus:`)
|
|
2653
|
+
console.log(` ${chalk.green('prjct now "build auth"')}`)
|
|
2654
|
+
console.log('')
|
|
2655
|
+
console.log(` ${chalk.bold('3.')} Ship & celebrate:`)
|
|
2656
|
+
console.log(` ${chalk.green('prjct ship "user login"')}`)
|
|
2657
|
+
console.log('')
|
|
2658
|
+
console.log(chalk.dim('─────────────────────────────────────────────────'))
|
|
2659
|
+
console.log('')
|
|
2660
|
+
console.log(` ${chalk.dim('Documentation:')} ${chalk.cyan('https://prjct.app')}`)
|
|
2661
|
+
console.log(` ${chalk.dim('Report issues:')} ${chalk.cyan('https://github.com/jlopezlira/prjct-cli/issues')}`)
|
|
2662
|
+
console.log('')
|
|
2663
|
+
console.log(chalk.bold.magenta('Happy shipping! 🚀'))
|
|
2664
|
+
console.log('')
|
|
2665
|
+
}
|
|
2666
|
+
|
|
2604
2667
|
/**
|
|
2605
2668
|
* Migrate all legacy projects
|
|
2606
2669
|
*/
|
|
@@ -210,10 +210,9 @@ class CommandInstaller {
|
|
|
210
210
|
|
|
211
211
|
/**
|
|
212
212
|
* Install to all detected editors (alias for installCommands)
|
|
213
|
-
* @param {boolean} interactive - Whether to show interactive prompts
|
|
214
213
|
* @returns {Promise<Object>} Installation results
|
|
215
214
|
*/
|
|
216
|
-
async installToAll(
|
|
215
|
+
async installToAll() {
|
|
217
216
|
return await this.installCommands()
|
|
218
217
|
}
|
|
219
218
|
|
|
@@ -239,6 +238,201 @@ class CommandInstaller {
|
|
|
239
238
|
return false
|
|
240
239
|
}
|
|
241
240
|
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Sync commands - intelligent update that detects and removes orphans
|
|
244
|
+
* @returns {Promise<Object>} Sync results with added, updated, removed counts
|
|
245
|
+
*/
|
|
246
|
+
async syncCommands() {
|
|
247
|
+
const claudeDetected = await this.detectClaude()
|
|
248
|
+
|
|
249
|
+
if (!claudeDetected) {
|
|
250
|
+
return {
|
|
251
|
+
success: false,
|
|
252
|
+
error: 'Claude not detected',
|
|
253
|
+
added: 0,
|
|
254
|
+
updated: 0,
|
|
255
|
+
removed: 0,
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
try {
|
|
260
|
+
// Ensure commands directory exists
|
|
261
|
+
await fs.mkdir(this.claudeCommandsPath, { recursive: true })
|
|
262
|
+
|
|
263
|
+
// Get current state
|
|
264
|
+
const templateFiles = await this.getCommandFiles()
|
|
265
|
+
let installedFiles = []
|
|
266
|
+
|
|
267
|
+
try {
|
|
268
|
+
installedFiles = await fs.readdir(this.claudeCommandsPath)
|
|
269
|
+
installedFiles = installedFiles.filter((f) => f.endsWith('.md'))
|
|
270
|
+
} catch {
|
|
271
|
+
// Directory doesn't exist yet
|
|
272
|
+
installedFiles = []
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const results = {
|
|
276
|
+
success: true,
|
|
277
|
+
added: 0,
|
|
278
|
+
updated: 0,
|
|
279
|
+
removed: 0,
|
|
280
|
+
errors: [],
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Detect new and updated files
|
|
284
|
+
for (const file of templateFiles) {
|
|
285
|
+
try {
|
|
286
|
+
const sourcePath = path.join(this.templatesDir, file)
|
|
287
|
+
const destPath = path.join(this.claudeCommandsPath, file)
|
|
288
|
+
|
|
289
|
+
// Check if file exists in installed location
|
|
290
|
+
const exists = installedFiles.includes(file)
|
|
291
|
+
|
|
292
|
+
if (!exists) {
|
|
293
|
+
// New file
|
|
294
|
+
const content = await fs.readFile(sourcePath, 'utf-8')
|
|
295
|
+
await fs.writeFile(destPath, content, 'utf-8')
|
|
296
|
+
results.added++
|
|
297
|
+
} else {
|
|
298
|
+
// Check if updated (compare modification time or content)
|
|
299
|
+
const sourceStats = await fs.stat(sourcePath)
|
|
300
|
+
const destStats = await fs.stat(destPath)
|
|
301
|
+
|
|
302
|
+
if (sourceStats.mtime > destStats.mtime) {
|
|
303
|
+
// Updated file
|
|
304
|
+
const content = await fs.readFile(sourcePath, 'utf-8')
|
|
305
|
+
await fs.writeFile(destPath, content, 'utf-8')
|
|
306
|
+
results.updated++
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
} catch (error) {
|
|
310
|
+
results.errors.push({ file, error: error.message })
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Detect and remove orphaned files
|
|
315
|
+
const orphans = installedFiles.filter((file) => !templateFiles.includes(file))
|
|
316
|
+
|
|
317
|
+
for (const orphan of orphans) {
|
|
318
|
+
try {
|
|
319
|
+
const orphanPath = path.join(this.claudeCommandsPath, orphan)
|
|
320
|
+
await fs.unlink(orphanPath)
|
|
321
|
+
results.removed++
|
|
322
|
+
} catch (error) {
|
|
323
|
+
results.errors.push({ file: orphan, error: error.message })
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return results
|
|
328
|
+
} catch (error) {
|
|
329
|
+
return {
|
|
330
|
+
success: false,
|
|
331
|
+
error: error.message,
|
|
332
|
+
added: 0,
|
|
333
|
+
updated: 0,
|
|
334
|
+
removed: 0,
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Install or update global CLAUDE.md configuration
|
|
341
|
+
* @returns {Promise<Object>} Result with success status and action taken
|
|
342
|
+
*/
|
|
343
|
+
async installGlobalConfig() {
|
|
344
|
+
const claudeDetected = await this.detectClaude()
|
|
345
|
+
|
|
346
|
+
if (!claudeDetected) {
|
|
347
|
+
return {
|
|
348
|
+
success: false,
|
|
349
|
+
error: 'Claude not detected',
|
|
350
|
+
action: 'skipped',
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
try {
|
|
355
|
+
// Ensure ~/.claude directory exists
|
|
356
|
+
const claudeDir = path.join(require('os').homedir(), '.claude')
|
|
357
|
+
await fs.mkdir(claudeDir, { recursive: true })
|
|
358
|
+
|
|
359
|
+
const globalConfigPath = path.join(claudeDir, 'CLAUDE.md')
|
|
360
|
+
const templatePath = path.join(__dirname, '../../templates/global/CLAUDE.md')
|
|
361
|
+
|
|
362
|
+
// Read template content
|
|
363
|
+
const templateContent = await fs.readFile(templatePath, 'utf-8')
|
|
364
|
+
|
|
365
|
+
// Check if global config already exists
|
|
366
|
+
let existingContent = ''
|
|
367
|
+
let fileExists = false
|
|
368
|
+
|
|
369
|
+
try {
|
|
370
|
+
existingContent = await fs.readFile(globalConfigPath, 'utf-8')
|
|
371
|
+
fileExists = true
|
|
372
|
+
} catch {
|
|
373
|
+
// File doesn't exist, will create new
|
|
374
|
+
fileExists = false
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
if (!fileExists) {
|
|
378
|
+
// Create new file with full template
|
|
379
|
+
await fs.writeFile(globalConfigPath, templateContent, 'utf-8')
|
|
380
|
+
return {
|
|
381
|
+
success: true,
|
|
382
|
+
action: 'created',
|
|
383
|
+
path: globalConfigPath,
|
|
384
|
+
}
|
|
385
|
+
} else {
|
|
386
|
+
// File exists - perform intelligent merge
|
|
387
|
+
const startMarker = '<!-- prjct:start - DO NOT REMOVE THIS MARKER -->'
|
|
388
|
+
const endMarker = '<!-- prjct:end - DO NOT REMOVE THIS MARKER -->'
|
|
389
|
+
|
|
390
|
+
// Check if markers exist in existing file
|
|
391
|
+
const hasMarkers =
|
|
392
|
+
existingContent.includes(startMarker) && existingContent.includes(endMarker)
|
|
393
|
+
|
|
394
|
+
if (!hasMarkers) {
|
|
395
|
+
// No markers - append prjct section at the end
|
|
396
|
+
const updatedContent = existingContent + '\n\n' + templateContent
|
|
397
|
+
await fs.writeFile(globalConfigPath, updatedContent, 'utf-8')
|
|
398
|
+
return {
|
|
399
|
+
success: true,
|
|
400
|
+
action: 'appended',
|
|
401
|
+
path: globalConfigPath,
|
|
402
|
+
}
|
|
403
|
+
} else {
|
|
404
|
+
// Markers exist - replace content between markers
|
|
405
|
+
const beforeMarker = existingContent.substring(
|
|
406
|
+
0,
|
|
407
|
+
existingContent.indexOf(startMarker)
|
|
408
|
+
)
|
|
409
|
+
const afterMarker = existingContent.substring(
|
|
410
|
+
existingContent.indexOf(endMarker) + endMarker.length
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
// Extract prjct section from template
|
|
414
|
+
const prjctSection = templateContent.substring(
|
|
415
|
+
templateContent.indexOf(startMarker),
|
|
416
|
+
templateContent.indexOf(endMarker) + endMarker.length
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
const updatedContent = beforeMarker + prjctSection + afterMarker
|
|
420
|
+
await fs.writeFile(globalConfigPath, updatedContent, 'utf-8')
|
|
421
|
+
return {
|
|
422
|
+
success: true,
|
|
423
|
+
action: 'updated',
|
|
424
|
+
path: globalConfigPath,
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
} catch (error) {
|
|
429
|
+
return {
|
|
430
|
+
success: false,
|
|
431
|
+
error: error.message,
|
|
432
|
+
action: 'failed',
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
242
436
|
}
|
|
243
437
|
|
|
244
438
|
module.exports = new CommandInstaller()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prjct-cli",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "Built for Claude - Ship fast, track progress, stay focused. Developer momentum tool for indie hackers.",
|
|
5
5
|
"main": "core/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
"registry": "https://registry.npmjs.org"
|
|
12
12
|
},
|
|
13
13
|
"scripts": {
|
|
14
|
+
"postinstall": "node scripts/postinstall.js",
|
|
15
|
+
"update-commands": "node -e \"const installer = require('./core/infrastructure/command-installer'); const i = new installer(); i.syncCommands().then(r => console.log('Commands updated:', r))\"",
|
|
14
16
|
"install-global": "./scripts/install.sh",
|
|
15
17
|
"update": "./scripts/update.sh",
|
|
16
18
|
"test": "vitest run --workspace=vitest.workspace.js",
|
|
@@ -74,6 +76,7 @@
|
|
|
74
76
|
"bin/",
|
|
75
77
|
"core/",
|
|
76
78
|
"templates/",
|
|
79
|
+
"scripts/postinstall.js",
|
|
77
80
|
"scripts/install.sh",
|
|
78
81
|
"LICENSE",
|
|
79
82
|
"README.md",
|
package/scripts/install.sh
CHANGED
|
@@ -1,13 +1,37 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
|
|
8
|
-
#
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
# ⚠️ DEPRECATED: This installation method is deprecated
|
|
4
|
+
# Use npm instead: npm install -g prjct-cli
|
|
5
|
+
#
|
|
6
|
+
# This script is kept for backward compatibility only.
|
|
7
|
+
|
|
8
|
+
# Colors
|
|
9
|
+
YELLOW='\033[1;33m'
|
|
10
|
+
CYAN='\033[0;36m'
|
|
11
|
+
GREEN='\033[0;32m'
|
|
12
|
+
NC='\033[0m'
|
|
13
|
+
|
|
14
|
+
echo ""
|
|
15
|
+
echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
16
|
+
echo -e "${YELLOW}⚠️ This installation method is DEPRECATED${NC}"
|
|
17
|
+
echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
18
|
+
echo ""
|
|
19
|
+
echo -e "Please use npm instead:"
|
|
20
|
+
echo ""
|
|
21
|
+
echo -e " ${GREEN}npm install -g prjct-cli${NC}"
|
|
22
|
+
echo ""
|
|
23
|
+
echo -e "Benefits of npm installation:"
|
|
24
|
+
echo -e " • ${CYAN}Automatic setup${NC} - No manual configuration needed"
|
|
25
|
+
echo -e " • ${CYAN}Auto-migration${NC} - Legacy projects migrated automatically"
|
|
26
|
+
echo -e " • ${CYAN}Beautiful ASCII art${NC} - See the installation success"
|
|
27
|
+
echo -e " • ${CYAN}Easy updates${NC} - Just npm update -g prjct-cli"
|
|
28
|
+
echo ""
|
|
29
|
+
echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
30
|
+
echo ""
|
|
31
|
+
exit 1
|
|
32
|
+
|
|
33
|
+
# Original install.sh preserved below (not executed)
|
|
34
|
+
# ------------------------------------------------
|
|
11
35
|
|
|
12
36
|
set -e
|
|
13
37
|
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Post-install hook for prjct-cli
|
|
5
|
+
*
|
|
6
|
+
* Runs automatically after npm install -g prjct-cli
|
|
7
|
+
*
|
|
8
|
+
* 1. Detects if global install
|
|
9
|
+
* 2. Installs/syncs commands to ~/.claude/commands/p/
|
|
10
|
+
* 3. Installs/updates global config to ~/.claude/CLAUDE.md
|
|
11
|
+
* 4. Shows beautiful ASCII art
|
|
12
|
+
*
|
|
13
|
+
* NOTE: Migration is now manual via /p:migrate-all or prjct migrate-all
|
|
14
|
+
*
|
|
15
|
+
* @version 0.8.2
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const path = require('path')
|
|
19
|
+
const installer = require('../core/infrastructure/command-installer')
|
|
20
|
+
const { VERSION } = require('../core/utils/version')
|
|
21
|
+
|
|
22
|
+
// Colors for terminal output
|
|
23
|
+
const CYAN = '\x1b[36m'
|
|
24
|
+
const GREEN = '\x1b[32m'
|
|
25
|
+
const YELLOW = '\x1b[33m'
|
|
26
|
+
const MAGENTA = '\x1b[35m'
|
|
27
|
+
const WHITE = '\x1b[37m'
|
|
28
|
+
const BOLD = '\x1b[1m'
|
|
29
|
+
const DIM = '\x1b[2m'
|
|
30
|
+
const NC = '\x1b[0m' // No Color
|
|
31
|
+
|
|
32
|
+
async function main() {
|
|
33
|
+
try {
|
|
34
|
+
// Detect if this is a global install
|
|
35
|
+
const isGlobal = await detectGlobalInstall()
|
|
36
|
+
|
|
37
|
+
if (!isGlobal) {
|
|
38
|
+
// Skip postinstall for local development installs
|
|
39
|
+
console.log(`${DIM}Skipping post-install (local development)${NC}`)
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.log('')
|
|
44
|
+
console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`)
|
|
45
|
+
console.log(`${BOLD}${CYAN}🚀 Setting up prjct-cli...${NC}`)
|
|
46
|
+
console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`)
|
|
47
|
+
console.log('')
|
|
48
|
+
|
|
49
|
+
// Step 1: Detect Claude Code
|
|
50
|
+
console.log(`${BOLD}[1/3]${NC} Detecting Claude Code...`)
|
|
51
|
+
const claudeDetected = await installer.detectClaude()
|
|
52
|
+
|
|
53
|
+
if (!claudeDetected) {
|
|
54
|
+
console.log(`${YELLOW}⚠️ Claude Code not detected${NC}`)
|
|
55
|
+
console.log(`${DIM}Install Claude Code from: https://claude.ai/code${NC}`)
|
|
56
|
+
console.log(`${DIM}Then run: prjct setup${NC}`)
|
|
57
|
+
console.log('')
|
|
58
|
+
} else {
|
|
59
|
+
console.log(`${GREEN}✓${NC} Claude Code found`)
|
|
60
|
+
console.log('')
|
|
61
|
+
|
|
62
|
+
// Step 2: Install/sync commands
|
|
63
|
+
console.log(`${BOLD}[2/3]${NC} Installing commands to ~/.claude...`)
|
|
64
|
+
const syncResult = await installer.syncCommands()
|
|
65
|
+
|
|
66
|
+
if (syncResult.success) {
|
|
67
|
+
const { added, updated, removed } = syncResult
|
|
68
|
+
const changes = []
|
|
69
|
+
if (added > 0) changes.push(`${added} nuevos`)
|
|
70
|
+
if (updated > 0) changes.push(`${updated} actualizados`)
|
|
71
|
+
if (removed > 0) changes.push(`${removed} eliminados`)
|
|
72
|
+
|
|
73
|
+
if (changes.length > 0) {
|
|
74
|
+
console.log(`${GREEN}✓${NC} ${changes.join(', ')}`)
|
|
75
|
+
} else {
|
|
76
|
+
console.log(`${GREEN}✓${NC} All commands up to date`)
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
console.log(`${YELLOW}⚠️ ${syncResult.error}${NC}`)
|
|
80
|
+
}
|
|
81
|
+
console.log('')
|
|
82
|
+
|
|
83
|
+
// Step 3: Install global configuration
|
|
84
|
+
console.log(`${BOLD}[3/3]${NC} Installing global configuration...`)
|
|
85
|
+
const configResult = await installer.installGlobalConfig()
|
|
86
|
+
|
|
87
|
+
if (configResult.success) {
|
|
88
|
+
if (configResult.action === 'created') {
|
|
89
|
+
console.log(`${GREEN}✓${NC} Created ~/.claude/CLAUDE.md`)
|
|
90
|
+
} else if (configResult.action === 'updated') {
|
|
91
|
+
console.log(`${GREEN}✓${NC} Updated ~/.claude/CLAUDE.md`)
|
|
92
|
+
} else if (configResult.action === 'appended') {
|
|
93
|
+
console.log(`${GREEN}✓${NC} Added prjct config to ~/.claude/CLAUDE.md`)
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
console.log(`${YELLOW}⚠️ ${configResult.error}${NC}`)
|
|
97
|
+
}
|
|
98
|
+
console.log('')
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Show ASCII art and quick start
|
|
102
|
+
showAsciiArt()
|
|
103
|
+
|
|
104
|
+
} catch (error) {
|
|
105
|
+
console.error(`${YELLOW}⚠️ Post-install error: ${error.message}${NC}`)
|
|
106
|
+
console.error(`${DIM}You can run 'prjct setup' manually later${NC}`)
|
|
107
|
+
// Don't fail the install if post-install has issues
|
|
108
|
+
process.exit(0)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Detect if this is a global npm install
|
|
114
|
+
*/
|
|
115
|
+
async function detectGlobalInstall() {
|
|
116
|
+
// Check if we're being installed globally
|
|
117
|
+
const npmConfig = process.env.npm_config_global
|
|
118
|
+
if (npmConfig === 'true') {
|
|
119
|
+
return true
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Check if install location is in global node_modules
|
|
123
|
+
const installPath = __dirname
|
|
124
|
+
const globalPaths = [
|
|
125
|
+
'/usr/local/lib/node_modules',
|
|
126
|
+
'/usr/lib/node_modules',
|
|
127
|
+
path.join(process.env.HOME || '', '.npm-global', 'lib', 'node_modules'),
|
|
128
|
+
path.join(process.env.HOME || '', '.nvm'),
|
|
129
|
+
path.join(process.env.APPDATA || '', 'npm', 'node_modules')
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
return globalPaths.some(globalPath => installPath.includes(globalPath))
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Show beautiful ASCII art with quick start
|
|
137
|
+
*/
|
|
138
|
+
function showAsciiArt() {
|
|
139
|
+
console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`)
|
|
140
|
+
console.log('')
|
|
141
|
+
console.log(` ${BOLD}${CYAN}██████╗ ██████╗ ██╗ ██████╗████████╗${NC}`)
|
|
142
|
+
console.log(` ${BOLD}${CYAN}██╔══██╗██╔══██╗ ██║██╔════╝╚══██╔══╝${NC}`)
|
|
143
|
+
console.log(` ${BOLD}${CYAN}██████╔╝██████╔╝ ██║██║ ██║${NC}`)
|
|
144
|
+
console.log(` ${BOLD}${CYAN}██╔═══╝ ██╔══██╗██ ██║██║ ██║${NC}`)
|
|
145
|
+
console.log(` ${BOLD}${CYAN}██║ ██║ ██║╚█████╔╝╚██████╗ ██║${NC}`)
|
|
146
|
+
console.log(` ${BOLD}${CYAN}╚═╝ ╚═╝ ╚═╝ ╚════╝ ╚═════╝ ╚═╝${NC}`)
|
|
147
|
+
console.log('')
|
|
148
|
+
console.log(` ${BOLD}${CYAN}prjct${NC}${MAGENTA}/${NC}${GREEN}cli${NC} ${DIM}${WHITE}v${VERSION} installed${NC}`)
|
|
149
|
+
console.log('')
|
|
150
|
+
console.log(` ${YELLOW}⚡${NC} Ship faster with zero friction`)
|
|
151
|
+
console.log(` ${GREEN}📝${NC} From idea to technical tasks in minutes`)
|
|
152
|
+
console.log(` ${CYAN}🤖${NC} Perfect context for AI agents`)
|
|
153
|
+
console.log('')
|
|
154
|
+
console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`)
|
|
155
|
+
console.log('')
|
|
156
|
+
console.log(`${BOLD}${CYAN}🚀 Quick Start${NC}`)
|
|
157
|
+
console.log(`${DIM}─────────────────────────────────────────────────${NC}`)
|
|
158
|
+
console.log('')
|
|
159
|
+
console.log(` ${BOLD}1.${NC} Initialize your project:`)
|
|
160
|
+
console.log(` ${GREEN}cd your-project && prjct init${NC}`)
|
|
161
|
+
console.log('')
|
|
162
|
+
console.log(` ${BOLD}2.${NC} Set your current focus:`)
|
|
163
|
+
console.log(` ${GREEN}prjct now "build auth"${NC}`)
|
|
164
|
+
console.log('')
|
|
165
|
+
console.log(` ${BOLD}3.${NC} Ship & celebrate:`)
|
|
166
|
+
console.log(` ${GREEN}prjct ship "user login"${NC}`)
|
|
167
|
+
console.log('')
|
|
168
|
+
console.log(`${DIM}─────────────────────────────────────────────────${NC}`)
|
|
169
|
+
console.log('')
|
|
170
|
+
console.log(` ${DIM}Documentation:${NC} ${CYAN}https://prjct.app${NC}`)
|
|
171
|
+
console.log(` ${DIM}Report issues:${NC} ${CYAN}https://github.com/jlopezlira/prjct-cli/issues${NC}`)
|
|
172
|
+
console.log('')
|
|
173
|
+
console.log(`${BOLD}${MAGENTA}Happy shipping! 🚀${NC}`)
|
|
174
|
+
console.log('')
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Run if executed directly
|
|
178
|
+
if (require.main === module) {
|
|
179
|
+
main().catch(error => {
|
|
180
|
+
console.error('Fatal error:', error.message)
|
|
181
|
+
process.exit(0) // Don't fail npm install
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
module.exports = main
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# /p:migrate-all - Migrate All Legacy Projects
|
|
2
|
+
|
|
3
|
+
Migrates all legacy prjct projects to the new global storage architecture.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/p:migrate-all [--deep-scan] [--remove-legacy] [--dry-run]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## What This Command Does
|
|
12
|
+
|
|
13
|
+
1. **Scans Global Storage**
|
|
14
|
+
- Reads all project IDs from `~/.prjct-cli/projects/`
|
|
15
|
+
- Retrieves project paths from `project.json` files
|
|
16
|
+
|
|
17
|
+
2. **Detects Legacy Structure**
|
|
18
|
+
- Checks each project for old `.prjct/` directory structure
|
|
19
|
+
- Identifies projects that need migration
|
|
20
|
+
|
|
21
|
+
3. **Migrates Each Project**
|
|
22
|
+
- Moves data from local `.prjct/` to global `~/.prjct-cli/projects/{id}/`
|
|
23
|
+
- Creates new minimal local config (`.prjct/prjct.config.json`)
|
|
24
|
+
- Preserves all project data and history
|
|
25
|
+
|
|
26
|
+
4. **Cleanup (Optional)**
|
|
27
|
+
- Removes legacy `.prjct/` directories (with `--remove-legacy`)
|
|
28
|
+
- Keeps only the new minimal config file
|
|
29
|
+
|
|
30
|
+
5. **Reports Summary**
|
|
31
|
+
- Shows migrated, skipped, and failed projects
|
|
32
|
+
- Lists detailed errors for any failures
|
|
33
|
+
|
|
34
|
+
## Options
|
|
35
|
+
|
|
36
|
+
- `--deep-scan`: Scan entire file system (slow but thorough)
|
|
37
|
+
- `--remove-legacy`: Delete old `.prjct/` directories after successful migration
|
|
38
|
+
- `--dry-run`: Show what would be migrated without making changes
|
|
39
|
+
|
|
40
|
+
## When to Use
|
|
41
|
+
|
|
42
|
+
- **After major version updates**: When architecture changes
|
|
43
|
+
- **Upgrading from v0.7.x to v0.8.x**: New global storage system
|
|
44
|
+
- **Consolidating projects**: Moving all projects to global storage
|
|
45
|
+
- **Troubleshooting**: If projects aren't working after update
|
|
46
|
+
|
|
47
|
+
## Migration Process
|
|
48
|
+
|
|
49
|
+
### Before (Legacy Structure)
|
|
50
|
+
```
|
|
51
|
+
your-project/
|
|
52
|
+
.prjct/
|
|
53
|
+
core/
|
|
54
|
+
planning/
|
|
55
|
+
progress/
|
|
56
|
+
memory/
|
|
57
|
+
analysis/
|
|
58
|
+
prjct.config.json # Full config
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### After (Global Storage)
|
|
62
|
+
```
|
|
63
|
+
your-project/
|
|
64
|
+
.prjct/
|
|
65
|
+
prjct.config.json # Minimal (projectId + dataPath only)
|
|
66
|
+
|
|
67
|
+
~/.prjct-cli/projects/3a5667a5dedb/
|
|
68
|
+
core/
|
|
69
|
+
planning/
|
|
70
|
+
progress/
|
|
71
|
+
memory/
|
|
72
|
+
analysis/
|
|
73
|
+
agents/
|
|
74
|
+
project.json # System config (authors, version, etc.)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Output Example
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
🔄 Scanning for legacy prjct projects...
|
|
81
|
+
|
|
82
|
+
📁 Found 3 projects in global storage
|
|
83
|
+
|
|
84
|
+
🔄 Migrating: /Users/jj/Apps/my-app
|
|
85
|
+
✅ Migrated successfully
|
|
86
|
+
|
|
87
|
+
🔄 Migrating: /Users/jj/Apps/other-project
|
|
88
|
+
⏭️ Already migrated
|
|
89
|
+
|
|
90
|
+
📊 Migration Summary:
|
|
91
|
+
✅ Migrated: 1
|
|
92
|
+
⏭️ Skipped: 1
|
|
93
|
+
❌ Failed: 0
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Error Handling
|
|
97
|
+
|
|
98
|
+
- **No global storage**: Creates directory structure
|
|
99
|
+
- **Missing project paths**: Skips projects with invalid paths
|
|
100
|
+
- **Permission errors**: Reports which projects couldn't be migrated
|
|
101
|
+
- **Already migrated**: Safely skips without changes
|
|
102
|
+
|
|
103
|
+
## Safety
|
|
104
|
+
|
|
105
|
+
- **Idempotent**: Safe to run multiple times
|
|
106
|
+
- **Non-destructive**: Original files only removed with `--remove-legacy`
|
|
107
|
+
- **Dry run available**: Test migration with `--dry-run` first
|
|
108
|
+
- **Automatic backup**: Legacy data preserved until explicitly removed
|
|
109
|
+
|
|
110
|
+
## Requirements
|
|
111
|
+
|
|
112
|
+
- Write permissions to `~/.prjct-cli/` and project directories
|
|
113
|
+
- Projects must have valid global config in `project.json`
|
|
114
|
+
|
|
115
|
+
## Notes
|
|
116
|
+
|
|
117
|
+
- This command does NOT require an initialized prjct project
|
|
118
|
+
- Migration is automatic on install (but manual execution is safer)
|
|
119
|
+
- Always test with `--dry-run` first for large migrations
|
|
120
|
+
- Can be safely interrupted and resumed
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# /p:setup - Reconfigure prjct-cli Installation
|
|
2
|
+
|
|
3
|
+
Reconfigures prjct-cli installation for Claude Code and Claude Desktop.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/p:setup [--force]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## What This Command Does
|
|
12
|
+
|
|
13
|
+
1. **Detects Claude Installation**
|
|
14
|
+
- Checks if `~/.claude/` directory exists
|
|
15
|
+
- Verifies Claude Code or Claude Desktop is installed
|
|
16
|
+
|
|
17
|
+
2. **Syncs Commands to Claude**
|
|
18
|
+
- Updates all `/p:*` commands in `~/.claude/commands/p/`
|
|
19
|
+
- Adds new commands from latest version
|
|
20
|
+
- Updates existing commands with latest templates
|
|
21
|
+
- Removes orphaned/deprecated commands
|
|
22
|
+
|
|
23
|
+
3. **Installs/Updates Global Configuration**
|
|
24
|
+
- Creates or updates `~/.claude/CLAUDE.md`
|
|
25
|
+
- Adds prjct-specific instructions for Claude
|
|
26
|
+
- Preserves existing user configuration
|
|
27
|
+
|
|
28
|
+
4. **Reports Results**
|
|
29
|
+
- Shows commands added, updated, removed
|
|
30
|
+
- Displays any errors encountered
|
|
31
|
+
- Confirms successful installation
|
|
32
|
+
|
|
33
|
+
## Options
|
|
34
|
+
|
|
35
|
+
- `--force`: Remove existing installation and reinstall from scratch
|
|
36
|
+
|
|
37
|
+
## When to Use
|
|
38
|
+
|
|
39
|
+
- **After updating prjct-cli**: `npm update -g prjct-cli && /p:setup`
|
|
40
|
+
- **Commands not working**: If `/p:*` commands aren't recognized
|
|
41
|
+
- **Fresh installation**: After installing on a new machine
|
|
42
|
+
- **Troubleshooting**: When encountering command-related issues
|
|
43
|
+
|
|
44
|
+
## Requirements
|
|
45
|
+
|
|
46
|
+
- Claude Code or Claude Desktop must be installed
|
|
47
|
+
- Write permissions to `~/.claude/` directory
|
|
48
|
+
|
|
49
|
+
## Output Example
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
🔧 Reconfiguring prjct...
|
|
53
|
+
|
|
54
|
+
📦 Installing /p:* commands...
|
|
55
|
+
✓ 3 nuevos, 12 actualizados, 1 eliminado
|
|
56
|
+
|
|
57
|
+
📝 Installing global configuration...
|
|
58
|
+
✓ Updated ~/.claude/CLAUDE.md
|
|
59
|
+
|
|
60
|
+
✅ Setup complete!
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Error Handling
|
|
64
|
+
|
|
65
|
+
- **Claude not detected**: Shows installation URLs for Claude Code/Desktop
|
|
66
|
+
- **Permission errors**: Reports which files couldn't be written
|
|
67
|
+
- **Template errors**: Lists which commands failed to install
|
|
68
|
+
|
|
69
|
+
## Notes
|
|
70
|
+
|
|
71
|
+
- This command does NOT migrate projects (use `/p:migrate-all` for that)
|
|
72
|
+
- This command does NOT require an initialized prjct project
|
|
73
|
+
- Safe to run multiple times (idempotent)
|
|
74
|
+
- Will not overwrite user customizations in `~/.claude/CLAUDE.md`
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
<!-- prjct:start - DO NOT REMOVE THIS MARKER -->
|
|
2
|
+
# prjct Configuration
|
|
3
|
+
|
|
4
|
+
This section provides global context for all `/p:*` commands across any prjct project.
|
|
5
|
+
|
|
6
|
+
**Auto-managed by prjct-cli** - This section is automatically updated when you install or update prjct.
|
|
7
|
+
|
|
8
|
+
## 🎯 Path Resolution for ALL /p:* Commands
|
|
9
|
+
|
|
10
|
+
**CRITICAL**: Every `/p:*` command operates on **global storage**, NOT local files.
|
|
11
|
+
|
|
12
|
+
### Resolution Steps:
|
|
13
|
+
|
|
14
|
+
1. **Detect prjct project**: Check if `.prjct/prjct.config.json` exists in current working directory
|
|
15
|
+
2. **Read config**: Extract `projectId` from `.prjct/prjct.config.json`
|
|
16
|
+
3. **Construct base path**: `~/.prjct-cli/projects/{projectId}/`
|
|
17
|
+
4. **Resolve all file operations**: All paths in command templates are relative to base path
|
|
18
|
+
|
|
19
|
+
### Examples:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
Template says: "Write: core/now.md"
|
|
23
|
+
Actual path: ~/.prjct-cli/projects/{projectId}/core/now.md
|
|
24
|
+
|
|
25
|
+
Template says: "Read: memory/context.jsonl"
|
|
26
|
+
Actual path: ~/.prjct-cli/projects/{projectId}/memory/context.jsonl
|
|
27
|
+
|
|
28
|
+
Template says: "Update: progress/shipped.md"
|
|
29
|
+
Actual path: ~/.prjct-cli/projects/{projectId}/progress/shipped.md
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Validation Rules:
|
|
33
|
+
|
|
34
|
+
- ❌ **NEVER** write to `.prjct/core/now.md` (local project directory)
|
|
35
|
+
- ❌ **NEVER** write to `./core/now.md` (current working directory)
|
|
36
|
+
- ✅ **ALWAYS** write to `~/.prjct-cli/projects/{projectId}/core/now.md` (global storage)
|
|
37
|
+
|
|
38
|
+
### When NOT in prjct Project:
|
|
39
|
+
|
|
40
|
+
If `.prjct/prjct.config.json` doesn't exist in current directory:
|
|
41
|
+
- Respond: "No prjct project detected. Initialize first with `/p:init`"
|
|
42
|
+
- Do NOT execute the command
|
|
43
|
+
- Do NOT create files
|
|
44
|
+
|
|
45
|
+
## 📁 File Structure
|
|
46
|
+
|
|
47
|
+
All prjct data lives in global storage with session-based architecture:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
~/.prjct-cli/projects/{projectId}/
|
|
51
|
+
├── core/ # Current focus (always small)
|
|
52
|
+
│ ├── now.md # Single current task
|
|
53
|
+
│ ├── next.md # Priority queue (max 100 tasks)
|
|
54
|
+
│ └── context.md # Project context summary
|
|
55
|
+
├── progress/ # Completed work
|
|
56
|
+
│ ├── shipped.md # Recent ships (last 30 days)
|
|
57
|
+
│ ├── metrics.md # Aggregated metrics
|
|
58
|
+
│ ├── sessions/ # Daily session logs (JSONL)
|
|
59
|
+
│ │ └── 2025-10/
|
|
60
|
+
│ │ └── 2025-10-05.jsonl
|
|
61
|
+
│ └── archive/ # Monthly archives
|
|
62
|
+
│ └── shipped-2025-10.md
|
|
63
|
+
├── planning/ # Future planning
|
|
64
|
+
│ ├── ideas.md # Active ideas (last 30 days)
|
|
65
|
+
│ ├── roadmap.md # Active roadmap (lightweight)
|
|
66
|
+
│ ├── sessions/ # Daily planning sessions (JSONL)
|
|
67
|
+
│ │ └── 2025-10/
|
|
68
|
+
│ │ └── 2025-10-05.jsonl
|
|
69
|
+
│ └── archive/ # Monthly archives
|
|
70
|
+
│ └── roadmap-2025-10.md
|
|
71
|
+
├── analysis/ # Technical analysis
|
|
72
|
+
│ └── repo-summary.md
|
|
73
|
+
├── memory/ # Decision history
|
|
74
|
+
│ ├── context.jsonl # Global decisions (append-only)
|
|
75
|
+
│ └── sessions/ # Daily context (structured)
|
|
76
|
+
│ └── 2025-10/
|
|
77
|
+
│ └── 2025-10-05.jsonl
|
|
78
|
+
└── agents/ # Dynamic AI agents
|
|
79
|
+
├── coordinator.md
|
|
80
|
+
├── ux.md
|
|
81
|
+
├── fe.md
|
|
82
|
+
├── be.md
|
|
83
|
+
├── qa.md
|
|
84
|
+
└── scribe.md
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Session Format (JSONL):
|
|
88
|
+
|
|
89
|
+
One JSON object per line, append-only:
|
|
90
|
+
|
|
91
|
+
```jsonl
|
|
92
|
+
{"ts":"2025-10-05T14:30:00Z","type":"feature_add","name":"auth","tasks":5,"impact":"high","effort":"6h"}
|
|
93
|
+
{"ts":"2025-10-05T15:00:00Z","type":"task_start","task":"JWT middleware","agent":"be","estimate":"2h"}
|
|
94
|
+
{"ts":"2025-10-05T17:15:00Z","type":"task_complete","task":"JWT middleware","duration":"2h15m"}
|
|
95
|
+
{"ts":"2025-10-05T18:00:00Z","type":"feature_ship","name":"auth","tasks_done":5,"total_time":"6h"}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## 🤖 Git Commit Format
|
|
99
|
+
|
|
100
|
+
**ALL commits made by prjct MUST use this footer:**
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
🤖 Generated with [p/](https://www.prjct.app/)
|
|
104
|
+
Designed for [Claude](https://www.anthropic.com/claude)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Never use:**
|
|
108
|
+
- ❌ "Generated with Claude Code"
|
|
109
|
+
- ❌ "Co-Authored-By: Claude"
|
|
110
|
+
|
|
111
|
+
**Always use:**
|
|
112
|
+
- ✅ The prjct footer format above
|
|
113
|
+
|
|
114
|
+
## 👤 Author Detection
|
|
115
|
+
|
|
116
|
+
All operations include author information. Detection order:
|
|
117
|
+
|
|
118
|
+
1. **GitHub CLI**: `gh api user` (preferred)
|
|
119
|
+
- Provides: name, email, username, avatarUrl
|
|
120
|
+
2. **Git Config**: Fallback if GitHub CLI not available
|
|
121
|
+
- `git config user.name`
|
|
122
|
+
- `git config user.email`
|
|
123
|
+
3. **Default**: If both fail
|
|
124
|
+
- name: "Unknown"
|
|
125
|
+
- email: "unknown@localhost"
|
|
126
|
+
|
|
127
|
+
Every log entry in `memory/context.jsonl` includes author field.
|
|
128
|
+
|
|
129
|
+
## ⚠️ Common Validation Patterns
|
|
130
|
+
|
|
131
|
+
### Before Executing /p:done:
|
|
132
|
+
```javascript
|
|
133
|
+
// Check if there's an active task
|
|
134
|
+
const nowContent = await Read('~/.prjct-cli/projects/{projectId}/core/now.md')
|
|
135
|
+
if (!nowContent || nowContent.trim() === '') {
|
|
136
|
+
return "Not working on anything. Use /p:now to start a task."
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Before Executing /p:ship:
|
|
141
|
+
```javascript
|
|
142
|
+
// Check if there's something to ship
|
|
143
|
+
const shippedContent = await Read('~/.prjct-cli/projects/{projectId}/progress/shipped.md')
|
|
144
|
+
const nowContent = await Read('~/.prjct-cli/projects/{projectId}/core/now.md')
|
|
145
|
+
if ((!nowContent || nowContent.trim() === '') &&
|
|
146
|
+
(!shippedContent || shippedContent.trim() === '')) {
|
|
147
|
+
return "Nothing to ship yet. Build something first with /p:now."
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Reading Project Config:
|
|
152
|
+
```javascript
|
|
153
|
+
// Always read config first
|
|
154
|
+
const configPath = '.prjct/prjct.config.json'
|
|
155
|
+
const configContent = await Read(configPath)
|
|
156
|
+
const config = JSON.parse(configContent)
|
|
157
|
+
const projectId = config.projectId
|
|
158
|
+
const basePath = `~/.prjct-cli/projects/${projectId}/`
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## 🔧 Error Handling
|
|
162
|
+
|
|
163
|
+
### File Not Found:
|
|
164
|
+
- If `core/now.md` doesn't exist when reading → return empty state
|
|
165
|
+
- If `core/next.md` doesn't exist → return "No tasks in queue"
|
|
166
|
+
- Always check file existence before operations
|
|
167
|
+
|
|
168
|
+
### Invalid JSON:
|
|
169
|
+
- If config file is corrupted → suggest running `/p:init` again
|
|
170
|
+
- Log error to `memory/context.jsonl` for debugging
|
|
171
|
+
|
|
172
|
+
### Permission Issues:
|
|
173
|
+
- If can't write to `~/.prjct-cli/` → check directory permissions
|
|
174
|
+
- Suggest: `chmod -R u+w ~/.prjct-cli/`
|
|
175
|
+
|
|
176
|
+
## 📊 Performance Guidelines
|
|
177
|
+
|
|
178
|
+
### Archive Rules:
|
|
179
|
+
- Index files (roadmap.md, shipped.md) keep only last 30 days
|
|
180
|
+
- Sessions older than 30 days → automatically moved to archive/
|
|
181
|
+
- When querying across time: read relevant session files from archive/
|
|
182
|
+
- Commands only read current index + today's session for performance
|
|
183
|
+
|
|
184
|
+
### File Size Limits:
|
|
185
|
+
- `core/now.md`: Single task only (< 1KB)
|
|
186
|
+
- `core/next.md`: Max 100 tasks (< 50KB)
|
|
187
|
+
- `progress/shipped.md`: Last 30 days only (auto-archive older)
|
|
188
|
+
- Session files: One file per day, JSONL format for efficient appending
|
|
189
|
+
|
|
190
|
+
## 🎯 Command Execution Flow
|
|
191
|
+
|
|
192
|
+
Standard pattern for all `/p:*` commands:
|
|
193
|
+
|
|
194
|
+
1. **Validate environment**: Check `.prjct/prjct.config.json` exists
|
|
195
|
+
2. **Read config**: Extract projectId
|
|
196
|
+
3. **Construct paths**: Build all file paths using base path
|
|
197
|
+
4. **Execute operations**: Read/write files in global storage
|
|
198
|
+
5. **Log action**: Append to `memory/context.jsonl` with timestamp and author
|
|
199
|
+
6. **Return response**: Formatted response with next action suggestions
|
|
200
|
+
|
|
201
|
+
## 📚 Additional Context
|
|
202
|
+
|
|
203
|
+
- **Website**: https://prjct.app
|
|
204
|
+
- **Documentation**: https://prjct.app/docs
|
|
205
|
+
- **Repository**: Private (proprietary software)
|
|
206
|
+
- **Support**: jlopezlira@gmail.com
|
|
207
|
+
- **Version**: Auto-updated with prjct-cli
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
**Last updated**: Auto-managed by prjct-cli
|
|
212
|
+
**Config version**: 0.8.2
|
|
213
|
+
|
|
214
|
+
<!-- prjct:end - DO NOT REMOVE THIS MARKER -->
|