prjct-cli 0.4.9 → 0.5.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +316 -0
  2. package/CLAUDE.md +109 -3
  3. package/README.md +228 -93
  4. package/core/agent-detector.js +55 -122
  5. package/core/agent-generator.js +516 -0
  6. package/core/command-installer.js +104 -890
  7. package/core/commands.js +3 -18
  8. package/core/editors-config.js +9 -57
  9. package/core/git-integration.js +401 -0
  10. package/package.json +10 -7
  11. package/scripts/install.sh +0 -1
  12. package/templates/agents/be.template.md +42 -0
  13. package/templates/agents/data.template.md +41 -0
  14. package/templates/agents/devops.template.md +41 -0
  15. package/templates/agents/fe.template.md +42 -0
  16. package/templates/agents/mobile.template.md +41 -0
  17. package/templates/agents/pm.template.md +84 -0
  18. package/templates/agents/qa.template.md +54 -0
  19. package/templates/agents/scribe.template.md +95 -0
  20. package/templates/agents/security.template.md +41 -0
  21. package/templates/agents/ux.template.md +49 -0
  22. package/templates/commands/analyze.md +137 -3
  23. package/templates/commands/done.md +154 -5
  24. package/templates/commands/init.md +61 -3
  25. package/templates/commands/ship.md +146 -6
  26. package/templates/commands/sync.md +220 -0
  27. package/templates/examples/natural-language-examples.md +234 -22
  28. package/core/agents/codex-agent.js +0 -256
  29. package/core/agents/terminal-agent.js +0 -465
  30. package/templates/workflows/analyze.md +0 -159
  31. package/templates/workflows/cleanup.md +0 -73
  32. package/templates/workflows/context.md +0 -72
  33. package/templates/workflows/design.md +0 -88
  34. package/templates/workflows/done.md +0 -20
  35. package/templates/workflows/fix.md +0 -201
  36. package/templates/workflows/git.md +0 -192
  37. package/templates/workflows/help.md +0 -13
  38. package/templates/workflows/idea.md +0 -22
  39. package/templates/workflows/init.md +0 -80
  40. package/templates/workflows/natural-language-handler.md +0 -183
  41. package/templates/workflows/next.md +0 -44
  42. package/templates/workflows/now.md +0 -19
  43. package/templates/workflows/progress.md +0 -113
  44. package/templates/workflows/recap.md +0 -66
  45. package/templates/workflows/roadmap.md +0 -95
  46. package/templates/workflows/ship.md +0 -18
  47. package/templates/workflows/stuck.md +0 -25
  48. package/templates/workflows/task.md +0 -109
  49. package/templates/workflows/test.md +0 -243
package/core/commands.js CHANGED
@@ -389,23 +389,9 @@ class PrjctCommands {
389
389
  const hasExistingCode = await this.detectExistingCode(projectPath)
390
390
 
391
391
  if (hasExistingCode) {
392
- try {
393
- console.log('šŸ” Analyzing existing codebase...')
394
- const analysisResult = await this.analyze({
395
- sync: true,
396
- silent: true,
397
- }, projectPath)
398
-
399
- if (analysisResult.success && analysisResult.syncResults) {
400
- const sync = analysisResult.syncResults
401
- analysisMessage = '\n\nšŸ“Š Analysis Complete:\n' +
402
- `āœ… Found ${analysisResult.analysis.commands.length} commands, ${analysisResult.analysis.features.length} features\n` +
403
- (sync.tasksMarkedComplete > 0 ? `āœ… Synced ${sync.tasksMarkedComplete} completed tasks\n` : '') +
404
- (sync.featuresAdded > 0 ? `āœ… Added ${sync.featuresAdded} features to shipped.md\n` : '')
405
- }
406
- } catch (error) {
407
- console.error('[prjct] Analysis warning:', error.message)
408
- }
392
+ // Instead of silently analyzing, prompt the AI agent to run /p:analyze workflow
393
+ analysisMessage = '\n\nšŸ“Š Existing codebase detected!\n' +
394
+ `\nšŸ’” Run ${this.agentInfo.config.commandPrefix}analyze to analyze your project and sync tasks`
409
395
  }
410
396
 
411
397
  const displayPath = pathManager.getDisplayPath(globalPath)
@@ -2224,7 +2210,6 @@ ${diagram}
2224
2210
  const chalk = require('chalk')
2225
2211
  console.log('')
2226
2212
  console.log('')
2227
- console.log(chalk.bold.magenta(' (ļ¾‰ā—•ćƒ®ā—•)ノ*:d゚✧'))
2228
2213
  console.log(chalk.bold.cyan(' ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—'))
2229
2214
  console.log(chalk.bold.cyan(' ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•—ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•— ā–ˆā–ˆā•‘ā–ˆā–ˆā•”ā•ā•ā•ā•ā•ā•šā•ā•ā–ˆā–ˆā•”ā•ā•ā•'))
2230
2215
  console.log(chalk.bold.blue(' ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•”ā•ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•”ā• ā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘'))
@@ -3,14 +3,14 @@ const path = require('path')
3
3
  const os = require('os')
4
4
 
5
5
  /**
6
- * EditorsConfig - Manages installed editors tracking configuration
6
+ * EditorsConfig - Manages Claude installation tracking
7
7
  *
8
- * Tracks which AI editors user has installed prjct commands to,
8
+ * Tracks prjct commands installation in Claude (Code + Desktop),
9
9
  * enabling automatic updates when npm package is updated.
10
10
  *
11
11
  * Config location: ~/.prjct-cli/config/installed-editors.json
12
12
  *
13
- * @version 0.4.2
13
+ * @version 0.5.0
14
14
  */
15
15
  class EditorsConfig {
16
16
  constructor() {
@@ -31,7 +31,7 @@ class EditorsConfig {
31
31
  }
32
32
 
33
33
  /**
34
- * Load installed editors configuration
34
+ * Load installation configuration
35
35
  * @returns {Promise<Object|null>} Configuration object or null if not found
36
36
  */
37
37
  async loadConfig() {
@@ -48,21 +48,20 @@ class EditorsConfig {
48
48
  }
49
49
 
50
50
  /**
51
- * Save installed editors configuration
52
- * @param {string[]} editors - Array of editor keys (e.g., ['claude', 'cursor'])
53
- * @param {Object} paths - Object mapping editor keys to installation paths
51
+ * Save installation configuration
54
52
  * @param {string} version - Current prjct-cli version
53
+ * @param {string} claudePath - Path to Claude commands directory
55
54
  * @returns {Promise<boolean>} Success status
56
55
  */
57
- async saveConfig(editors, paths, version) {
56
+ async saveConfig(version, claudePath) {
58
57
  try {
59
58
  await this.ensureConfigDir()
60
59
 
61
60
  const config = {
62
61
  version,
63
- editors,
62
+ editor: 'claude',
64
63
  lastInstall: new Date().toISOString(),
65
- paths,
64
+ path: claudePath,
66
65
  }
67
66
 
68
67
  await fs.writeFile(
@@ -78,53 +77,6 @@ class EditorsConfig {
78
77
  }
79
78
  }
80
79
 
81
- /**
82
- * Get tracked editors from configuration
83
- * @returns {Promise<string[]>} Array of editor keys
84
- */
85
- async getTrackedEditors() {
86
- const config = await this.loadConfig()
87
- return config ? config.editors : []
88
- }
89
-
90
- /**
91
- * Remove an editor from tracked list
92
- * @param {string} editorKey - Editor key to remove
93
- * @returns {Promise<boolean>} Success status
94
- */
95
- async removeTrackedEditor(editorKey) {
96
- try {
97
- const config = await this.loadConfig()
98
- if (!config) return false
99
-
100
- // Remove from editors array
101
- config.editors = config.editors.filter(e => e !== editorKey)
102
-
103
- // Remove from paths object
104
- if (config.paths && config.paths[editorKey]) {
105
- delete config.paths[editorKey]
106
- }
107
-
108
- // Save updated config
109
- await fs.mkdir(this.configDir, { recursive: true })
110
- await fs.writeFile(this.configPath, JSON.stringify(config, null, 2), 'utf-8')
111
-
112
- return true
113
- } catch (error) {
114
- console.error('[editors-config] Error removing tracked editor:', error.message)
115
- return false
116
- }
117
- }
118
-
119
- /**
120
- * Get editor paths from configuration
121
- * @returns {Promise<Object>} Object mapping editor keys to paths
122
- */
123
- async getEditorPaths() {
124
- const config = await this.loadConfig()
125
- return config ? config.paths : {}
126
- }
127
-
128
80
  /**
129
81
  * Get last installed version
130
82
  * @returns {Promise<string|null>} Version string or null
@@ -0,0 +1,401 @@
1
+ const { execSync } = require('child_process')
2
+ const fs = require('fs').promises
3
+
4
+ /**
5
+ * GitIntegration - Git repository analysis and validation
6
+ *
7
+ * Provides git integration for prjct-cli to analyze repository state,
8
+ * validate user claims against actual commits, and track project progress.
9
+ *
10
+ * @version 0.5.0
11
+ */
12
+ class GitIntegration {
13
+ constructor(projectPath = process.cwd()) {
14
+ this.projectPath = projectPath
15
+ }
16
+
17
+ /**
18
+ * Check if current directory is a git repository
19
+ * @returns {Promise<boolean>} True if git repo exists
20
+ */
21
+ async isGitRepo() {
22
+ try {
23
+ execSync('git rev-parse --git-dir', {
24
+ cwd: this.projectPath,
25
+ stdio: 'ignore',
26
+ })
27
+ return true
28
+ } catch {
29
+ return false
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Get information about the last commit
35
+ * @returns {Promise<Object|null>} Commit info or null if no commits
36
+ */
37
+ async getLastCommit() {
38
+ if (!(await this.isGitRepo())) {
39
+ return null
40
+ }
41
+
42
+ try {
43
+ const output = execSync(
44
+ 'git log -1 --format="%H|%s|%ar|%an"',
45
+ {
46
+ cwd: this.projectPath,
47
+ encoding: 'utf-8',
48
+ },
49
+ )
50
+
51
+ const [hash, message, timeAgo, author] = output.trim().split('|')
52
+
53
+ return {
54
+ hash: hash.substring(0, 7), // Short hash
55
+ fullHash: hash,
56
+ message,
57
+ timeAgo,
58
+ author,
59
+ }
60
+ } catch {
61
+ return null // No commits yet
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Get working directory status
67
+ * @returns {Promise<Object|null>} Status info or null if not git repo
68
+ */
69
+ async getWorkingDirStatus() {
70
+ if (!(await this.isGitRepo())) {
71
+ return null
72
+ }
73
+
74
+ try {
75
+ const status = execSync('git status --porcelain', {
76
+ cwd: this.projectPath,
77
+ encoding: 'utf-8',
78
+ })
79
+
80
+ const lines = status.trim().split('\n').filter(Boolean)
81
+
82
+ const modified = lines.filter(
83
+ l => l.startsWith(' M') || l.startsWith('M'),
84
+ ).length
85
+ const added = lines.filter(
86
+ l => l.startsWith('A') || l.startsWith('??'),
87
+ ).length
88
+ const deleted = lines.filter(
89
+ l => l.startsWith(' D') || l.startsWith('D'),
90
+ ).length
91
+ const renamed = lines.filter(l => l.startsWith('R')).length
92
+
93
+ return {
94
+ modified,
95
+ added,
96
+ deleted,
97
+ renamed,
98
+ totalChanges: lines.length,
99
+ isClean: lines.length === 0,
100
+ files: lines.map(l => l.substring(3)), // Remove status prefix
101
+ }
102
+ } catch {
103
+ return null
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Get diff summary between HEAD and working directory
109
+ * @returns {Promise<Object|null>} Diff summary or null
110
+ */
111
+ async getDiffSummary() {
112
+ if (!(await this.isGitRepo())) {
113
+ return null
114
+ }
115
+
116
+ try {
117
+ const diff = execSync('git diff HEAD --name-only', {
118
+ cwd: this.projectPath,
119
+ encoding: 'utf-8',
120
+ })
121
+
122
+ const files = diff.trim().split('\n').filter(Boolean)
123
+
124
+ return {
125
+ files,
126
+ count: files.length,
127
+ }
128
+ } catch {
129
+ return null
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Get files changed since a specific time
135
+ * @param {Date|number} since - Timestamp or Date object
136
+ * @returns {Promise<Array>} Array of changed files
137
+ */
138
+ async getChangesSince(since) {
139
+ if (!(await this.isGitRepo())) {
140
+ return []
141
+ }
142
+
143
+ try {
144
+ const timestamp =
145
+ since instanceof Date ? since.toISOString() : new Date(since).toISOString()
146
+
147
+ const files = execSync(
148
+ `git log --since="${timestamp}" --name-only --pretty=format:`,
149
+ {
150
+ cwd: this.projectPath,
151
+ encoding: 'utf-8',
152
+ },
153
+ )
154
+
155
+ return [...new Set(files.trim().split('\n').filter(Boolean))]
156
+ } catch {
157
+ return []
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Validate user claim against git state
163
+ * @param {string} claim - User's claim (e.g., "login is complete")
164
+ * @returns {Promise<Object>} Validation result
165
+ */
166
+ async validateUserClaim(claim) {
167
+ if (!(await this.isGitRepo())) {
168
+ return {
169
+ valid: true,
170
+ warning: null,
171
+ note: 'Not a git repository - cannot validate against commits',
172
+ }
173
+ }
174
+
175
+ const lastCommit = await this.getLastCommit()
176
+ const workingStatus = await this.getWorkingDirStatus()
177
+
178
+ if (!lastCommit) {
179
+ return {
180
+ valid: true,
181
+ warning: null,
182
+ note: 'No commits yet - cannot validate',
183
+ }
184
+ }
185
+
186
+ // Extract keywords from claim
187
+ const keywords = this.extractKeywords(claim)
188
+ const completionClaimed = /complete|done|finished|ready|shipped/i.test(claim)
189
+
190
+ // Check if keywords appear in last commit
191
+ const inLastCommit = keywords.some(keyword =>
192
+ lastCommit.message.toLowerCase().includes(keyword),
193
+ )
194
+
195
+ // Check if there are uncommitted changes
196
+ const hasUncommittedChanges = !workingStatus.isClean
197
+
198
+ // Validation logic
199
+ if (completionClaimed && !inLastCommit && hasUncommittedChanges) {
200
+ return {
201
+ valid: false,
202
+ warning: `āš ļø Discrepancy detected: You claim "${claim}" but it's not in the last commit`,
203
+ details: {
204
+ lastCommit: lastCommit.message,
205
+ uncommittedFiles: workingStatus.totalChanges,
206
+ suggestion:
207
+ 'Consider committing your changes if the work is truly complete',
208
+ },
209
+ }
210
+ }
211
+
212
+ if (completionClaimed && !inLastCommit && !hasUncommittedChanges) {
213
+ return {
214
+ valid: true,
215
+ warning: `ā„¹ļø Note: "${claim}" not mentioned in recent commits`,
216
+ details: {
217
+ lastCommit: lastCommit.message,
218
+ note: 'Work may have been completed in earlier commits',
219
+ },
220
+ }
221
+ }
222
+
223
+ return {
224
+ valid: true,
225
+ warning: null,
226
+ note: inLastCommit
227
+ ? `āœ… Confirmed in last commit: "${lastCommit.message}"`
228
+ : null,
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Extract meaningful keywords from a claim
234
+ * @param {string} claim - User's claim
235
+ * @returns {Array<string>} Extracted keywords
236
+ */
237
+ extractKeywords(claim) {
238
+ // Remove common words
239
+ const stopWords = new Set([
240
+ 'the',
241
+ 'is',
242
+ 'are',
243
+ 'was',
244
+ 'were',
245
+ 'a',
246
+ 'an',
247
+ 'and',
248
+ 'or',
249
+ 'but',
250
+ 'in',
251
+ 'on',
252
+ 'at',
253
+ 'to',
254
+ 'for',
255
+ 'of',
256
+ 'with',
257
+ 'by',
258
+ 'from',
259
+ 'up',
260
+ 'about',
261
+ 'into',
262
+ 'through',
263
+ 'during',
264
+ 'before',
265
+ 'after',
266
+ 'above',
267
+ 'below',
268
+ 'between',
269
+ 'under',
270
+ 'complete',
271
+ 'done',
272
+ 'finished',
273
+ 'ready',
274
+ 'shipped',
275
+ ])
276
+
277
+ return claim
278
+ .toLowerCase()
279
+ .split(/\s+/)
280
+ .filter(word => word.length > 2 && !stopWords.has(word))
281
+ }
282
+
283
+ /**
284
+ * Get git statistics for analysis
285
+ * @returns {Promise<Object>} Git statistics
286
+ */
287
+ async getGitStats() {
288
+ if (!(await this.isGitRepo())) {
289
+ return {
290
+ isGitRepo: false,
291
+ hasCommits: false,
292
+ totalCommits: 0,
293
+ contributors: [],
294
+ lastCommit: null,
295
+ workingStatus: null,
296
+ }
297
+ }
298
+
299
+ try {
300
+ // Total commits
301
+ const totalCommits = parseInt(
302
+ execSync('git rev-list --count HEAD', {
303
+ cwd: this.projectPath,
304
+ encoding: 'utf-8',
305
+ }).trim(),
306
+ )
307
+
308
+ // Contributors
309
+ const contributorsOutput = execSync(
310
+ 'git log --format="%an" | sort -u',
311
+ {
312
+ cwd: this.projectPath,
313
+ encoding: 'utf-8',
314
+ },
315
+ )
316
+ const contributors = contributorsOutput.trim().split('\n').filter(Boolean)
317
+
318
+ const lastCommit = await this.getLastCommit()
319
+ const workingStatus = await this.getWorkingDirStatus()
320
+
321
+ return {
322
+ isGitRepo: true,
323
+ hasCommits: totalCommits > 0,
324
+ totalCommits,
325
+ contributors,
326
+ lastCommit,
327
+ workingStatus,
328
+ }
329
+ } catch (error) {
330
+ return {
331
+ isGitRepo: true,
332
+ hasCommits: false,
333
+ totalCommits: 0,
334
+ contributors: [],
335
+ lastCommit: null,
336
+ workingStatus: null,
337
+ error: error.message,
338
+ }
339
+ }
340
+ }
341
+
342
+ /**
343
+ * Check if a specific feature/file is in git history
344
+ * @param {string} searchTerm - Term to search for
345
+ * @returns {Promise<boolean>} True if found in history
346
+ */
347
+ async isInGitHistory(searchTerm) {
348
+ if (!(await this.isGitRepo())) {
349
+ return false
350
+ }
351
+
352
+ try {
353
+ const result = execSync(
354
+ `git log --all --grep="${searchTerm}" --oneline`,
355
+ {
356
+ cwd: this.projectPath,
357
+ encoding: 'utf-8',
358
+ },
359
+ )
360
+
361
+ return result.trim().length > 0
362
+ } catch {
363
+ return false
364
+ }
365
+ }
366
+
367
+ /**
368
+ * Get branch information
369
+ * @returns {Promise<Object|null>} Branch info or null
370
+ */
371
+ async getBranchInfo() {
372
+ if (!(await this.isGitRepo())) {
373
+ return null
374
+ }
375
+
376
+ try {
377
+ const currentBranch = execSync('git branch --show-current', {
378
+ cwd: this.projectPath,
379
+ encoding: 'utf-8',
380
+ }).trim()
381
+
382
+ const allBranches = execSync('git branch --list', {
383
+ cwd: this.projectPath,
384
+ encoding: 'utf-8',
385
+ })
386
+ .trim()
387
+ .split('\n')
388
+ .map(b => b.trim().replace('* ', ''))
389
+
390
+ return {
391
+ current: currentBranch,
392
+ all: allBranches,
393
+ count: allBranches.length,
394
+ }
395
+ } catch {
396
+ return null
397
+ }
398
+ }
399
+ }
400
+
401
+ module.exports = new GitIntegration()
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "prjct-cli",
3
- "version": "0.4.9",
4
- "description": "AI-integrated project management for indie hackers - works with Claude Code, Cursor, and Warp",
3
+ "version": "0.5.0",
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
7
  "prjct": "./bin/prjct"
@@ -25,13 +25,16 @@
25
25
  "website:install": "cd website && npm install"
26
26
  },
27
27
  "keywords": [
28
- "project-management",
28
+ "claude-code",
29
+ "claude-desktop",
30
+ "developer-momentum",
29
31
  "indie-hacker",
32
+ "ship-fast",
30
33
  "ai-assistant",
31
- "claude-code",
32
- "cursor",
33
- "warp",
34
- "productivity"
34
+ "productivity",
35
+ "developer-tools",
36
+ "no-bs",
37
+ "focus"
35
38
  ],
36
39
  "author": "prjct.dev",
37
40
  "license": "MIT",
@@ -99,7 +99,6 @@ clear
99
99
  # Clean header with Catppuccin colors
100
100
  echo ""
101
101
  echo ""
102
- echo -e " ${BOLD}${CYAN}(ļ¾‰ā—•ćƒ®ā—•)ノ*:d゚✧${NC}"
103
102
  echo -e " ${BOLD}${CYAN}ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—${NC}"
104
103
  echo -e " ${BOLD}${CYAN}ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•—ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•— ā–ˆā–ˆā•‘ā–ˆā–ˆā•”ā•ā•ā•ā•ā•ā•šā•ā•ā–ˆā–ˆā•”ā•ā•ā•${NC}"
105
104
  echo -e " ${BOLD}${CYAN}ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•”ā•ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•”ā• ā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘${NC}"
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: p_agent_be
3
+ description: Backend Engineer for [PROJECT_NAME]. Expert in [FRAMEWORK]. Triggers on: "backend", "API", "database", "server", "authentication", "microservice".
4
+ tools: str_replace_editor, create_file, delete_file, find_files, list_dir, search_files, view_file, run_terminal_command
5
+ model: opus
6
+ color: yellow
7
+ ---
8
+
9
+ You are a Senior Backend Engineer for **[PROJECT_NAME]**.
10
+
11
+ ## Project Context
12
+ - **Stack**: [DETECTED_STACK]
13
+ - **Architecture**: [DETECTED_PATTERN]
14
+ - **Primary Language**: [PRIMARY_LANGUAGE]
15
+
16
+ ## Core Expertise
17
+ - **API Design**: RESTful, GraphQL, efficient endpoints
18
+ - **Database**: Schema design, queries, optimization
19
+ - **Authentication**: JWT, OAuth, session management
20
+ - **Architecture**: Clean code, SOLID principles, DRY
21
+ - **Performance**: Caching, query optimization, scalability
22
+
23
+ ## NOT Your Expertise
24
+ - Frontend UI implementation
25
+ - DevOps infrastructure (defer to DevOps)
26
+ - UX design decisions
27
+
28
+ ## Development Principles
29
+ 1. **SOLID Principles**: Single responsibility, dependency inversion
30
+ 2. **Security First**: Validate inputs, protect endpoints
31
+ 3. **Scalability**: Design for growth
32
+ 4. **Testing**: Unit tests, integration tests
33
+ 5. **Documentation**: Clear API docs
34
+
35
+ ## Focus Areas
36
+ - API endpoints and business logic
37
+ - Database schema and queries
38
+ - Authentication and authorization
39
+ - Data validation and error handling
40
+ - Performance optimization
41
+
42
+ Remember: You build the server layer. Collaborate with Frontend for API contracts and Security for hardening.
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: p_agent_data
3
+ description: Data Science Engineer for [PROJECT_NAME]. Expert in ML, data analysis, and pipelines. Triggers on: "ML", "machine learning", "data", "model", "training", "analysis", "pipeline".
4
+ tools: str_replace_editor, create_file, delete_file, find_files, list_dir, search_files, view_file, run_terminal_command
5
+ model: opus
6
+ color: teal
7
+ ---
8
+
9
+ You are a Data Science Engineer for **[PROJECT_NAME]**.
10
+
11
+ ## Project Context
12
+ - **Stack**: [DETECTED_STACK]
13
+ - **Type**: [PROJECT_TYPE]
14
+
15
+ ## Core Expertise
16
+ - **Machine Learning**: Model training, evaluation, deployment
17
+ - **Data Pipelines**: ETL, data processing
18
+ - **Analysis**: Statistical analysis, visualization
19
+ - **Optimization**: Model performance, inference speed
20
+ - **MLOps**: Model versioning, monitoring
21
+
22
+ ## NOT Your Expertise
23
+ - Frontend UI implementation
24
+ - Infrastructure (defer to DevOps)
25
+ - Non-ML backend logic
26
+
27
+ ## Data Science Principles
28
+ 1. **Data Quality**: Garbage in, garbage out
29
+ 2. **Reproducibility**: Version everything
30
+ 3. **Validation**: Always validate models
31
+ 4. **Monitoring**: Track model performance
32
+ 5. **Ethics**: Consider bias and fairness
33
+
34
+ ## Focus Areas
35
+ - Model development and training
36
+ - Data preprocessing and feature engineering
37
+ - Model evaluation and validation
38
+ - Deployment and monitoring
39
+ - Data visualization
40
+
41
+ Remember: Models are only as good as the data and evaluation. Prioritize data quality and proper validation.