prjct-cli 0.54.0 → 0.54.2

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 CHANGED
@@ -1,12 +1,39 @@
1
1
  # Changelog
2
2
 
3
- ## [0.54.0] - 2026-01-30
3
+ ## [0.54.2] - 2026-01-30
4
4
 
5
- ### Features
5
+ ### Bug Fixes
6
+
7
+ - LLM debe manejar los prompts, no el CLI - PRJ-149 (#84)
8
+
9
+
10
+ ## [0.55.3] - 2026-01-30
11
+
12
+ ### Fixed
13
+
14
+ - **LLM debe manejar los prompts, no el CLI** (PRJ-149)
15
+ - Added `--json` flag to `prjct sync` for non-interactive mode
16
+ - CLI now detects non-TTY mode and outputs structured JSON instead of interactive prompts
17
+ - Updated `sync.md` template so LLM uses AskUserQuestion for confirmation
18
+ - Enables proper flow: `prjct sync --json` → show diff → AskUserQuestion → `prjct sync --yes`
19
+
20
+
21
+ ## [0.54.1] - 2026-01-30
22
+
23
+ ### Bug Fixes
24
+
25
+ - Claude over-plans simple commands like p. sync - PRJ-148 (#83)
26
+
27
+
28
+ ## [0.55.2] - 2026-01-30
29
+
30
+ ### Fixed
6
31
 
7
- - Add showMetrics config option - PRJ-70 (#82)
8
- - Selective memory retrieval based on task relevance - PRJ-107 (#81)
9
- - Add session stats to p. stats command - PRJ-89 (#80)
32
+ - **Claude over-plans simple commands** (PRJ-148)
33
+ - Added "⚡ FAST vs 🧠 SMART COMMANDS" section to CLAUDE.md
34
+ - FAST commands (sync, next, dash, pause, resume) now execute immediately without exploration/planning
35
+ - SMART commands (task, ship, bug, done) continue to use intelligent behavior
36
+ - Clarified that "Key Intelligence Rules" only apply to SMART commands
10
37
 
11
38
 
12
39
  ## [0.55.1] - 2026-01-30
@@ -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
- out.spin('Analyzing changes...')
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
- out.stop()
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
- // Show diff preview
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)
@@ -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
- output_default.spin("Analyzing changes...");
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
- output_default.stop();
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.0",
25076
+ version: "0.54.2",
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prjct-cli",
3
- "version": "0.54.0",
3
+ "version": "0.54.2",
4
4
  "description": "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
5
5
  "main": "core/index.ts",
6
6
  "bin": {
@@ -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
- CLI handles: git analysis, context generation, agents, skills.
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
- **Output**:
101
+ ## Output
102
+
39
103
  ```
40
104
  ✅ Synced: {projectName}
41
105
 
@@ -16,6 +16,50 @@ p. ship X → templates/commands/ship.md
16
16
 
17
17
  ---
18
18
 
19
+ ## ⚡ FAST vs 🧠 SMART COMMANDS (CRITICAL)
20
+
21
+ **Some commands just run a CLI. Others need intelligence. Know the difference.**
22
+
23
+ ### ⚡ FAST COMMANDS (Execute Immediately - NO planning, NO exploration)
24
+
25
+ | Command | Action | Time |
26
+ |---------|--------|------|
27
+ | `p. sync` | Run `prjct sync` | <5s |
28
+ | `p. next` | Run `prjct next` | <2s |
29
+ | `p. dash` | Run `prjct dash` | <2s |
30
+ | `p. pause` | Run `prjct pause` | <2s |
31
+ | `p. resume` | Run `prjct resume` | <2s |
32
+
33
+ **For these commands:**
34
+ ```
35
+ 1. Read template
36
+ 2. Run the CLI command shown
37
+ 3. Done
38
+ ```
39
+
40
+ **⛔ DO NOT:** explore codebase, create plans, ask questions, read project files
41
+
42
+ ### 🧠 SMART COMMANDS (Require intelligence)
43
+
44
+ | Command | Why it needs intelligence |
45
+ |---------|--------------------------|
46
+ | `p. task` | Must explore codebase, break down work |
47
+ | `p. ship` | Must validate changes, create PR |
48
+ | `p. bug` | Must classify severity, find affected files |
49
+ | `p. done` | Must verify completion, update state |
50
+
51
+ **For these commands:** Follow the full INTELLIGENT BEHAVIOR rules below.
52
+
53
+ ### Decision Rule
54
+ ```
55
+ IF template just says "run CLI command":
56
+ → Execute immediately, no planning
57
+ ELSE:
58
+ → Use intelligent behavior (explore, ask, plan)
59
+ ```
60
+
61
+ ---
62
+
19
63
  ## ⛔ CRITICAL RULES - READ BEFORE EVERY COMMAND
20
64
 
21
65
  ### 0. FOLLOW TEMPLATES STEP BY STEP (NON-NEGOTIABLE)
@@ -264,13 +308,15 @@ User Action → Storage (JSON) → Context (MD) → Sync Events
264
308
  4. Update CHANGELOG
265
309
  5. Create git tag
266
310
 
267
- ### Key Intelligence Rules
311
+ ### Key Intelligence Rules (For 🧠 SMART commands only)
268
312
  - **Read before write** - Always read existing files before modifying
269
313
  - **Explore before coding** - Use Task(Explore) to understand codebase
270
314
  - **Ask when uncertain** - Use AskUserQuestion to clarify
271
- - **Adapt templates** - Templates are guidance, not rigid scripts
272
315
  - **Log everything** - Append to memory/events.jsonl
273
316
 
317
+ **⚠️ These rules apply ONLY to 🧠 SMART commands (task, ship, bug, done).**
318
+ **⚡ FAST commands skip all of this - just run the CLI.**
319
+
274
320
  ---
275
321
 
276
322
  ## OUTPUT FORMAT