prjct-cli 0.5.1 → 0.7.0
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 +220 -7
- package/CLAUDE.md +476 -55
- package/README.md +48 -55
- package/bin/prjct +170 -225
- package/core/agentic/command-executor.js +113 -0
- package/core/agentic/context-builder.js +85 -0
- package/core/agentic/prompt-builder.js +86 -0
- package/core/agentic/template-loader.js +104 -0
- package/core/agentic/tool-registry.js +117 -0
- package/core/command-registry.js +597 -0
- package/core/commands.js +2046 -2028
- package/core/domain/agent-generator.js +118 -0
- package/core/domain/analyzer.js +211 -0
- package/core/domain/architect-session.js +300 -0
- package/core/{agents → infrastructure/agents}/claude-agent.js +16 -13
- package/core/{author-detector.js → infrastructure/author-detector.js} +3 -1
- package/core/{capability-installer.js → infrastructure/capability-installer.js} +3 -6
- package/core/{command-installer.js → infrastructure/command-installer.js} +4 -2
- package/core/{config-manager.js → infrastructure/config-manager.js} +4 -4
- package/core/{editors-config.js → infrastructure/editors-config.js} +2 -10
- package/core/{migrator.js → infrastructure/migrator.js} +34 -19
- package/core/{path-manager.js → infrastructure/path-manager.js} +20 -44
- package/core/{session-manager.js → infrastructure/session-manager.js} +45 -105
- package/core/{update-checker.js → infrastructure/update-checker.js} +67 -67
- package/core/{animations-simple.js → utils/animations.js} +3 -23
- package/core/utils/date-helper.js +238 -0
- package/core/utils/file-helper.js +327 -0
- package/core/utils/jsonl-helper.js +206 -0
- package/core/{project-capabilities.js → utils/project-capabilities.js} +21 -22
- package/core/utils/session-helper.js +277 -0
- package/core/{version.js → utils/version.js} +1 -1
- package/package.json +5 -12
- package/templates/agents/AGENTS.md +151 -99
- package/templates/analysis/analyze.md +84 -0
- package/templates/commands/analyze.md +37 -233
- package/templates/commands/bug.md +79 -0
- package/templates/commands/build.md +44 -0
- package/templates/commands/cleanup.md +24 -84
- package/templates/commands/design.md +20 -95
- package/templates/commands/done.md +17 -180
- package/templates/commands/feature.md +113 -0
- package/templates/commands/fix.md +58 -66
- package/templates/commands/git.md +35 -57
- package/templates/commands/help.md +18 -52
- package/templates/commands/idea.md +18 -34
- package/templates/commands/init.md +65 -257
- package/templates/commands/next.md +20 -60
- package/templates/commands/now.md +21 -23
- package/templates/commands/progress.md +40 -73
- package/templates/commands/recap.md +52 -75
- package/templates/commands/roadmap.md +30 -85
- package/templates/commands/ship.md +93 -126
- package/templates/commands/status.md +42 -0
- package/templates/commands/sync.md +19 -205
- package/templates/commands/task.md +19 -79
- package/templates/commands/test.md +25 -71
- package/templates/commands/workflow.md +20 -210
- package/core/agent-generator.js +0 -516
- package/core/analyzer.js +0 -600
- package/core/animations.js +0 -277
- package/core/git-integration.js +0 -401
- package/core/workflow-engine.js +0 -213
- package/core/workflow-prompts.js +0 -192
- package/core/workflow-rules.js +0 -147
- package/scripts/post-install.js +0 -121
- package/scripts/preuninstall.js +0 -94
- package/scripts/verify-installation.sh +0 -158
- package/templates/agents/be.template.md +0 -42
- package/templates/agents/data.template.md +0 -41
- package/templates/agents/devops.template.md +0 -41
- package/templates/agents/fe.template.md +0 -42
- package/templates/agents/mobile.template.md +0 -41
- package/templates/agents/pm.template.md +0 -84
- package/templates/agents/qa.template.md +0 -54
- package/templates/agents/scribe.template.md +0 -95
- package/templates/agents/security.template.md +0 -41
- package/templates/agents/ux.template.md +0 -49
- package/templates/commands/context.md +0 -105
- package/templates/commands/stuck.md +0 -48
- package/templates/examples/natural-language-examples.md +0 -532
- /package/core/{agent-detector.js → infrastructure/agent-detector.js} +0 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const dateHelper = require('./date-helper')
|
|
3
|
+
const jsonlHelper = require('./jsonl-helper')
|
|
4
|
+
const fileHelper = require('./file-helper')
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Session Helper - High-level session operations
|
|
8
|
+
*
|
|
9
|
+
* Simplifies common session workflows by combining:
|
|
10
|
+
* - date-helper (date formatting)
|
|
11
|
+
* - jsonl-helper (JSONL parsing)
|
|
12
|
+
* - file-helper (file operations)
|
|
13
|
+
* - path-manager (path construction)
|
|
14
|
+
*
|
|
15
|
+
* @module session-helper
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Build session file path for today
|
|
20
|
+
*
|
|
21
|
+
* @param {string} projectGlobalPath - Global project path
|
|
22
|
+
* @param {string} layer - Layer (planning/progress/memory)
|
|
23
|
+
* @param {string} filename - Filename (e.g., '2025-10-04.jsonl')
|
|
24
|
+
* @returns {string} - Full path to session file
|
|
25
|
+
*/
|
|
26
|
+
function getTodaySessionFilePath(projectGlobalPath, layer, filename = null) {
|
|
27
|
+
const today = dateHelper.getTodayKey()
|
|
28
|
+
const yearMonth = dateHelper.formatMonth(new Date())
|
|
29
|
+
const [year, month] = yearMonth.split('-')
|
|
30
|
+
|
|
31
|
+
const sessionDir = path.join(projectGlobalPath, layer, 'sessions', year, month)
|
|
32
|
+
|
|
33
|
+
if (filename) {
|
|
34
|
+
return path.join(sessionDir, filename)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return path.join(sessionDir, `${today}.jsonl`)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Ensure today's session directory exists
|
|
42
|
+
*
|
|
43
|
+
* @param {string} projectGlobalPath - Global project path
|
|
44
|
+
* @param {string} layer - Layer (planning/progress/memory)
|
|
45
|
+
* @returns {Promise<string>} - Path to session directory
|
|
46
|
+
*/
|
|
47
|
+
async function ensureTodaySessionDir(projectGlobalPath, layer) {
|
|
48
|
+
const yearMonth = dateHelper.formatMonth(new Date())
|
|
49
|
+
const [year, month] = yearMonth.split('-')
|
|
50
|
+
|
|
51
|
+
const sessionDir = path.join(projectGlobalPath, layer, 'sessions', year, month)
|
|
52
|
+
await fileHelper.ensureDir(sessionDir)
|
|
53
|
+
|
|
54
|
+
return sessionDir
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Write log entry to today's session
|
|
59
|
+
*
|
|
60
|
+
* @param {string} projectGlobalPath - Global project path
|
|
61
|
+
* @param {string} layer - Layer (planning/progress/memory)
|
|
62
|
+
* @param {Object} entry - Log entry to write
|
|
63
|
+
* @param {string} filename - Optional custom filename (defaults to YYYY-MM-DD.jsonl)
|
|
64
|
+
* @returns {Promise<void>}
|
|
65
|
+
*/
|
|
66
|
+
async function writeToSession(projectGlobalPath, layer, entry, filename = null) {
|
|
67
|
+
await ensureTodaySessionDir(projectGlobalPath, layer)
|
|
68
|
+
|
|
69
|
+
const filePath = getTodaySessionFilePath(projectGlobalPath, layer, filename)
|
|
70
|
+
|
|
71
|
+
// Add timestamp if not present
|
|
72
|
+
if (!entry.ts && !entry.timestamp) {
|
|
73
|
+
entry.ts = dateHelper.getTimestamp()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
await jsonlHelper.appendJsonLine(filePath, entry)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Read today's session logs
|
|
81
|
+
*
|
|
82
|
+
* @param {string} projectGlobalPath - Global project path
|
|
83
|
+
* @param {string} layer - Layer (planning/progress/memory)
|
|
84
|
+
* @param {string} filename - Optional custom filename
|
|
85
|
+
* @returns {Promise<Array<Object>>} - Array of log entries
|
|
86
|
+
*/
|
|
87
|
+
async function readTodaySession(projectGlobalPath, layer, filename = null) {
|
|
88
|
+
const filePath = getTodaySessionFilePath(projectGlobalPath, layer, filename)
|
|
89
|
+
return await jsonlHelper.readJsonLines(filePath)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Read session logs for a date range
|
|
94
|
+
*
|
|
95
|
+
* @param {string} projectGlobalPath - Global project path
|
|
96
|
+
* @param {string} layer - Layer (planning/progress/memory)
|
|
97
|
+
* @param {number} daysBack - Number of days to look back
|
|
98
|
+
* @returns {Promise<Array<Object>>} - Array of all log entries
|
|
99
|
+
*/
|
|
100
|
+
async function readRecentSessions(projectGlobalPath, layer, daysBack = 7) {
|
|
101
|
+
const fromDate = dateHelper.getDaysAgo(daysBack)
|
|
102
|
+
const toDate = new Date()
|
|
103
|
+
|
|
104
|
+
const dates = dateHelper.getDateRange(fromDate, toDate)
|
|
105
|
+
const allEntries = []
|
|
106
|
+
|
|
107
|
+
for (const date of dates) {
|
|
108
|
+
const yearMonth = dateHelper.formatMonth(date)
|
|
109
|
+
const dateKey = dateHelper.getDateKey(date)
|
|
110
|
+
const [year, month] = yearMonth.split('-')
|
|
111
|
+
|
|
112
|
+
const filePath = path.join(
|
|
113
|
+
projectGlobalPath,
|
|
114
|
+
layer,
|
|
115
|
+
'sessions',
|
|
116
|
+
year,
|
|
117
|
+
month,
|
|
118
|
+
`${dateKey}.jsonl`
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
const entries = await jsonlHelper.readJsonLines(filePath)
|
|
122
|
+
allEntries.push(...entries)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return allEntries
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Get session statistics for a layer
|
|
130
|
+
*
|
|
131
|
+
* @param {string} projectGlobalPath - Global project path
|
|
132
|
+
* @param {string} layer - Layer (planning/progress/memory)
|
|
133
|
+
* @param {number} daysBack - Number of days to analyze
|
|
134
|
+
* @returns {Promise<Object>} - Statistics object
|
|
135
|
+
*/
|
|
136
|
+
async function getSessionStats(projectGlobalPath, layer, daysBack = 30) {
|
|
137
|
+
const entries = await readRecentSessions(projectGlobalPath, layer, daysBack)
|
|
138
|
+
|
|
139
|
+
// Group by type
|
|
140
|
+
const byType = {}
|
|
141
|
+
for (const entry of entries) {
|
|
142
|
+
const type = entry.type || 'unknown'
|
|
143
|
+
byType[type] = (byType[type] || 0) + 1
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Group by date
|
|
147
|
+
const byDate = {}
|
|
148
|
+
for (const entry of entries) {
|
|
149
|
+
const timestamp = entry.ts || entry.timestamp
|
|
150
|
+
if (timestamp) {
|
|
151
|
+
const date = dateHelper.getDateKey(new Date(timestamp))
|
|
152
|
+
byDate[date] = (byDate[date] || 0) + 1
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
totalEntries: entries.length,
|
|
158
|
+
byType,
|
|
159
|
+
byDate,
|
|
160
|
+
activeDays: Object.keys(byDate).length,
|
|
161
|
+
averagePerDay: entries.length / Math.max(daysBack, 1),
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Archive old session data (move sessions older than N days)
|
|
167
|
+
*
|
|
168
|
+
* @param {string} projectGlobalPath - Global project path
|
|
169
|
+
* @param {string} layer - Layer (planning/progress/memory)
|
|
170
|
+
* @param {number} daysToKeep - Keep sessions newer than this (default: 30)
|
|
171
|
+
* @returns {Promise<Object>} - Archive result
|
|
172
|
+
*/
|
|
173
|
+
async function archiveOldSessions(projectGlobalPath, layer, daysToKeep = 30) {
|
|
174
|
+
const cutoffDate = dateHelper.getDaysAgo(daysToKeep)
|
|
175
|
+
const archiveDir = path.join(projectGlobalPath, layer, 'archive')
|
|
176
|
+
await fileHelper.ensureDir(archiveDir)
|
|
177
|
+
|
|
178
|
+
const sessionsDir = path.join(projectGlobalPath, layer, 'sessions')
|
|
179
|
+
|
|
180
|
+
// Find all session files older than cutoff
|
|
181
|
+
const archived = []
|
|
182
|
+
const errors = []
|
|
183
|
+
|
|
184
|
+
try {
|
|
185
|
+
const years = await fileHelper.listFiles(sessionsDir, { dirsOnly: true })
|
|
186
|
+
|
|
187
|
+
for (const year of years) {
|
|
188
|
+
const yearPath = path.join(sessionsDir, year)
|
|
189
|
+
const months = await fileHelper.listFiles(yearPath, { dirsOnly: true })
|
|
190
|
+
|
|
191
|
+
for (const month of months) {
|
|
192
|
+
const monthPath = path.join(yearPath, month)
|
|
193
|
+
const sessionFiles = await fileHelper.listFiles(monthPath, { filesOnly: true })
|
|
194
|
+
|
|
195
|
+
for (const filename of sessionFiles) {
|
|
196
|
+
// Parse date from filename (YYYY-MM-DD.jsonl)
|
|
197
|
+
const dateMatch = filename.match(/(\d{4}-\d{2}-\d{2})/)
|
|
198
|
+
if (!dateMatch) continue
|
|
199
|
+
|
|
200
|
+
const sessionDate = new Date(dateMatch[1])
|
|
201
|
+
if (sessionDate < cutoffDate) {
|
|
202
|
+
const sourcePath = path.join(monthPath, filename)
|
|
203
|
+
const destPath = path.join(archiveDir, filename)
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
await fileHelper.moveFile(sourcePath, destPath)
|
|
207
|
+
archived.push(filename)
|
|
208
|
+
} catch (error) {
|
|
209
|
+
errors.push({ filename, error: error.message })
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
} catch (error) {
|
|
216
|
+
// Sessions directory might not exist yet
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
archived: archived.length,
|
|
221
|
+
files: archived,
|
|
222
|
+
errors,
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Clean empty session directories
|
|
228
|
+
*
|
|
229
|
+
* @param {string} projectGlobalPath - Global project path
|
|
230
|
+
* @param {string} layer - Layer (planning/progress/memory)
|
|
231
|
+
* @returns {Promise<number>} - Number of directories removed
|
|
232
|
+
*/
|
|
233
|
+
async function cleanEmptySessionDirs(projectGlobalPath, layer) {
|
|
234
|
+
const sessionsDir = path.join(projectGlobalPath, layer, 'sessions')
|
|
235
|
+
let cleaned = 0
|
|
236
|
+
|
|
237
|
+
try {
|
|
238
|
+
const years = await fileHelper.listFiles(sessionsDir, { dirsOnly: true })
|
|
239
|
+
|
|
240
|
+
for (const year of years) {
|
|
241
|
+
const yearPath = path.join(sessionsDir, year)
|
|
242
|
+
const months = await fileHelper.listFiles(yearPath, { dirsOnly: true })
|
|
243
|
+
|
|
244
|
+
for (const month of months) {
|
|
245
|
+
const monthPath = path.join(yearPath, month)
|
|
246
|
+
const files = await fileHelper.listFiles(monthPath)
|
|
247
|
+
|
|
248
|
+
if (files.length === 0) {
|
|
249
|
+
await fileHelper.deleteDir(monthPath)
|
|
250
|
+
cleaned++
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Check if year directory is now empty
|
|
255
|
+
const remainingMonths = await fileHelper.listFiles(yearPath, { dirsOnly: true })
|
|
256
|
+
if (remainingMonths.length === 0) {
|
|
257
|
+
await fileHelper.deleteDir(yearPath)
|
|
258
|
+
cleaned++
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
} catch (error) {
|
|
262
|
+
// Sessions directory might not exist
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return cleaned
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
module.exports = {
|
|
269
|
+
getTodaySessionFilePath,
|
|
270
|
+
ensureTodaySessionDir,
|
|
271
|
+
writeToSession,
|
|
272
|
+
readTodaySession,
|
|
273
|
+
readRecentSessions,
|
|
274
|
+
getSessionStats,
|
|
275
|
+
archiveOldSessions,
|
|
276
|
+
cleanEmptySessionDirs,
|
|
277
|
+
}
|
|
@@ -24,7 +24,7 @@ function getVersion() {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
try {
|
|
27
|
-
const packageJsonPath = path.join(__dirname, '..', 'package.json')
|
|
27
|
+
const packageJsonPath = path.join(__dirname, '..', '..', 'package.json')
|
|
28
28
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))
|
|
29
29
|
cachedVersion = packageJson.version
|
|
30
30
|
cachedPackageJson = packageJson
|
package/package.json
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prjct-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
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": {
|
|
7
|
-
"prjct": "
|
|
7
|
+
"prjct": "bin/prjct"
|
|
8
8
|
},
|
|
9
9
|
"publishConfig": {
|
|
10
10
|
"access": "public",
|
|
11
11
|
"registry": "https://registry.npmjs.org"
|
|
12
12
|
},
|
|
13
13
|
"scripts": {
|
|
14
|
-
"postinstall": "node scripts/post-install.js",
|
|
15
|
-
"preuninstall": "node scripts/preuninstall.js",
|
|
16
14
|
"install-global": "./scripts/install.sh",
|
|
17
15
|
"test": "echo 'No tests configured'",
|
|
16
|
+
"validate": "node scripts/validate-commands.js",
|
|
18
17
|
"lint": "eslint \"**/*.js\" --ignore-pattern \"node_modules/**\" --ignore-pattern \"website/**\"",
|
|
19
18
|
"lint:fix": "eslint \"**/*.js\" --fix --ignore-pattern \"node_modules/**\" --ignore-pattern \"website/**\"",
|
|
20
19
|
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,css,md}\" --config .config/.prettierrc --ignore-path .config/.prettierignore",
|
|
@@ -40,13 +39,12 @@
|
|
|
40
39
|
"license": "MIT",
|
|
41
40
|
"dependencies": {
|
|
42
41
|
"chalk": "^4.1.2",
|
|
43
|
-
"commander": "^11.0.0",
|
|
44
|
-
"ora": "^5.4.1",
|
|
45
42
|
"prompts": "^2.4.2"
|
|
46
43
|
},
|
|
47
44
|
"devDependencies": {
|
|
48
45
|
"@types/node": "^20.0.0",
|
|
49
46
|
"eslint": "^8.57.1",
|
|
47
|
+
"eslint-config-prettier": "^10.1.8",
|
|
50
48
|
"eslint-config-standard": "^17.1.0",
|
|
51
49
|
"eslint-plugin-import": "^2.32.0",
|
|
52
50
|
"eslint-plugin-n": "^16.6.2",
|
|
@@ -57,7 +55,7 @@
|
|
|
57
55
|
},
|
|
58
56
|
"repository": {
|
|
59
57
|
"type": "git",
|
|
60
|
-
"url": "https://github.com/jlopezlira/prjct-cli"
|
|
58
|
+
"url": "git+https://github.com/jlopezlira/prjct-cli.git"
|
|
61
59
|
},
|
|
62
60
|
"bugs": {
|
|
63
61
|
"url": "https://github.com/jlopezlira/prjct-cli/issues"
|
|
@@ -71,9 +69,6 @@
|
|
|
71
69
|
"core/",
|
|
72
70
|
"templates/",
|
|
73
71
|
"scripts/install.sh",
|
|
74
|
-
"scripts/verify-installation.sh",
|
|
75
|
-
"scripts/post-install.js",
|
|
76
|
-
"scripts/preuninstall.js",
|
|
77
72
|
"LICENSE",
|
|
78
73
|
"README.md",
|
|
79
74
|
"CHANGELOG.md",
|
|
@@ -81,8 +76,6 @@
|
|
|
81
76
|
],
|
|
82
77
|
"trustedDependencies": [
|
|
83
78
|
"chalk",
|
|
84
|
-
"commander",
|
|
85
|
-
"ora",
|
|
86
79
|
"prompts"
|
|
87
80
|
]
|
|
88
81
|
}
|
|
@@ -1,37 +1,112 @@
|
|
|
1
1
|
# AGENTS.md
|
|
2
2
|
|
|
3
|
-
AI assistant guidance for prjct-cli.
|
|
3
|
+
AI assistant guidance for **prjct-cli** - developer momentum tool for solo builders & small teams (2-5 people). Just ship. No BS.
|
|
4
|
+
|
|
5
|
+
## What This Is
|
|
6
|
+
|
|
7
|
+
**NOT** project management. NO sprints, story points, ceremonies, or meetings.
|
|
8
|
+
|
|
9
|
+
**IS** frictionless progress tracking. Talk naturally, ship features, celebrate wins.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Dynamic Agent Generation
|
|
14
|
+
|
|
15
|
+
**YOU decide** what specialists to generate based on project analysis. No predetermined lists.
|
|
16
|
+
|
|
17
|
+
### When to Generate Agents
|
|
18
|
+
|
|
19
|
+
From commands that analyze the project:
|
|
20
|
+
|
|
21
|
+
- `/p:sync` - Sync and generate agents
|
|
22
|
+
- `/p:init` - Initialize with existing code
|
|
23
|
+
- `/p:architect` - After generating project plan
|
|
24
|
+
|
|
25
|
+
### How to Generate
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
const generator = new AgentGenerator(projectId)
|
|
29
|
+
|
|
30
|
+
await generator.generateDynamicAgent('agent-name', {
|
|
31
|
+
role: 'Clear Role Description',
|
|
32
|
+
expertise: 'Specific technologies, versions, tools',
|
|
33
|
+
responsibilities: 'What they handle in this project',
|
|
34
|
+
projectContext: {
|
|
35
|
+
/* optional context */
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Example Usage
|
|
41
|
+
|
|
42
|
+
**1. Read the analysis first:**
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
// Read analysis/repo-summary.md to understand the stack
|
|
46
|
+
const analysis = await readAnalysis('analysis/repo-summary.md')
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**2. Generate specialists for technologies YOU find:**
|
|
50
|
+
|
|
51
|
+
```javascript
|
|
52
|
+
// For EACH major technology found in the analysis, create a specialist
|
|
53
|
+
// Use descriptive names and specific details from the analysis
|
|
54
|
+
|
|
55
|
+
await generator.generateDynamicAgent('descriptive-name', {
|
|
56
|
+
role: 'Clear role based on what you found',
|
|
57
|
+
expertise: 'Specific versions, frameworks, tools from analysis',
|
|
58
|
+
responsibilities: 'What this agent handles in THIS specific project',
|
|
59
|
+
projectContext: {
|
|
60
|
+
/* any relevant context from analysis */
|
|
61
|
+
},
|
|
62
|
+
})
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**You decide everything** - read the analysis, understand the stack, generate appropriate specialists. No predetermined lists, no assumptions, no limitations.
|
|
66
|
+
|
|
67
|
+
### Guidelines
|
|
68
|
+
|
|
69
|
+
1. **Read analysis** - Understand full stack from analysis/repo-summary.md
|
|
70
|
+
2. **Create specialists** - For each major technology found
|
|
71
|
+
3. **Name descriptively** - `go-backend` not `be`, `vuejs-frontend` not `fe`
|
|
72
|
+
4. **Be specific** - Include versions, frameworks, tools
|
|
73
|
+
5. **No predetermined list** - ANY stack works (Elixir, Phoenix, Svelte, etc.)
|
|
74
|
+
6. **Follow project plan** - Only generate agents for technologies found in project plan and related to your role
|
|
75
|
+
7. **Best practices** - Allways use best practices for your role
|
|
76
|
+
|
|
77
|
+
---
|
|
4
78
|
|
|
5
79
|
## Talk Naturally
|
|
6
80
|
|
|
7
|
-
**
|
|
81
|
+
**Zero memorization** - just describe what you want!
|
|
8
82
|
|
|
9
|
-
|
|
83
|
+
Works in **any language** via semantic understanding.
|
|
10
84
|
|
|
11
85
|
**Examples:**
|
|
86
|
+
|
|
12
87
|
```
|
|
13
|
-
|
|
88
|
+
Start working:
|
|
14
89
|
→ "I want to build the login page"
|
|
15
|
-
→ "Let me work on authentication"
|
|
16
|
-
→ "Voy a hacer el dashboard"
|
|
17
90
|
→ Command: /p:now
|
|
18
91
|
|
|
19
|
-
|
|
20
|
-
→ "I'm done" | "
|
|
92
|
+
Finished:
|
|
93
|
+
→ "I'm done" | "completed"
|
|
21
94
|
→ Command: /p:done
|
|
22
95
|
|
|
23
|
-
|
|
96
|
+
Ship:
|
|
24
97
|
→ "ship this" | "deploy it" | "ready to launch"
|
|
25
98
|
→ Command: /p:ship
|
|
26
99
|
```
|
|
27
100
|
|
|
28
|
-
**Both work
|
|
29
|
-
|
|
30
|
-
-
|
|
101
|
+
**Both work:**
|
|
102
|
+
|
|
103
|
+
- Natural: "I want to start building auth"
|
|
104
|
+
- Direct: `/p:now "building auth"`
|
|
31
105
|
|
|
32
106
|
## Architecture
|
|
33
107
|
|
|
34
108
|
**Global**: `~/.prjct-cli/projects/{id}/`
|
|
109
|
+
|
|
35
110
|
```
|
|
36
111
|
core/ # now.md, next.md, context.md
|
|
37
112
|
progress/ # shipped.md, metrics.md
|
|
@@ -42,123 +117,100 @@ memory/ # context.jsonl
|
|
|
42
117
|
|
|
43
118
|
**Local**: `.prjct/prjct.config.json`
|
|
44
119
|
|
|
45
|
-
## MCP Servers
|
|
46
|
-
|
|
47
|
-
- **Context7**: Library docs (always on)
|
|
48
|
-
- **Filesystem**: File ops
|
|
49
|
-
- **Memory**: Persistence
|
|
50
|
-
- **Sequential**: Complex reasoning
|
|
51
|
-
|
|
52
120
|
## Quick Start
|
|
53
121
|
|
|
54
|
-
1.
|
|
55
|
-
2.
|
|
56
|
-
3. Or
|
|
122
|
+
1. `/p:init` - Initialize
|
|
123
|
+
2. `/p:help` - Guide
|
|
124
|
+
3. Or talk: "I want to start [task]"
|
|
57
125
|
|
|
58
126
|
## Commands
|
|
59
127
|
|
|
60
|
-
**💡 Tip**:
|
|
61
|
-
|
|
62
|
-
| Command
|
|
63
|
-
|
|
64
|
-
| `/p:help`
|
|
65
|
-
| `/p:init`
|
|
66
|
-
| `/p:now [task]`
|
|
67
|
-
| `/p:done`
|
|
68
|
-
| `/p:ship <feature>`
|
|
69
|
-
| `/p:next`
|
|
70
|
-
| `/p:idea <text>`
|
|
71
|
-
| `/p:recap`
|
|
72
|
-
| `/p:progress [period]` | "how am I doing?" |
|
|
73
|
-
| `/p:stuck <issue>`
|
|
74
|
-
| `/p:context`
|
|
75
|
-
| `/p:
|
|
76
|
-
| `/p:
|
|
77
|
-
| `/p:
|
|
78
|
-
| `/p:git` | - | Smart commits with context |
|
|
79
|
-
| `/p:fix` | "help me fix [x]" | Quick problem solving |
|
|
80
|
-
| `/p:test` | "run tests" | Execute + report |
|
|
81
|
-
| `/p:design` | "design [x]" | Generate diagrams + specs |
|
|
82
|
-
| `/p:cleanup` | "clean up code" | Remove dead code/deps |
|
|
128
|
+
**💡 Tip**: `/p:help` for interactive guide
|
|
129
|
+
|
|
130
|
+
| Command | Say This | Action |
|
|
131
|
+
| ---------------------- | ----------------- | ----------------- |
|
|
132
|
+
| `/p:help` | "help" | Interactive guide |
|
|
133
|
+
| `/p:init` | - | Create structure |
|
|
134
|
+
| `/p:now [task]` | "start [task]" | Set current task |
|
|
135
|
+
| `/p:done` | "I'm done" | Complete & next |
|
|
136
|
+
| `/p:ship <feature>` | "ship [feature]" | Celebrate win |
|
|
137
|
+
| `/p:next` | "what's next?" | Show queue |
|
|
138
|
+
| `/p:idea <text>` | "idea about [x]" | Capture ideas |
|
|
139
|
+
| `/p:recap` | "show progress" | Overview |
|
|
140
|
+
| `/p:progress [period]` | "how am I doing?" | Metrics |
|
|
141
|
+
| `/p:stuck <issue>` | "I'm stuck" | Get help |
|
|
142
|
+
| `/p:context` | "show context" | Display state |
|
|
143
|
+
| `/p:analyze` | "analyze repo" | Generate summary |
|
|
144
|
+
| `/p:design` | "design [x]" | Generate specs |
|
|
145
|
+
| `/p:cleanup` | "clean up" | Remove dead code |
|
|
83
146
|
|
|
84
147
|
## How It Works
|
|
85
148
|
|
|
86
|
-
**
|
|
87
|
-
- System detects intent from your message
|
|
88
|
-
- Maps to appropriate command automatically
|
|
89
|
-
- Responds conversationally with options
|
|
90
|
-
- Always suggests what to do next
|
|
149
|
+
**Natural conversation:**
|
|
91
150
|
|
|
92
|
-
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
151
|
+
- Detect intent
|
|
152
|
+
- Map to command
|
|
153
|
+
- Respond with options
|
|
154
|
+
- Suggest next steps
|
|
96
155
|
|
|
97
|
-
**
|
|
156
|
+
**Every response:**
|
|
98
157
|
|
|
99
|
-
|
|
158
|
+
- What you did
|
|
159
|
+
- Natural options
|
|
160
|
+
- Command alternatives
|
|
100
161
|
|
|
101
|
-
|
|
162
|
+
**Zero memorization!**
|
|
102
163
|
|
|
103
|
-
|
|
164
|
+
## Intent Detection
|
|
104
165
|
|
|
105
|
-
|
|
166
|
+
Semantic understanding, not pattern matching.
|
|
106
167
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
168
|
+
| Intent | Command | Examples |
|
|
169
|
+
| ---------- | ---------- | -------------------------------------------- |
|
|
170
|
+
| Start task | `/p:now` | "work on X", "starting API", "voy a hacer X" |
|
|
171
|
+
| Finish | `/p:done` | "done", "finished", "terminé", "listo" |
|
|
172
|
+
| Ship | `/p:ship` | "ship this", "deploy X", "it's ready" |
|
|
173
|
+
| Idea | `/p:idea` | "I have an idea", "what if we..." |
|
|
174
|
+
| Progress | `/p:recap` | "show progress", "how am I doing" |
|
|
175
|
+
| Stuck | `/p:stuck` | "I'm stuck", "help with X" |
|
|
176
|
+
| Next | `/p:next` | "what's next", "qué sigue" |
|
|
112
177
|
|
|
113
|
-
|
|
178
|
+
**Any language works** - if you understand intent, execute the command.
|
|
114
179
|
|
|
115
|
-
|
|
116
|
-
|-------------|---------|-------------------------------|
|
|
117
|
-
| Start/focus on task | `/p:now` | "let me work on X", "starting the API", "voy a hacer X" |
|
|
118
|
-
| Finished current work | `/p:done` | "done", "finished", "terminé", "completed", "listo" |
|
|
119
|
-
| Ship/deploy feature | `/p:ship` | "ship this", "deploy X", "it's ready", "let's launch" |
|
|
120
|
-
| Capture an idea | `/p:idea` | "I have an idea", "what if we...", "tengo una idea" |
|
|
121
|
-
| Check progress/status | `/p:recap` | "show progress", "how am I doing", "muéstrame el avance" |
|
|
122
|
-
| Stuck on problem | `/p:stuck` | "I'm stuck", "help with X", "estoy atascado" |
|
|
123
|
-
| What to work on next | `/p:next` | "what's next", "qué sigue", "what should I do" |
|
|
180
|
+
### Example
|
|
124
181
|
|
|
125
|
-
**
|
|
182
|
+
**User:** "I want to start building the login page"
|
|
126
183
|
|
|
127
|
-
|
|
184
|
+
**Your reasoning:**
|
|
128
185
|
|
|
129
|
-
|
|
186
|
+
- Intent: Start working
|
|
187
|
+
- Command: `/p:now`
|
|
188
|
+
- Param: "building the login page"
|
|
130
189
|
|
|
131
|
-
**
|
|
132
|
-
- Intent detected: User wants to begin working on something
|
|
133
|
-
- Appropriate command: `/p:now`
|
|
134
|
-
- Parameter to extract: "building the login page"
|
|
190
|
+
**Response:**
|
|
135
191
|
|
|
136
|
-
**Your Response:**
|
|
137
192
|
```
|
|
138
|
-
💬
|
|
193
|
+
💬 Understood: "start building the login page"
|
|
139
194
|
⚡ Executing: /p:now "building the login page"
|
|
140
195
|
|
|
141
|
-
✅ Starting
|
|
196
|
+
✅ Starting: building the login page
|
|
142
197
|
|
|
143
|
-
|
|
198
|
+
Next:
|
|
144
199
|
• Say "I'm done" when finished
|
|
145
200
|
• Or: /p:done
|
|
146
201
|
```
|
|
147
202
|
|
|
148
|
-
### Works in Any Language
|
|
149
|
-
|
|
150
|
-
If you understand the user's intent in **any language**, execute the command:
|
|
151
|
-
- English: "I want to start the API"
|
|
152
|
-
- Spanish: "Quiero empezar con la autenticación"
|
|
153
|
-
- Casual: "gonna work on that login thing"
|
|
154
|
-
- Formal: "I shall commence development of the authentication module"
|
|
155
|
-
|
|
156
|
-
All map to: `/p:now`
|
|
157
|
-
|
|
158
203
|
## Implementation
|
|
159
204
|
|
|
160
205
|
- All ops atomic
|
|
161
|
-
- Log to `memory/context.jsonl`
|
|
162
|
-
- Conversational responses
|
|
163
|
-
- Intent detection (
|
|
164
|
-
- Handle missing files
|
|
206
|
+
- Log to `memory/context.jsonl`
|
|
207
|
+
- Conversational responses
|
|
208
|
+
- Intent detection (any language)
|
|
209
|
+
- Handle missing files
|
|
210
|
+
|
|
211
|
+
## MCP Servers
|
|
212
|
+
|
|
213
|
+
- **Context7**: Library docs (always on)
|
|
214
|
+
- **Filesystem**: File ops
|
|
215
|
+
- **Memory**: Persistence
|
|
216
|
+
- **Sequential**: Complex reasoning
|