planflow-plugin 0.1.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.
Files changed (66) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -0
  3. package/bin/cli.js +169 -0
  4. package/bin/postinstall.js +87 -0
  5. package/commands/pfActivity/SKILL.md +725 -0
  6. package/commands/pfAssign/SKILL.md +623 -0
  7. package/commands/pfCloudLink/SKILL.md +192 -0
  8. package/commands/pfCloudList/SKILL.md +222 -0
  9. package/commands/pfCloudNew/SKILL.md +187 -0
  10. package/commands/pfCloudUnlink/SKILL.md +152 -0
  11. package/commands/pfComment/SKILL.md +227 -0
  12. package/commands/pfComments/SKILL.md +159 -0
  13. package/commands/pfConnectionStatus/SKILL.md +433 -0
  14. package/commands/pfDiscord/SKILL.md +740 -0
  15. package/commands/pfGithubBranch/SKILL.md +672 -0
  16. package/commands/pfGithubIssue/SKILL.md +963 -0
  17. package/commands/pfGithubLink/SKILL.md +859 -0
  18. package/commands/pfGithubPr/SKILL.md +1335 -0
  19. package/commands/pfGithubUnlink/SKILL.md +401 -0
  20. package/commands/pfLive/SKILL.md +185 -0
  21. package/commands/pfLogin/SKILL.md +249 -0
  22. package/commands/pfLogout/SKILL.md +155 -0
  23. package/commands/pfMyTasks/SKILL.md +198 -0
  24. package/commands/pfNotificationSettings/SKILL.md +619 -0
  25. package/commands/pfNotifications/SKILL.md +420 -0
  26. package/commands/pfNotificationsClear/SKILL.md +421 -0
  27. package/commands/pfReact/SKILL.md +232 -0
  28. package/commands/pfSlack/SKILL.md +659 -0
  29. package/commands/pfSyncPull/SKILL.md +210 -0
  30. package/commands/pfSyncPush/SKILL.md +299 -0
  31. package/commands/pfSyncStatus/SKILL.md +212 -0
  32. package/commands/pfTeamInvite/SKILL.md +161 -0
  33. package/commands/pfTeamList/SKILL.md +253 -0
  34. package/commands/pfTeamRemove/SKILL.md +115 -0
  35. package/commands/pfTeamRole/SKILL.md +160 -0
  36. package/commands/pfTestWebhooks/SKILL.md +722 -0
  37. package/commands/pfUnassign/SKILL.md +134 -0
  38. package/commands/pfWhoami/SKILL.md +258 -0
  39. package/commands/pfWorkload/SKILL.md +219 -0
  40. package/commands/planExportCsv/SKILL.md +106 -0
  41. package/commands/planExportGithub/SKILL.md +222 -0
  42. package/commands/planExportJson/SKILL.md +159 -0
  43. package/commands/planExportSummary/SKILL.md +158 -0
  44. package/commands/planNew/SKILL.md +641 -0
  45. package/commands/planNext/SKILL.md +1200 -0
  46. package/commands/planSettingsAutoSync/SKILL.md +199 -0
  47. package/commands/planSettingsLanguage/SKILL.md +201 -0
  48. package/commands/planSettingsReset/SKILL.md +237 -0
  49. package/commands/planSettingsShow/SKILL.md +482 -0
  50. package/commands/planSpec/SKILL.md +929 -0
  51. package/commands/planUpdate/SKILL.md +2518 -0
  52. package/commands/team/SKILL.md +740 -0
  53. package/locales/en.json +1499 -0
  54. package/locales/ka.json +1499 -0
  55. package/package.json +48 -0
  56. package/templates/PROJECT_PLAN.template.md +157 -0
  57. package/templates/backend-api.template.md +562 -0
  58. package/templates/frontend-spa.template.md +610 -0
  59. package/templates/fullstack.template.md +397 -0
  60. package/templates/ka/backend-api.template.md +562 -0
  61. package/templates/ka/frontend-spa.template.md +610 -0
  62. package/templates/ka/fullstack.template.md +397 -0
  63. package/templates/sections/architecture.md +21 -0
  64. package/templates/sections/overview.md +15 -0
  65. package/templates/sections/tasks.md +22 -0
  66. package/templates/sections/tech-stack.md +19 -0
@@ -0,0 +1,859 @@
1
+ ---
2
+ name: pfGithubLink
3
+ description: Link a GitHub repository to the current PlanFlow project
4
+ ---
5
+
6
+ # PlanFlow GitHub Link
7
+
8
+ Link a GitHub repository to the current PlanFlow cloud project for issue tracking, branch creation, and PR integration.
9
+
10
+ ## Usage
11
+
12
+ ```bash
13
+ /pfGithubLink owner/repo # Link to GitHub repository
14
+ /pfGithubLink # Show current link status
15
+ /pfGithubLink autocomplete on # Enable auto-complete tasks on PR merge
16
+ /pfGithubLink autocomplete off # Disable auto-complete tasks on PR merge
17
+ ```
18
+
19
+ ## Step 0: Load Configuration
20
+
21
+ ```javascript
22
+ function getMergedConfig() {
23
+ let globalConfig = {}
24
+ let localConfig = {}
25
+
26
+ const globalPath = expandPath("~/.config/claude/plan-plugin-config.json")
27
+ if (fileExists(globalPath)) {
28
+ try { globalConfig = JSON.parse(readFile(globalPath)) } catch (e) {}
29
+ }
30
+
31
+ if (fileExists("./.plan-config.json")) {
32
+ try { localConfig = JSON.parse(readFile("./.plan-config.json")) } catch (e) {}
33
+ }
34
+
35
+ return {
36
+ ...globalConfig,
37
+ ...localConfig,
38
+ cloud: {
39
+ ...(globalConfig.cloud || {}),
40
+ ...(localConfig.cloud || {})
41
+ }
42
+ }
43
+ }
44
+
45
+ const config = getMergedConfig()
46
+ const language = config.language || "en"
47
+ const cloudConfig = config.cloud || {}
48
+ const isAuthenticated = !!cloudConfig.apiToken
49
+ const apiUrl = cloudConfig.apiUrl || "https://api.planflow.tools"
50
+ const projectId = cloudConfig.projectId || null
51
+
52
+ const t = JSON.parse(readFile(`locales/${language}.json`))
53
+ ```
54
+
55
+ ## Step 0.5: Show Notification Badge
56
+
57
+ Only if authenticated AND linked to a project:
58
+
59
+ ```bash
60
+ if [ -n "$TOKEN" ] && [ -n "$PROJECT_ID" ]; then
61
+ RESPONSE=$(curl -s --connect-timeout 3 --max-time 5 \
62
+ -X GET \
63
+ -H "Accept: application/json" \
64
+ -H "Authorization: Bearer $TOKEN" \
65
+ "${API_URL}/projects/${PROJECT_ID}/notifications?limit=1&unread=true" 2>/dev/null)
66
+
67
+ if [ $? -eq 0 ]; then
68
+ UNREAD_COUNT=$(echo "$RESPONSE" | grep -o '"unreadCount":[0-9]*' | grep -o '[0-9]*')
69
+ if [ -n "$UNREAD_COUNT" ] && [ "$UNREAD_COUNT" -gt 0 ]; then
70
+ echo "🔔 $UNREAD_COUNT unread notification(s) — /pfNotifications to view"
71
+ echo ""
72
+ fi
73
+ fi
74
+ fi
75
+ ```
76
+
77
+ ## Step 1: Parse Arguments
78
+
79
+ ```javascript
80
+ const args = commandArgs.trim()
81
+ const repoPattern = /^([a-zA-Z0-9_.-]+)\/([a-zA-Z0-9_.-]+)$/
82
+ const autocompletePattern = /^autocomplete\s+(on|off)$/i
83
+
84
+ if (args === "") {
85
+ // Show current status
86
+ showGitHubStatus()
87
+ } else if (autocompletePattern.test(args)) {
88
+ // Toggle auto-complete setting
89
+ const match = args.match(autocompletePattern)
90
+ const enabled = match[1].toLowerCase() === "on"
91
+ toggleAutoComplete(enabled)
92
+ } else if (repoPattern.test(args)) {
93
+ // Link to repo
94
+ const [owner, repo] = args.split("/")
95
+ linkGitHubRepo(owner, repo)
96
+ } else {
97
+ showUsageError()
98
+ }
99
+ ```
100
+
101
+ ## Step 2: Validate Prerequisites
102
+
103
+ ### 2a: Check Authentication
104
+
105
+ If not authenticated:
106
+
107
+ ```
108
+ ╭──────────────────────────────────────────────────────────────────────────────╮
109
+ │ ❌ ERROR │
110
+ ├──────────────────────────────────────────────────────────────────────────────┤
111
+ │ │
112
+ │ {t.commands.sync.notAuthenticated} │
113
+ │ │
114
+ │ You must be logged in to link GitHub repositories. │
115
+ │ │
116
+ │ 💡 Next Steps: │
117
+ │ • /pfLogin Sign in to PlanFlow │
118
+ │ │
119
+ ╰──────────────────────────────────────────────────────────────────────────────╯
120
+ ```
121
+
122
+ ### 2b: Check Project Link
123
+
124
+ If not linked to a cloud project:
125
+
126
+ ```
127
+ ╭──────────────────────────────────────────────────────────────────────────────╮
128
+ │ ❌ ERROR │
129
+ ├──────────────────────────────────────────────────────────────────────────────┤
130
+ │ │
131
+ │ {t.commands.sync.notLinked} │
132
+ │ │
133
+ │ You must link to a cloud project first. │
134
+ │ │
135
+ │ 💡 Next Steps: │
136
+ │ • /pfCloudLink Link to existing project │
137
+ │ • /pfCloudNew Create new cloud project │
138
+ │ │
139
+ ╰──────────────────────────────────────────────────────────────────────────────╯
140
+ ```
141
+
142
+ ### 2c: Check GitHub CLI (Optional Enhancement)
143
+
144
+ Optionally check if `gh` CLI is available for enhanced features:
145
+
146
+ ```bash
147
+ if command -v gh &> /dev/null; then
148
+ GH_AVAILABLE=true
149
+ # Check if gh is authenticated
150
+ if gh auth status &> /dev/null; then
151
+ GH_AUTHENTICATED=true
152
+ fi
153
+ fi
154
+ ```
155
+
156
+ ## Step 3: Show Current Status (No Arguments)
157
+
158
+ If no arguments provided, show current GitHub link status:
159
+
160
+ ### 3a: Fetch Current Integration Status
161
+
162
+ ```bash
163
+ RESPONSE=$(curl -s -w "\n%{http_code}" \
164
+ --connect-timeout 5 \
165
+ --max-time 10 \
166
+ -X GET \
167
+ -H "Accept: application/json" \
168
+ -H "Authorization: Bearer $TOKEN" \
169
+ "${API_URL}/projects/${PROJECT_ID}/integrations/github")
170
+
171
+ HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
172
+ BODY=$(echo "$RESPONSE" | sed '$d')
173
+ ```
174
+
175
+ ### 3b: Show Status Card
176
+
177
+ **If linked:**
178
+
179
+ ```
180
+ ╭──────────────────────────────────────────────────────────────────────────────╮
181
+ │ 🐙 GitHub Integration │
182
+ ├──────────────────────────────────────────────────────────────────────────────┤
183
+ │ │
184
+ │ ── Repository ──────────────────────────────────────────────────────────── │
185
+ │ │
186
+ │ 📦 Repository: owner/repo-name │
187
+ │ 🔗 URL: https://github.com/owner/repo-name │
188
+ │ 📅 Linked: 2026-02-15 │
189
+ │ │
190
+ │ ╭────────────────╮ │
191
+ │ │ ✓ Connected │ │
192
+ │ ╰────────────────╯ │
193
+ │ │
194
+ │ ── Features ────────────────────────────────────────────────────────────── │
195
+ │ │
196
+ │ ✅ Create branches from tasks │
197
+ │ ✅ Create issues from tasks │
198
+ │ ✅ Link PRs to tasks │
199
+ │ │
200
+ │ ── Auto-Complete Settings ──────────────────────────────────────────────── │
201
+ │ │
202
+ │ ✅ Auto-complete on PR merge: Enabled │
203
+ │ When a PR with "Closes TX.X" is merged, the task is marked DONE │
204
+ │ │
205
+ ├──────────────────────────────────────────────────────────────────────────────┤
206
+ │ │
207
+ │ 💡 Commands: │
208
+ │ • /pfGithubBranch T1.1 Create branch for task │
209
+ │ • /pfGithubIssue T1.1 Create GitHub issue │
210
+ │ • /pfGithubLink autocomplete Toggle auto-complete (on|off) │
211
+ │ • /pfGithubUnlink Disconnect repository │
212
+ │ │
213
+ ╰──────────────────────────────────────────────────────────────────────────────╯
214
+ ```
215
+
216
+ **If not linked:**
217
+
218
+ ```
219
+ ╭──────────────────────────────────────────────────────────────────────────────╮
220
+ │ 🐙 GitHub Integration │
221
+ ├──────────────────────────────────────────────────────────────────────────────┤
222
+ │ │
223
+ │ {t.commands.github.notLinked} │
224
+ │ │
225
+ │ No GitHub repository is linked to this project. │
226
+ │ │
227
+ │ ╭────────────────╮ │
228
+ │ │ ○ Not Connected│ │
229
+ │ ╰────────────────╯ │
230
+ │ │
231
+ │ ── Benefits of Linking ─────────────────────────────────────────────────── │
232
+ │ │
233
+ │ • Create feature branches directly from tasks │
234
+ │ • Sync tasks to GitHub Issues │
235
+ │ • Link Pull Requests to tasks │
236
+ │ • Auto-complete tasks when PRs are merged │
237
+ │ │
238
+ ├──────────────────────────────────────────────────────────────────────────────┤
239
+ │ │
240
+ │ 💡 To link a repository: │
241
+ │ • /pfGithubLink owner/repo │
242
+ │ │
243
+ │ Example: │
244
+ │ • /pfGithubLink acme/my-project │
245
+ │ │
246
+ ╰──────────────────────────────────────────────────────────────────────────────╯
247
+ ```
248
+
249
+ ## Step 4: Link GitHub Repository
250
+
251
+ ### 4a: Validate Repository Format
252
+
253
+ ```javascript
254
+ const repoRegex = /^([a-zA-Z0-9_.-]+)\/([a-zA-Z0-9_.-]+)$/
255
+ if (!repoRegex.test(repoArg)) {
256
+ // Show error
257
+ }
258
+ ```
259
+
260
+ **Invalid format error:**
261
+
262
+ ```
263
+ ╭──────────────────────────────────────────────────────────────────────────────╮
264
+ │ ❌ ERROR │
265
+ ├──────────────────────────────────────────────────────────────────────────────┤
266
+ │ │
267
+ │ {t.commands.github.invalidFormat} │
268
+ │ │
269
+ │ Invalid repository format: {input} │
270
+ │ │
271
+ │ Expected format: owner/repo │
272
+ │ │
273
+ │ Examples: │
274
+ │ • /pfGithubLink microsoft/vscode │
275
+ │ • /pfGithubLink facebook/react │
276
+ │ • /pfGithubLink my-org/my-project │
277
+ │ │
278
+ ╰──────────────────────────────────────────────────────────────────────────────╯
279
+ ```
280
+
281
+ ### 4b: Check if Already Linked
282
+
283
+ If project already has a GitHub repo linked:
284
+
285
+ ```
286
+ ╭──────────────────────────────────────────────────────────────────────────────╮
287
+ │ ⚠️ WARNING │
288
+ ├──────────────────────────────────────────────────────────────────────────────┤
289
+ │ │
290
+ │ {t.commands.github.alreadyLinked} │
291
+ │ │
292
+ │ This project is already linked to: {currentRepo} │
293
+ │ │
294
+ │ To switch repositories: │
295
+ │ 1. /pfGithubUnlink Remove current link │
296
+ │ 2. /pfGithubLink {newRepo} Link new repository │
297
+ │ │
298
+ ╰──────────────────────────────────────────────────────────────────────────────╯
299
+ ```
300
+
301
+ ### 4c: Verify Repository Exists (Optional)
302
+
303
+ If `gh` CLI is available, verify the repository exists:
304
+
305
+ ```bash
306
+ if [ "$GH_AVAILABLE" = true ] && [ "$GH_AUTHENTICATED" = true ]; then
307
+ if ! gh repo view "$OWNER/$REPO" &> /dev/null; then
308
+ echo "Repository not found or inaccessible: $OWNER/$REPO"
309
+ exit 1
310
+ fi
311
+ fi
312
+ ```
313
+
314
+ ### 4d: Link Repository via API
315
+
316
+ ```bash
317
+ RESPONSE=$(curl -s -w "\n%{http_code}" \
318
+ --connect-timeout 5 \
319
+ --max-time 15 \
320
+ -X POST \
321
+ -H "Content-Type: application/json" \
322
+ -H "Accept: application/json" \
323
+ -H "Authorization: Bearer $TOKEN" \
324
+ -d "{\"owner\": \"$OWNER\", \"repo\": \"$REPO\"}" \
325
+ "${API_URL}/projects/${PROJECT_ID}/integrations/github")
326
+
327
+ HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
328
+ BODY=$(echo "$RESPONSE" | sed '$d')
329
+ ```
330
+
331
+ ### 4e: Handle Response
332
+
333
+ **Success (200/201):**
334
+
335
+ ```
336
+ ╭──────────────────────────────────────────────────────────────────────────────╮
337
+ │ ✅ SUCCESS │
338
+ ├──────────────────────────────────────────────────────────────────────────────┤
339
+ │ │
340
+ │ {t.commands.github.linkSuccess} │
341
+ │ │
342
+ │ ── Repository Linked ───────────────────────────────────────────────────── │
343
+ │ │
344
+ │ 📦 Repository: owner/repo-name │
345
+ │ 🔗 URL: https://github.com/owner/repo-name │
346
+ │ 📁 Project: {projectName} │
347
+ │ │
348
+ │ ╭────────────────╮ │
349
+ │ │ ✓ Connected │ │
350
+ │ ╰────────────────╯ │
351
+ │ │
352
+ │ ── What's Next? ────────────────────────────────────────────────────────── │
353
+ │ │
354
+ │ You can now: │
355
+ │ • Create branches: /pfGithubBranch T1.1 │
356
+ │ • Create issues: /pfGithubIssue T1.1 │
357
+ │ • View status: /pfGithubLink │
358
+ │ │
359
+ ├──────────────────────────────────────────────────────────────────────────────┤
360
+ │ │
361
+ │ 💡 Tip: When you merge a PR with "Closes T1.1" in the description, │
362
+ │ the task will automatically be marked as complete! │
363
+ │ │
364
+ ╰──────────────────────────────────────────────────────────────────────────────╯
365
+ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
366
+ ```
367
+
368
+ **Repository Not Found (404):**
369
+
370
+ ```
371
+ ╭──────────────────────────────────────────────────────────────────────────────╮
372
+ │ ❌ ERROR │
373
+ ├──────────────────────────────────────────────────────────────────────────────┤
374
+ │ │
375
+ │ {t.commands.github.repoNotFound} │
376
+ │ │
377
+ │ Repository not found: owner/repo │
378
+ │ │
379
+ │ Possible reasons: │
380
+ │ • Repository doesn't exist │
381
+ │ • Repository is private and you don't have access │
382
+ │ • Typo in owner or repository name │
383
+ │ │
384
+ │ 💡 Tip: Check the repository URL in your browser first. │
385
+ │ │
386
+ ╰──────────────────────────────────────────────────────────────────────────────╯
387
+ ```
388
+
389
+ **Permission Denied (403):**
390
+
391
+ ```
392
+ ╭──────────────────────────────────────────────────────────────────────────────╮
393
+ │ ❌ ERROR │
394
+ ├──────────────────────────────────────────────────────────────────────────────┤
395
+ │ │
396
+ │ {t.commands.github.noPermission} │
397
+ │ │
398
+ │ You don't have permission to link this repository. │
399
+ │ │
400
+ │ To link a GitHub repository, you need: │
401
+ │ • Admin or Editor role in the PlanFlow project │
402
+ │ • Read access to the GitHub repository │
403
+ │ │
404
+ ╰──────────────────────────────────────────────────────────────────────────────╯
405
+ ```
406
+
407
+ **Already Linked to Different Project (409):**
408
+
409
+ ```
410
+ ╭──────────────────────────────────────────────────────────────────────────────╮
411
+ │ ❌ ERROR │
412
+ ├──────────────────────────────────────────────────────────────────────────────┤
413
+ │ │
414
+ │ {t.commands.github.repoAlreadyLinked} │
415
+ │ │
416
+ │ This repository is already linked to another project. │
417
+ │ │
418
+ │ Repository: owner/repo │
419
+ │ Linked to: Other Project Name │
420
+ │ │
421
+ │ 💡 A repository can only be linked to one project at a time. │
422
+ │ │
423
+ ╰──────────────────────────────────────────────────────────────────────────────╯
424
+ ```
425
+
426
+ ## Step 5: Toggle Auto-Complete Setting
427
+
428
+ When the user runs `/pfGithubLink autocomplete on` or `/pfGithubLink autocomplete off`:
429
+
430
+ ### 5a: Validate Auto-Complete Toggle Value
431
+
432
+ ```bash
433
+ if [[ ! "$ACTION" =~ ^(on|off)$ ]]; then
434
+ echo "❌ {t.github.autoComplete.invalidAction}"
435
+ echo ""
436
+ echo "Usage: /pfGithubLink autocomplete on|off"
437
+ exit 1
438
+ fi
439
+ ```
440
+
441
+ ### 5b: Send PATCH Request to Update Setting
442
+
443
+ ```bash
444
+ toggle_autocomplete() {
445
+ local ENABLED="$1"
446
+ local AUTO_COMPLETE_VALUE="false"
447
+ [ "$ENABLED" = "on" ] && AUTO_COMPLETE_VALUE="true"
448
+
449
+ RESPONSE=$(curl -s -w "\n%{http_code}" \
450
+ --connect-timeout 5 \
451
+ --max-time 15 \
452
+ -X PATCH \
453
+ -H "Content-Type: application/json" \
454
+ -H "Accept: application/json" \
455
+ -H "Authorization: Bearer $API_TOKEN" \
456
+ -d "{\"autoComplete\": $AUTO_COMPLETE_VALUE}" \
457
+ "${API_URL}/projects/${PROJECT_ID}/integrations/github")
458
+
459
+ HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
460
+ BODY=$(echo "$RESPONSE" | sed '$d')
461
+
462
+ if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
463
+ if [ "$ENABLED" = "on" ]; then
464
+ echo "✅ {t.github.autoComplete.enabled}"
465
+ echo ""
466
+ echo "💡 {t.github.autoComplete.tip}"
467
+ else
468
+ echo "{t.github.autoComplete.disabled}"
469
+ fi
470
+ elif [ "$HTTP_CODE" -eq 401 ]; then
471
+ echo "❌ Authentication failed. Run /pfLogin to refresh."
472
+ elif [ "$HTTP_CODE" -eq 403 ]; then
473
+ echo "❌ Permission denied. You need Editor role or higher."
474
+ elif [ "$HTTP_CODE" -eq 404 ]; then
475
+ echo "❌ GitHub integration not found. Link a repository first with /pfGithubLink owner/repo"
476
+ else
477
+ echo "❌ Failed to update auto-complete setting (HTTP $HTTP_CODE)"
478
+ fi
479
+ }
480
+ ```
481
+
482
+ ### 5c: Display Success Cards
483
+
484
+ **Auto-complete enabled:**
485
+
486
+ ```
487
+ ╭──────────────────────────────────────────────────────────────────────────────╮
488
+ │ ✅ {t.github.autoComplete.enabled} │
489
+ ├──────────────────────────────────────────────────────────────────────────────┤
490
+ │ │
491
+ │ {t.github.autoComplete.description} │
492
+ │ │
493
+ │ ╭────────────────╮ │
494
+ │ │ ✓ Enabled │ │
495
+ │ ╰────────────────╯ │
496
+ │ │
497
+ │ 💡 {t.github.autoComplete.tip} │
498
+ │ │
499
+ ╰──────────────────────────────────────────────────────────────────────────────╯
500
+ ```
501
+
502
+ **Auto-complete disabled:**
503
+
504
+ ```
505
+ ╭──────────────────────────────────────────────────────────────────────────────╮
506
+ │ {t.github.autoComplete.disabled} │
507
+ ├──────────────────────────────────────────────────────────────────────────────┤
508
+ │ │
509
+ │ Auto-complete on PR merge is now disabled. │
510
+ │ │
511
+ │ ╭────────────────╮ │
512
+ │ │ ○ Disabled │ │
513
+ │ ╰────────────────╯ │
514
+ │ │
515
+ │ 💡 To re-enable: │
516
+ │ • /pfGithubLink autocomplete on │
517
+ │ │
518
+ ╰──────────────────────────────────────────────────────────────────────────────╯
519
+ ```
520
+
521
+ ## Step 6: Update Local Config (Optional)
522
+
523
+ Store GitHub link info locally for offline reference:
524
+
525
+ ```javascript
526
+ // Read current local config
527
+ let localConfig = {}
528
+ try {
529
+ localConfig = JSON.parse(readFile("./.plan-config.json"))
530
+ } catch {}
531
+
532
+ // Add GitHub info
533
+ localConfig.github = {
534
+ owner: owner,
535
+ repo: repo,
536
+ linkedAt: new Date().toISOString()
537
+ }
538
+
539
+ // Save
540
+ writeFile("./.plan-config.json", JSON.stringify(localConfig, null, 2))
541
+ ```
542
+
543
+ ## Error Handling
544
+
545
+ ### Network Error
546
+
547
+ ```
548
+ ╭──────────────────────────────────────────────────────────────────────────────╮
549
+ │ ❌ ERROR │
550
+ ├──────────────────────────────────────────────────────────────────────────────┤
551
+ │ │
552
+ │ Network error. Could not connect to PlanFlow API. │
553
+ │ │
554
+ │ Please check your internet connection and try again. │
555
+ │ │
556
+ │ 💡 To retry: │
557
+ │ • /pfGithubLink owner/repo │
558
+ │ │
559
+ ╰──────────────────────────────────────────────────────────────────────────────╯
560
+ ```
561
+
562
+ ### Token Expired (401)
563
+
564
+ ```
565
+ ╭──────────────────────────────────────────────────────────────────────────────╮
566
+ │ ❌ ERROR │
567
+ ├──────────────────────────────────────────────────────────────────────────────┤
568
+ │ │
569
+ │ Authentication failed. Your session may have expired. │
570
+ │ │
571
+ │ 💡 To re-authenticate: │
572
+ │ • /pfLogin │
573
+ │ │
574
+ ╰──────────────────────────────────────────────────────────────────────────────╯
575
+ ```
576
+
577
+ ## Translation Keys
578
+
579
+ Add to `locales/en.json` and `locales/ka.json`:
580
+
581
+ ```json
582
+ {
583
+ "commands": {
584
+ "github": {
585
+ "title": "GitHub Integration",
586
+ "linkSuccess": "GitHub repository linked successfully!",
587
+ "unlinkSuccess": "GitHub repository unlinked.",
588
+ "notLinked": "No GitHub repository linked.",
589
+ "alreadyLinked": "A GitHub repository is already linked.",
590
+ "invalidFormat": "Invalid repository format.",
591
+ "formatHint": "Use format: owner/repo",
592
+ "repoNotFound": "Repository not found.",
593
+ "noPermission": "You don't have permission to link repositories.",
594
+ "repoAlreadyLinked": "This repository is linked to another project.",
595
+ "repository": "Repository:",
596
+ "url": "URL:",
597
+ "linkedAt": "Linked:",
598
+ "connected": "Connected",
599
+ "notConnected": "Not Connected",
600
+ "features": "Features",
601
+ "featureBranch": "Create branches from tasks",
602
+ "featureIssue": "Create issues from tasks",
603
+ "featurePR": "Link PRs to tasks",
604
+ "featureAutoComplete": "Auto-complete tasks on PR merge",
605
+ "benefits": "Benefits of Linking",
606
+ "benefitBranch": "Create feature branches directly from tasks",
607
+ "benefitIssue": "Sync tasks to GitHub Issues",
608
+ "benefitPR": "Link Pull Requests to tasks",
609
+ "benefitAuto": "Auto-complete tasks when PRs are merged",
610
+ "toLink": "To link a repository:",
611
+ "example": "Example:",
612
+ "tip": "Tip:",
613
+ "autoCompleteTip": "When you merge a PR with \"Closes TX.X\" in the description, the task will automatically be marked as complete!",
614
+ "commands": "Commands:",
615
+ "branchCommand": "Create branch for task",
616
+ "issueCommand": "Create GitHub issue",
617
+ "unlinkCommand": "Disconnect repository",
618
+ "statusCommand": "View integration status"
619
+ }
620
+ }
621
+ }
622
+ ```
623
+
624
+ ## Full Bash Implementation
625
+
626
+ ```bash
627
+ #!/bin/bash
628
+
629
+ # Step 0: Load config
630
+ GLOBAL_CONFIG_PATH="$HOME/.config/claude/plan-plugin-config.json"
631
+ LOCAL_CONFIG_PATH="./.plan-config.json"
632
+
633
+ # Read configs and merge
634
+ if [ -f "$GLOBAL_CONFIG_PATH" ]; then
635
+ API_TOKEN=$(jq -r '.cloud.apiToken // empty' "$GLOBAL_CONFIG_PATH")
636
+ API_URL=$(jq -r '.cloud.apiUrl // "https://api.planflow.tools"' "$GLOBAL_CONFIG_PATH")
637
+ fi
638
+
639
+ if [ -f "$LOCAL_CONFIG_PATH" ]; then
640
+ PROJECT_ID=$(jq -r '.cloud.projectId // empty' "$LOCAL_CONFIG_PATH")
641
+ # Local can override global
642
+ LOCAL_TOKEN=$(jq -r '.cloud.apiToken // empty' "$LOCAL_CONFIG_PATH")
643
+ [ -n "$LOCAL_TOKEN" ] && API_TOKEN="$LOCAL_TOKEN"
644
+ fi
645
+
646
+ # Parse arguments
647
+ ARGS="$*"
648
+
649
+ # Validate prerequisites
650
+ if [ -z "$API_TOKEN" ]; then
651
+ echo "❌ Not authenticated. Run /pfLogin first."
652
+ exit 1
653
+ fi
654
+
655
+ if [ -z "$PROJECT_ID" ]; then
656
+ echo "❌ No project linked. Run /pfCloudLink first."
657
+ exit 1
658
+ fi
659
+
660
+ # Check for autocomplete toggle command
661
+ if echo "$ARGS" | grep -qiE '^autocomplete[[:space:]]+(on|off)$'; then
662
+ ACTION=$(echo "$ARGS" | sed -E 's/^autocomplete[[:space:]]+//i' | tr '[:upper:]' '[:lower:]')
663
+ AUTO_COMPLETE_VALUE="false"
664
+ [ "$ACTION" = "on" ] && AUTO_COMPLETE_VALUE="true"
665
+
666
+ RESPONSE=$(curl -s -w "\n%{http_code}" \
667
+ --connect-timeout 5 \
668
+ --max-time 15 \
669
+ -X PATCH \
670
+ -H "Content-Type: application/json" \
671
+ -H "Accept: application/json" \
672
+ -H "Authorization: Bearer $API_TOKEN" \
673
+ -d "{\"autoComplete\": $AUTO_COMPLETE_VALUE}" \
674
+ "${API_URL}/projects/${PROJECT_ID}/integrations/github")
675
+
676
+ HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
677
+ BODY=$(echo "$RESPONSE" | sed '$d')
678
+
679
+ if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
680
+ if [ "$ACTION" = "on" ]; then
681
+ echo "✅ Auto-complete is now enabled!"
682
+ echo ""
683
+ echo "💡 When a PR with \"Closes T1.1\" is merged, T1.1 will be marked DONE automatically!"
684
+ else
685
+ echo "Auto-complete is now disabled."
686
+ fi
687
+ elif [ "$HTTP_CODE" -eq 401 ]; then
688
+ echo "❌ Authentication failed. Run /pfLogin to refresh."
689
+ elif [ "$HTTP_CODE" -eq 403 ]; then
690
+ echo "❌ Permission denied. You need Editor role or higher."
691
+ elif [ "$HTTP_CODE" -eq 404 ]; then
692
+ echo "❌ GitHub integration not found. Link a repository first."
693
+ else
694
+ echo "❌ Failed to update auto-complete setting (HTTP $HTTP_CODE)"
695
+ fi
696
+ exit 0
697
+ fi
698
+
699
+ REPO_ARG="$1"
700
+
701
+ # If no argument, show status
702
+ if [ -z "$REPO_ARG" ]; then
703
+ RESPONSE=$(curl -s -w "\n%{http_code}" \
704
+ --connect-timeout 5 \
705
+ --max-time 10 \
706
+ -X GET \
707
+ -H "Accept: application/json" \
708
+ -H "Authorization: Bearer $API_TOKEN" \
709
+ "${API_URL}/projects/${PROJECT_ID}/integrations/github")
710
+
711
+ HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
712
+ BODY=$(echo "$RESPONSE" | sed '$d')
713
+
714
+ if [ "$HTTP_CODE" -eq 200 ]; then
715
+ OWNER=$(echo "$BODY" | jq -r '.data.owner // empty')
716
+ REPO=$(echo "$BODY" | jq -r '.data.repo // empty')
717
+
718
+ if [ -n "$OWNER" ] && [ -n "$REPO" ]; then
719
+ AUTO_COMPLETE=$(echo "$BODY" | jq -r '.data.autoComplete // false')
720
+ echo "🐙 GitHub Integration"
721
+ echo ""
722
+ echo " Repository: $OWNER/$REPO"
723
+ echo " URL: https://github.com/$OWNER/$REPO"
724
+ echo " Status: ✓ Connected"
725
+ echo ""
726
+ if [ "$AUTO_COMPLETE" = "true" ]; then
727
+ echo " ✅ Auto-complete on PR merge: Enabled"
728
+ else
729
+ echo " ○ Auto-complete on PR merge: Disabled"
730
+ fi
731
+ else
732
+ echo "🐙 GitHub Integration"
733
+ echo ""
734
+ echo " Status: ○ Not Connected"
735
+ echo ""
736
+ echo " To link: /pfGithubLink owner/repo"
737
+ fi
738
+ else
739
+ echo "🐙 GitHub Integration"
740
+ echo ""
741
+ echo " Status: ○ Not Connected"
742
+ echo ""
743
+ echo " To link: /pfGithubLink owner/repo"
744
+ fi
745
+ exit 0
746
+ fi
747
+
748
+ # Validate repo format
749
+ if ! echo "$REPO_ARG" | grep -qE '^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$'; then
750
+ echo "❌ Invalid format: $REPO_ARG"
751
+ echo ""
752
+ echo "Expected: owner/repo"
753
+ echo "Example: /pfGithubLink microsoft/vscode"
754
+ exit 1
755
+ fi
756
+
757
+ # Extract owner and repo
758
+ OWNER=$(echo "$REPO_ARG" | cut -d'/' -f1)
759
+ REPO=$(echo "$REPO_ARG" | cut -d'/' -f2)
760
+
761
+ # Link repository
762
+ RESPONSE=$(curl -s -w "\n%{http_code}" \
763
+ --connect-timeout 5 \
764
+ --max-time 15 \
765
+ -X POST \
766
+ -H "Content-Type: application/json" \
767
+ -H "Accept: application/json" \
768
+ -H "Authorization: Bearer $API_TOKEN" \
769
+ -d "{\"owner\": \"$OWNER\", \"repo\": \"$REPO\"}" \
770
+ "${API_URL}/projects/${PROJECT_ID}/integrations/github")
771
+
772
+ HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
773
+ BODY=$(echo "$RESPONSE" | sed '$d')
774
+
775
+ if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
776
+ echo "✅ GitHub repository linked!"
777
+ echo ""
778
+ echo " Repository: $OWNER/$REPO"
779
+ echo " URL: https://github.com/$OWNER/$REPO"
780
+ echo ""
781
+ echo " You can now:"
782
+ echo " • /pfGithubBranch T1.1 - Create branch"
783
+ echo " • /pfGithubIssue T1.1 - Create issue"
784
+ elif [ "$HTTP_CODE" -eq 404 ]; then
785
+ echo "❌ Repository not found: $OWNER/$REPO"
786
+ elif [ "$HTTP_CODE" -eq 401 ]; then
787
+ echo "❌ Authentication failed. Run /pfLogin to refresh."
788
+ elif [ "$HTTP_CODE" -eq 403 ]; then
789
+ echo "❌ Permission denied. You need Editor role or higher."
790
+ elif [ "$HTTP_CODE" -eq 409 ]; then
791
+ echo "❌ This repository is already linked to another project."
792
+ else
793
+ echo "❌ Failed to link repository (HTTP $HTTP_CODE)"
794
+ echo "$BODY"
795
+ fi
796
+ ```
797
+
798
+ ## Testing
799
+
800
+ ```bash
801
+ # Test 1: Show status (not linked)
802
+ /pfGithubLink
803
+ # Expected: Shows "Not Connected" status
804
+
805
+ # Test 2: Link repository
806
+ /pfGithubLink microsoft/vscode
807
+ # Expected: Success message with repo details
808
+
809
+ # Test 3: Show status (linked)
810
+ /pfGithubLink
811
+ # Expected: Shows connected repository details with auto-complete status
812
+
813
+ # Test 4: Invalid format
814
+ /pfGithubLink invalid-format
815
+ # Expected: Error with format hint
816
+
817
+ # Test 5: Repo not found
818
+ /pfGithubLink nonexistent/nonexistent-repo-12345
819
+ # Expected: Error "Repository not found"
820
+
821
+ # Test 6: Not authenticated
822
+ # (Clear token first)
823
+ /pfGithubLink owner/repo
824
+ # Expected: Error "Not authenticated"
825
+
826
+ # Test 7: No project linked
827
+ # (Clear projectId first)
828
+ /pfGithubLink owner/repo
829
+ # Expected: Error "No project linked"
830
+
831
+ # Test 8: Enable auto-complete
832
+ /pfGithubLink autocomplete on
833
+ # Expected: "✅ Auto-complete is now enabled!"
834
+
835
+ # Test 9: Disable auto-complete
836
+ /pfGithubLink autocomplete off
837
+ # Expected: "Auto-complete is now disabled."
838
+
839
+ # Test 10: Show status (verify auto-complete setting)
840
+ /pfGithubLink
841
+ # Expected: Shows "✅ Auto-complete on PR merge: Enabled" or "○ Auto-complete on PR merge: Disabled"
842
+
843
+ # Test 11: Invalid autocomplete argument
844
+ /pfGithubLink autocomplete maybe
845
+ # Expected: Error with usage hint
846
+ ```
847
+
848
+ ## Success Criteria
849
+
850
+ - [ ] Shows current GitHub link status when no arguments
851
+ - [ ] Links GitHub repository with owner/repo format
852
+ - [ ] Validates repository format before API call
853
+ - [ ] Handles all error cases gracefully
854
+ - [ ] Updates local config with GitHub info
855
+ - [ ] Shows helpful next steps after linking
856
+ - [ ] Works in both English and Georgian
857
+ - [ ] `/pfGithubLink autocomplete on` enables auto-complete
858
+ - [ ] `/pfGithubLink autocomplete off` disables auto-complete
859
+ - [ ] Status display shows auto-complete setting