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 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, etc.)
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 'install':
111
- const installOptions = {};
112
- const installArgs = args.slice(1);
113
-
114
- for (let i = 0; i < installArgs.length; i++) {
115
- if (installArgs[i] === '--force') {
116
- installOptions.force = true;
117
- } else if (installArgs[i] === '--editor') {
118
- installOptions.editor = installArgs[++i];
119
- } else if (installArgs[i] === '--create-templates') {
120
- installOptions.createTemplates = true;
121
- } else if (installArgs[i] === '--no-interactive') {
122
- installOptions.interactive = false;
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.install(installOptions);
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
- Install options:
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
- Install options:
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
- const designDir = path.join(projectPath, this.prjctDir, 'designs')
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
- const memoryFile = path.join(projectPath, this.prjctDir, 'memory.jsonl')
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
- const prjctPath = path.join(projectPath, this.prjctDir)
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(prjctPath, 'temp')
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(prjctPath, 'memory.jsonl')
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(prjctPath, `memory-archive-${now.toISOString().split('T')[0]}.jsonl`)
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(prjctPath)
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(prjctPath, file)
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(prjctPath, 'shipped.md')
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 install(options = {}) {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prjct-cli",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
4
4
  "description": "AI-integrated project management for indie hackers - works with Claude Code, Cursor, and Warp",
5
5
  "main": "core/index.js",
6
6
  "bin": {
@@ -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 - auto-detect and install to all editors
38
- console.log(chalk.cyan('\n🔍 First-time installation detected...\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 and paths
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