prjct-cli 0.42.0 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prjct-cli",
3
- "version": "0.42.0",
3
+ "version": "0.44.0",
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": {
@@ -9,6 +9,17 @@ description: 'Base template for issue tracker integrations'
9
9
 
10
10
  All issue tracker integrations (Linear, JIRA, GitHub Issues, Monday.com) inherit from this base.
11
11
 
12
+ ## CRITICAL - SDK vs MCP
13
+
14
+ | Tracker | Method | Why |
15
+ |---------|--------|-----|
16
+ | **Linear** | **SDK ONLY** | Per-project credentials, 4x faster |
17
+ | **JIRA** | **SDK ONLY** | Per-project credentials, 4x faster |
18
+ | GitHub | MCP | Simple token auth |
19
+ | Monday | MCP | OAuth only |
20
+
21
+ **For Linear and JIRA**: NEVER use MCP tools (`mcp__linear__*`, `mcp__jira__*`). ALWAYS use the SDK CLI helper.
22
+
12
23
  ---
13
24
 
14
25
  ## Common Context Variables
@@ -26,20 +26,25 @@ WRITE `{globalPath}/storage/state.json`
26
26
 
27
27
  ## Sync Issue Tracker Status
28
28
 
29
- IF `currentTask.externalId` exists:
29
+ IF `currentTask.linearId` exists:
30
30
 
31
31
  ```
32
- IF currentTask.externalProvider == "linear":
33
- # Update Linear issue to Done
34
- IMPORT: linearService from core/integrations/linear
35
- CALL: linearService.markDone(currentTask.externalId)
36
- OUTPUT: "Linear: {externalId} → Done"
37
-
38
- ELSE IF currentTask.externalProvider == "jira":
39
- # Update JIRA issue to Done
40
- IMPORT: jiraService from core/integrations/jira
41
- CALL: jiraService.markDone(currentTask.externalId)
42
- OUTPUT: "JIRA: {externalId} → Done"
32
+ # Update Linear issue to Done using sync layer
33
+ # This updates both Linear API and local issues.json cache
34
+
35
+ IMPORT: linearSync from core/integrations/linear
36
+ CALL: linearSync.pushStatus(projectId, currentTask.linearId, 'done')
37
+
38
+ OUTPUT: "Linear: {linearId} Done"
39
+ ```
40
+
41
+ ELSE IF `currentTask.externalId` AND `currentTask.externalProvider == "jira"`:
42
+
43
+ ```
44
+ # Update JIRA issue to Done
45
+ IMPORT: jiraService from core/integrations/jira
46
+ CALL: jiraService.markDone(currentTask.externalId)
47
+ OUTPUT: "JIRA: {externalId} → Done"
43
48
  ```
44
49
 
45
50
  ---
@@ -49,7 +54,7 @@ ELSE IF currentTask.externalProvider == "jira":
49
54
  {task} ({duration})
50
55
 
51
56
  Files: {count} | Commits: {count}
52
- {externalId ? "{externalProvider}: {externalId} → Done" : ""}
57
+ {linearId ? "Linear: {linearId} → Done" : ""}
53
58
 
54
59
  Next:
55
60
  - More work? → `p. task "description"`
@@ -10,6 +10,22 @@ prjct sync
10
10
 
11
11
  CLI handles: git analysis, context generation, agents, skills.
12
12
 
13
+ ## Linear Sync (when enabled)
14
+
15
+ ```
16
+ READ: .prjct/prjct.config.json → get projectId
17
+ READ: {globalPath}/project.json → check integrations.linear.enabled
18
+
19
+ IF integrations.linear.enabled:
20
+ # Sync Linear issues to local cache
21
+ RUN: bun core/cli/linear.ts --project {projectId} sync
22
+
23
+ # Result stored in {globalPath}/storage/issues.json
24
+ # Contains all assigned issues from Linear
25
+
26
+ OUTPUT: "Linear: {fetched} issues synced"
27
+ ```
28
+
13
29
  ## Cursor Router Regeneration
14
30
 
15
31
  If `.cursor/` exists but `.cursor/rules/prjct.mdc` is missing:
@@ -25,6 +41,7 @@ If `.cursor/` exists but `.cursor/rules/prjct.mdc` is missing:
25
41
 
26
42
  Ecosystem: {ecosystem}
27
43
  Agents: {count} generated
44
+ Linear: {issueCount} issues synced (or "not enabled")
28
45
  Cursor: {regenerated/ready/not detected}
29
46
 
30
47
  Next:
@@ -17,20 +17,29 @@ READ: {globalPath}/project.json
17
17
  CHECK: integrations.linear OR integrations.jira
18
18
 
19
19
  IF integrations.linear.enabled:
20
- # Linear issue detected
21
- IMPORT: linearService from core/integrations/linear
22
- CALL: linearService.fetchIssue("$ARGUMENTS")
20
+ # Linear issue detected - use LOCAL-FIRST approach
21
+ # Try local cache first (issues.json), then API if not found
22
+
23
+ RUN: bun core/cli/linear.ts --project {projectId} get-local "$ARGUMENTS"
24
+
25
+ IF issue found in local cache:
26
+ USE cached issue data (no API call needed)
27
+ ELSE:
28
+ # Fallback to API
29
+ IMPORT: linearSync from core/integrations/linear
30
+ CALL: linearSync.getIssue(projectId, "$ARGUMENTS") # Fetches + caches
23
31
 
24
32
  IF issue found:
25
- SET: task.externalId = issue.externalId
26
- SET: task.externalProvider = "linear"
33
+ SET: task.linearId = issue.identifier # "PRJ-123"
34
+ SET: task.linearUuid = issue.id # Linear internal UUID
27
35
  SET: task.description = issue.title
28
36
  SET: $ARGUMENTS = issue.title # Use title for task
29
37
 
30
- # Mark issue as In Progress in Linear
31
- CALL: linearService.markInProgress(issue.id)
38
+ # Mark issue as In Progress in Linear (pushes status change)
39
+ IMPORT: linearSync from core/integrations/linear
40
+ CALL: linearSync.pushStatus(projectId, issue.identifier, 'in_progress')
32
41
 
33
- OUTPUT: "Linked to Linear: {issue.externalId} - {issue.title}"
42
+ OUTPUT: "Linked to Linear: {issue.identifier} - {issue.title}"
34
43
  OUTPUT: "Linear: In Progress"
35
44
 
36
45
  ELSE IF integrations.jira.enabled:
@@ -83,8 +92,8 @@ WRITE `{globalPath}/storage/state.json`:
83
92
  "subtasks": [...],
84
93
  "currentSubtaskIndex": 0,
85
94
  "parentDescription": "$ARGUMENTS",
86
- "externalId": "{externalId or null}",
87
- "externalProvider": "{linear|jira|null}"
95
+ "linearId": "{identifier or null}", // "PRJ-123" - Linear identifier
96
+ "linearUuid": "{uuid or null}" // Linear internal UUID
88
97
  }
89
98
  }
90
99
  ```
@@ -94,7 +103,7 @@ WRITE `{globalPath}/storage/state.json`:
94
103
  {type}: $ARGUMENTS
95
104
 
96
105
  Branch: {branch} | Subtasks: {count}
97
- {externalId ? "Linked: {externalProvider} {externalId}" : ""}
106
+ {linearId ? "Linear: {linearId} → In Progress" : ""}
98
107
 
99
108
  Next: Work on subtask, then `p. done`
100
109
  ```
@@ -229,6 +229,64 @@ Next: [suggested action]
229
229
 
230
230
  ---
231
231
 
232
+ ## CLEAN TERMINAL UX (CRITICAL)
233
+
234
+ **Tool calls MUST be user-friendly.** The terminal output represents prjct's quality.
235
+
236
+ ### Rules for Tool Calls
237
+
238
+ 1. **ALWAYS use clear descriptions** in Bash tool calls:
239
+ ```
240
+ GOOD: description: "Building project"
241
+ BAD: description: "bun run build 2>&1 | tail -5"
242
+ ```
243
+
244
+ 2. **Hide implementation details** - Users don't need to see:
245
+ - Pipe chains (`| tail -5`, `| grep`, `2>&1`)
246
+ - Internal paths (`/Users/jj/.prjct-cli/...`)
247
+ - JSON parsing (`jq -r '.field'`)
248
+
249
+ 3. **Use action verbs** for descriptions:
250
+ - "Building project"
251
+ - "Running tests"
252
+ - "Checking git status"
253
+ - "Fetching Linear issues"
254
+
255
+ 4. **Group related operations** - Don't show 5 separate tool calls when 1 will do
256
+
257
+ 5. **Prefer prjct CLI over raw commands**:
258
+ ```
259
+ GOOD: bun core/cli/linear.ts list
260
+ BAD: curl -X POST https://api.linear.app/graphql...
261
+ ```
262
+
263
+ ### Examples
264
+
265
+ ```
266
+ # GOOD - Clean, understandable
267
+ ⏺ Bash: Building project
268
+ ✓ Build complete
269
+
270
+ # BAD - Technical noise
271
+ ⏺ Bash(cd /Users/jj/Apps/prjct && bun run build 2>&1 | tail -5)
272
+ → core/infrastructure/editors-config.js
273
+ → core/utils/version.js
274
+ ```
275
+
276
+ ### When Reading Files
277
+
278
+ - Don't announce every file read
279
+ - Group related reads
280
+ - Only mention files relevant to user's question
281
+
282
+ ### When Running Commands
283
+
284
+ - Show WHAT you're doing, not HOW
285
+ - Suppress stderr noise when possible
286
+ - Return only meaningful output
287
+
288
+ ---
289
+
232
290
  ## LOADING DOMAIN AGENTS
233
291
 
234
292
  When working on tasks, load relevant agents from `{globalPath}/agents/`: