prjct-cli 0.35.3 → 0.36.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.
Files changed (68) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/README.md +63 -618
  3. package/bin/prjct.ts +116 -17
  4. package/core/cli/start.ts +387 -0
  5. package/core/commands/analysis.ts +58 -32
  6. package/core/commands/command-data.ts +11 -50
  7. package/core/commands/commands.ts +18 -21
  8. package/core/commands/context.ts +238 -0
  9. package/core/commands/register.ts +7 -5
  10. package/core/commands/setup.ts +1 -17
  11. package/core/index.ts +103 -39
  12. package/core/infrastructure/ai-provider.ts +312 -0
  13. package/core/infrastructure/command-installer.ts +49 -5
  14. package/core/infrastructure/editors-config.ts +20 -6
  15. package/core/infrastructure/setup.ts +227 -62
  16. package/core/services/index.ts +2 -0
  17. package/core/services/skill-service.ts +52 -16
  18. package/core/services/sync-service.ts +1080 -0
  19. package/core/types/commands.ts +0 -12
  20. package/core/types/index.ts +12 -1
  21. package/core/types/provider.ts +110 -0
  22. package/core/utils/branding.ts +20 -3
  23. package/dist/bin/prjct.mjs +1053 -1426
  24. package/dist/core/infrastructure/command-installer.js +33 -2
  25. package/dist/core/infrastructure/editors-config.js +13 -3
  26. package/dist/core/infrastructure/setup.js +293 -73
  27. package/package.json +10 -16
  28. package/scripts/postinstall.js +17 -119
  29. package/templates/agentic/agent-routing.md +22 -88
  30. package/templates/agentic/agents/uxui.md +42 -197
  31. package/templates/agentic/context-filtering.md +14 -56
  32. package/templates/agentic/orchestrator.md +26 -302
  33. package/templates/agentic/skill-integration.md +37 -289
  34. package/templates/agentic/subagent-generation.md +31 -104
  35. package/templates/agentic/task-fragmentation.md +39 -273
  36. package/templates/agents/AGENTS.md +33 -181
  37. package/templates/commands/bug.md +22 -520
  38. package/templates/commands/dash.md +26 -161
  39. package/templates/commands/done.md +19 -250
  40. package/templates/commands/enrich.md +21 -732
  41. package/templates/commands/idea.md +18 -160
  42. package/templates/commands/init.md +20 -209
  43. package/templates/commands/merge.md +21 -185
  44. package/templates/commands/next.md +21 -103
  45. package/templates/commands/p.md +1 -1
  46. package/templates/commands/p.toml +37 -0
  47. package/templates/commands/pause.md +21 -272
  48. package/templates/commands/resume.md +18 -411
  49. package/templates/commands/setup.md +0 -1
  50. package/templates/commands/ship.md +30 -627
  51. package/templates/commands/sync.md +11 -1448
  52. package/templates/commands/task.md +17 -439
  53. package/templates/commands/test.md +30 -259
  54. package/templates/global/CLAUDE.md +33 -1
  55. package/templates/global/GEMINI.md +265 -0
  56. package/templates/global/STORAGE-SPEC.md +256 -0
  57. package/templates/global/docs/agents.md +88 -0
  58. package/templates/global/docs/architecture.md +103 -0
  59. package/templates/global/docs/commands.md +96 -0
  60. package/templates/global/docs/validation.md +95 -0
  61. package/CLAUDE.md +0 -211
  62. package/packages/shared/package.json +0 -29
  63. package/packages/shared/src/index.ts +0 -10
  64. package/packages/shared/src/schemas.ts +0 -124
  65. package/packages/shared/src/types.ts +0 -187
  66. package/packages/shared/src/unified.ts +0 -174
  67. package/packages/shared/src/utils.ts +0 -148
  68. package/packages/shared/tsconfig.json +0 -18
@@ -62,17 +62,6 @@ export const COMMANDS: CommandMeta[] = [
62
62
  requiresProject: true,
63
63
  features: ['Agentic type classification', '7-phase workflow', 'Git branch management', 'Task breakdown'],
64
64
  },
65
- {
66
- name: 'feature',
67
- group: 'core',
68
- description: 'DEPRECATED - Use /p:task instead',
69
- usage: { claude: '/p:task "<description>"', terminal: 'prjct task "<description>"' },
70
- params: '<description>',
71
- implemented: true,
72
- hasTemplate: true,
73
- requiresProject: true,
74
- deprecated: true,
75
- },
76
65
  {
77
66
  name: 'spec',
78
67
  group: 'core',
@@ -83,28 +72,6 @@ export const COMMANDS: CommandMeta[] = [
83
72
  hasTemplate: true,
84
73
  requiresProject: true,
85
74
  },
86
- {
87
- name: 'now',
88
- group: 'core',
89
- description: 'DEPRECATED - Use /p:task instead',
90
- usage: { claude: '/p:task "<description>"', terminal: 'prjct task "<description>"' },
91
- params: '[task]',
92
- implemented: true,
93
- hasTemplate: true,
94
- requiresProject: true,
95
- deprecated: true,
96
- },
97
- {
98
- name: 'work',
99
- group: 'core',
100
- description: 'DEPRECATED - Use /p:task instead',
101
- usage: { claude: '/p:task "<description>"', terminal: 'prjct task "<description>"' },
102
- params: '[task]',
103
- implemented: true,
104
- hasTemplate: true,
105
- requiresProject: true,
106
- deprecated: true,
107
- },
108
75
  {
109
76
  name: 'pause',
110
77
  group: 'core',
@@ -328,16 +295,6 @@ export const COMMANDS: CommandMeta[] = [
328
295
  hasTemplate: true,
329
296
  requiresProject: true,
330
297
  },
331
- {
332
- name: 'migrate-all',
333
- group: 'setup',
334
- description: 'Migrate all legacy projects to UUID format',
335
- usage: { claude: '/p:migrate-all', terminal: 'prjct migrate-all' },
336
- params: '[--deep-scan] [--dry-run]',
337
- implemented: true,
338
- hasTemplate: true,
339
- requiresProject: false,
340
- },
341
298
  {
342
299
  name: 'auth',
343
300
  group: 'setup',
@@ -348,12 +305,16 @@ export const COMMANDS: CommandMeta[] = [
348
305
  hasTemplate: true,
349
306
  requiresProject: false,
350
307
  },
308
+ {
309
+ name: 'context',
310
+ group: 'setup',
311
+ description: 'Get project context as JSON for Claude templates',
312
+ usage: { claude: null, terminal: 'prjct context <command> [args]' },
313
+ params: '<command> [args]',
314
+ implemented: true,
315
+ hasTemplate: false,
316
+ requiresProject: true,
317
+ features: ['Returns JSON with project context', 'Runs orchestrator', 'Loads agents and skills'],
318
+ },
351
319
  ]
352
320
 
353
- // Legacy compatibility - category field mapping
354
- export function getCommandsWithCategory(): Array<CommandMeta & { category: string }> {
355
- return COMMANDS.map(cmd => ({
356
- ...cmd,
357
- category: cmd.group, // Map group to category for backward compat
358
- }))
359
- }
@@ -3,14 +3,15 @@
3
3
  *
4
4
  * MD-First Architecture - All state in Markdown files.
5
5
  *
6
- * COMMANDS (22 total):
7
- * - Workflow (5): work, done, next, pause, resume
8
- * - Planning (5): init, feature, bug, idea, spec
9
- * - Shipping (1): ship
10
- * - Analytics (2): dash, help
11
- * - Maintenance (5): cleanup, design, recover, undo, redo, history
12
- * - Analysis (2): analyze, sync
13
- * - Setup (3): start, setup, migrateAll
6
+ * COMMANDS:
7
+ * - Workflow: done, next, pause, resume
8
+ * - Planning: init, bug, idea, spec
9
+ * - Shipping: ship
10
+ * - Analytics: dash, help
11
+ * - Maintenance: cleanup, design, recover, undo, redo, history
12
+ * - Analysis: analyze, sync
13
+ * - Setup: start, setup
14
+ * - Context: context
14
15
  */
15
16
 
16
17
  import { WorkflowCommands } from './workflow'
@@ -20,6 +21,7 @@ import { AnalyticsCommands } from './analytics'
20
21
  import { MaintenanceCommands } from './maintenance'
21
22
  import { AnalysisCommands } from './analysis'
22
23
  import { SetupCommands } from './setup'
24
+ import { ContextCommands } from './context'
23
25
 
24
26
  import type {
25
27
  CommandResult,
@@ -28,7 +30,6 @@ import type {
28
30
  DesignOptions,
29
31
  CleanupOptions,
30
32
  SetupOptions,
31
- MigrateOptions,
32
33
  AnalyzeOptions
33
34
  } from '../types'
34
35
 
@@ -45,6 +46,7 @@ class PrjctCommands {
45
46
  private maintenance: MaintenanceCommands
46
47
  private analysis: AnalysisCommands
47
48
  private setupCmds: SetupCommands
49
+ private contextCmds: ContextCommands
48
50
 
49
51
  // Shared state
50
52
  agent: unknown
@@ -60,6 +62,7 @@ class PrjctCommands {
60
62
  this.maintenance = new MaintenanceCommands()
61
63
  this.analysis = new AnalysisCommands()
62
64
  this.setupCmds = new SetupCommands()
65
+ this.contextCmds = new ContextCommands()
63
66
 
64
67
  this.agent = null
65
68
  this.agentInfo = null
@@ -69,10 +72,6 @@ class PrjctCommands {
69
72
 
70
73
  // ========== Workflow Commands ==========
71
74
 
72
- async work(task: string | null = null, projectPath: string = process.cwd()): Promise<CommandResult> {
73
- return this.workflow.now(task, projectPath)
74
- }
75
-
76
75
  async done(projectPath: string = process.cwd()): Promise<CommandResult> {
77
76
  return this.workflow.done(projectPath)
78
77
  }
@@ -95,10 +94,6 @@ class PrjctCommands {
95
94
  return this.planning.init(idea, projectPath)
96
95
  }
97
96
 
98
- async feature(description: string, projectPath: string = process.cwd()): Promise<CommandResult> {
99
- return this.planning.feature(description, projectPath)
100
- }
101
-
102
97
  async bug(description: string, projectPath: string = process.cwd()): Promise<CommandResult> {
103
98
  return this.planning.bug(description, projectPath)
104
99
  }
@@ -163,6 +158,12 @@ class PrjctCommands {
163
158
  return this.analysis.sync(projectPath)
164
159
  }
165
160
 
161
+ // ========== Context Commands ==========
162
+
163
+ async context(input: string | null = null, projectPath: string = process.cwd()): Promise<CommandResult> {
164
+ return this.contextCmds.context(input, projectPath)
165
+ }
166
+
166
167
  // ========== Setup Commands ==========
167
168
 
168
169
  async start(): Promise<CommandResult> {
@@ -173,10 +174,6 @@ class PrjctCommands {
173
174
  return this.setupCmds.setup(options)
174
175
  }
175
176
 
176
- async migrateAll(options: MigrateOptions = {}): Promise<CommandResult> {
177
- return this.setupCmds.migrateAll(options)
178
- }
179
-
180
177
  async installStatusLine(): Promise<{ success: boolean; error?: string }> {
181
178
  return this.setupCmds.installStatusLine()
182
179
  }
@@ -0,0 +1,238 @@
1
+ /**
2
+ * Context Commands - Exposes orchestrator context to Claude
3
+ *
4
+ * The `context` command runs the orchestrator and returns JSON with everything
5
+ * Claude needs to execute workflows:
6
+ * - projectId and globalPath for file operations
7
+ * - detected domains from task description
8
+ * - loaded agents with file paths and previews
9
+ * - current task state (if any)
10
+ * - repo analysis data
11
+ *
12
+ * This bridges the gap between TypeScript orchestration and Claude Code templates.
13
+ *
14
+ * @module commands/context
15
+ * @version 1.0.0
16
+ */
17
+
18
+ import fs from 'fs/promises'
19
+ import path from 'path'
20
+ import configManager from '../infrastructure/config-manager'
21
+ import pathManager from '../infrastructure/path-manager'
22
+ import { stateStorage } from '../storage'
23
+ import orchestratorExecutor from '../agentic/orchestrator-executor'
24
+ import { isNotFoundError } from '../types/fs'
25
+ import type { CommandResult } from '../types'
26
+
27
+ // =============================================================================
28
+ // Types
29
+ // =============================================================================
30
+
31
+ export interface ContextOutput {
32
+ projectId: string
33
+ globalPath: string
34
+ currentTask: {
35
+ id: string
36
+ description: string
37
+ startedAt: string
38
+ subtasks?: Array<{
39
+ id: string
40
+ description: string
41
+ status: string
42
+ domain: string
43
+ }>
44
+ currentSubtaskIndex?: number
45
+ } | null
46
+ domains: string[]
47
+ primaryDomain: string | null
48
+ agents: Array<{
49
+ name: string
50
+ domain: string
51
+ filePath: string
52
+ skills: string[]
53
+ preview: string
54
+ }>
55
+ subtasks: Array<{
56
+ id: string
57
+ description: string
58
+ domain: string
59
+ agent: string
60
+ status: string
61
+ order: number
62
+ }> | null
63
+ repoAnalysis: {
64
+ ecosystem: string
65
+ frameworks: string[]
66
+ hasTests: boolean
67
+ technologies: string[]
68
+ }
69
+ }
70
+
71
+ // =============================================================================
72
+ // Context Commands Class
73
+ // =============================================================================
74
+
75
+ export class ContextCommands {
76
+ /**
77
+ * Get full project context for Claude
78
+ *
79
+ * Usage:
80
+ * prjct context task "add user auth"
81
+ * prjct context done
82
+ * prjct context ship
83
+ *
84
+ * Returns JSON with all orchestrator data.
85
+ */
86
+ async context(
87
+ input: string | null = null,
88
+ projectPath: string = process.cwd()
89
+ ): Promise<CommandResult> {
90
+ try {
91
+ // Parse input: first word is command, rest is arguments
92
+ const parts = (input || '').trim().split(/\s+/)
93
+ const command = parts[0] || 'task'
94
+ const taskDescription = parts.slice(1).join(' ')
95
+
96
+ // Get project info
97
+ const config = await configManager.readConfig(projectPath)
98
+ if (!config || !config.projectId) {
99
+ const output: Partial<ContextOutput> = {
100
+ projectId: '',
101
+ globalPath: '',
102
+ currentTask: null,
103
+ domains: [],
104
+ primaryDomain: null,
105
+ agents: [],
106
+ subtasks: null,
107
+ repoAnalysis: {
108
+ ecosystem: 'unknown',
109
+ frameworks: [],
110
+ hasTests: false,
111
+ technologies: [],
112
+ },
113
+ }
114
+ console.log(JSON.stringify(output, null, 2))
115
+ return {
116
+ success: false,
117
+ message: 'No prjct project. Run `p. init` first.',
118
+ }
119
+ }
120
+
121
+ const projectId = config.projectId
122
+ const globalPath = pathManager.getGlobalProjectPath(projectId)
123
+
124
+ // Get current task state
125
+ const state = await stateStorage.read(projectId)
126
+ const currentTask = state?.currentTask
127
+ ? {
128
+ id: state.currentTask.id,
129
+ description: state.currentTask.description,
130
+ startedAt: state.currentTask.startedAt,
131
+ subtasks: state.currentTask.subtasks?.map((st) => ({
132
+ id: st.id,
133
+ description: st.description,
134
+ status: st.status,
135
+ domain: st.domain,
136
+ })),
137
+ currentSubtaskIndex: state.currentTask.currentSubtaskIndex,
138
+ }
139
+ : null
140
+
141
+ // Run orchestrator if we have a task description
142
+ let orchestratorContext = null
143
+ if (taskDescription) {
144
+ try {
145
+ orchestratorContext = await orchestratorExecutor.execute(
146
+ command,
147
+ taskDescription,
148
+ projectPath
149
+ )
150
+ } catch (error) {
151
+ // Orchestration failed - continue without it
152
+ console.error(`Warning: Orchestrator failed: ${(error as Error).message}`)
153
+ }
154
+ }
155
+
156
+ // Load repo analysis
157
+ const repoAnalysis = await this.loadRepoAnalysis(globalPath)
158
+
159
+ // Build output
160
+ const output: ContextOutput = {
161
+ projectId,
162
+ globalPath,
163
+ currentTask,
164
+ domains: orchestratorContext?.detectedDomains || [],
165
+ primaryDomain: orchestratorContext?.primaryDomain || null,
166
+ agents:
167
+ orchestratorContext?.agents.map((a) => ({
168
+ name: a.name,
169
+ domain: a.domain,
170
+ filePath: a.filePath,
171
+ skills: a.skills,
172
+ preview: a.content.substring(0, 500),
173
+ })) || [],
174
+ subtasks:
175
+ orchestratorContext?.subtasks?.map((st) => ({
176
+ id: st.id,
177
+ description: st.description,
178
+ domain: st.domain,
179
+ agent: st.agent,
180
+ status: st.status,
181
+ order: st.order,
182
+ })) || null,
183
+ repoAnalysis: {
184
+ ecosystem: repoAnalysis?.ecosystem || 'unknown',
185
+ frameworks: repoAnalysis?.frameworks || [],
186
+ hasTests: repoAnalysis?.hasTests || false,
187
+ technologies: repoAnalysis?.technologies || [],
188
+ },
189
+ }
190
+
191
+ // Output JSON to stdout
192
+ console.log(JSON.stringify(output, null, 2))
193
+
194
+ return {
195
+ success: true,
196
+ message: '', // Empty message - JSON output is the result
197
+ }
198
+ } catch (error) {
199
+ return {
200
+ success: false,
201
+ message: `Context error: ${(error as Error).message}`,
202
+ }
203
+ }
204
+ }
205
+
206
+ /**
207
+ * Load repo analysis from analysis/repo-analysis.json
208
+ */
209
+ private async loadRepoAnalysis(globalPath: string): Promise<{
210
+ ecosystem: string
211
+ frameworks: string[]
212
+ hasTests: boolean
213
+ technologies: string[]
214
+ } | null> {
215
+ try {
216
+ const analysisPath = path.join(globalPath, 'analysis', 'repo-analysis.json')
217
+ const content = await fs.readFile(analysisPath, 'utf-8')
218
+ const data = JSON.parse(content)
219
+ return {
220
+ ecosystem: data.ecosystem || 'unknown',
221
+ frameworks: data.frameworks || [],
222
+ hasTests: data.hasTests ?? false,
223
+ technologies: data.technologies || [],
224
+ }
225
+ } catch (error) {
226
+ if (isNotFoundError(error)) return null
227
+ return null
228
+ }
229
+ }
230
+ }
231
+
232
+ // =============================================================================
233
+ // Exports
234
+ // =============================================================================
235
+
236
+ const contextCommands = new ContextCommands()
237
+ export default contextCommands
238
+ export { contextCommands }
@@ -17,6 +17,7 @@ import { AnalyticsCommands } from './analytics'
17
17
  import { MaintenanceCommands } from './maintenance'
18
18
  import { AnalysisCommands } from './analysis'
19
19
  import { SetupCommands } from './setup'
20
+ import { ContextCommands } from './context'
20
21
 
21
22
  // Singleton instances of command groups
22
23
  const workflow = new WorkflowCommands()
@@ -26,6 +27,7 @@ const analytics = new AnalyticsCommands()
26
27
  const maintenance = new MaintenanceCommands()
27
28
  const analysis = new AnalysisCommands()
28
29
  const setup = new SetupCommands()
30
+ const context = new ContextCommands()
29
31
 
30
32
  /**
31
33
  * Register categories
@@ -50,8 +52,6 @@ export function registerAllCommands(): void {
50
52
  const getMeta = (name: string) => COMMANDS.find(c => c.name === name)
51
53
 
52
54
  // Workflow commands
53
- commandRegistry.registerMethod('work', workflow, 'now', getMeta('work'))
54
- commandRegistry.registerMethod('now', workflow, 'now', getMeta('now'))
55
55
  commandRegistry.registerMethod('done', workflow, 'done', getMeta('done'))
56
56
  commandRegistry.registerMethod('next', workflow, 'next', getMeta('next'))
57
57
  commandRegistry.registerMethod('pause', workflow, 'pause', getMeta('pause'))
@@ -59,7 +59,6 @@ export function registerAllCommands(): void {
59
59
 
60
60
  // Planning commands
61
61
  commandRegistry.registerMethod('init', planning, 'init', getMeta('init'))
62
- commandRegistry.registerMethod('feature', planning, 'feature', getMeta('feature'))
63
62
  commandRegistry.registerMethod('bug', planning, 'bug', getMeta('bug'))
64
63
  commandRegistry.registerMethod('idea', planning, 'idea', getMeta('idea'))
65
64
  commandRegistry.registerMethod('spec', planning, 'spec', getMeta('spec'))
@@ -86,7 +85,9 @@ export function registerAllCommands(): void {
86
85
  // Setup commands
87
86
  commandRegistry.registerMethod('start', setup, 'start', getMeta('start'))
88
87
  commandRegistry.registerMethod('setup', setup, 'setup', getMeta('setup'))
89
- commandRegistry.registerMethod('migrateAll', setup, 'migrateAll', getMeta('migrate-all'))
88
+
89
+ // Context command (for Claude templates)
90
+ commandRegistry.registerMethod('context', context, 'context', getMeta('context'))
90
91
  }
91
92
 
92
93
  // Auto-register on import
@@ -100,5 +101,6 @@ export {
100
101
  analytics,
101
102
  maintenance,
102
103
  analysis,
103
- setup
104
+ setup,
105
+ context
104
106
  }
@@ -8,7 +8,7 @@ import chalk from 'chalk'
8
8
 
9
9
  import commandInstaller from '../infrastructure/command-installer'
10
10
  import pathManager from '../infrastructure/path-manager'
11
- import type { CommandResult, SetupOptions, MigrateOptions } from '../types'
11
+ import type { CommandResult, SetupOptions } from '../types'
12
12
  import { PrjctCommandsBase } from './base'
13
13
  import { VERSION } from '../utils/version'
14
14
 
@@ -254,20 +254,4 @@ echo "⚡ prjct"
254
254
  console.log('')
255
255
  }
256
256
 
257
- /**
258
- * Migrate all projects to UUID format
259
- */
260
- async migrateAll(_options: MigrateOptions = {}): Promise<CommandResult> {
261
- console.log('🔄 Migrating all projects to UUID format...\n')
262
-
263
- // TODO: Implement full migration logic
264
- // For now, return success as this is a stub
265
- console.log('✅ Migration complete (no projects needed migration)\n')
266
-
267
- return {
268
- success: true,
269
- message: 'Migration complete',
270
- }
271
- }
272
-
273
257
  }
package/core/index.ts CHANGED
@@ -9,6 +9,10 @@ import { commandRegistry } from './commands/registry'
9
9
  import './commands/register' // Ensure commands are registered
10
10
  import out from './utils/output'
11
11
  import type { CommandMeta } from './commands/registry'
12
+ import { detectAllProviders, Providers } from './infrastructure/ai-provider'
13
+ import fs from 'fs'
14
+ import path from 'path'
15
+ import os from 'os'
12
16
 
13
17
  interface ParsedCommandArgs {
14
18
  parsedArgs: string[]
@@ -27,7 +31,7 @@ async function main(): Promise<void> {
27
31
 
28
32
  if (['-v', '--version', 'version'].includes(commandName)) {
29
33
  const packageJson = await import('../package.json')
30
- console.log(`prjct-cli v${packageJson.version}`)
34
+ displayVersion(packageJson.version)
31
35
  process.exit(0)
32
36
  }
33
37
 
@@ -90,21 +94,17 @@ async function main(): Promise<void> {
90
94
  result = await commands.cleanup(options)
91
95
  } else if (commandName === 'setup') {
92
96
  result = await commands.setup(options)
93
- } else if (commandName === 'migrate-all') {
94
- result = await commands.migrateAll(options)
95
97
  } else {
96
98
  // Standard commands - type-safe invocation
97
99
  const param = parsedArgs.join(' ') || null
98
100
  const standardCommands: Record<string, (p: string | null) => Promise<CommandResult>> = {
99
101
  // Core workflow
100
- work: (p) => commands.work(p),
101
102
  done: () => commands.done(),
102
103
  next: () => commands.next(),
103
104
  pause: (p) => commands.pause(p || ''),
104
105
  resume: (p) => commands.resume(p),
105
106
  // Planning
106
107
  init: (p) => commands.init(p),
107
- feature: (p) => commands.feature(p || ''),
108
108
  bug: (p) => commands.bug(p || ''),
109
109
  idea: (p) => commands.idea(p || ''),
110
110
  spec: (p) => commands.spec(p),
@@ -120,6 +120,8 @@ async function main(): Promise<void> {
120
120
  // Setup
121
121
  sync: () => commands.sync(),
122
122
  start: () => commands.start(),
123
+ // Context (for Claude templates)
124
+ context: (p) => commands.context(p),
123
125
  }
124
126
 
125
127
  const handler = standardCommands[commandName]
@@ -177,44 +179,106 @@ function parseCommandArgs(cmd: CommandMeta, rawArgs: string[]): ParsedCommandArg
177
179
  return { parsedArgs, options }
178
180
  }
179
181
 
182
+ // Colors for version display
183
+ const CYAN = '\x1b[36m'
184
+ const GREEN = '\x1b[32m'
185
+ const YELLOW = '\x1b[33m'
186
+ const DIM = '\x1b[2m'
187
+ const RESET = '\x1b[0m'
188
+
180
189
  /**
181
- * Display help using registry
190
+ * Display version with provider status
182
191
  */
183
- function displayHelp(): void {
184
- const categories = commandRegistry.getAllCategories()
185
- const categorizedCommands: Record<string, CommandMeta[]> = {}
192
+ function displayVersion(version: string): void {
193
+ const detection = detectAllProviders()
194
+
195
+ // Check if prjct commands are installed for each provider
196
+ const claudeCommandPath = path.join(os.homedir(), '.claude', 'commands', 'p.md')
197
+ const geminiCommandPath = path.join(os.homedir(), '.gemini', 'commands', 'p.toml')
198
+ const claudeConfigured = fs.existsSync(claudeCommandPath)
199
+ const geminiConfigured = fs.existsSync(geminiCommandPath)
200
+
201
+ console.log(`
202
+ ${CYAN}p/${RESET} prjct v${version}
203
+ ${DIM}Context layer for AI coding agents${RESET}
204
+
205
+ ${DIM}Providers:${RESET}`)
206
+
207
+ // Claude status
208
+ if (detection.claude.installed) {
209
+ const status = claudeConfigured ? `${GREEN}✓ ready${RESET}` : `${YELLOW}● installed${RESET}`
210
+ const ver = detection.claude.version ? ` (v${detection.claude.version})` : ''
211
+ console.log(` Claude Code ${status}${DIM}${ver}${RESET}`)
212
+ } else {
213
+ console.log(` Claude Code ${DIM}○ not installed${RESET}`)
214
+ }
186
215
 
187
- // Group commands by category (exclude deprecated)
188
- commandRegistry.getTerminalCommands().forEach((cmd) => {
189
- if (cmd.deprecated) return
216
+ // Gemini status
217
+ if (detection.gemini.installed) {
218
+ const status = geminiConfigured ? `${GREEN}✓ ready${RESET}` : `${YELLOW}● installed${RESET}`
219
+ const ver = detection.gemini.version ? ` (v${detection.gemini.version})` : ''
220
+ console.log(` Gemini CLI ${status}${DIM}${ver}${RESET}`)
221
+ } else {
222
+ console.log(` Gemini CLI ${DIM}○ not installed${RESET}`)
223
+ }
190
224
 
191
- if (!categorizedCommands[cmd.group]) {
192
- categorizedCommands[cmd.group] = []
193
- }
194
- categorizedCommands[cmd.group].push(cmd)
195
- })
196
-
197
- console.log('prjct - Developer momentum tool for solo builders')
198
- console.log('\nAvailable commands:\n')
199
-
200
- // Display commands by category
201
- Object.entries(categorizedCommands).forEach(([categoryKey, cmds]) => {
202
- const categoryInfo = categories.get(categoryKey)
203
- console.log(` ${categoryInfo?.title || categoryKey}:`)
204
-
205
- cmds.forEach((cmd) => {
206
- const params = cmd.params ? ` ${cmd.params}` : ''
207
- const spacing = ' '.repeat(Math.max(20 - cmd.name.length - params.length, 1))
208
- const impl = cmd.implemented ? '' : ' (not implemented)'
209
- console.log(` ${cmd.name}${params}${spacing}${cmd.description}${impl}`)
210
- })
211
-
212
- console.log('')
213
- })
214
-
215
- const stats = commandRegistry.getStats()
216
- console.log(`Total: ${stats.implemented} implemented / ${stats.total} commands`)
217
- console.log('\nFor more info: https://prjct.app')
225
+ console.log(`
226
+ ${DIM}Run 'prjct start' to configure providers${RESET}
227
+ ${CYAN}https://prjct.app${RESET}
228
+ `)
229
+ }
230
+
231
+ /**
232
+ * Display help using registry
233
+ */
234
+ function displayHelp(): void {
235
+ console.log(`
236
+ prjct - Context layer for AI coding agents
237
+ Works with Claude Code, Gemini CLI, and more.
238
+
239
+ QUICK START
240
+ -----------
241
+ 1. prjct start Configure your AI provider (Claude/Gemini)
242
+ 2. Open project in your AI coding agent
243
+ 3. Type: p. sync Analyze project and generate context
244
+ 4. Type: p. task "..." Start working on a task
245
+
246
+ HOW IT WORKS
247
+ ------------
248
+ prjct gives AI agents the context they need about your project.
249
+ Use "p." commands inside Claude Code or Gemini CLI:
250
+
251
+ p. sync Analyze project, generate domain agents
252
+ p. task "desc" Start task with auto-classification
253
+ p. done Complete current subtask
254
+ p. ship "name" Ship feature with PR + version
255
+
256
+ TERMINAL COMMANDS (this CLI)
257
+ ----------------------------
258
+ prjct start First-time setup
259
+ prjct setup Reconfigure installations
260
+ prjct init Initialize project (creates .prjct/)
261
+ prjct sync Sync project state
262
+
263
+ EXAMPLES
264
+ --------
265
+ # First time setup
266
+ $ prjct start
267
+
268
+ # Initialize a new project
269
+ $ cd my-project && prjct init
270
+
271
+ # Inside Claude Code or Gemini CLI
272
+ > p. sync
273
+ > p. task "add user authentication"
274
+ > p. done
275
+ > p. ship "user auth"
276
+
277
+ MORE INFO
278
+ ---------
279
+ Documentation: https://prjct.app
280
+ GitHub: https://github.com/jlopezlira/prjct-cli
281
+ `)
218
282
  }
219
283
 
220
284
  // Run CLI