prjct-cli 0.54.1 → 0.54.3
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 +34 -0
- package/core/commands/analysis.ts +71 -5
- package/core/commands/commands.ts +1 -1
- package/core/index.ts +3 -0
- package/dist/bin/prjct.mjs +64 -4
- package/package.json +1 -1
- package/templates/commands/git.md +53 -11
- package/templates/commands/merge.md +22 -2
- package/templates/commands/ship.md +28 -2
- package/templates/commands/sync.md +70 -6
- package/templates/commands/task.md +30 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.54.3] - 2026-01-30
|
|
4
|
+
|
|
5
|
+
### Bug Fixes
|
|
6
|
+
|
|
7
|
+
- standardize confirmation pattern across all commands (#85)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## [0.54.3] - 2026-01-30
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Standardize confirmation pattern across all commands to use AskUserQuestion
|
|
15
|
+
- Updated `ship.md`, `merge.md`, `git.md`, `task.md` templates
|
|
16
|
+
- Replaces inconsistent "Proceed? (yes/no)" text prompts
|
|
17
|
+
- All confirmations now use consistent options: "Yes (Recommended)", "No, cancel"
|
|
18
|
+
|
|
19
|
+
## [0.54.2] - 2026-01-30
|
|
20
|
+
|
|
21
|
+
### Bug Fixes
|
|
22
|
+
|
|
23
|
+
- LLM debe manejar los prompts, no el CLI - PRJ-149 (#84)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## [0.55.3] - 2026-01-30
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- **LLM debe manejar los prompts, no el CLI** (PRJ-149)
|
|
31
|
+
- Added `--json` flag to `prjct sync` for non-interactive mode
|
|
32
|
+
- CLI now detects non-TTY mode and outputs structured JSON instead of interactive prompts
|
|
33
|
+
- Updated `sync.md` template so LLM uses AskUserQuestion for confirmation
|
|
34
|
+
- Enables proper flow: `prjct sync --json` → show diff → AskUserQuestion → `prjct sync --yes`
|
|
35
|
+
|
|
36
|
+
|
|
3
37
|
## [0.54.1] - 2026-01-30
|
|
4
38
|
|
|
5
39
|
### Bug Fixes
|
|
@@ -213,6 +213,13 @@ export class AnalysisCommands extends PrjctCommandsBase {
|
|
|
213
213
|
* Options:
|
|
214
214
|
* - --preview: Show what would change without applying
|
|
215
215
|
* - --yes: Skip confirmation prompt
|
|
216
|
+
* - --json: Output structured JSON for LLM consumption (non-interactive)
|
|
217
|
+
*
|
|
218
|
+
* When running in non-TTY mode (e.g., from an LLM), the CLI outputs
|
|
219
|
+
* structured JSON instead of interactive prompts. The LLM should:
|
|
220
|
+
* 1. Run `prjct sync --preview --json` to get diff data
|
|
221
|
+
* 2. Show diff to user and use AskUserQuestion for confirmation
|
|
222
|
+
* 3. Run `prjct sync --yes` if user confirms
|
|
216
223
|
*
|
|
217
224
|
* This eliminates the need for Claude to make 50+ individual tool calls.
|
|
218
225
|
*
|
|
@@ -220,7 +227,7 @@ export class AnalysisCommands extends PrjctCommandsBase {
|
|
|
220
227
|
*/
|
|
221
228
|
async sync(
|
|
222
229
|
projectPath: string = process.cwd(),
|
|
223
|
-
options: { aiTools?: string[]; preview?: boolean; yes?: boolean } = {}
|
|
230
|
+
options: { aiTools?: string[]; preview?: boolean; yes?: boolean; json?: boolean } = {}
|
|
224
231
|
): Promise<CommandResult> {
|
|
225
232
|
try {
|
|
226
233
|
const initResult = await this.ensureProjectInit(projectPath)
|
|
@@ -244,14 +251,23 @@ export class AnalysisCommands extends PrjctCommandsBase {
|
|
|
244
251
|
// No existing file - first sync
|
|
245
252
|
}
|
|
246
253
|
|
|
254
|
+
// Detect non-interactive mode (LLM or piped input)
|
|
255
|
+
const isNonInteractive = !process.stdin.isTTY || options.json
|
|
256
|
+
|
|
247
257
|
// For preview mode or when we have existing content, show diff first
|
|
248
258
|
if (existingContent && !options.yes) {
|
|
249
|
-
|
|
259
|
+
if (!isNonInteractive) {
|
|
260
|
+
out.spin('Analyzing changes...')
|
|
261
|
+
}
|
|
250
262
|
|
|
251
263
|
// Do a dry-run sync to see what would change
|
|
252
264
|
const result = await syncService.sync(projectPath, { aiTools: options.aiTools })
|
|
253
265
|
|
|
254
266
|
if (!result.success) {
|
|
267
|
+
if (isNonInteractive) {
|
|
268
|
+
console.log(JSON.stringify({ success: false, error: result.error || 'Sync failed' }))
|
|
269
|
+
return { success: false, error: result.error }
|
|
270
|
+
}
|
|
255
271
|
out.fail(result.error || 'Sync failed')
|
|
256
272
|
return { success: false, error: result.error }
|
|
257
273
|
}
|
|
@@ -267,14 +283,64 @@ export class AnalysisCommands extends PrjctCommandsBase {
|
|
|
267
283
|
// Generate diff
|
|
268
284
|
const diff = generateSyncDiff(existingContent, newContent)
|
|
269
285
|
|
|
270
|
-
|
|
286
|
+
if (!isNonInteractive) {
|
|
287
|
+
out.stop()
|
|
288
|
+
}
|
|
271
289
|
|
|
272
290
|
if (!diff.hasChanges) {
|
|
291
|
+
if (isNonInteractive) {
|
|
292
|
+
console.log(
|
|
293
|
+
JSON.stringify({
|
|
294
|
+
success: true,
|
|
295
|
+
action: 'no_changes',
|
|
296
|
+
message: 'No changes detected (context is up to date)',
|
|
297
|
+
})
|
|
298
|
+
)
|
|
299
|
+
return { success: true, message: 'No changes' }
|
|
300
|
+
}
|
|
273
301
|
out.done('No changes detected (context is up to date)')
|
|
274
302
|
return { success: true, message: 'No changes' }
|
|
275
303
|
}
|
|
276
304
|
|
|
277
|
-
//
|
|
305
|
+
// Non-interactive mode: return JSON for LLM to handle
|
|
306
|
+
if (isNonInteractive) {
|
|
307
|
+
// Build a plain-text diff summary for LLM to show user
|
|
308
|
+
const diffSummary = {
|
|
309
|
+
added: diff.added.map((s) => ({ name: s.name, lineCount: s.lineCount })),
|
|
310
|
+
modified: diff.modified.map((s) => ({ name: s.name, lineCount: s.lineCount })),
|
|
311
|
+
removed: diff.removed.map((s) => ({ name: s.name, lineCount: s.lineCount })),
|
|
312
|
+
preserved: diff.preserved,
|
|
313
|
+
tokensBefore: diff.tokensBefore,
|
|
314
|
+
tokensAfter: diff.tokensAfter,
|
|
315
|
+
tokenDelta: diff.tokenDelta,
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
console.log(
|
|
319
|
+
JSON.stringify({
|
|
320
|
+
success: true,
|
|
321
|
+
action: 'confirm_required',
|
|
322
|
+
message: 'Changes detected. Confirmation required to apply.',
|
|
323
|
+
diff: diffSummary,
|
|
324
|
+
fullDiff: options.preview
|
|
325
|
+
? {
|
|
326
|
+
added: diff.added,
|
|
327
|
+
modified: diff.modified,
|
|
328
|
+
removed: diff.removed,
|
|
329
|
+
}
|
|
330
|
+
: undefined,
|
|
331
|
+
hint: 'Run `prjct sync --yes` to apply changes',
|
|
332
|
+
})
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
return {
|
|
336
|
+
success: true,
|
|
337
|
+
isPreview: true,
|
|
338
|
+
diff,
|
|
339
|
+
message: 'Preview complete (awaiting confirmation)',
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Show diff preview (interactive mode)
|
|
278
344
|
console.log(formatDiffPreview(diff))
|
|
279
345
|
|
|
280
346
|
// Preview-only mode - don't apply
|
|
@@ -287,7 +353,7 @@ export class AnalysisCommands extends PrjctCommandsBase {
|
|
|
287
353
|
}
|
|
288
354
|
}
|
|
289
355
|
|
|
290
|
-
// Interactive confirmation
|
|
356
|
+
// Interactive confirmation (TTY mode only)
|
|
291
357
|
const response = await prompts({
|
|
292
358
|
type: 'select',
|
|
293
359
|
name: 'action',
|
|
@@ -184,7 +184,7 @@ class PrjctCommands {
|
|
|
184
184
|
|
|
185
185
|
async sync(
|
|
186
186
|
projectPath: string = process.cwd(),
|
|
187
|
-
options: { aiTools?: string[] } = {}
|
|
187
|
+
options: { aiTools?: string[]; preview?: boolean; yes?: boolean; json?: boolean } = {}
|
|
188
188
|
): Promise<CommandResult> {
|
|
189
189
|
return this.analysis.sync(projectPath, options)
|
|
190
190
|
}
|
package/core/index.ts
CHANGED
|
@@ -126,6 +126,9 @@ async function main(): Promise<void> {
|
|
|
126
126
|
sync: () =>
|
|
127
127
|
commands.sync(process.cwd(), {
|
|
128
128
|
aiTools: options.agents ? String(options.agents).split(',') : undefined,
|
|
129
|
+
preview: options.preview === true,
|
|
130
|
+
yes: options.yes === true,
|
|
131
|
+
json: options.json === true,
|
|
129
132
|
}),
|
|
130
133
|
start: () => commands.start(),
|
|
131
134
|
// Context (for Claude templates)
|
package/dist/bin/prjct.mjs
CHANGED
|
@@ -16998,6 +16998,13 @@ var init_analysis2 = __esm({
|
|
|
16998
16998
|
* Options:
|
|
16999
16999
|
* - --preview: Show what would change without applying
|
|
17000
17000
|
* - --yes: Skip confirmation prompt
|
|
17001
|
+
* - --json: Output structured JSON for LLM consumption (non-interactive)
|
|
17002
|
+
*
|
|
17003
|
+
* When running in non-TTY mode (e.g., from an LLM), the CLI outputs
|
|
17004
|
+
* structured JSON instead of interactive prompts. The LLM should:
|
|
17005
|
+
* 1. Run `prjct sync --preview --json` to get diff data
|
|
17006
|
+
* 2. Show diff to user and use AskUserQuestion for confirmation
|
|
17007
|
+
* 3. Run `prjct sync --yes` if user confirms
|
|
17001
17008
|
*
|
|
17002
17009
|
* This eliminates the need for Claude to make 50+ individual tool calls.
|
|
17003
17010
|
*
|
|
@@ -17020,10 +17027,17 @@ var init_analysis2 = __esm({
|
|
|
17020
17027
|
existingContent = await fs34.readFile(claudeMdPath, "utf-8");
|
|
17021
17028
|
} catch {
|
|
17022
17029
|
}
|
|
17030
|
+
const isNonInteractive = !process.stdin.isTTY || options.json;
|
|
17023
17031
|
if (existingContent && !options.yes) {
|
|
17024
|
-
|
|
17032
|
+
if (!isNonInteractive) {
|
|
17033
|
+
output_default.spin("Analyzing changes...");
|
|
17034
|
+
}
|
|
17025
17035
|
const result2 = await syncService.sync(projectPath, { aiTools: options.aiTools });
|
|
17026
17036
|
if (!result2.success) {
|
|
17037
|
+
if (isNonInteractive) {
|
|
17038
|
+
console.log(JSON.stringify({ success: false, error: result2.error || "Sync failed" }));
|
|
17039
|
+
return { success: false, error: result2.error };
|
|
17040
|
+
}
|
|
17027
17041
|
output_default.fail(result2.error || "Sync failed");
|
|
17028
17042
|
return { success: false, error: result2.error };
|
|
17029
17043
|
}
|
|
@@ -17034,11 +17048,54 @@ var init_analysis2 = __esm({
|
|
|
17034
17048
|
newContent = "";
|
|
17035
17049
|
}
|
|
17036
17050
|
const diff = generateSyncDiff(existingContent, newContent);
|
|
17037
|
-
|
|
17051
|
+
if (!isNonInteractive) {
|
|
17052
|
+
output_default.stop();
|
|
17053
|
+
}
|
|
17038
17054
|
if (!diff.hasChanges) {
|
|
17055
|
+
if (isNonInteractive) {
|
|
17056
|
+
console.log(
|
|
17057
|
+
JSON.stringify({
|
|
17058
|
+
success: true,
|
|
17059
|
+
action: "no_changes",
|
|
17060
|
+
message: "No changes detected (context is up to date)"
|
|
17061
|
+
})
|
|
17062
|
+
);
|
|
17063
|
+
return { success: true, message: "No changes" };
|
|
17064
|
+
}
|
|
17039
17065
|
output_default.done("No changes detected (context is up to date)");
|
|
17040
17066
|
return { success: true, message: "No changes" };
|
|
17041
17067
|
}
|
|
17068
|
+
if (isNonInteractive) {
|
|
17069
|
+
const diffSummary = {
|
|
17070
|
+
added: diff.added.map((s) => ({ name: s.name, lineCount: s.lineCount })),
|
|
17071
|
+
modified: diff.modified.map((s) => ({ name: s.name, lineCount: s.lineCount })),
|
|
17072
|
+
removed: diff.removed.map((s) => ({ name: s.name, lineCount: s.lineCount })),
|
|
17073
|
+
preserved: diff.preserved,
|
|
17074
|
+
tokensBefore: diff.tokensBefore,
|
|
17075
|
+
tokensAfter: diff.tokensAfter,
|
|
17076
|
+
tokenDelta: diff.tokenDelta
|
|
17077
|
+
};
|
|
17078
|
+
console.log(
|
|
17079
|
+
JSON.stringify({
|
|
17080
|
+
success: true,
|
|
17081
|
+
action: "confirm_required",
|
|
17082
|
+
message: "Changes detected. Confirmation required to apply.",
|
|
17083
|
+
diff: diffSummary,
|
|
17084
|
+
fullDiff: options.preview ? {
|
|
17085
|
+
added: diff.added,
|
|
17086
|
+
modified: diff.modified,
|
|
17087
|
+
removed: diff.removed
|
|
17088
|
+
} : void 0,
|
|
17089
|
+
hint: "Run `prjct sync --yes` to apply changes"
|
|
17090
|
+
})
|
|
17091
|
+
);
|
|
17092
|
+
return {
|
|
17093
|
+
success: true,
|
|
17094
|
+
isPreview: true,
|
|
17095
|
+
diff,
|
|
17096
|
+
message: "Preview complete (awaiting confirmation)"
|
|
17097
|
+
};
|
|
17098
|
+
}
|
|
17042
17099
|
console.log(formatDiffPreview(diff));
|
|
17043
17100
|
if (options.preview) {
|
|
17044
17101
|
return {
|
|
@@ -25016,7 +25073,7 @@ var require_package = __commonJS({
|
|
|
25016
25073
|
"package.json"(exports, module) {
|
|
25017
25074
|
module.exports = {
|
|
25018
25075
|
name: "prjct-cli",
|
|
25019
|
-
version: "0.54.
|
|
25076
|
+
version: "0.54.3",
|
|
25020
25077
|
description: "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
|
|
25021
25078
|
main: "core/index.ts",
|
|
25022
25079
|
bin: {
|
|
@@ -25201,7 +25258,10 @@ Use 'prjct --help' to see available commands.`);
|
|
|
25201
25258
|
history: /* @__PURE__ */ __name(() => commands.history(), "history"),
|
|
25202
25259
|
// Setup
|
|
25203
25260
|
sync: /* @__PURE__ */ __name(() => commands.sync(process.cwd(), {
|
|
25204
|
-
aiTools: options.agents ? String(options.agents).split(",") : void 0
|
|
25261
|
+
aiTools: options.agents ? String(options.agents).split(",") : void 0,
|
|
25262
|
+
preview: options.preview === true,
|
|
25263
|
+
yes: options.yes === true,
|
|
25264
|
+
json: options.json === true
|
|
25205
25265
|
}), "sync"),
|
|
25206
25266
|
start: /* @__PURE__ */ __name(() => commands.start(), "start"),
|
|
25207
25267
|
// Context (for Claude templates)
|
package/package.json
CHANGED
|
@@ -91,9 +91,8 @@ ABORT.
|
|
|
91
91
|
git diff --stat
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
+
Show the user:
|
|
94
95
|
```
|
|
95
|
-
OUTPUT:
|
|
96
|
-
"""
|
|
97
96
|
## Commit Plan
|
|
98
97
|
|
|
99
98
|
Branch: {currentBranch}
|
|
@@ -101,13 +100,38 @@ Changes:
|
|
|
101
100
|
{git diff --stat output}
|
|
102
101
|
|
|
103
102
|
Will create commit with prjct footer.
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Then ask for confirmation:
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
AskUserQuestion:
|
|
109
|
+
question: "Create this commit?"
|
|
110
|
+
header: "Commit"
|
|
111
|
+
options:
|
|
112
|
+
- label: "Yes, commit (Recommended)"
|
|
113
|
+
description: "Stage all changes and commit"
|
|
114
|
+
- label: "No, cancel"
|
|
115
|
+
description: "Abort commit"
|
|
116
|
+
- label: "Show full diff"
|
|
117
|
+
description: "See detailed changes"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Handle responses:**
|
|
106
121
|
|
|
107
|
-
|
|
108
|
-
|
|
122
|
+
**If "Show full diff":**
|
|
123
|
+
- Run `git diff` to show full changes
|
|
124
|
+
- Ask again with Yes/No options only
|
|
125
|
+
|
|
126
|
+
**If "No, cancel":**
|
|
127
|
+
```
|
|
128
|
+
OUTPUT: "✅ Commit cancelled"
|
|
129
|
+
STOP - Do not continue
|
|
109
130
|
```
|
|
110
131
|
|
|
132
|
+
**If "Yes, commit":**
|
|
133
|
+
CONTINUE to Step 3
|
|
134
|
+
|
|
111
135
|
### Step 3: Stage and Commit
|
|
112
136
|
|
|
113
137
|
```bash
|
|
@@ -159,20 +183,38 @@ ABORT.
|
|
|
159
183
|
git log origin/{currentBranch}..HEAD --oneline 2>/dev/null || git log --oneline -3
|
|
160
184
|
```
|
|
161
185
|
|
|
186
|
+
Show the user:
|
|
162
187
|
```
|
|
163
|
-
OUTPUT:
|
|
164
|
-
"""
|
|
165
188
|
## Push Plan
|
|
166
189
|
|
|
167
190
|
Branch: {currentBranch}
|
|
168
191
|
Commits to push:
|
|
169
192
|
{commits}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Then ask for confirmation:
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
AskUserQuestion:
|
|
199
|
+
question: "Push these commits?"
|
|
200
|
+
header: "Push"
|
|
201
|
+
options:
|
|
202
|
+
- label: "Yes, push (Recommended)"
|
|
203
|
+
description: "Push to remote origin"
|
|
204
|
+
- label: "No, cancel"
|
|
205
|
+
description: "Keep commits local"
|
|
206
|
+
```
|
|
170
207
|
|
|
171
|
-
|
|
172
|
-
"""
|
|
208
|
+
**Handle responses:**
|
|
173
209
|
|
|
174
|
-
|
|
210
|
+
**If "No, cancel":**
|
|
175
211
|
```
|
|
212
|
+
OUTPUT: "✅ Push cancelled"
|
|
213
|
+
STOP - Do not continue
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**If "Yes, push":**
|
|
217
|
+
CONTINUE to Step 3
|
|
176
218
|
|
|
177
219
|
### Step 3: Execute Push
|
|
178
220
|
|
|
@@ -79,11 +79,31 @@ Will do:
|
|
|
79
79
|
1. Merge PR with squash
|
|
80
80
|
2. Delete feature branch
|
|
81
81
|
3. Update local main
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Then ask for confirmation:
|
|
82
85
|
|
|
83
|
-
|
|
86
|
+
```
|
|
87
|
+
AskUserQuestion:
|
|
88
|
+
question: "Merge this PR?"
|
|
89
|
+
header: "Merge"
|
|
90
|
+
options:
|
|
91
|
+
- label: "Yes, merge (Recommended)"
|
|
92
|
+
description: "Squash merge and delete branch"
|
|
93
|
+
- label: "No, cancel"
|
|
94
|
+
description: "Keep PR open"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Handle responses:**
|
|
98
|
+
|
|
99
|
+
**If "No, cancel":**
|
|
100
|
+
```
|
|
101
|
+
OUTPUT: "✅ Merge cancelled"
|
|
102
|
+
STOP - Do not continue
|
|
84
103
|
```
|
|
85
104
|
|
|
86
|
-
|
|
105
|
+
**If "Yes, merge":**
|
|
106
|
+
CONTINUE to Step 4
|
|
87
107
|
|
|
88
108
|
---
|
|
89
109
|
|
|
@@ -69,11 +69,37 @@ Will do:
|
|
|
69
69
|
4. Commit with prjct footer
|
|
70
70
|
5. Push branch
|
|
71
71
|
6. Create PR to main
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Then ask for confirmation:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
AskUserQuestion:
|
|
78
|
+
question: "Ready to ship these changes?"
|
|
79
|
+
header: "Ship"
|
|
80
|
+
options:
|
|
81
|
+
- label: "Yes, ship it (Recommended)"
|
|
82
|
+
description: "Run tests, bump version, create PR"
|
|
83
|
+
- label: "No, cancel"
|
|
84
|
+
description: "Abort ship operation"
|
|
85
|
+
- label: "Show full diff"
|
|
86
|
+
description: "See all file changes before deciding"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Handle responses:**
|
|
72
90
|
|
|
73
|
-
|
|
91
|
+
**If "Show full diff":**
|
|
92
|
+
- Run `git diff` to show full changes
|
|
93
|
+
- Ask again with Yes/No options only
|
|
94
|
+
|
|
95
|
+
**If "No, cancel":**
|
|
96
|
+
```
|
|
97
|
+
OUTPUT: "✅ Ship cancelled"
|
|
98
|
+
STOP - Do not continue
|
|
74
99
|
```
|
|
75
100
|
|
|
76
|
-
|
|
101
|
+
**If "Yes, ship it":**
|
|
102
|
+
CONTINUE to Step 3
|
|
77
103
|
|
|
78
104
|
---
|
|
79
105
|
|
|
@@ -1,14 +1,79 @@
|
|
|
1
1
|
---
|
|
2
|
-
allowed-tools: [Bash, Read, Write]
|
|
2
|
+
allowed-tools: [Bash, Read, Write, AskUserQuestion]
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
# p. sync
|
|
6
6
|
|
|
7
|
+
## Step 1: Run sync with JSON output
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
prjct sync --json
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Parse the JSON output to determine next action.
|
|
14
|
+
|
|
15
|
+
## Step 2: Handle response
|
|
16
|
+
|
|
17
|
+
**If `action: "no_changes"`:**
|
|
18
|
+
```
|
|
19
|
+
Output: "✅ Context is up to date"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**If `action: "confirm_required"`:**
|
|
23
|
+
|
|
24
|
+
Show the diff summary to the user:
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
📋 Changes to context files:
|
|
28
|
+
|
|
29
|
+
+ Added: {list added sections}
|
|
30
|
+
~ Modified: {list modified sections}
|
|
31
|
+
- Removed: {list removed sections}
|
|
32
|
+
|
|
33
|
+
Tokens: {tokensBefore} → {tokensAfter} ({tokenDelta})
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Then ask for confirmation:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
AskUserQuestion:
|
|
40
|
+
question: "Apply these context changes?"
|
|
41
|
+
header: "Sync"
|
|
42
|
+
options:
|
|
43
|
+
- label: "Yes, apply changes"
|
|
44
|
+
description: "Update context files with the changes shown above"
|
|
45
|
+
- label: "No, cancel"
|
|
46
|
+
description: "Keep existing context files unchanged"
|
|
47
|
+
- label: "Show full diff"
|
|
48
|
+
description: "See detailed before/after for each section"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Step 3: Apply based on response
|
|
52
|
+
|
|
53
|
+
**If "Yes, apply changes":**
|
|
54
|
+
```bash
|
|
55
|
+
prjct sync --yes
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**If "No, cancel":**
|
|
59
|
+
```
|
|
60
|
+
Output: "✅ Sync cancelled"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**If "Show full diff":**
|
|
64
|
+
- Run `prjct sync --preview --json` to get full diff details
|
|
65
|
+
- Display the full diff to user
|
|
66
|
+
- Ask again with Yes/No options only
|
|
67
|
+
|
|
68
|
+
## First sync (no existing files)
|
|
69
|
+
|
|
70
|
+
When there's no existing context, the CLI will apply changes directly:
|
|
71
|
+
|
|
7
72
|
```bash
|
|
8
|
-
prjct sync
|
|
73
|
+
prjct sync --json
|
|
9
74
|
```
|
|
10
75
|
|
|
11
|
-
|
|
76
|
+
This returns success without needing confirmation.
|
|
12
77
|
|
|
13
78
|
## Linear Sync (when enabled)
|
|
14
79
|
|
|
@@ -21,8 +86,6 @@ IF integrations.linear.enabled:
|
|
|
21
86
|
RUN: bun $PRJCT_CLI/core/cli/linear.ts --project {projectId} sync
|
|
22
87
|
|
|
23
88
|
# Result stored in {globalPath}/storage/issues.json
|
|
24
|
-
# Contains all assigned issues from Linear
|
|
25
|
-
|
|
26
89
|
OUTPUT: "Linear: {fetched} issues synced"
|
|
27
90
|
```
|
|
28
91
|
|
|
@@ -35,7 +98,8 @@ If `.cursor/` exists but `.cursor/rules/prjct.mdc` is missing:
|
|
|
35
98
|
4. Copy commands: `{npmRoot}/prjct-cli/templates/cursor/p.md` → `.cursor/commands/p.md`
|
|
36
99
|
5. Report: "Cursor routers regenerated"
|
|
37
100
|
|
|
38
|
-
|
|
101
|
+
## Output
|
|
102
|
+
|
|
39
103
|
```
|
|
40
104
|
✅ Synced: {projectName}
|
|
41
105
|
|
|
@@ -123,9 +123,8 @@ ELSE:
|
|
|
123
123
|
|
|
124
124
|
**⛔ DO NOT create branches or modify state without user approval.**
|
|
125
125
|
|
|
126
|
+
Show the user:
|
|
126
127
|
```
|
|
127
|
-
OUTPUT:
|
|
128
|
-
"""
|
|
129
128
|
## Task Plan
|
|
130
129
|
|
|
131
130
|
Description: $ARGUMENTS
|
|
@@ -137,13 +136,38 @@ Will do:
|
|
|
137
136
|
2. Initialize task tracking in state.json
|
|
138
137
|
3. Break down into subtasks
|
|
139
138
|
4. {If Linear: Update issue status to In Progress}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Then ask for confirmation:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
AskUserQuestion:
|
|
145
|
+
question: "Start this task?"
|
|
146
|
+
header: "Task"
|
|
147
|
+
options:
|
|
148
|
+
- label: "Yes, start task (Recommended)"
|
|
149
|
+
description: "Create branch and begin tracking"
|
|
150
|
+
- label: "No, cancel"
|
|
151
|
+
description: "Don't create task"
|
|
152
|
+
- label: "Modify plan"
|
|
153
|
+
description: "Change type, branch name, or subtasks"
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Handle responses:**
|
|
140
157
|
|
|
141
|
-
|
|
142
|
-
""
|
|
158
|
+
**If "Modify plan":**
|
|
159
|
+
- Ask: "What would you like to change?"
|
|
160
|
+
- Update plan accordingly
|
|
161
|
+
- Ask again with Yes/No options only
|
|
143
162
|
|
|
144
|
-
|
|
145
|
-
DO NOT assume
|
|
163
|
+
**If "No, cancel":**
|
|
146
164
|
```
|
|
165
|
+
OUTPUT: "✅ Task creation cancelled"
|
|
166
|
+
STOP - Do not continue
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**If "Yes, start task":**
|
|
170
|
+
CONTINUE to Step B
|
|
147
171
|
|
|
148
172
|
### Step B: Explore Codebase
|
|
149
173
|
|