prjct-cli 0.4.4 → 0.4.6
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 +71 -2
- package/bin/prjct +36 -18
- package/core/commands.js +215 -11
- package/core/migrator.js +1 -1
- package/package.json +1 -1
- package/scripts/post-install.js +11 -36
package/CHANGELOG.md
CHANGED
|
@@ -15,6 +15,59 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
15
15
|
- Cross-platform file operations
|
|
16
16
|
- Windows Terminal integration
|
|
17
17
|
|
|
18
|
+
## [0.4.6] - 2025-10-02
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- **`prjct start` Command** - First-time setup with interactive editor selection
|
|
22
|
+
- Beautiful ASCII art welcome message
|
|
23
|
+
- Auto-detects installed AI editors (Claude Code, Cursor, Windsurf)
|
|
24
|
+
- Interactive prompt to choose which editors to install commands to
|
|
25
|
+
- Replaces confusing `prjct install` command with clearer naming
|
|
26
|
+
- Only runs once (blocks if already configured, suggests `prjct setup` to reconfigure)
|
|
27
|
+
|
|
28
|
+
- **Auto-Initialization** - Commands auto-run `prjct init` when needed
|
|
29
|
+
- All core commands (now, done, ship, next, idea, recap, stuck, context) check initialization
|
|
30
|
+
- Shows warning and runs init automatically if project not configured
|
|
31
|
+
- Zero friction - users don't need to remember to run init first
|
|
32
|
+
- Seamless workflow: `cd project/ && prjct now "task"` just works
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
- **Simplified Installation Flow**
|
|
36
|
+
- `npm install -g prjct-cli` → Shows welcome message, tells user to run `prjct start`
|
|
37
|
+
- `prjct start` → Interactive setup (first-time only)
|
|
38
|
+
- `prjct init` → Initialize project (links to global data)
|
|
39
|
+
- `prjct setup` → Reconfigure editors (replaces old `prjct install`)
|
|
40
|
+
- `npm update -g prjct-cli` → Auto-updates commands in tracked editors
|
|
41
|
+
|
|
42
|
+
- **Post-Install Behavior**
|
|
43
|
+
- Removed auto-installation on npm install (was non-interactive and confusing)
|
|
44
|
+
- First install shows: `Run: prjct start to get started`
|
|
45
|
+
- Updates auto-update commands in previously selected editors
|
|
46
|
+
- Cleaner, more predictable behavior
|
|
47
|
+
|
|
48
|
+
### Fixed
|
|
49
|
+
- **Critical Bug Fixes** - All commands now enforce global architecture correctly
|
|
50
|
+
- `/p:design` now creates designs in global `analysis/designs/` instead of local `.prjct/designs/`
|
|
51
|
+
- `/p:cleanup` now operates on global project data instead of local `.prjct/`
|
|
52
|
+
- `getDaysSinceLastShip()` now reads from global `memory/context.jsonl` instead of local
|
|
53
|
+
- All commands verify project is initialized before execution
|
|
54
|
+
- Prevents creation of invalid local `.prjct/` structures
|
|
55
|
+
- **Fixed post-install.js** - `currentVersion` now declared before use (prevents ReferenceError)
|
|
56
|
+
- **Added 'Apps' directory** to migration scanner for better project detection
|
|
57
|
+
|
|
58
|
+
### Technical Details
|
|
59
|
+
- **New Commands**:
|
|
60
|
+
- `start()` - First-time setup with ASCII art and interactive editor selection
|
|
61
|
+
- `setup()` - Renamed from `install()` for clarity
|
|
62
|
+
- `ensureProjectInit()` - Helper function for auto-initialization
|
|
63
|
+
- **Global Architecture**: All commands now use `pathManager.getGlobalProjectPath(projectId)`
|
|
64
|
+
- design(), cleanup(), getDaysSinceLastShip() fully migrated
|
|
65
|
+
- Prevents LOCAL .prjct/ creation
|
|
66
|
+
- Requires project initialization before command execution
|
|
67
|
+
- **Auto-Init Integration**: now(), done(), ship(), next(), idea(), recap(), stuck(), context() all auto-initialize
|
|
68
|
+
- **Migration Enhancement**: Added ~/Apps to common directories scan
|
|
69
|
+
- **Post-Install Fix**: currentVersion variable properly declared at function start
|
|
70
|
+
|
|
18
71
|
## [0.4.4] - 2025-10-02
|
|
19
72
|
|
|
20
73
|
### Added
|
|
@@ -39,7 +92,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
39
92
|
- **Automatic Data Migration** - Seamless upgrade from v0.1.0 to v0.4.4
|
|
40
93
|
- Post-install hook automatically detects legacy `.prjct/` projects
|
|
41
94
|
- Migrates data from local structure to new global architecture (`~/.prjct-cli/projects/{id}/`)
|
|
42
|
-
- Scans common project directories (Projects, Documents, Developer, Code,
|
|
95
|
+
- Scans common project directories (Projects, Documents, Developer, Code, **Apps**)
|
|
43
96
|
- Preserves all project data during migration (now, next, shipped, ideas, memory)
|
|
44
97
|
- Cleans up legacy directories while keeping config for compatibility
|
|
45
98
|
- No user intervention required - migration happens automatically on update
|
|
@@ -51,23 +104,39 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
51
104
|
- Ensures tracking happens even during force updates
|
|
52
105
|
- Enables reliable auto-updates across all configured editors
|
|
53
106
|
|
|
107
|
+
### Fixed
|
|
108
|
+
- **Global Architecture Enforcement** - All commands now enforce global architecture correctly
|
|
109
|
+
- `/p:design` now creates designs in global `analysis/designs/` instead of local `.prjct/designs/`
|
|
110
|
+
- `/p:cleanup` now operates on global project data instead of local `.prjct/`
|
|
111
|
+
- `getDaysSinceLastShip()` now reads from global `memory/context.jsonl` instead of local
|
|
112
|
+
- All commands verify project is initialized before execution
|
|
113
|
+
- Prevents creation of invalid local `.prjct/` structures
|
|
114
|
+
- **Fixed post-install.js** - `currentVersion` now declared before use (prevents ReferenceError)
|
|
115
|
+
- **Added 'Apps' directory** to migration scanner for better project detection
|
|
116
|
+
|
|
54
117
|
### Technical Details
|
|
55
118
|
- **Post-Install Hook**: Runs after `npm install -g prjct-cli` or `npm update -g prjct-cli`
|
|
56
119
|
- First install: Auto-detects editors and installs commands
|
|
57
120
|
- Updates: Checks version change and auto-updates commands in tracked editors
|
|
58
121
|
- **Migration**: Automatically detects and migrates legacy projects from v0.1.0
|
|
59
122
|
- Silent operation with debug mode via `DEBUG=1` environment variable
|
|
123
|
+
- **Fixed**: currentVersion variable now properly declared at function start
|
|
124
|
+
- **Enhanced**: Better error handling with debug logging
|
|
60
125
|
- **Pre-Uninstall Hook**: Runs before `npm uninstall -g prjct-cli`
|
|
61
126
|
- Reads tracking config to find all installed editors
|
|
62
127
|
- Removes command directories from each editor
|
|
63
128
|
- Cleans up tracking configuration
|
|
64
129
|
- Fails gracefully to not block uninstall
|
|
65
130
|
- **Migration System**: Automatic upgrade path from v0.1.0 to v0.4.4
|
|
66
|
-
- Scans common project directories (fast, non-intrusive)
|
|
131
|
+
- Scans common project directories including **~/Apps** (fast, non-intrusive)
|
|
67
132
|
- Migrates local `.prjct/` to global `~/.prjct-cli/projects/{id}/`
|
|
68
133
|
- Preserves all data: core, progress, planning, analysis, memory layers
|
|
69
134
|
- Cleans legacy directories while keeping compatibility config
|
|
70
135
|
- Zero data loss, seamless upgrade experience
|
|
136
|
+
- **Global Architecture**: All commands now use `pathManager.getGlobalProjectPath(projectId)`
|
|
137
|
+
- design(), cleanup(), getDaysSinceLastShip() fully migrated
|
|
138
|
+
- Prevents LOCAL .prjct/ creation
|
|
139
|
+
- Requires project initialization before command execution
|
|
71
140
|
|
|
72
141
|
## [0.4.3] - 2025-10-02
|
|
73
142
|
|
package/bin/prjct
CHANGED
|
@@ -8,6 +8,9 @@ async function main() {
|
|
|
8
8
|
|
|
9
9
|
let result;
|
|
10
10
|
switch(command) {
|
|
11
|
+
case 'start':
|
|
12
|
+
result = await commands.start();
|
|
13
|
+
break;
|
|
11
14
|
case 'init':
|
|
12
15
|
result = await commands.init();
|
|
13
16
|
break;
|
|
@@ -107,23 +110,23 @@ async function main() {
|
|
|
107
110
|
|
|
108
111
|
result = await commands.migrateAll(migrateOptions);
|
|
109
112
|
break;
|
|
110
|
-
case '
|
|
111
|
-
const
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
for (let i = 0; i <
|
|
115
|
-
if (
|
|
116
|
-
|
|
117
|
-
} else if (
|
|
118
|
-
|
|
119
|
-
} else if (
|
|
120
|
-
|
|
121
|
-
} else if (
|
|
122
|
-
|
|
113
|
+
case 'setup':
|
|
114
|
+
const setupOptions = {};
|
|
115
|
+
const setupArgs = args.slice(1);
|
|
116
|
+
|
|
117
|
+
for (let i = 0; i < setupArgs.length; i++) {
|
|
118
|
+
if (setupArgs[i] === '--force') {
|
|
119
|
+
setupOptions.force = true;
|
|
120
|
+
} else if (setupArgs[i] === '--editor') {
|
|
121
|
+
setupOptions.editor = setupArgs[++i];
|
|
122
|
+
} else if (setupArgs[i] === '--create-templates') {
|
|
123
|
+
setupOptions.createTemplates = true;
|
|
124
|
+
} else if (setupArgs[i] === '--no-interactive') {
|
|
125
|
+
setupOptions.interactive = false;
|
|
123
126
|
}
|
|
124
127
|
}
|
|
125
128
|
|
|
126
|
-
result = await commands.
|
|
129
|
+
result = await commands.setup(setupOptions);
|
|
127
130
|
break;
|
|
128
131
|
case 'analyze':
|
|
129
132
|
const analyzeOptions = {};
|
|
@@ -139,6 +142,15 @@ async function main() {
|
|
|
139
142
|
|
|
140
143
|
result = await commands.analyze(analyzeOptions);
|
|
141
144
|
break;
|
|
145
|
+
case '--version':
|
|
146
|
+
case '-v':
|
|
147
|
+
case 'version':
|
|
148
|
+
const packageJson = require('../package.json');
|
|
149
|
+
result = {
|
|
150
|
+
success: true,
|
|
151
|
+
message: `prjct-cli v${packageJson.version}`
|
|
152
|
+
};
|
|
153
|
+
break;
|
|
142
154
|
case '--help':
|
|
143
155
|
case '-h':
|
|
144
156
|
case 'help':
|
|
@@ -146,6 +158,10 @@ async function main() {
|
|
|
146
158
|
result = {
|
|
147
159
|
success: true,
|
|
148
160
|
message: `Available commands:
|
|
161
|
+
Setup:
|
|
162
|
+
start First-time setup (install commands to editors)
|
|
163
|
+
setup Reconfigure editor installations
|
|
164
|
+
|
|
149
165
|
Core workflow:
|
|
150
166
|
init Initialize prjct in current project
|
|
151
167
|
now [task] Set or show current task
|
|
@@ -164,9 +180,8 @@ async function main() {
|
|
|
164
180
|
design [target] Design system/architecture
|
|
165
181
|
analyze Analyze codebase and sync state
|
|
166
182
|
migrate-all Migrate all legacy projects
|
|
167
|
-
install Install commands to AI editors
|
|
168
183
|
|
|
169
|
-
|
|
184
|
+
Setup options:
|
|
170
185
|
--force Force update existing commands
|
|
171
186
|
--editor <name> Install to specific editor (claude|cursor|codex|windsurf)
|
|
172
187
|
--no-interactive Skip interactive selection, install to all
|
|
@@ -179,6 +194,10 @@ async function main() {
|
|
|
179
194
|
message: `Unknown command: ${command}
|
|
180
195
|
|
|
181
196
|
Available commands:
|
|
197
|
+
Setup:
|
|
198
|
+
start First-time setup (install commands to editors)
|
|
199
|
+
setup Reconfigure editor installations
|
|
200
|
+
|
|
182
201
|
Core workflow:
|
|
183
202
|
init Initialize prjct in current project
|
|
184
203
|
now [task] Set or show current task
|
|
@@ -197,9 +216,8 @@ Available commands:
|
|
|
197
216
|
design [target] Design system/architecture
|
|
198
217
|
analyze Analyze codebase and sync state
|
|
199
218
|
migrate-all Migrate all legacy projects
|
|
200
|
-
install Install commands to AI editors
|
|
201
219
|
|
|
202
|
-
|
|
220
|
+
Setup options:
|
|
203
221
|
--force Force update existing commands
|
|
204
222
|
--editor <name> Install to specific editor (claude|cursor|codex|windsurf)
|
|
205
223
|
--no-interactive Skip interactive selection, install to all
|
package/core/commands.js
CHANGED
|
@@ -249,6 +249,31 @@ class PrjctCommands {
|
|
|
249
249
|
return this.currentAuthor
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
+
/**
|
|
253
|
+
* Auto-initialize project if not configured
|
|
254
|
+
* Shows warning and runs init automatically
|
|
255
|
+
*
|
|
256
|
+
* @param {string} projectPath - Local project path
|
|
257
|
+
* @returns {Promise<{success: boolean, message?: string}>} Success or init result
|
|
258
|
+
*/
|
|
259
|
+
async ensureProjectInit(projectPath) {
|
|
260
|
+
if (await configManager.isConfigured(projectPath)) {
|
|
261
|
+
return { success: true }
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const chalk = require('chalk')
|
|
265
|
+
console.log(chalk.yellow('⚠️ Project not initialized'))
|
|
266
|
+
console.log(chalk.cyan('🔧 Running prjct init...\n'))
|
|
267
|
+
|
|
268
|
+
const initResult = await this.init(projectPath)
|
|
269
|
+
if (!initResult.success) {
|
|
270
|
+
return initResult
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
console.log(chalk.green('✅ Project initialized!\n'))
|
|
274
|
+
return { success: true }
|
|
275
|
+
}
|
|
276
|
+
|
|
252
277
|
/**
|
|
253
278
|
* Get the global project path for a project
|
|
254
279
|
* Ensures migration if needed
|
|
@@ -413,6 +438,12 @@ class PrjctCommands {
|
|
|
413
438
|
await this.initializeAgent()
|
|
414
439
|
await this.ensureAuthor()
|
|
415
440
|
|
|
441
|
+
// Auto-init if not configured
|
|
442
|
+
const initCheck = await this.ensureProjectInit(projectPath)
|
|
443
|
+
if (!initCheck.success) {
|
|
444
|
+
return initCheck
|
|
445
|
+
}
|
|
446
|
+
|
|
416
447
|
const nowFile = await this.getFilePath(projectPath, 'core', 'now.md')
|
|
417
448
|
|
|
418
449
|
if (!task) {
|
|
@@ -494,6 +525,13 @@ class PrjctCommands {
|
|
|
494
525
|
async done(projectPath = process.cwd()) {
|
|
495
526
|
try {
|
|
496
527
|
await this.initializeAgent()
|
|
528
|
+
|
|
529
|
+
// Auto-init if not configured
|
|
530
|
+
const initCheck = await this.ensureProjectInit(projectPath)
|
|
531
|
+
if (!initCheck.success) {
|
|
532
|
+
return initCheck
|
|
533
|
+
}
|
|
534
|
+
|
|
497
535
|
const nowFile = await this.getFilePath(projectPath, 'core', 'now.md')
|
|
498
536
|
const nextFile = await this.getFilePath(projectPath, 'core', 'next.md')
|
|
499
537
|
|
|
@@ -655,6 +693,12 @@ ${nextStep.agent}
|
|
|
655
693
|
try {
|
|
656
694
|
await this.initializeAgent()
|
|
657
695
|
|
|
696
|
+
// Auto-init if not configured
|
|
697
|
+
const initCheck = await this.ensureProjectInit(projectPath)
|
|
698
|
+
if (!initCheck.success) {
|
|
699
|
+
return initCheck
|
|
700
|
+
}
|
|
701
|
+
|
|
658
702
|
if (!feature) {
|
|
659
703
|
return {
|
|
660
704
|
success: false,
|
|
@@ -764,6 +808,13 @@ ${nextStep.agent}
|
|
|
764
808
|
async next(projectPath = process.cwd()) {
|
|
765
809
|
try {
|
|
766
810
|
await this.initializeAgent()
|
|
811
|
+
|
|
812
|
+
// Auto-init if not configured
|
|
813
|
+
const initCheck = await this.ensureProjectInit(projectPath)
|
|
814
|
+
if (!initCheck.success) {
|
|
815
|
+
return initCheck
|
|
816
|
+
}
|
|
817
|
+
|
|
767
818
|
const nextFile = await this.getFilePath(projectPath, 'core', 'next.md')
|
|
768
819
|
const content = await this.agent.readFile(nextFile)
|
|
769
820
|
|
|
@@ -806,6 +857,12 @@ ${nextStep.agent}
|
|
|
806
857
|
try {
|
|
807
858
|
await this.initializeAgent()
|
|
808
859
|
|
|
860
|
+
// Auto-init if not configured
|
|
861
|
+
const initCheck = await this.ensureProjectInit(projectPath)
|
|
862
|
+
if (!initCheck.success) {
|
|
863
|
+
return initCheck
|
|
864
|
+
}
|
|
865
|
+
|
|
809
866
|
if (!text) {
|
|
810
867
|
return {
|
|
811
868
|
success: false,
|
|
@@ -862,6 +919,12 @@ ${nextStep.agent}
|
|
|
862
919
|
try {
|
|
863
920
|
await this.initializeAgent()
|
|
864
921
|
|
|
922
|
+
// Auto-init if not configured
|
|
923
|
+
const initCheck = await this.ensureProjectInit(projectPath)
|
|
924
|
+
if (!initCheck.success) {
|
|
925
|
+
return initCheck
|
|
926
|
+
}
|
|
927
|
+
|
|
865
928
|
const nowFilePath = await this.getFilePath(projectPath, 'core', 'now.md')
|
|
866
929
|
const nextFilePath = await this.getFilePath(projectPath, 'core', 'next.md')
|
|
867
930
|
const ideasFilePath = await this.getFilePath(projectPath, 'planning', 'ideas.md')
|
|
@@ -1100,6 +1163,12 @@ ${nextStep.agent}
|
|
|
1100
1163
|
try {
|
|
1101
1164
|
await this.initializeAgent()
|
|
1102
1165
|
|
|
1166
|
+
// Auto-init if not configured
|
|
1167
|
+
const initCheck = await this.ensureProjectInit(projectPath)
|
|
1168
|
+
if (!initCheck.success) {
|
|
1169
|
+
return initCheck
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1103
1172
|
if (!issue) {
|
|
1104
1173
|
return {
|
|
1105
1174
|
success: false,
|
|
@@ -1236,9 +1305,23 @@ ${dryRun ? '⚠️ DRY RUN - No changes were made' : '✅ All changes applied su
|
|
|
1236
1305
|
try {
|
|
1237
1306
|
await this.initializeAgent()
|
|
1238
1307
|
|
|
1308
|
+
// Verify project is initialized
|
|
1309
|
+
if (!await configManager.isConfigured(projectPath)) {
|
|
1310
|
+
return {
|
|
1311
|
+
success: false,
|
|
1312
|
+
message: this.agent.formatResponse(
|
|
1313
|
+
`Project not initialized. Run ${this.agentInfo.config.commandPrefix}init first.`,
|
|
1314
|
+
'warning'
|
|
1315
|
+
),
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1239
1319
|
const type = options.type || 'architecture'
|
|
1240
1320
|
|
|
1241
|
-
|
|
1321
|
+
// Use global architecture
|
|
1322
|
+
const projectId = await configManager.getProjectId(projectPath)
|
|
1323
|
+
const globalPath = pathManager.getGlobalProjectPath(projectId)
|
|
1324
|
+
const designDir = path.join(globalPath, 'analysis', 'designs')
|
|
1242
1325
|
await this.agent.createDirectory(designDir)
|
|
1243
1326
|
|
|
1244
1327
|
let designContent = ''
|
|
@@ -1380,6 +1463,12 @@ ${diagram}
|
|
|
1380
1463
|
try {
|
|
1381
1464
|
await this.initializeAgent()
|
|
1382
1465
|
|
|
1466
|
+
// Auto-init if not configured
|
|
1467
|
+
const initCheck = await this.ensureProjectInit(projectPath)
|
|
1468
|
+
if (!initCheck.success) {
|
|
1469
|
+
return initCheck
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1383
1472
|
const projectInfo = await this.detectProjectType(projectPath)
|
|
1384
1473
|
|
|
1385
1474
|
const nowFilePath = await this.getFilePath(projectPath, 'core', 'now.md')
|
|
@@ -1484,7 +1573,11 @@ ${diagram}
|
|
|
1484
1573
|
async getDaysSinceLastShip(projectPath) {
|
|
1485
1574
|
try {
|
|
1486
1575
|
await this.initializeAgent()
|
|
1487
|
-
|
|
1576
|
+
|
|
1577
|
+
// Use global architecture
|
|
1578
|
+
const projectId = await configManager.getProjectId(projectPath)
|
|
1579
|
+
const globalPath = pathManager.getGlobalProjectPath(projectId)
|
|
1580
|
+
const memoryFile = path.join(globalPath, 'memory', 'context.jsonl')
|
|
1488
1581
|
const memory = await this.agent.readFile(memoryFile)
|
|
1489
1582
|
const lines = memory
|
|
1490
1583
|
.trim()
|
|
@@ -1670,14 +1763,28 @@ ${diagram}
|
|
|
1670
1763
|
async cleanup(projectPath = process.cwd()) {
|
|
1671
1764
|
try {
|
|
1672
1765
|
await this.initializeAgent()
|
|
1673
|
-
|
|
1766
|
+
|
|
1767
|
+
// Verify project is initialized
|
|
1768
|
+
if (!await configManager.isConfigured(projectPath)) {
|
|
1769
|
+
return {
|
|
1770
|
+
success: false,
|
|
1771
|
+
message: this.agent.formatResponse(
|
|
1772
|
+
`Project not initialized. Run ${this.agentInfo.config.commandPrefix}init first.`,
|
|
1773
|
+
'warning'
|
|
1774
|
+
),
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
// Use global architecture
|
|
1779
|
+
const projectId = await configManager.getProjectId(projectPath)
|
|
1780
|
+
const globalPath = pathManager.getGlobalProjectPath(projectId)
|
|
1674
1781
|
|
|
1675
1782
|
let totalFreed = 0
|
|
1676
1783
|
let filesRemoved = 0
|
|
1677
1784
|
let tasksArchived = 0
|
|
1678
1785
|
|
|
1679
1786
|
try {
|
|
1680
|
-
const tempDir = path.join(
|
|
1787
|
+
const tempDir = path.join(globalPath, 'temp')
|
|
1681
1788
|
const tempFiles = await fs.readdir(tempDir).catch(() => [])
|
|
1682
1789
|
for (const file of tempFiles) {
|
|
1683
1790
|
const filePath = path.join(tempDir, file)
|
|
@@ -1690,7 +1797,7 @@ ${diagram}
|
|
|
1690
1797
|
}
|
|
1691
1798
|
|
|
1692
1799
|
try {
|
|
1693
|
-
const memoryFile = path.join(
|
|
1800
|
+
const memoryFile = path.join(globalPath, 'memory', 'context.jsonl')
|
|
1694
1801
|
const content = await this.agent.readFile(memoryFile)
|
|
1695
1802
|
const lines = content.split('\n').filter(line => line.trim())
|
|
1696
1803
|
const now = new Date()
|
|
@@ -1714,7 +1821,7 @@ ${diagram}
|
|
|
1714
1821
|
}
|
|
1715
1822
|
|
|
1716
1823
|
if (archivedLines.length > 0) {
|
|
1717
|
-
const archiveFile = path.join(
|
|
1824
|
+
const archiveFile = path.join(globalPath, 'memory', `archive-${now.toISOString().split('T')[0]}.jsonl`)
|
|
1718
1825
|
await this.agent.writeFile(archiveFile, archivedLines.join('\n') + '\n')
|
|
1719
1826
|
await this.agent.writeFile(memoryFile, recentLines.join('\n') + '\n')
|
|
1720
1827
|
tasksArchived = archivedLines.length
|
|
@@ -1722,10 +1829,10 @@ ${diagram}
|
|
|
1722
1829
|
} catch (e) {
|
|
1723
1830
|
}
|
|
1724
1831
|
|
|
1725
|
-
const files = await fs.readdir(
|
|
1832
|
+
const files = await fs.readdir(globalPath)
|
|
1726
1833
|
for (const file of files) {
|
|
1727
1834
|
if (file.endsWith('.md') || file.endsWith('.txt')) {
|
|
1728
|
-
const filePath = path.join(
|
|
1835
|
+
const filePath = path.join(globalPath, file)
|
|
1729
1836
|
const stats = await fs.stat(filePath)
|
|
1730
1837
|
if (stats.size === 0) {
|
|
1731
1838
|
await fs.unlink(filePath)
|
|
@@ -1735,7 +1842,7 @@ ${diagram}
|
|
|
1735
1842
|
}
|
|
1736
1843
|
|
|
1737
1844
|
try {
|
|
1738
|
-
const shippedFile = path.join(
|
|
1845
|
+
const shippedFile = path.join(globalPath, 'progress', 'shipped.md')
|
|
1739
1846
|
const content = await this.agent.readFile(shippedFile)
|
|
1740
1847
|
const lines = content.split('\n')
|
|
1741
1848
|
const now = new Date()
|
|
@@ -1834,12 +1941,109 @@ ${diagram}
|
|
|
1834
1941
|
}
|
|
1835
1942
|
|
|
1836
1943
|
/**
|
|
1837
|
-
* Install commands to AI editors
|
|
1944
|
+
* First-time setup - Install commands to AI editors with ASCII art welcome
|
|
1945
|
+
*
|
|
1946
|
+
* @returns {Promise<Object>} Result object with success flag and message
|
|
1947
|
+
*/
|
|
1948
|
+
async start() {
|
|
1949
|
+
try {
|
|
1950
|
+
await this.initializeAgent()
|
|
1951
|
+
|
|
1952
|
+
// Check if already configured
|
|
1953
|
+
const editorsConfig = require('./editors-config')
|
|
1954
|
+
const configExists = await editorsConfig.configExists()
|
|
1955
|
+
|
|
1956
|
+
if (configExists) {
|
|
1957
|
+
return {
|
|
1958
|
+
success: false,
|
|
1959
|
+
message: this.agent.formatResponse(
|
|
1960
|
+
'prjct is already set up!\n\nTo reconfigure editors: prjct setup',
|
|
1961
|
+
'warning'
|
|
1962
|
+
),
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
// ASCII Art
|
|
1967
|
+
const chalk = require('chalk')
|
|
1968
|
+
console.log(
|
|
1969
|
+
chalk.cyan(`
|
|
1970
|
+
___ ____ _ ____ _____
|
|
1971
|
+
/ _ \\| _ \\ | / ___|_ _|
|
|
1972
|
+
| |_| | |_) |_| | | | |
|
|
1973
|
+
| __/| _ <| | | |___ | |
|
|
1974
|
+
| | | |_) | | |\\____| | |
|
|
1975
|
+
|_| |____/|_| | |_|
|
|
1976
|
+
`)
|
|
1977
|
+
)
|
|
1978
|
+
|
|
1979
|
+
console.log(chalk.cyan('\n📦 Welcome to prjct-cli!\n'))
|
|
1980
|
+
|
|
1981
|
+
// Detect editors
|
|
1982
|
+
const commandInstaller = require('./command-installer')
|
|
1983
|
+
const detection = await commandInstaller.detectEditors()
|
|
1984
|
+
const detectedEditors = Object.entries(detection).filter(([_, info]) => info.detected)
|
|
1985
|
+
|
|
1986
|
+
if (detectedEditors.length === 0) {
|
|
1987
|
+
return {
|
|
1988
|
+
success: false,
|
|
1989
|
+
message: this.agent.formatResponse(
|
|
1990
|
+
'No AI editors detected.\n\nSupported: Claude Code, Cursor, Windsurf',
|
|
1991
|
+
'error'
|
|
1992
|
+
),
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1996
|
+
console.log(chalk.cyan('🔍 Detected AI editors:'))
|
|
1997
|
+
detectedEditors.forEach(([key, info]) => {
|
|
1998
|
+
console.log(chalk.green(` [✓] ${info.name} (${info.path})`))
|
|
1999
|
+
})
|
|
2000
|
+
console.log('')
|
|
2001
|
+
|
|
2002
|
+
// Interactive selection
|
|
2003
|
+
const installResult = await commandInstaller.interactiveInstall(false)
|
|
2004
|
+
|
|
2005
|
+
if (!installResult.success) {
|
|
2006
|
+
return {
|
|
2007
|
+
success: false,
|
|
2008
|
+
message: this.agent.formatResponse(installResult.message || 'Setup failed', 'error'),
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
|
|
2012
|
+
// Install Context7 MCP
|
|
2013
|
+
const mcpResult = await commandInstaller.installContext7MCP()
|
|
2014
|
+
|
|
2015
|
+
// Success message
|
|
2016
|
+
let message = `✅ Commands installed in: ${installResult.editors.join(', ')}\n`
|
|
2017
|
+
|
|
2018
|
+
if (mcpResult.success && mcpResult.editors.length > 0) {
|
|
2019
|
+
message += `\n🔌 Context7 MCP enabled in: ${mcpResult.editors.join(', ')}`
|
|
2020
|
+
}
|
|
2021
|
+
|
|
2022
|
+
message += '\n\n✨ prjct is ready to use!'
|
|
2023
|
+
message += '\n\nNext steps:'
|
|
2024
|
+
message += '\n cd your-project/'
|
|
2025
|
+
message += '\n prjct init'
|
|
2026
|
+
|
|
2027
|
+
return {
|
|
2028
|
+
success: true,
|
|
2029
|
+
message: this.agent.formatResponse(message, 'celebrate'),
|
|
2030
|
+
}
|
|
2031
|
+
} catch (error) {
|
|
2032
|
+
await this.initializeAgent()
|
|
2033
|
+
return {
|
|
2034
|
+
success: false,
|
|
2035
|
+
message: this.agent.formatResponse(`Setup failed: ${error.message}`, 'error'),
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
/**
|
|
2041
|
+
* Setup/reconfigure commands in AI editors
|
|
1838
2042
|
*
|
|
1839
2043
|
* @param {Object} [options={}] - Installation options
|
|
1840
2044
|
* @returns {Promise<Object>} Result object with success flag and message
|
|
1841
2045
|
*/
|
|
1842
|
-
async
|
|
2046
|
+
async setup(options = {}) {
|
|
1843
2047
|
try {
|
|
1844
2048
|
await this.initializeAgent()
|
|
1845
2049
|
|
package/core/migrator.js
CHANGED
|
@@ -510,7 +510,7 @@ class Migrator {
|
|
|
510
510
|
if (deepScan) {
|
|
511
511
|
searchPaths = [os.homedir()]
|
|
512
512
|
} else {
|
|
513
|
-
const commonDirs = ['Projects', 'Documents', 'Developer', 'Code', 'dev', 'workspace', 'repos', 'src']
|
|
513
|
+
const commonDirs = ['Projects', 'Documents', 'Developer', 'Code', 'dev', 'workspace', 'repos', 'src', 'Apps']
|
|
514
514
|
searchPaths = commonDirs
|
|
515
515
|
.map(dir => path.join(os.homedir(), dir))
|
|
516
516
|
.filter(dirPath => {
|
package/package.json
CHANGED
package/scripts/post-install.js
CHANGED
|
@@ -21,11 +21,18 @@ const { execSync } = require('child_process')
|
|
|
21
21
|
|
|
22
22
|
async function main() {
|
|
23
23
|
try {
|
|
24
|
+
// Get current package version
|
|
25
|
+
const packageJson = require('../package.json')
|
|
26
|
+
const currentVersion = packageJson.version
|
|
27
|
+
|
|
24
28
|
// Check if this is a global installation
|
|
25
29
|
const isGlobal = await checkIfGlobalInstall()
|
|
26
30
|
|
|
27
31
|
if (!isGlobal) {
|
|
28
32
|
// Skip post-install for local/dev installations
|
|
33
|
+
if (process.env.DEBUG) {
|
|
34
|
+
console.log(chalk.gray('[post-install] Skipping - not a global install'))
|
|
35
|
+
}
|
|
29
36
|
return
|
|
30
37
|
}
|
|
31
38
|
|
|
@@ -34,43 +41,12 @@ async function main() {
|
|
|
34
41
|
const configExists = await editorsConfig.configExists()
|
|
35
42
|
|
|
36
43
|
if (!configExists) {
|
|
37
|
-
// First-time install -
|
|
38
|
-
console.log(chalk.cyan('\n
|
|
39
|
-
|
|
40
|
-
// Load command installer
|
|
41
|
-
const commandInstaller = require('../core/command-installer')
|
|
42
|
-
|
|
43
|
-
// Detect available editors
|
|
44
|
-
const detected = await commandInstaller.detectEditors()
|
|
45
|
-
const detectedEditors = Object.entries(detected)
|
|
46
|
-
.filter(([_, info]) => info.detected)
|
|
47
|
-
.map(([key, _]) => key)
|
|
48
|
-
|
|
49
|
-
if (detectedEditors.length === 0) {
|
|
50
|
-
// No editors detected, user will install manually later
|
|
51
|
-
console.log(chalk.yellow('ℹ️ No AI editors detected'))
|
|
52
|
-
console.log(chalk.gray(' Run `prjct install` when you set up Claude Code, Cursor, or Windsurf\n'))
|
|
53
|
-
return
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
console.log(chalk.cyan(`📦 Installing commands to: ${detectedEditors.map(k => commandInstaller.editors[k]?.name || k).join(', ')}\n`))
|
|
57
|
-
|
|
58
|
-
// Install to all detected editors
|
|
59
|
-
const results = await commandInstaller.installToAll(false)
|
|
60
|
-
|
|
61
|
-
if (results.success) {
|
|
62
|
-
console.log(chalk.green(`✅ Commands installed in: ${results.editors.join(', ')}`))
|
|
63
|
-
console.log(chalk.gray(` Commands installed: ${results.totalInstalled}`))
|
|
64
|
-
console.log(chalk.cyan(`\n✨ prjct-cli ${currentVersion} is ready!\n`))
|
|
65
|
-
}
|
|
66
|
-
|
|
44
|
+
// First-time install - show welcome message
|
|
45
|
+
console.log(chalk.cyan('\n✨ prjct-cli installed successfully!\n'))
|
|
46
|
+
console.log(chalk.gray('Run: ') + chalk.cyan('prjct start') + chalk.gray(' to get started\n'))
|
|
67
47
|
return
|
|
68
48
|
}
|
|
69
49
|
|
|
70
|
-
// Get current package version
|
|
71
|
-
const packageJson = require('../package.json')
|
|
72
|
-
const currentVersion = packageJson.version
|
|
73
|
-
|
|
74
50
|
// Check if version has changed
|
|
75
51
|
const versionChanged = await editorsConfig.hasVersionChanged(currentVersion)
|
|
76
52
|
|
|
@@ -79,9 +55,8 @@ async function main() {
|
|
|
79
55
|
return
|
|
80
56
|
}
|
|
81
57
|
|
|
82
|
-
// Get tracked editors
|
|
58
|
+
// Get tracked editors
|
|
83
59
|
const trackedEditors = await editorsConfig.getTrackedEditors()
|
|
84
|
-
const editorPaths = await editorsConfig.getEditorPaths()
|
|
85
60
|
|
|
86
61
|
if (trackedEditors.length === 0) {
|
|
87
62
|
// No editors tracked yet
|