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.
- package/CHANGELOG.md +43 -0
- package/README.md +63 -618
- package/bin/prjct.ts +116 -17
- package/core/cli/start.ts +387 -0
- package/core/commands/analysis.ts +58 -32
- package/core/commands/command-data.ts +11 -50
- package/core/commands/commands.ts +18 -21
- package/core/commands/context.ts +238 -0
- package/core/commands/register.ts +7 -5
- package/core/commands/setup.ts +1 -17
- package/core/index.ts +103 -39
- package/core/infrastructure/ai-provider.ts +312 -0
- package/core/infrastructure/command-installer.ts +49 -5
- package/core/infrastructure/editors-config.ts +20 -6
- package/core/infrastructure/setup.ts +227 -62
- package/core/services/index.ts +2 -0
- package/core/services/skill-service.ts +52 -16
- package/core/services/sync-service.ts +1080 -0
- package/core/types/commands.ts +0 -12
- package/core/types/index.ts +12 -1
- package/core/types/provider.ts +110 -0
- package/core/utils/branding.ts +20 -3
- package/dist/bin/prjct.mjs +1053 -1426
- package/dist/core/infrastructure/command-installer.js +33 -2
- package/dist/core/infrastructure/editors-config.js +13 -3
- package/dist/core/infrastructure/setup.js +293 -73
- package/package.json +10 -16
- package/scripts/postinstall.js +17 -119
- package/templates/agentic/agent-routing.md +22 -88
- package/templates/agentic/agents/uxui.md +42 -197
- package/templates/agentic/context-filtering.md +14 -56
- package/templates/agentic/orchestrator.md +26 -302
- package/templates/agentic/skill-integration.md +37 -289
- package/templates/agentic/subagent-generation.md +31 -104
- package/templates/agentic/task-fragmentation.md +39 -273
- package/templates/agents/AGENTS.md +33 -181
- package/templates/commands/bug.md +22 -520
- package/templates/commands/dash.md +26 -161
- package/templates/commands/done.md +19 -250
- package/templates/commands/enrich.md +21 -732
- package/templates/commands/idea.md +18 -160
- package/templates/commands/init.md +20 -209
- package/templates/commands/merge.md +21 -185
- package/templates/commands/next.md +21 -103
- package/templates/commands/p.md +1 -1
- package/templates/commands/p.toml +37 -0
- package/templates/commands/pause.md +21 -272
- package/templates/commands/resume.md +18 -411
- package/templates/commands/setup.md +0 -1
- package/templates/commands/ship.md +30 -627
- package/templates/commands/sync.md +11 -1448
- package/templates/commands/task.md +17 -439
- package/templates/commands/test.md +30 -259
- package/templates/global/CLAUDE.md +33 -1
- package/templates/global/GEMINI.md +265 -0
- package/templates/global/STORAGE-SPEC.md +256 -0
- package/templates/global/docs/agents.md +88 -0
- package/templates/global/docs/architecture.md +103 -0
- package/templates/global/docs/commands.md +96 -0
- package/templates/global/docs/validation.md +95 -0
- package/CLAUDE.md +0 -211
- package/packages/shared/package.json +0 -29
- package/packages/shared/src/index.ts +0 -10
- package/packages/shared/src/schemas.ts +0 -124
- package/packages/shared/src/types.ts +0 -187
- package/packages/shared/src/unified.ts +0 -174
- package/packages/shared/src/utils.ts +0 -148
- 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
|
|
7
|
-
* - Workflow
|
|
8
|
-
* - Planning
|
|
9
|
-
* - Shipping
|
|
10
|
-
* - Analytics
|
|
11
|
-
* - Maintenance
|
|
12
|
-
* - Analysis
|
|
13
|
-
* - Setup
|
|
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
|
-
|
|
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
|
}
|
package/core/commands/setup.ts
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
|
190
|
+
* Display version with provider status
|
|
182
191
|
*/
|
|
183
|
-
function
|
|
184
|
-
const
|
|
185
|
-
|
|
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
|
-
//
|
|
188
|
-
|
|
189
|
-
|
|
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
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|