prjct-cli 0.8.4 β†’ 0.8.8

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.
@@ -0,0 +1,185 @@
1
+ const { execSync } = require('child_process')
2
+ const installer = require('./command-installer')
3
+ const migrator = require('./migrator')
4
+ const legacyDetector = require('./legacy-installer-detector')
5
+ const editorsConfig = require('./editors-config')
6
+ const { VERSION } = require('../utils/version')
7
+
8
+ /**
9
+ * Setup Module - Core installation logic
10
+ *
11
+ * Executes ALL setup needed for prjct-cli:
12
+ * 1. Detect and clean legacy installation (curl-based)
13
+ * 2. Install Claude Code CLI if missing
14
+ * 3. Sync commands to ~/.claude/commands/p/
15
+ * 4. Install global config ~/.claude/CLAUDE.md
16
+ * 5. Migrate legacy projects automatically
17
+ * 6. Save version in editors-config
18
+ *
19
+ * This module is called from:
20
+ * - core/index.js (on first CLI use)
21
+ * - scripts/postinstall.js (if npm scripts are enabled)
22
+ *
23
+ * @version 0.8.8
24
+ */
25
+
26
+ // Colors
27
+ const GREEN = '\x1b[32m'
28
+ const YELLOW = '\x1b[33m'
29
+ const MAGENTA = '\x1b[35m'
30
+ const BOLD = '\x1b[1m'
31
+ const DIM = '\x1b[2m'
32
+ const NC = '\x1b[0m'
33
+
34
+ /**
35
+ * Check if Claude Code CLI is installed
36
+ */
37
+ async function hasClaudeCodeCLI() {
38
+ try {
39
+ execSync('which claude', { stdio: 'ignore' })
40
+ return true
41
+ } catch {
42
+ return false
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Install Claude Code CLI
48
+ */
49
+ async function installClaudeCode() {
50
+ try {
51
+ console.log(`${YELLOW}πŸ“¦ Claude Code not found. Installing...${NC}`)
52
+ console.log('')
53
+ execSync('npm install -g @anthropic-ai/claude-code', { stdio: 'inherit' })
54
+ console.log('')
55
+ console.log(`${GREEN}βœ“${NC} Claude Code installed successfully`)
56
+ console.log('')
57
+ return true
58
+ } catch (error) {
59
+ console.log(`${YELLOW}⚠️ Failed to install Claude Code: ${error.message}${NC}`)
60
+ console.log(`${DIM}Please install manually: npm install -g @anthropic-ai/claude-code${NC}`)
61
+ console.log('')
62
+ return false
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Main setup function
68
+ */
69
+ async function run() {
70
+ const results = {
71
+ legacyCleaned: false,
72
+ legacyProjectsMigrated: 0,
73
+ claudeInstalled: false,
74
+ commandsAdded: 0,
75
+ commandsUpdated: 0,
76
+ configAction: null,
77
+ projectsMigrated: 0
78
+ }
79
+
80
+ // Step 0: Detect and clean legacy curl installation
81
+ const needsLegacyCleanup = await legacyDetector.needsCleanup()
82
+ if (needsLegacyCleanup) {
83
+ const cleanupResult = await legacyDetector.performCleanup({ verbose: true })
84
+ results.legacyCleaned = cleanupResult.success
85
+ results.legacyProjectsMigrated = cleanupResult.steps.projectsMigrated
86
+ }
87
+
88
+ // Step 1: Ensure Claude Code CLI is installed
89
+ const hasClaude = await hasClaudeCodeCLI()
90
+
91
+ if (!hasClaude) {
92
+ const installed = await installClaudeCode()
93
+ if (installed) {
94
+ results.claudeInstalled = true
95
+ } else {
96
+ throw new Error('Claude Code installation failed')
97
+ }
98
+ }
99
+
100
+ // Step 2: Detect Claude directory (for commands)
101
+ const claudeDetected = await installer.detectClaude()
102
+
103
+ if (claudeDetected) {
104
+ // Step 3: Sync commands
105
+ const syncResult = await installer.syncCommands()
106
+
107
+ if (syncResult.success) {
108
+ results.commandsAdded = syncResult.added
109
+ results.commandsUpdated = syncResult.updated
110
+ }
111
+
112
+ // Step 4: Install global configuration
113
+ const configResult = await installer.installGlobalConfig()
114
+
115
+ if (configResult.success) {
116
+ results.configAction = configResult.action
117
+ }
118
+
119
+ // Step 5: Migrate legacy projects automatically
120
+ const migrationResult = await migrator.migrateAll({
121
+ deepScan: false,
122
+ cleanupLegacy: true,
123
+ dryRun: false
124
+ })
125
+
126
+ if (migrationResult.successfullyMigrated > 0) {
127
+ results.projectsMigrated = migrationResult.successfullyMigrated
128
+ }
129
+ }
130
+
131
+ // Step 6: Save version in editors-config
132
+ await editorsConfig.saveConfig(VERSION, installer.getInstallPath())
133
+
134
+ // Show results
135
+ showResults(results)
136
+
137
+ return results
138
+ }
139
+
140
+ /**
141
+ * Show setup results
142
+ */
143
+ function showResults(results) {
144
+ console.log('')
145
+
146
+ // Show what was done
147
+ if (results.legacyCleaned) {
148
+ console.log(` ${GREEN}βœ“${NC} Legacy curl installation cleaned up`)
149
+ if (results.legacyProjectsMigrated > 0) {
150
+ console.log(` ${GREEN}βœ“${NC} ${results.legacyProjectsMigrated} project(s) migrated from legacy`)
151
+ }
152
+ }
153
+
154
+ if (results.claudeInstalled) {
155
+ console.log(` ${GREEN}βœ“${NC} Claude Code CLI installed`)
156
+ } else {
157
+ console.log(` ${GREEN}βœ“${NC} Claude Code CLI found`)
158
+ }
159
+
160
+ const totalCommands = results.commandsAdded + results.commandsUpdated
161
+ if (totalCommands > 0) {
162
+ const parts = []
163
+ if (results.commandsAdded > 0) parts.push(`${results.commandsAdded} new`)
164
+ if (results.commandsUpdated > 0) parts.push(`${results.commandsUpdated} updated`)
165
+ console.log(` ${GREEN}βœ“${NC} Commands synced (${parts.join(', ')})`)
166
+ } else {
167
+ console.log(` ${GREEN}βœ“${NC} Commands up to date`)
168
+ }
169
+
170
+ if (results.configAction === 'created') {
171
+ console.log(` ${GREEN}βœ“${NC} Global config created`)
172
+ } else if (results.configAction === 'updated') {
173
+ console.log(` ${GREEN}βœ“${NC} Global config updated`)
174
+ } else if (results.configAction === 'appended') {
175
+ console.log(` ${GREEN}βœ“${NC} Global config merged`)
176
+ }
177
+
178
+ if (results.projectsMigrated > 0) {
179
+ console.log(` ${GREEN}βœ“${NC} ${results.projectsMigrated} projects migrated to global storage`)
180
+ }
181
+
182
+ console.log('')
183
+ }
184
+
185
+ module.exports = { run }
@@ -1,4 +1,7 @@
1
1
  const fs = require('fs').promises
2
+ const fsSync = require('fs')
3
+ const readline = require('readline')
4
+ const path = require('path')
2
5
 
3
6
  /**
4
7
  * JSONL Helper - Centralized JSONL parsing and writing
@@ -190,6 +193,134 @@ async function isJsonLinesEmpty(filePath) {
190
193
  return count === 0
191
194
  }
192
195
 
196
+ /**
197
+ * Read JSONL file with streaming (memory-efficient for large files)
198
+ * Only reads last N lines instead of loading entire file
199
+ *
200
+ * @param {string} filePath - Path to JSONL file
201
+ * @param {number} maxLines - Maximum lines to read (default: 1000)
202
+ * @returns {Promise<Array<Object>>} - Array of parsed objects (last N lines)
203
+ */
204
+ async function readJsonLinesStreaming(filePath, maxLines = 1000) {
205
+ try {
206
+ const fileStream = fsSync.createReadStream(filePath)
207
+ const rl = readline.createInterface({
208
+ input: fileStream,
209
+ crlfDelay: Infinity,
210
+ })
211
+
212
+ const lines = []
213
+
214
+ for await (const line of rl) {
215
+ if (line.trim()) {
216
+ try {
217
+ lines.push(JSON.parse(line))
218
+ } catch {
219
+ // Skip malformed lines
220
+ }
221
+
222
+ // Keep only last maxLines
223
+ if (lines.length > maxLines) {
224
+ lines.shift()
225
+ }
226
+ }
227
+ }
228
+
229
+ return lines
230
+ } catch (error) {
231
+ if (error.code === 'ENOENT') {
232
+ return []
233
+ }
234
+ throw error
235
+ }
236
+ }
237
+
238
+ /**
239
+ * Get file size in MB
240
+ *
241
+ * @param {string} filePath - Path to file
242
+ * @returns {Promise<number>} - File size in MB
243
+ */
244
+ async function getFileSizeMB(filePath) {
245
+ try {
246
+ const stats = await fs.stat(filePath)
247
+ return stats.size / (1024 * 1024)
248
+ } catch (error) {
249
+ if (error.code === 'ENOENT') {
250
+ return 0
251
+ }
252
+ throw error
253
+ }
254
+ }
255
+
256
+ /**
257
+ * Rotate JSONL file if it exceeds size limit
258
+ * Moves large file to archive with timestamp
259
+ *
260
+ * @param {string} filePath - Path to JSONL file
261
+ * @param {number} maxSizeMB - Maximum size in MB before rotation (default: 10)
262
+ * @returns {Promise<boolean>} - True if rotated, false if not needed
263
+ */
264
+ async function rotateJsonLinesIfNeeded(filePath, maxSizeMB = 10) {
265
+ const sizeMB = await getFileSizeMB(filePath)
266
+
267
+ if (sizeMB < maxSizeMB) {
268
+ return false // No rotation needed
269
+ }
270
+
271
+ // Generate archive filename with timestamp
272
+ const timestamp = new Date().toISOString().split('T')[0] // YYYY-MM-DD
273
+ const dir = path.dirname(filePath)
274
+ const ext = path.extname(filePath)
275
+ const base = path.basename(filePath, ext)
276
+ const archivePath = path.join(dir, `${base}-${timestamp}${ext}`)
277
+
278
+ // Move file to archive
279
+ await fs.rename(filePath, archivePath)
280
+
281
+ console.log(`πŸ“¦ Rotated ${path.basename(filePath)} (${sizeMB.toFixed(1)}MB) β†’ ${path.basename(archivePath)}`)
282
+
283
+ return true
284
+ }
285
+
286
+ /**
287
+ * Append JSON line with automatic rotation
288
+ * Checks file size before append and rotates if needed
289
+ *
290
+ * @param {string} filePath - Path to JSONL file
291
+ * @param {Object} object - Object to append
292
+ * @param {number} maxSizeMB - Maximum size before rotation (default: 10)
293
+ * @returns {Promise<void>}
294
+ */
295
+ async function appendJsonLineWithRotation(filePath, object, maxSizeMB = 10) {
296
+ // Rotate if needed (before appending)
297
+ await rotateJsonLinesIfNeeded(filePath, maxSizeMB)
298
+
299
+ // Append normally
300
+ await appendJsonLine(filePath, object)
301
+ }
302
+
303
+ /**
304
+ * Warn if file is large before reading
305
+ * Returns size and whether it's considered large
306
+ *
307
+ * @param {string} filePath - Path to file
308
+ * @param {number} warnThresholdMB - Threshold in MB to warn (default: 50)
309
+ * @returns {Promise<{sizeMB: number, isLarge: boolean}>}
310
+ */
311
+ async function checkFileSizeWarning(filePath, warnThresholdMB = 50) {
312
+ const sizeMB = await getFileSizeMB(filePath)
313
+ const isLarge = sizeMB > warnThresholdMB
314
+
315
+ if (isLarge) {
316
+ console.warn(
317
+ `⚠️ Large file detected: ${path.basename(filePath)} (${sizeMB.toFixed(1)}MB). Reading may use significant memory.`
318
+ )
319
+ }
320
+
321
+ return { sizeMB, isLarge }
322
+ }
323
+
193
324
  module.exports = {
194
325
  parseJsonLines,
195
326
  stringifyJsonLines,
@@ -203,4 +334,10 @@ module.exports = {
203
334
  getFirstJsonLines,
204
335
  mergeJsonLines,
205
336
  isJsonLinesEmpty,
337
+ // NEW: Memory-efficient functions
338
+ readJsonLinesStreaming,
339
+ getFileSizeMB,
340
+ rotateJsonLinesIfNeeded,
341
+ appendJsonLineWithRotation,
342
+ checkFileSizeWarning,
206
343
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prjct-cli",
3
- "version": "0.8.4",
3
+ "version": "0.8.8",
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": {
@@ -9,22 +9,59 @@
9
9
  YELLOW='\033[1;33m'
10
10
  CYAN='\033[0;36m'
11
11
  GREEN='\033[0;32m'
12
+ RED='\033[0;31m'
13
+ BOLD='\033[1m'
14
+ DIM='\033[2m'
12
15
  NC='\033[0m'
13
16
 
17
+ # Check if legacy installation exists
18
+ LEGACY_DIR="$HOME/.prjct-cli"
19
+ HAS_LEGACY=false
20
+ LEGACY_VERSION="unknown"
21
+
22
+ if [ -d "$LEGACY_DIR" ]; then
23
+ # Check if it's a git clone (legacy curl install)
24
+ if [ -d "$LEGACY_DIR/.git" ]; then
25
+ HAS_LEGACY=true
26
+ if [ -f "$LEGACY_DIR/package.json" ]; then
27
+ LEGACY_VERSION=$(grep -o '"version":[[:space:]]*"[^"]*"' "$LEGACY_DIR/package.json" | head -1 | cut -d'"' -f4)
28
+ fi
29
+ fi
30
+ fi
31
+
14
32
  echo ""
15
33
  echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
16
34
  echo -e "${YELLOW}⚠️ This installation method is DEPRECATED${NC}"
17
35
  echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
18
36
  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"
37
+
38
+ if [ "$HAS_LEGACY" = true ]; then
39
+ echo -e "${RED}⚠️ Legacy curl installation detected!${NC}"
40
+ echo ""
41
+ echo -e " ${DIM}Version: ${LEGACY_VERSION}${NC}"
42
+ echo -e " ${DIM}Location: ~/.prjct-cli/${NC}"
43
+ echo ""
44
+ echo -e "${CYAN}Migration Required:${NC}"
45
+ echo ""
46
+ echo -e " 1. ${BOLD}Install via npm:${NC}"
47
+ echo -e " ${GREEN}npm install -g prjct-cli${NC}"
48
+ echo ""
49
+ echo -e " 2. ${BOLD}Automatic cleanup:${NC}"
50
+ echo -e " ${DIM}Legacy installation will be cleaned automatically${NC}"
51
+ echo -e " ${DIM}Your project data will be preserved${NC}"
52
+ echo ""
53
+ else
54
+ echo -e "${CYAN}Please install using npm:${NC}"
55
+ echo ""
56
+ echo -e " ${GREEN}npm install -g prjct-cli${NC}"
57
+ echo ""
58
+ fi
59
+
60
+ echo -e "${BOLD}Benefits of npm installation:${NC}"
61
+ echo -e " β€’ ${CYAN}Automatic cleanup${NC} - Removes old curl installations"
62
+ echo -e " β€’ ${CYAN}Data preservation${NC} - Your projects are migrated safely"
27
63
  echo -e " β€’ ${CYAN}Easy updates${NC} - Just npm update -g prjct-cli"
64
+ echo -e " β€’ ${CYAN}Proper versioning${NC} - npm handles everything"
28
65
  echo ""
29
66
  echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
30
67
  echo ""
@@ -1,114 +1,35 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * Post-install hook for prjct-cli
4
+ * Post-install hook for prjct-cli (OPTIONAL)
5
5
  *
6
- * Runs automatically after npm install -g prjct-cli
6
+ * Attempts to run setup if npm scripts are enabled.
7
+ * If it fails or doesn't run, no problem - setup will run
8
+ * automatically on first CLI use (like Astro, Vite, etc.)
7
9
  *
8
- * 1. Detects if global install
9
- * 2. Installs Claude Code CLI if not found (automatic)
10
- * 3. Installs/syncs commands to ~/.claude/commands/p/
11
- * 4. Installs/updates global config to ~/.claude/CLAUDE.md
12
- * 5. Migrates all legacy projects automatically
13
- * 6. Shows success message with results
10
+ * This hook is an optimization but NOT critical.
14
11
  *
15
- * ZERO MANUAL STEPS - Everything is automatic
16
- *
17
- * @version 0.8.4
12
+ * @version 0.8.8
18
13
  */
19
14
 
20
15
  const path = require('path')
21
- const { execSync } = require('child_process')
22
- const installer = require('../core/infrastructure/command-installer')
23
- const migrator = require('../core/infrastructure/migrator')
24
- const { VERSION } = require('../core/utils/version')
25
-
26
- // Colors for terminal output
27
- const CYAN = '\x1b[36m'
28
- const GREEN = '\x1b[32m'
29
- const YELLOW = '\x1b[33m'
30
- const MAGENTA = '\x1b[35m'
31
- const WHITE = '\x1b[37m'
32
- const BOLD = '\x1b[1m'
33
- const DIM = '\x1b[2m'
34
- const NC = '\x1b[0m' // No Color
16
+ const setup = require('../core/infrastructure/setup')
35
17
 
36
18
  async function main() {
37
19
  try {
38
20
  // Detect if this is a global install
39
- const isGlobal = await detectGlobalInstall()
21
+ const isGlobal = detectGlobalInstall()
40
22
 
41
23
  if (!isGlobal) {
42
24
  // Skip postinstall for local development installs
43
- console.log(`${DIM}Skipping post-install (local development)${NC}`)
44
25
  return
45
26
  }
46
27
 
47
- console.log('')
48
- console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`)
49
- console.log(`${BOLD}${CYAN}πŸš€ Setting up prjct-cli v${VERSION}${NC}`)
50
- console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`)
51
- console.log('')
52
-
53
- const results = {
54
- claudeInstalled: false,
55
- commandsAdded: 0,
56
- commandsUpdated: 0,
57
- configAction: null,
58
- projectsMigrated: 0
59
- }
60
-
61
- // Step 1: Ensure Claude Code CLI is installed
62
- const hasClaude = await hasClaudeCodeCLI()
63
-
64
- if (!hasClaude) {
65
- const installed = await installClaudeCode()
66
- if (installed) {
67
- results.claudeInstalled = true
68
- } else {
69
- // Cannot continue without Claude Code
70
- showFailureMessage()
71
- return
72
- }
73
- }
74
-
75
- // Step 2: Detect Claude directory (for commands)
76
- const claudeDetected = await installer.detectClaude()
77
-
78
- if (claudeDetected) {
79
- // Step 3: Sync commands
80
- const syncResult = await installer.syncCommands()
81
-
82
- if (syncResult.success) {
83
- results.commandsAdded = syncResult.added
84
- results.commandsUpdated = syncResult.updated
85
- }
86
-
87
- // Step 4: Install global configuration
88
- const configResult = await installer.installGlobalConfig()
89
-
90
- if (configResult.success) {
91
- results.configAction = configResult.action
92
- }
93
-
94
- // Step 5: Migrate legacy projects automatically
95
- const migrationResult = await migrator.migrateAll({
96
- deepScan: false,
97
- cleanupLegacy: true,
98
- dryRun: false
99
- })
100
-
101
- if (migrationResult.successfullyMigrated > 0) {
102
- results.projectsMigrated = migrationResult.successfullyMigrated
103
- }
104
- }
105
-
106
- // Show final success message
107
- showSuccessMessage(results)
28
+ // Run setup (all logic is in core/infrastructure/setup.js)
29
+ await setup.run()
108
30
 
109
31
  } catch (error) {
110
- console.error(`${YELLOW}⚠️ Post-install error: ${error.message}${NC}`)
111
- console.error(`${DIM}You can run 'prjct setup' manually later${NC}`)
32
+ // Silent failure - setup will run on first use anyway
112
33
  // Don't fail the install if post-install has issues
113
34
  process.exit(0)
114
35
  }
@@ -117,7 +38,7 @@ async function main() {
117
38
  /**
118
39
  * Detect if this is a global npm install
119
40
  */
120
- async function detectGlobalInstall() {
41
+ function detectGlobalInstall() {
121
42
  // Check if we're being installed globally
122
43
  const npmConfig = process.env.npm_config_global
123
44
  if (npmConfig === 'true') {
@@ -137,118 +58,6 @@ async function detectGlobalInstall() {
137
58
  return globalPaths.some(globalPath => installPath.includes(globalPath))
138
59
  }
139
60
 
140
- /**
141
- * Check if Claude Code CLI is installed
142
- */
143
- async function hasClaudeCodeCLI() {
144
- try {
145
- execSync('which claude', { stdio: 'ignore' })
146
- return true
147
- } catch {
148
- return false
149
- }
150
- }
151
-
152
- /**
153
- * Install Claude Code CLI
154
- */
155
- async function installClaudeCode() {
156
- try {
157
- console.log(`${YELLOW}πŸ“¦ Claude Code not found. Installing...${NC}`)
158
- console.log('')
159
- execSync('npm install -g @anthropic-ai/claude-code', { stdio: 'inherit' })
160
- console.log('')
161
- console.log(`${GREEN}βœ“${NC} Claude Code installed successfully`)
162
- console.log('')
163
- return true
164
- } catch (error) {
165
- console.log(`${YELLOW}⚠️ Failed to install Claude Code: ${error.message}${NC}`)
166
- console.log(`${DIM}Please install manually: npm install -g @anthropic-ai/claude-code${NC}`)
167
- console.log('')
168
- return false
169
- }
170
- }
171
-
172
- /**
173
- * Show success message with results
174
- */
175
- function showSuccessMessage(results) {
176
- console.log('')
177
- console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`)
178
- console.log('')
179
- console.log(` ${BOLD}${CYAN}β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—${NC}`)
180
- console.log(` ${BOLD}${CYAN}β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β•β•β•šβ•β•β–ˆβ–ˆβ•”β•β•β•${NC}`)
181
- console.log(` ${BOLD}${CYAN}β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β• β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘${NC}`)
182
- console.log(` ${BOLD}${CYAN}β–ˆβ–ˆβ•”β•β•β•β• β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘${NC}`)
183
- console.log(` ${BOLD}${CYAN}β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘${NC}`)
184
- console.log(` ${BOLD}${CYAN}β•šβ•β• β•šβ•β• β•šβ•β• β•šβ•β•β•β•β• β•šβ•β•β•β•β•β• β•šβ•β•${NC}`)
185
- console.log('')
186
- console.log(` ${BOLD}${GREEN}v${VERSION} READY!${NC}`)
187
- console.log('')
188
- console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`)
189
- console.log('')
190
-
191
- // Show what was done
192
- if (results.claudeInstalled) {
193
- console.log(` ${GREEN}βœ“${NC} Claude Code CLI installed`)
194
- } else {
195
- console.log(` ${GREEN}βœ“${NC} Claude Code CLI found`)
196
- }
197
-
198
- const totalCommands = results.commandsAdded + results.commandsUpdated
199
- if (totalCommands > 0) {
200
- const parts = []
201
- if (results.commandsAdded > 0) parts.push(`${results.commandsAdded} new`)
202
- if (results.commandsUpdated > 0) parts.push(`${results.commandsUpdated} updated`)
203
- console.log(` ${GREEN}βœ“${NC} Commands synced (${parts.join(', ')})`)
204
- } else {
205
- console.log(` ${GREEN}βœ“${NC} Commands up to date`)
206
- }
207
-
208
- if (results.configAction === 'created') {
209
- console.log(` ${GREEN}βœ“${NC} Global config created`)
210
- } else if (results.configAction === 'updated') {
211
- console.log(` ${GREEN}βœ“${NC} Global config updated`)
212
- } else if (results.configAction === 'appended') {
213
- console.log(` ${GREEN}βœ“${NC} Global config merged`)
214
- }
215
-
216
- if (results.projectsMigrated > 0) {
217
- console.log(` ${GREEN}βœ“${NC} ${results.projectsMigrated} projects migrated to global storage`)
218
- }
219
-
220
- console.log('')
221
- console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`)
222
- console.log('')
223
- console.log(`${BOLD}Next steps:${NC}`)
224
- console.log(` ${DIM}cd your-project${NC}`)
225
- console.log(` ${GREEN}/p:init${NC}`)
226
- console.log('')
227
- console.log(`${BOLD}${MAGENTA}Happy shipping! πŸš€${NC}`)
228
- console.log('')
229
- }
230
-
231
- /**
232
- * Show failure message
233
- */
234
- function showFailureMessage() {
235
- console.log('')
236
- console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`)
237
- console.log('')
238
- console.log(`${YELLOW}⚠️ Setup incomplete${NC}`)
239
- console.log('')
240
- console.log(`Claude Code is required for prjct-cli.`)
241
- console.log('')
242
- console.log(`Please install manually:`)
243
- console.log(` ${GREEN}npm install -g @anthropic-ai/claude-code${NC}`)
244
- console.log('')
245
- console.log(`Then run:`)
246
- console.log(` ${GREEN}prjct setup${NC}`)
247
- console.log('')
248
- console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`)
249
- console.log('')
250
- }
251
-
252
61
  // Run if executed directly
253
62
  if (require.main === module) {
254
63
  main().catch(error => {
@@ -167,13 +167,13 @@ Semantic understanding, not pattern matching.
167
167
 
168
168
  | Intent | Command | Examples |
169
169
  | ---------- | ---------- | -------------------------------------------- |
170
- | Start task | `/p:now` | "work on X", "starting API", "voy a hacer X" |
171
- | Finish | `/p:done` | "done", "finished", "terminΓ©", "listo" |
170
+ | Start task | `/p:now` | "work on X", "starting API", "begin auth" |
171
+ | Finish | `/p:done` | "done", "finished", "completed", "all set" |
172
172
  | Ship | `/p:ship` | "ship this", "deploy X", "it's ready" |
173
173
  | Idea | `/p:idea` | "I have an idea", "what if we..." |
174
174
  | Progress | `/p:recap` | "show progress", "how am I doing" |
175
175
  | Stuck | `/p:stuck` | "I'm stuck", "help with X" |
176
- | Next | `/p:next` | "what's next", "quΓ© sigue" |
176
+ | Next | `/p:next` | "what's next", "show queue", "priority list" |
177
177
 
178
178
  **Any language works** - if you understand intent, execute the command.
179
179