prjct-cli 0.8.6 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +216 -0
- package/CLAUDE.md +34 -0
- package/core/agentic/agent-router.js +482 -0
- package/core/agentic/command-executor.js +70 -15
- package/core/agentic/context-builder.js +4 -3
- package/core/agentic/context-filter.js +545 -0
- package/core/agentic/prompt-builder.js +48 -38
- package/core/agentic/tool-registry.js +35 -0
- package/core/command-registry.js +104 -164
- package/core/commands.js +84 -0
- package/core/domain/agent-generator.js +55 -44
- package/core/domain/architecture-generator.js +561 -0
- package/core/domain/task-stack.js +496 -0
- package/core/infrastructure/legacy-installer-detector.js +546 -0
- package/core/infrastructure/session-manager.js +14 -2
- package/core/infrastructure/setup.js +29 -11
- package/core/utils/jsonl-helper.js +137 -0
- package/package.json +1 -1
- package/scripts/install.sh +45 -8
- package/scripts/postinstall.js +5 -5
- package/templates/agents/AGENTS.md +3 -3
- package/templates/commands/analyze.md +10 -53
- package/templates/commands/ask.md +25 -338
- package/templates/commands/bug.md +11 -70
- package/templates/commands/build.md +8 -35
- package/templates/commands/cleanup.md +9 -32
- package/templates/commands/dash.md +241 -0
- package/templates/commands/design.md +5 -28
- package/templates/commands/done.md +6 -20
- package/templates/commands/feature.md +12 -225
- package/templates/commands/help.md +26 -313
- package/templates/commands/idea.md +7 -25
- package/templates/commands/init.md +15 -191
- package/templates/commands/migrate-all.md +25 -84
- package/templates/commands/next.md +6 -26
- package/templates/commands/now.md +6 -25
- package/templates/commands/pause.md +18 -0
- package/templates/commands/progress.md +5 -50
- package/templates/commands/recap.md +5 -54
- package/templates/commands/resume.md +97 -0
- package/templates/commands/ship.md +14 -135
- package/templates/commands/status.md +7 -32
- package/templates/commands/suggest.md +36 -495
- package/templates/commands/sync.md +7 -24
- package/templates/commands/work.md +44 -0
- package/templates/commands/workflow.md +3 -25
- package/templates/planning-methodology.md +195 -0
|
@@ -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
package/scripts/install.sh
CHANGED
|
@@ -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
|
-
|
|
20
|
-
|
|
21
|
-
echo -e "
|
|
22
|
-
echo ""
|
|
23
|
-
echo -e "
|
|
24
|
-
echo -e "
|
|
25
|
-
echo
|
|
26
|
-
echo -e "
|
|
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 ""
|
package/scripts/postinstall.js
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* Post-install hook for prjct-cli (OPTIONAL)
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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.)
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* This hook is an optimization but NOT critical.
|
|
11
11
|
*
|
|
12
|
-
* @version 0.8.
|
|
12
|
+
* @version 0.8.8
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
const path = require('path')
|
|
@@ -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", "
|
|
171
|
-
| Finish | `/p:done` | "done", "finished", "
|
|
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", "
|
|
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
|
|
|
@@ -1,63 +1,20 @@
|
|
|
1
1
|
---
|
|
2
2
|
allowed-tools: [Read, Grep, Glob, Bash, TodoWrite]
|
|
3
|
-
description: 'Analyze
|
|
3
|
+
description: 'Analyze repo + generate summary'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /p:analyze
|
|
7
7
|
|
|
8
8
|
## Flow
|
|
9
|
+
1. Scan structure → Detect tech (package.json, Gemfile, etc.)
|
|
10
|
+
2. Analyze patterns → Git status
|
|
11
|
+
3. Generate → `analysis/repo-summary.md`
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
6. Save: `analysis/repo-summary.md`
|
|
16
|
-
|
|
17
|
-
## Report Format
|
|
18
|
-
|
|
19
|
-
```markdown
|
|
20
|
-
# Repository Analysis
|
|
21
|
-
|
|
22
|
-
## Overview
|
|
23
|
-
|
|
24
|
-
- Type: {type}
|
|
25
|
-
- Language: {lang}
|
|
26
|
-
- Framework: {framework}
|
|
27
|
-
|
|
28
|
-
## Git Status
|
|
29
|
-
|
|
30
|
-
- Last commit: {hash} "{msg}" ({time_ago})
|
|
31
|
-
- Status: {clean/has_changes}
|
|
32
|
-
|
|
33
|
-
## Stack
|
|
34
|
-
|
|
35
|
-
- Languages: {list}
|
|
36
|
-
- Frameworks: {list}
|
|
37
|
-
- Dependencies: {count}
|
|
38
|
-
|
|
39
|
-
## Architecture
|
|
40
|
-
|
|
41
|
-
- Pattern: {pattern}
|
|
42
|
-
- Entry points: {files}
|
|
43
|
-
|
|
44
|
-
## Recommended Agents
|
|
45
|
-
|
|
46
|
-
Base (6): PM, UX, FE, BE, QA, Scribe
|
|
47
|
-
Additional: {conditional_agents}
|
|
48
|
-
|
|
49
|
-
Generated: {timestamp}
|
|
50
|
-
```
|
|
13
|
+
## Report
|
|
14
|
+
- Overview: type, lang, framework
|
|
15
|
+
- Stack: technologies detected
|
|
16
|
+
- Architecture: patterns, entry points
|
|
17
|
+
- Agents: recommend specialists
|
|
51
18
|
|
|
52
19
|
## Response
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
🔍 Analysis complete!
|
|
56
|
-
|
|
57
|
-
Project: {name} ({type})
|
|
58
|
-
Stack: {stack}
|
|
59
|
-
|
|
60
|
-
📄 Full report: analysis/repo-summary.md
|
|
61
|
-
|
|
62
|
-
/p:roadmap | /p:now
|
|
63
|
-
```
|
|
20
|
+
`🔍 {project} | Stack: {tech} | Saved: analysis/repo-summary.md`
|