@mmerterden/multi-agent-pipeline 11.2.0 → 11.3.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 (331) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +2 -2
  3. package/docs/FIGMA_PIPELINE.md +12 -25
  4. package/docs/architecture.md +3 -5
  5. package/docs/features.md +8 -8
  6. package/install/_dev-only-files.mjs +0 -6
  7. package/install/claude.mjs +33 -15
  8. package/install/copilot.mjs +16 -14
  9. package/install/templates/copilot-instructions.md +3 -3
  10. package/package.json +1 -1
  11. package/pipeline/commands/{multi-agent.md → multi-agent/SKILL.md} +39 -39
  12. package/pipeline/commands/multi-agent/{analysis.md → analysis/SKILL.md} +18 -18
  13. package/pipeline/commands/multi-agent/{analysis-resolve.md → analysis-resolve/SKILL.md} +4 -4
  14. package/pipeline/commands/multi-agent/{autopilot.md → autopilot/SKILL.md} +4 -4
  15. package/pipeline/commands/multi-agent/{build-optimize.md → build-optimize/SKILL.md} +1 -1
  16. package/pipeline/commands/multi-agent/{channels.md → channels/SKILL.md} +12 -12
  17. package/pipeline/commands/multi-agent/{dev.md → dev/SKILL.md} +4 -4
  18. package/pipeline/commands/multi-agent/{dev-autopilot.md → dev-autopilot/SKILL.md} +4 -4
  19. package/pipeline/commands/multi-agent/{dev-local.md → dev-local/SKILL.md} +5 -5
  20. package/pipeline/commands/multi-agent/{dev-local-autopilot.md → dev-local-autopilot/SKILL.md} +4 -4
  21. package/pipeline/commands/multi-agent/{finish.md → finish/SKILL.md} +6 -6
  22. package/pipeline/commands/multi-agent/{generate.md → generate/SKILL.md} +3 -3
  23. package/pipeline/commands/multi-agent/{help.md → help/SKILL.md} +4 -4
  24. package/pipeline/commands/multi-agent/{local.md → local/SKILL.md} +5 -5
  25. package/pipeline/commands/multi-agent/{local-autopilot.md → local-autopilot/SKILL.md} +5 -5
  26. package/pipeline/commands/multi-agent/{manual-test.md → manual-test/SKILL.md} +1 -1
  27. package/pipeline/commands/multi-agent/refactor/SKILL.md +257 -0
  28. package/pipeline/commands/multi-agent/{resume.md → resume/SKILL.md} +1 -1
  29. package/pipeline/commands/multi-agent/{review.md → review/SKILL.md} +5 -5
  30. package/pipeline/commands/multi-agent/{setup.md → setup/SKILL.md} +1 -1
  31. package/pipeline/commands/multi-agent/{sync.md → sync/SKILL.md} +20 -58
  32. package/pipeline/{commands/multi-agent → multi-agent-refs}/_account-picker.md +2 -2
  33. package/pipeline/{commands/multi-agent → multi-agent-refs}/_dev-context.md +2 -2
  34. package/pipeline/{commands/multi-agent → multi-agent-refs}/_repo-picker.md +2 -2
  35. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/android-guide.md +1 -1
  36. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/jira.md +1 -1
  37. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/wiki.md +7 -7
  38. package/pipeline/multi-agent-refs/component-dispatch.md +92 -0
  39. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/cross-cli-contract.md +10 -77
  40. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/verify-by-test.md +1 -1
  41. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/generate-issue.md +2 -2
  42. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/issue-jira-triad.md +1 -1
  43. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/keychain.md +1 -1
  44. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/log-format.md +1 -1
  45. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/modes.md +2 -2
  46. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/operations.md +1 -1
  47. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-0-init.md +10 -10
  48. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-1-analysis.md +6 -6
  49. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-2-planning.md +3 -3
  50. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-3-dev.md +10 -10
  51. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-4-review.md +8 -8
  52. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-5-test.md +3 -3
  53. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-6-commit.md +4 -4
  54. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-7-report.md +6 -6
  55. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases.md +12 -12
  56. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/progress-contract.md +4 -4
  57. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/swiftui-guide.md +1 -1
  58. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/tracker-contract.md +3 -3
  59. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/wiki-capture.md +4 -4
  60. package/pipeline/preferences-template.json +17 -1
  61. package/pipeline/rules/figma-pipeline.md +2 -2
  62. package/pipeline/schemas/prefs.schema.json +0 -34
  63. package/pipeline/scripts/README.md +1 -3
  64. package/pipeline/scripts/fixtures/install-layout.tsv +6 -5
  65. package/pipeline/scripts/gen-mode-dispatch.mjs +3 -3
  66. package/pipeline/scripts/phase-banner.sh +2 -2
  67. package/pipeline/scripts/review-scope.mjs +94 -0
  68. package/pipeline/scripts/scan-agent-config.sh +2 -2
  69. package/pipeline/scripts/smoke-agent-log-cost.sh +1 -1
  70. package/pipeline/scripts/smoke-agent-model-routing.sh +4 -4
  71. package/pipeline/scripts/smoke-autopilot-circuit-breaker.sh +2 -2
  72. package/pipeline/scripts/smoke-channels-approval-gate.sh +2 -2
  73. package/pipeline/scripts/smoke-channels-flow.sh +5 -5
  74. package/pipeline/scripts/smoke-clarify.sh +1 -1
  75. package/pipeline/scripts/smoke-commands-skills-parity.sh +3 -3
  76. package/pipeline/scripts/smoke-community-gates.sh +1 -1
  77. package/pipeline/scripts/smoke-compliance-skills.sh +2 -2
  78. package/pipeline/scripts/smoke-cost-summary.sh +1 -1
  79. package/pipeline/scripts/smoke-cross-cli-behavior.sh +17 -43
  80. package/pipeline/scripts/smoke-cross-phase-cohesion.sh +1 -1
  81. package/pipeline/scripts/smoke-dev-critic.sh +1 -1
  82. package/pipeline/scripts/smoke-diff-explain.sh +1 -1
  83. package/pipeline/scripts/smoke-diff-risk.sh +1 -1
  84. package/pipeline/scripts/smoke-evidence-gate.sh +1 -1
  85. package/pipeline/scripts/smoke-figma-dispatch.sh +46 -57
  86. package/pipeline/scripts/smoke-gate-hooks.sh +1 -1
  87. package/pipeline/scripts/smoke-generate-issue.sh +8 -8
  88. package/pipeline/scripts/smoke-handoff-contract.sh +3 -3
  89. package/pipeline/scripts/smoke-identity-isolation.sh +2 -2
  90. package/pipeline/scripts/smoke-intent-guard.sh +1 -1
  91. package/pipeline/scripts/smoke-issue-comment-template.sh +2 -2
  92. package/pipeline/scripts/smoke-issue-jira-triad.sh +4 -4
  93. package/pipeline/scripts/smoke-language-axis.sh +6 -6
  94. package/pipeline/scripts/smoke-learnings-ledger.sh +3 -3
  95. package/pipeline/scripts/smoke-mode-dispatch-drift.sh +16 -16
  96. package/pipeline/scripts/smoke-model-fallback.sh +3 -3
  97. package/pipeline/scripts/smoke-multi-repo-integration.sh +2 -2
  98. package/pipeline/scripts/smoke-multi-repo-worktree.sh +1 -1
  99. package/pipeline/scripts/smoke-no-token-prompt.sh +5 -5
  100. package/pipeline/scripts/smoke-phase-0-multi-repo.sh +1 -1
  101. package/pipeline/scripts/smoke-phase-6-multi.sh +1 -1
  102. package/pipeline/scripts/smoke-phase4-gates.sh +45 -0
  103. package/pipeline/scripts/smoke-plan-approval-gate.sh +5 -5
  104. package/pipeline/scripts/smoke-plan-todos.sh +3 -3
  105. package/pipeline/scripts/smoke-pr-review-actions.sh +3 -3
  106. package/pipeline/scripts/smoke-prefs-language.sh +1 -1
  107. package/pipeline/scripts/smoke-progress-contract.sh +2 -2
  108. package/pipeline/scripts/smoke-push-retry.sh +1 -1
  109. package/pipeline/scripts/smoke-repo-map.sh +2 -2
  110. package/pipeline/scripts/smoke-shadow-git.sh +1 -1
  111. package/pipeline/scripts/smoke-skill-authoring.sh +4 -9
  112. package/pipeline/scripts/smoke-tasklist-ordering.sh +10 -10
  113. package/pipeline/scripts/smoke-test-gap.sh +1 -1
  114. package/pipeline/scripts/smoke-token-budget.sh +1 -1
  115. package/pipeline/scripts/smoke-token-preflight.sh +2 -2
  116. package/pipeline/scripts/smoke-tracker-contract.sh +13 -13
  117. package/pipeline/scripts/smoke-tracker-tokens-invocation.sh +5 -5
  118. package/pipeline/scripts/smoke-triage-memory.sh +2 -2
  119. package/pipeline/scripts/smoke-update-check.sh +1 -1
  120. package/pipeline/scripts/smoke-url-enrichment.sh +2 -2
  121. package/pipeline/scripts/smoke-validator-gates.sh +1 -1
  122. package/pipeline/scripts/smoke-verify-by-test.sh +3 -3
  123. package/pipeline/scripts/smoke-wiki-integration.sh +9 -33
  124. package/pipeline/scripts/smoke-work-summary.sh +1 -1
  125. package/pipeline/scripts/smoke-worktree-path-convention.sh +4 -4
  126. package/pipeline/scripts/test-integrity-gate.mjs +83 -0
  127. package/pipeline/scripts/uninstall.mjs +2 -2
  128. package/pipeline/skills/.skill-manifest.json +40 -160
  129. package/pipeline/skills/.skills-index.json +3 -372
  130. package/pipeline/skills/shared/README.md +1 -1
  131. package/pipeline/skills/shared/core/multi-agent/SKILL.md +1 -1
  132. package/pipeline/skills/shared/core/multi-agent-analysis/SKILL.md +2 -2
  133. package/pipeline/skills/shared/core/multi-agent-analysis-resolve/SKILL.md +3 -3
  134. package/pipeline/skills/shared/core/multi-agent-build-optimize/SKILL.md +1 -1
  135. package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +1 -1
  136. package/pipeline/skills/shared/core/multi-agent-finish/SKILL.md +1 -1
  137. package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +1 -1
  138. package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +116 -51
  139. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +8 -30
  140. package/pipeline/skills/shared/external/compose-components/SKILL.md +14 -14
  141. package/pipeline/skills/skills-index.md +2 -43
  142. package/pipeline/commands/multi-agent/refactor.md +0 -188
  143. package/pipeline/commands/multi-agent/refs/component-dispatch.md +0 -92
  144. package/pipeline/scripts/smoke-existing-discovery-gate.sh +0 -71
  145. package/pipeline/scripts/smoke-figma-android-parity.sh +0 -148
  146. package/pipeline/scripts/smoke-figma-credential-store.sh +0 -105
  147. package/pipeline/scripts/smoke-figma-cross-cli-inventory.sh +0 -177
  148. package/pipeline/scripts/smoke-figma-sync.sh +0 -149
  149. package/pipeline/scripts/smoke-sync-delegation.sh +0 -74
  150. package/pipeline/skills/figma-android/README.md +0 -38
  151. package/pipeline/skills/figma-android/figma-component-code-connect/SKILL.md +0 -62
  152. package/pipeline/skills/figma-android/figma-component-implement/SKILL.md +0 -158
  153. package/pipeline/skills/figma-android/figma-component-test/SKILL.md +0 -120
  154. package/pipeline/skills/figma-android/figma-component-wiki/SKILL.md +0 -35
  155. package/pipeline/skills/figma-android/figma-to-component/SKILL.md +0 -124
  156. package/pipeline/skills/figma-common/README.md +0 -64
  157. package/pipeline/skills/figma-common/figma-bottom-sheets/SKILL.md +0 -152
  158. package/pipeline/skills/figma-common/figma-cli-iterate/SKILL.md +0 -282
  159. package/pipeline/skills/figma-common/figma-cli-iterate-mend/SKILL.md +0 -503
  160. package/pipeline/skills/figma-common/figma-cli-lean-iterate/SKILL.md +0 -288
  161. package/pipeline/skills/figma-common/figma-cli-skip/SKILL.md +0 -362
  162. package/pipeline/skills/figma-common/figma-commit/COMMON_REBASE.md +0 -206
  163. package/pipeline/skills/figma-common/figma-commit/REVIEW.md +0 -337
  164. package/pipeline/skills/figma-common/figma-commit/SKILL.md +0 -216
  165. package/pipeline/skills/figma-common/figma-component-confluence-sync/SKILL.md +0 -223
  166. package/pipeline/skills/figma-common/figma-component-start/SKILL.md +0 -251
  167. package/pipeline/skills/figma-common/figma-component-status-update/SKILL.md +0 -78
  168. package/pipeline/skills/figma-common/figma-evolve-component/SKILL.md +0 -61
  169. package/pipeline/skills/figma-common/figma-fix/SKILL.md +0 -321
  170. package/pipeline/skills/figma-common/figma-form-integration/SKILL.md +0 -542
  171. package/pipeline/skills/figma-common/figma-issue/SKILL.md +0 -750
  172. package/pipeline/skills/figma-common/figma-iterate/SKILL.md +0 -208
  173. package/pipeline/skills/figma-common/figma-iteration-commit/SKILL.md +0 -1020
  174. package/pipeline/skills/figma-common/figma-mend/SKILL.md +0 -331
  175. package/pipeline/skills/figma-common/figma-navigation/SKILL.md +0 -156
  176. package/pipeline/skills/figma-common/figma-overlays/SKILL.md +0 -142
  177. package/pipeline/skills/figma-common/figma-price-integration/SKILL.md +0 -398
  178. package/pipeline/skills/figma-common/figma-remote-mcp-auth/SKILL.md +0 -104
  179. package/pipeline/skills/figma-common/figma-review/SKILL.md +0 -400
  180. package/pipeline/skills/figma-common/figma-setup/SKILL.md +0 -514
  181. package/pipeline/skills/figma-common/figma-setup/scripts/fetch-mcp-token.py +0 -592
  182. package/pipeline/skills/figma-common/figma-skip/SKILL.md +0 -129
  183. package/pipeline/skills/figma-common/figma-ui-patterns/SKILL.md +0 -105
  184. package/pipeline/skills/figma-common/figma-ui-patterns/patterns/animated-gradient-border.md +0 -116
  185. package/pipeline/skills/figma-common/figma-utility/SKILL.md +0 -274
  186. package/pipeline/skills/figma-common/figma-utility/scripts/figma-utility.py +0 -808
  187. package/pipeline/skills/figma-common/figma-validate/SKILL.md +0 -633
  188. package/pipeline/skills/figma-common/performance-iteration-commit-all/SKILL.md +0 -716
  189. package/pipeline/skills/figma-common/performance-review-next/SKILL.md +0 -238
  190. package/pipeline/skills/figma-common/performance-start/SKILL.md +0 -430
  191. package/pipeline/skills/figma-common/performance-swiftui/SKILL.md +0 -706
  192. package/pipeline/skills/figma-common/performance-tour/SKILL.md +0 -423
  193. package/pipeline/skills/figma-ios/REVIEW_CHECKLIST.md +0 -67
  194. package/pipeline/skills/figma-ios/figma-component-code-connect/SKILL.md +0 -178
  195. package/pipeline/skills/figma-ios/figma-component-implement/SKILL.md +0 -184
  196. package/pipeline/skills/figma-ios/figma-component-test/SKILL.md +0 -219
  197. package/pipeline/skills/figma-ios/figma-component-wiki/SKILL.md +0 -274
  198. package/pipeline/skills/figma-ios/figma-to-component/SKILL.md +0 -416
  199. package/pipeline/skills/figma-ios/figma-to-component/halt-return-protocol.md +0 -57
  200. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-0-init.md +0 -307
  201. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-1-gathering.md +0 -119
  202. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-1.5-existing-discovery.md +0 -174
  203. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2-orchestrator.md +0 -333
  204. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2a-testing-identifiers.md +0 -368
  205. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2b-localization.md +0 -393
  206. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2c-accessibility.md +0 -617
  207. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2d-analytics.md +0 -352
  208. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3-orchestrator.md +0 -337
  209. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3a-location.md +0 -206
  210. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3b-tokens.md +0 -235
  211. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3c-nested.md +0 -214
  212. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3d-patterns.md +0 -902
  213. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3e-assets.md +0 -156
  214. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3f-utilities.md +0 -175
  215. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3g-property-coverage.md +0 -176
  216. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3h-variant-config.md +0 -333
  217. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4-orchestrator.md +0 -412
  218. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4a-configuration.md +0 -336
  219. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4b-view.md +0 -705
  220. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4c-documentation.md +0 -332
  221. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4d-preview.md +0 -380
  222. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4e-modifiers.md +0 -262
  223. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5-orchestrator.md +0 -482
  224. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5a-viewinspector.md +0 -274
  225. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5b-snapshot.md +0 -636
  226. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5c-unit.md +0 -142
  227. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-6-code-connect.md +0 -547
  228. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-7-wiki.md +0 -39
  229. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-7a-confluence-generate.md +0 -659
  230. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-7a-wiki-generate.md +0 -580
  231. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-8-cleanup.md +0 -51
  232. package/pipeline/skills/figma-ios/figma-to-component/reference/accessibility.md +0 -183
  233. package/pipeline/skills/figma-ios/figma-to-component/reference/analytics-events.md +0 -64
  234. package/pipeline/skills/figma-ios/figma-to-component/reference/code-connect.md +0 -531
  235. package/pipeline/skills/figma-ios/figma-to-component/reference/confluence-api.md +0 -89
  236. package/pipeline/skills/figma-ios/figma-to-component/reference/confluence-xhtml.md +0 -155
  237. package/pipeline/skills/figma-ios/figma-to-component/reference/figma-to-swiftui-effects.md +0 -196
  238. package/pipeline/skills/figma-ios/figma-to-component/reference/halt-return-protocol.md +0 -57
  239. package/pipeline/skills/figma-ios/figma-to-component/reference/localization-naming.md +0 -89
  240. package/pipeline/skills/figma-ios/figma-to-component/reference/macros.md +0 -227
  241. package/pipeline/skills/figma-ios/figma-to-component/reference/missing-tokens.md +0 -157
  242. package/pipeline/skills/figma-ios/figma-to-component/reference/orchestrator-discipline.md +0 -90
  243. package/pipeline/skills/figma-ios/figma-to-component/reference/registry.md +0 -116
  244. package/pipeline/skills/figma-ios/figma-to-component/reference/remote-mcp-script.md +0 -153
  245. package/pipeline/skills/figma-ios/figma-to-component/reference/rest-api-script.md +0 -130
  246. package/pipeline/skills/figma-ios/figma-to-component/reference/scripts-inventory.md +0 -218
  247. package/pipeline/skills/figma-ios/figma-to-component/reference/snapshot-testing.md +0 -188
  248. package/pipeline/skills/figma-ios/figma-to-component/reference/subcomponent-graph.md +0 -93
  249. package/pipeline/skills/figma-ios/figma-to-component/reference/testing-identifiers-naming.md +0 -98
  250. package/pipeline/skills/figma-ios/figma-to-component/reference/tools.md +0 -261
  251. package/pipeline/skills/figma-ios/figma-to-component/reference/viewinspector.md +0 -147
  252. package/pipeline/skills/figma-ios/figma-to-component/reference/wiki-to-confluence-mapping.md +0 -182
  253. package/pipeline/skills/figma-ios/figma-to-component/scripts/apply-author-login-map.py +0 -185
  254. package/pipeline/skills/figma-ios/figma-to-component/scripts/backfill-status.py +0 -609
  255. package/pipeline/skills/figma-ios/figma-to-component/scripts/build-author-registry.py +0 -332
  256. package/pipeline/skills/figma-ios/figma-to-component/scripts/bulk-sync-issues.py +0 -261
  257. package/pipeline/skills/figma-ios/figma-to-component/scripts/code-connect-data-gather.py +0 -184
  258. package/pipeline/skills/figma-ios/figma-to-component/scripts/code-connect-publish.sh +0 -188
  259. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-component-status-upload.py +0 -768
  260. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-component-status.py +0 -191
  261. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-data-gather.py +0 -420
  262. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-page-ids.example.json +0 -9
  263. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-publish.py +0 -336
  264. package/pipeline/skills/figma-ios/figma-to-component/scripts/figma-subcomponent-graph.py +0 -391
  265. package/pipeline/skills/figma-ios/figma-to-component/scripts/figma-update.py +0 -292
  266. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/__init__.py +0 -1
  267. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/issue_sync_propagate.py +0 -93
  268. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/registry_writer.py +0 -299
  269. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_backfill_status.py +0 -343
  270. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_figma_update.py +0 -206
  271. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_figma_update_http.py +0 -149
  272. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_phase_clis.py +0 -281
  273. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_registry_writer.py +0 -332
  274. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_skill_figma_issue.py +0 -176
  275. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_skill_figma_review.py +0 -98
  276. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_update_issue.py +0 -298
  277. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_update_issue_gh.py +0 -195
  278. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase1-gather.py +0 -1298
  279. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase2-finalize.py +0 -228
  280. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase3-scripts.py +0 -1089
  281. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase4-finalize.py +0 -141
  282. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase5-finalize.py +0 -106
  283. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase6-finalize.py +0 -162
  284. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase7-finalize.py +0 -105
  285. package/pipeline/skills/figma-ios/figma-to-component/scripts/register-icons-codeconnect.py +0 -179
  286. package/pipeline/skills/figma-ios/figma-to-component/scripts/remote-mcp-fetch.py +0 -260
  287. package/pipeline/skills/figma-ios/figma-to-component/scripts/resolve-author-logins.py +0 -260
  288. package/pipeline/skills/figma-ios/figma-to-component/scripts/run-uicomponents-tests.sh +0 -86
  289. package/pipeline/skills/figma-ios/figma-to-component/scripts/sidebar-generator.py +0 -321
  290. package/pipeline/skills/figma-ios/figma-to-component/scripts/update-issue-from-registry.py +0 -1470
  291. package/pipeline/skills/figma-ios/figma-to-component/scripts/validate-phase4.sh +0 -176
  292. package/pipeline/skills/figma-ios/figma-to-component/scripts/validate-phase6.sh +0 -147
  293. package/pipeline/skills/figma-ios/figma-to-component/scripts/validate-phase7a.py +0 -629
  294. /package/pipeline/commands/multi-agent/{delete.md → delete/SKILL.md} +0 -0
  295. /package/pipeline/commands/multi-agent/{diff-explain.md → diff-explain/SKILL.md} +0 -0
  296. /package/pipeline/commands/multi-agent/{garbage-collect.md → garbage-collect/SKILL.md} +0 -0
  297. /package/pipeline/commands/multi-agent/{issue.md → issue/SKILL.md} +0 -0
  298. /package/pipeline/commands/multi-agent/{jira.md → jira/SKILL.md} +0 -0
  299. /package/pipeline/commands/multi-agent/{kill.md → kill/SKILL.md} +0 -0
  300. /package/pipeline/commands/multi-agent/{language.md → language/SKILL.md} +0 -0
  301. /package/pipeline/commands/multi-agent/{log.md → log/SKILL.md} +0 -0
  302. /package/pipeline/commands/multi-agent/{prune-logs.md → prune-logs/SKILL.md} +0 -0
  303. /package/pipeline/commands/multi-agent/{purge.md → purge/SKILL.md} +0 -0
  304. /package/pipeline/commands/multi-agent/{scan.md → scan/SKILL.md} +0 -0
  305. /package/pipeline/commands/multi-agent/{search.md → search/SKILL.md} +0 -0
  306. /package/pipeline/commands/multi-agent/{stack.md → stack/SKILL.md} +0 -0
  307. /package/pipeline/commands/multi-agent/{status.md → status/SKILL.md} +0 -0
  308. /package/pipeline/commands/multi-agent/{test.md → test/SKILL.md} +0 -0
  309. /package/pipeline/commands/multi-agent/{update.md → update/SKILL.md} +0 -0
  310. /package/pipeline/{commands/multi-agent → multi-agent-refs}/_input-parser.md +0 -0
  311. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/analysis-template.md +0 -0
  312. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/audit-guide.md +0 -0
  313. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/backend-guide.md +0 -0
  314. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/confluence.md +0 -0
  315. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/issue-comment.md +0 -0
  316. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/pr-review-actions.md +0 -0
  317. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/pr.md +0 -0
  318. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/conventions-defaults.md +0 -0
  319. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/autopilot-circuit-breaker.md +0 -0
  320. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/dev-critic.md +0 -0
  321. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/external-context-injection.md +0 -0
  322. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/model-fallback.md +0 -0
  323. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/plan-todos.md +0 -0
  324. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/prior-fix-detection.md +0 -0
  325. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/repo-map.md +0 -0
  326. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/shadow-git.md +0 -0
  327. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/frontend-guide.md +0 -0
  328. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/knowledge.md +0 -0
  329. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/multi-repo-integration-build.md +0 -0
  330. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/picker-contract.md +0 -0
  331. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/rules.md +0 -0
@@ -1,592 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Figma Remote MCP Token Fetcher
4
-
5
- Retrieves or refreshes a Figma MCP OAuth token. Three modes:
6
-
7
- MODE 1 - Extract (default):
8
- Reads existing token from Keychain or Claude Code credentials.
9
- python3 fetch-mcp-token.py
10
-
11
- MODE 2 - OAuth (--oauth):
12
- Runs full OAuth flow. Opens browser for Figma consent, runs local
13
- callback server, exchanges code for token. Works from ANY terminal.
14
- python3 fetch-mcp-token.py --oauth --client-id X --client-secret Y --save-keychain
15
-
16
- Credentials are extracted from Claude Code keychain if available,
17
- or must be provided via --client-id and --client-secret.
18
-
19
- COMMON FLAGS:
20
- --save-keychain Save token to macOS Keychain as FIGMA_MCP_TOKEN
21
- --verify Verify token against Figma MCP server
22
- --quiet Only print the token to stdout
23
- --port PORT Local callback server port (default: 8923)
24
- --client-id OAuth client ID (required for --oauth if no Claude Code)
25
- --client-secret OAuth client secret (required for --oauth if no Claude Code)
26
- --show-clients Show OAuth clients from Claude Code credentials
27
- """
28
-
29
- import argparse
30
- import base64
31
- import hashlib
32
- import http.server
33
- import json
34
- import os
35
- import re
36
- import secrets
37
- import subprocess
38
- import sys
39
- import threading
40
- import time
41
- import urllib.parse
42
- import urllib.request
43
-
44
- # ─── Configuration ──────────────────────────────────────────────────────────
45
-
46
- KEYCHAIN_SERVICE = "FIGMA_MCP_TOKEN"
47
- KEYCHAIN_REFRESH_SERVICE = "FIGMA_MCP_REFRESH_TOKEN"
48
- KEYCHAIN_CLIENT_ID_SERVICE = "FIGMA_MCP_CLIENT_ID"
49
- KEYCHAIN_CLIENT_SECRET_SERVICE = "FIGMA_MCP_CLIENT_SECRET"
50
- CLAUDE_CREDENTIALS_SERVICE = "Claude Code-credentials"
51
- MCP_SERVER_URL = "https://mcp.figma.com/mcp"
52
- AUTH_ENDPOINT = "https://www.figma.com/oauth/mcp"
53
- TOKEN_ENDPOINT = "https://api.figma.com/v1/oauth/token"
54
- REFRESH_ENDPOINT = "https://api.figma.com/v1/oauth/refresh"
55
- DEFAULT_PORT = 8923
56
-
57
-
58
- # ─── Helpers ────────────────────────────────────────────────────────────────
59
-
60
- def log(msg):
61
- print(f"[fetch-mcp-token] {msg}", file=sys.stderr)
62
-
63
-
64
- def get_claude_credentials_raw():
65
- """Read raw Claude Code credentials from Keychain."""
66
- try:
67
- return subprocess.check_output(
68
- ["security", "find-generic-password", "-s", CLAUDE_CREDENTIALS_SERVICE,
69
- "-a", os.environ["USER"], "-w"],
70
- stderr=subprocess.DEVNULL
71
- ).decode()
72
- except (subprocess.CalledProcessError, KeyError):
73
- return None
74
-
75
-
76
- # ─── Token Sources ──────────────────────────────────────────────────────────
77
-
78
- def get_from_dedicated_keychain():
79
- """Source 1: Dedicated FIGMA_MCP_TOKEN keychain entry."""
80
- try:
81
- token = subprocess.check_output(
82
- ["security", "find-generic-password", "-a", os.environ["USER"],
83
- "-s", KEYCHAIN_SERVICE, "-w"],
84
- stderr=subprocess.DEVNULL
85
- ).decode().strip()
86
- if token and token.startswith("figu_"):
87
- return token, "keychain:FIGMA_MCP_TOKEN"
88
- except (subprocess.CalledProcessError, KeyError):
89
- pass
90
- return None, None
91
-
92
-
93
- def get_from_claude_credentials():
94
- """Source 2: Extract accessToken from Claude Code's credential store."""
95
- raw = get_claude_credentials_raw()
96
- if not raw:
97
- return None, None
98
- match = re.search(
99
- r'"figma-remote\|[^"]+":\{[^}]*"accessToken":"([^"]+)"', raw
100
- )
101
- if match:
102
- token = match.group(1)
103
- if token.startswith("figu_"):
104
- return token, "keychain:Claude Code-credentials"
105
- return None, None
106
-
107
-
108
- def get_expiry_from_claude_credentials():
109
- """Extract expiresAt from Claude Code credentials."""
110
- raw = get_claude_credentials_raw()
111
- if not raw:
112
- return None
113
- match = re.search(
114
- r'"figma-remote\|[^"]+":\{[^}]*"expiresAt":(\d+)', raw
115
- )
116
- if match:
117
- import datetime
118
- ts = int(match.group(1)) / 1000
119
- return datetime.datetime.fromtimestamp(ts).isoformat()
120
- return None
121
-
122
-
123
- def get_client_credentials_from_claude():
124
- """Extract clientId + clientSecret from Claude Code credentials."""
125
- raw = get_claude_credentials_raw()
126
- if not raw:
127
- return []
128
- clients = []
129
- # Find all clientRegistration blocks with their parent server context
130
- for m in re.finditer(r'"clientId":"([^"]+)"', raw):
131
- cid = m.group(1)
132
- # Look for clientSecret right after
133
- after = raw[m.end():m.end() + 200]
134
- sec_match = re.search(r'"clientSecret":"([^"]+)"', after)
135
- # Look backwards for serverName
136
- before = raw[max(0, m.start() - 500):m.start()]
137
- srv_match = re.search(r'"serverName":"([^"]+)"', before)
138
- url_match = re.search(r'"serverUrl":"([^"]+)"', before)
139
- clients.append({
140
- "clientId": cid,
141
- "clientSecret": sec_match.group(1) if sec_match else None,
142
- "serverName": srv_match.group(1) if srv_match else "unknown",
143
- "serverUrl": url_match.group(1) if url_match else "unknown",
144
- })
145
- return clients
146
-
147
-
148
- # ─── Keychain & Verify ──────────────────────────────────────────────────────
149
-
150
- def save_to_keychain(token, service=KEYCHAIN_SERVICE):
151
- """Save token to macOS Keychain."""
152
- user = os.environ.get("USER", "")
153
- subprocess.run(
154
- ["security", "delete-generic-password", "-a", user, "-s", service],
155
- capture_output=True
156
- )
157
- result = subprocess.run(
158
- ["security", "add-generic-password", "-a", user, "-s", service, "-w", token],
159
- capture_output=True
160
- )
161
- return result.returncode == 0
162
-
163
-
164
- def get_refresh_token_from_keychain():
165
- """Read refresh token from macOS Keychain."""
166
- try:
167
- return subprocess.check_output(
168
- ["security", "find-generic-password", "-a", os.environ["USER"],
169
- "-s", KEYCHAIN_REFRESH_SERVICE, "-w"],
170
- stderr=subprocess.DEVNULL
171
- ).decode().strip() or None
172
- except (subprocess.CalledProcessError, KeyError):
173
- return None
174
-
175
-
176
- def get_client_credentials_from_keychain():
177
- """Read client_id and client_secret from macOS Keychain."""
178
- try:
179
- cid = subprocess.check_output(
180
- ["security", "find-generic-password", "-a", os.environ["USER"],
181
- "-s", KEYCHAIN_CLIENT_ID_SERVICE, "-w"],
182
- stderr=subprocess.DEVNULL
183
- ).decode().strip()
184
- csec = subprocess.check_output(
185
- ["security", "find-generic-password", "-a", os.environ["USER"],
186
- "-s", KEYCHAIN_CLIENT_SECRET_SERVICE, "-w"],
187
- stderr=subprocess.DEVNULL
188
- ).decode().strip()
189
- if cid and csec:
190
- return cid, csec
191
- except (subprocess.CalledProcessError, KeyError):
192
- pass
193
- return None, None
194
-
195
-
196
- def refresh_access_token(refresh_token, client_id, client_secret):
197
- """Use refresh_token to obtain a new access_token from Figma."""
198
- auth_str = base64.b64encode(f"{client_id}:{client_secret}".encode()).decode()
199
- body = urllib.parse.urlencode({"refresh_token": refresh_token}).encode()
200
- req = urllib.request.Request(
201
- REFRESH_ENDPOINT,
202
- data=body,
203
- headers={
204
- "Content-Type": "application/x-www-form-urlencoded",
205
- "Authorization": f"Basic {auth_str}",
206
- },
207
- method="POST",
208
- )
209
- try:
210
- with urllib.request.urlopen(req) as resp:
211
- result = json.loads(resp.read().decode())
212
- except urllib.error.HTTPError as e:
213
- body_text = e.read().decode()
214
- log(f"Refresh failed (HTTP {e.code}): {body_text}")
215
- return None
216
-
217
- new_token = result.get("access_token")
218
- expires_in = result.get("expires_in", "unknown")
219
- if new_token:
220
- log(f"Token refreshed: {new_token[:10]}...{new_token[-6:]}")
221
- log(f"Expires in: {expires_in}s")
222
- else:
223
- log(f"No access_token in refresh response: {json.dumps(result, indent=2)}")
224
- return new_token
225
-
226
-
227
- def verify_token(token):
228
- """Verify token against Figma MCP server."""
229
- try:
230
- req = urllib.request.Request(
231
- MCP_SERVER_URL,
232
- data=json.dumps({
233
- "jsonrpc": "2.0",
234
- "method": "initialize",
235
- "params": {
236
- "capabilities": {},
237
- "clientInfo": {"name": "token-verify", "version": "1.0.0"},
238
- "protocolVersion": "2025-03-26"
239
- },
240
- "id": 1
241
- }).encode(),
242
- headers={
243
- "Content-Type": "application/json",
244
- "Accept": "application/json, text/event-stream",
245
- "Authorization": f"Bearer {token}"
246
- },
247
- method="POST"
248
- )
249
- with urllib.request.urlopen(req) as resp:
250
- return resp.status == 200
251
- except urllib.error.HTTPError as e:
252
- if e.code == 401:
253
- return False
254
- raise
255
- except Exception:
256
- return False
257
-
258
-
259
- # ─── OAuth Flow ─────────────────────────────────────────────────────────────
260
-
261
- class OAuthCallbackHandler(http.server.BaseHTTPRequestHandler):
262
- """HTTP handler that captures the OAuth callback."""
263
- auth_code = None
264
- auth_state = None
265
- error = None
266
-
267
- def do_GET(self):
268
- parsed = urllib.parse.urlparse(self.path)
269
- params = urllib.parse.parse_qs(parsed.query)
270
- if parsed.path == "/callback":
271
- if "error" in params:
272
- OAuthCallbackHandler.error = params["error"][0]
273
- self._respond(200, "<h2>Authorization failed.</h2><p>You can close this tab.</p>")
274
- elif "code" in params:
275
- OAuthCallbackHandler.auth_code = params["code"][0]
276
- OAuthCallbackHandler.auth_state = params.get("state", [None])[0]
277
- self._respond(200, "<h2>Authorization successful!</h2><p>Return to your terminal.</p>")
278
- else:
279
- self._respond(400, "Missing code parameter")
280
- else:
281
- self._respond(404, "Not found")
282
-
283
- def _respond(self, code, body):
284
- self.send_response(code)
285
- self.send_header("Content-Type", "text/html")
286
- self.end_headers()
287
- self.wfile.write(f"<html><body>{body}</body></html>".encode())
288
-
289
- def log_message(self, format, *args):
290
- pass
291
-
292
-
293
- def generate_pkce():
294
- """Generate PKCE code_verifier and code_challenge (S256)."""
295
- verifier = secrets.token_urlsafe(64)[:128]
296
- digest = hashlib.sha256(verifier.encode("ascii")).digest()
297
- challenge = base64.urlsafe_b64encode(digest).rstrip(b"=").decode("ascii")
298
- return verifier, challenge
299
-
300
-
301
- def run_oauth_flow(client_id, client_secret, port):
302
- """Run the full OAuth 2.0 + PKCE flow and return access_token."""
303
- redirect_uri = f"http://localhost:{port}/callback"
304
-
305
- # Reset handler state
306
- OAuthCallbackHandler.auth_code = None
307
- OAuthCallbackHandler.auth_state = None
308
- OAuthCallbackHandler.error = None
309
-
310
- # Generate PKCE
311
- code_verifier, code_challenge = generate_pkce()
312
- state = secrets.token_urlsafe(32)
313
-
314
- # Start callback server
315
- log(f"Starting callback server on port {port}...")
316
- server = http.server.HTTPServer(("localhost", port), OAuthCallbackHandler)
317
- server_thread = threading.Thread(target=server.serve_forever, daemon=True)
318
- server_thread.start()
319
-
320
- # Build authorization URL
321
- auth_params = urllib.parse.urlencode({
322
- "client_id": client_id,
323
- "redirect_uri": redirect_uri,
324
- "response_type": "code",
325
- "scope": "mcp:connect",
326
- "state": state,
327
- "code_challenge": code_challenge,
328
- "code_challenge_method": "S256",
329
- })
330
- auth_url = f"{AUTH_ENDPOINT}?{auth_params}"
331
-
332
- log("Opening browser for Figma authorization...")
333
- log(f" If browser doesn't open, visit:")
334
- log(f" {auth_url}")
335
-
336
- import webbrowser
337
- webbrowser.open(auth_url)
338
-
339
- # Wait for callback
340
- log("Waiting for authorization (120s timeout)...")
341
- timeout = 120
342
- start = time.time()
343
- while OAuthCallbackHandler.auth_code is None and OAuthCallbackHandler.error is None:
344
- if time.time() - start > timeout:
345
- server.shutdown()
346
- log("Timeout waiting for authorization.")
347
- return None
348
- time.sleep(0.5)
349
-
350
- server.shutdown()
351
-
352
- if OAuthCallbackHandler.error:
353
- log(f"Authorization error: {OAuthCallbackHandler.error}")
354
- return None
355
-
356
- if OAuthCallbackHandler.auth_state != state:
357
- log("State mismatch - possible CSRF.")
358
- return None
359
-
360
- auth_code = OAuthCallbackHandler.auth_code
361
- log("Authorization code received. Exchanging for token...")
362
-
363
- # Exchange code for token
364
- token_data = urllib.parse.urlencode({
365
- "grant_type": "authorization_code",
366
- "code": auth_code,
367
- "redirect_uri": redirect_uri,
368
- "client_id": client_id,
369
- "client_secret": client_secret,
370
- "code_verifier": code_verifier,
371
- }).encode()
372
-
373
- req = urllib.request.Request(
374
- TOKEN_ENDPOINT,
375
- data=token_data,
376
- headers={"Content-Type": "application/x-www-form-urlencoded"},
377
- method="POST",
378
- )
379
-
380
- try:
381
- with urllib.request.urlopen(req) as resp:
382
- result = json.loads(resp.read().decode())
383
- except urllib.error.HTTPError as e:
384
- body = e.read().decode()
385
- log(f"Token exchange failed (HTTP {e.code}): {body}")
386
- return None
387
-
388
- access_token = result.get("access_token")
389
- refresh_token = result.get("refresh_token")
390
- expires_in = result.get("expires_in", "unknown")
391
-
392
- if access_token:
393
- log(f"Token obtained: {access_token[:10]}...{access_token[-6:]}")
394
- log(f"Expires in: {expires_in}s")
395
- if refresh_token:
396
- log(f"Refresh token obtained: {refresh_token[:10]}...{refresh_token[-6:]}")
397
- else:
398
- log(f"No access_token in response: {json.dumps(result, indent=2)}")
399
-
400
- return access_token, refresh_token
401
-
402
-
403
- # ─── Main ───────────────────────────────────────────────────────────────────
404
-
405
- def main():
406
- parser = argparse.ArgumentParser(
407
- description="Retrieve or refresh Figma MCP OAuth token"
408
- )
409
- parser.add_argument("--oauth", action="store_true",
410
- help="Run full OAuth flow (opens browser)")
411
- parser.add_argument("--client-id",
412
- help="OAuth client ID (extracted from Claude Code or provided manually)")
413
- parser.add_argument("--client-secret",
414
- help="OAuth client secret")
415
- parser.add_argument("--show-clients", action="store_true",
416
- help="Show registered OAuth clients from Claude Code credentials")
417
- parser.add_argument("--save-keychain", action="store_true",
418
- help=f"Save token to macOS Keychain as {KEYCHAIN_SERVICE}")
419
- parser.add_argument("--verify", action="store_true",
420
- help="Verify token against Figma MCP server")
421
- parser.add_argument("--quiet", action="store_true",
422
- help="Only print the token to stdout")
423
- parser.add_argument("--port", type=int, default=DEFAULT_PORT,
424
- help=f"Callback server port (default: {DEFAULT_PORT})")
425
- args = parser.parse_args()
426
-
427
- # ── Show clients mode ───────────────────────────────────────────────
428
- if args.show_clients:
429
- clients = get_client_credentials_from_claude()
430
- if not clients:
431
- log("No OAuth clients found in Claude Code credentials.")
432
- sys.exit(1)
433
- for i, c in enumerate(clients):
434
- print(f"Client {i+1}:")
435
- print(f" Server: {c['serverName']}")
436
- print(f" URL: {c['serverUrl']}")
437
- print(f" clientId: {c['clientId']}")
438
- print(f" clientSecret: {c['clientSecret']}")
439
- print()
440
- log(f"Found {len(clients)} registered client(s).")
441
- log("Use with: --oauth --client-id <id> --client-secret <secret>")
442
- sys.exit(0)
443
-
444
- # ── OAuth mode ──────────────────────────────────────────────────────
445
- if args.oauth:
446
- client_id = args.client_id
447
- client_secret = args.client_secret
448
-
449
- # Auto-extract from Claude Code credentials if not provided
450
- if not client_id or not client_secret:
451
- clients = get_client_credentials_from_claude()
452
- figma_clients = [c for c in clients if "figma" in c.get("serverUrl", "")]
453
- if figma_clients:
454
- client_id = client_id or figma_clients[0]["clientId"]
455
- client_secret = client_secret or figma_clients[0]["clientSecret"]
456
- else:
457
- log("No client credentials provided and none found in Claude Code.")
458
- log("Use: --client-id <id> --client-secret <secret>")
459
- sys.exit(1)
460
-
461
- if not args.quiet:
462
- log(f"Using client credentials ({client_id})")
463
-
464
- token, refresh_token = run_oauth_flow(client_id, client_secret, args.port)
465
- if not token:
466
- sys.exit(1)
467
-
468
- if args.verify:
469
- if not args.quiet:
470
- log("Verifying token...")
471
- if verify_token(token):
472
- if not args.quiet:
473
- log("Token is VALID.")
474
- else:
475
- if not args.quiet:
476
- log("Token is INVALID.")
477
- sys.exit(2)
478
-
479
- if args.save_keychain:
480
- if save_to_keychain(token):
481
- if not args.quiet:
482
- log(f"Saved to Keychain as '{KEYCHAIN_SERVICE}'.")
483
- else:
484
- if not args.quiet:
485
- log("Failed to save to Keychain.")
486
- sys.exit(3)
487
- # Save refresh_token alongside access_token
488
- if refresh_token:
489
- if save_to_keychain(refresh_token, service=KEYCHAIN_REFRESH_SERVICE):
490
- if not args.quiet:
491
- log(f"Saved refresh token to Keychain as '{KEYCHAIN_REFRESH_SERVICE}'.")
492
- else:
493
- if not args.quiet:
494
- log("Failed to save refresh token to Keychain.")
495
- # Save client credentials for future auto-refresh
496
- save_to_keychain(client_id, service=KEYCHAIN_CLIENT_ID_SERVICE)
497
- save_to_keychain(client_secret, service=KEYCHAIN_CLIENT_SECRET_SERVICE)
498
- if not args.quiet:
499
- log("Saved client credentials to Keychain for future auto-refresh.")
500
-
501
- print(token)
502
- sys.exit(0)
503
-
504
- # ── Extract mode (default) ──────────────────────────────────────────
505
- token, source = get_from_dedicated_keychain()
506
- if not token:
507
- token, source = get_from_claude_credentials()
508
-
509
- if not token:
510
- if not args.quiet:
511
- log("No Figma MCP token found.")
512
- log("")
513
- log("Options:")
514
- log(" 1. Run with --oauth to get a new token via browser")
515
- log(" 2. Use an MCP-enabled session to trigger OAuth first")
516
- log(" 3. Get credentials from a colleague: --show-clients")
517
- sys.exit(1)
518
-
519
- if not args.quiet:
520
- log(f"Token from: {source}")
521
- log(f"Token: {token[:10]}...{token[-6:]}")
522
- expiry = get_expiry_from_claude_credentials()
523
- if expiry:
524
- log(f"Expires: {expiry}")
525
-
526
- if args.verify:
527
- if not args.quiet:
528
- log("Verifying...")
529
- if verify_token(token):
530
- if not args.quiet:
531
- log("Token is VALID.")
532
- else:
533
- # Token invalid - try auto-refresh before giving up
534
- if not args.quiet:
535
- log("Token is INVALID or EXPIRED. Attempting auto-refresh...")
536
- refresh_tok = get_refresh_token_from_keychain()
537
- refreshed = False
538
- if refresh_tok:
539
- # Need client credentials for refresh
540
- cid = args.client_id
541
- csec = args.client_secret
542
- # Try Keychain first (saved during --oauth --save-keychain)
543
- if not cid or not csec:
544
- kc_cid, kc_csec = get_client_credentials_from_keychain()
545
- cid = cid or kc_cid
546
- csec = csec or kc_csec
547
- # Fall back to Claude Code credentials
548
- if not cid or not csec:
549
- clients = get_client_credentials_from_claude()
550
- figma_clients = [c for c in clients if "figma" in c.get("serverUrl", "")]
551
- if figma_clients:
552
- cid = cid or figma_clients[0]["clientId"]
553
- csec = csec or figma_clients[0]["clientSecret"]
554
- if cid and csec:
555
- new_token = refresh_access_token(refresh_tok, cid, csec)
556
- if new_token and verify_token(new_token):
557
- token = new_token
558
- refreshed = True
559
- if not args.quiet:
560
- log("Token refreshed successfully.")
561
- if args.save_keychain or source == f"keychain:{KEYCHAIN_SERVICE}":
562
- save_to_keychain(token)
563
- if not args.quiet:
564
- log(f"Updated Keychain '{KEYCHAIN_SERVICE}'.")
565
- else:
566
- if not args.quiet:
567
- log("Refresh failed - token or credentials expired.")
568
- else:
569
- if not args.quiet:
570
- log("No client credentials available for refresh.")
571
- else:
572
- if not args.quiet:
573
- log("No refresh token in Keychain.")
574
- if not refreshed:
575
- if not args.quiet:
576
- log("Try --oauth to get a new token via browser.")
577
- sys.exit(2)
578
-
579
- if args.save_keychain and source != f"keychain:{KEYCHAIN_SERVICE}":
580
- if save_to_keychain(token):
581
- if not args.quiet:
582
- log(f"Saved to Keychain as '{KEYCHAIN_SERVICE}'.")
583
- else:
584
- if not args.quiet:
585
- log("Failed to save to Keychain.")
586
- sys.exit(3)
587
-
588
- print(token)
589
-
590
-
591
- if __name__ == "__main__":
592
- main()