oh-my-claude-sisyphus 3.6.1 → 3.6.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.
Files changed (300) hide show
  1. package/commands/psm.md +180 -0
  2. package/dist/__tests__/analytics/analytics-summary.test.d.ts +2 -0
  3. package/dist/__tests__/analytics/analytics-summary.test.d.ts.map +1 -0
  4. package/dist/__tests__/analytics/analytics-summary.test.js +267 -0
  5. package/dist/__tests__/analytics/analytics-summary.test.js.map +1 -0
  6. package/dist/__tests__/analytics/cost-estimator.test.d.ts +2 -0
  7. package/dist/__tests__/analytics/cost-estimator.test.d.ts.map +1 -0
  8. package/dist/__tests__/analytics/cost-estimator.test.js +212 -0
  9. package/dist/__tests__/analytics/cost-estimator.test.js.map +1 -0
  10. package/dist/__tests__/hooks/auto-slash-command/executor.test.d.ts +7 -0
  11. package/dist/__tests__/hooks/auto-slash-command/executor.test.d.ts.map +1 -0
  12. package/dist/__tests__/hooks/auto-slash-command/executor.test.js +374 -0
  13. package/dist/__tests__/hooks/auto-slash-command/executor.test.js.map +1 -0
  14. package/dist/__tests__/hud/auto-tracking.integration.test.d.ts +2 -0
  15. package/dist/__tests__/hud/auto-tracking.integration.test.d.ts.map +1 -0
  16. package/dist/__tests__/hud/auto-tracking.integration.test.js +12 -0
  17. package/dist/__tests__/hud/auto-tracking.integration.test.js.map +1 -0
  18. package/dist/__tests__/learned-skills/config.test.d.ts +2 -0
  19. package/dist/__tests__/learned-skills/config.test.d.ts.map +1 -0
  20. package/dist/__tests__/learned-skills/config.test.js +37 -0
  21. package/dist/__tests__/learned-skills/config.test.js.map +1 -0
  22. package/dist/__tests__/learned-skills/detector.test.d.ts +2 -0
  23. package/dist/__tests__/learned-skills/detector.test.d.ts.map +1 -0
  24. package/dist/__tests__/learned-skills/detector.test.js +99 -0
  25. package/dist/__tests__/learned-skills/detector.test.js.map +1 -0
  26. package/dist/__tests__/learned-skills/finder.test.d.ts +2 -0
  27. package/dist/__tests__/learned-skills/finder.test.d.ts.map +1 -0
  28. package/dist/__tests__/learned-skills/finder.test.js +59 -0
  29. package/dist/__tests__/learned-skills/finder.test.js.map +1 -0
  30. package/dist/__tests__/learned-skills/loader.test.d.ts +2 -0
  31. package/dist/__tests__/learned-skills/loader.test.d.ts.map +1 -0
  32. package/dist/__tests__/learned-skills/loader.test.js +69 -0
  33. package/dist/__tests__/learned-skills/loader.test.js.map +1 -0
  34. package/dist/__tests__/learned-skills/parser.test.d.ts +2 -0
  35. package/dist/__tests__/learned-skills/parser.test.d.ts.map +1 -0
  36. package/dist/__tests__/learned-skills/parser.test.js +81 -0
  37. package/dist/__tests__/learned-skills/parser.test.js.map +1 -0
  38. package/dist/__tests__/learned-skills/validator.test.d.ts +2 -0
  39. package/dist/__tests__/learned-skills/validator.test.d.ts.map +1 -0
  40. package/dist/__tests__/learned-skills/validator.test.js +85 -0
  41. package/dist/__tests__/learned-skills/validator.test.js.map +1 -0
  42. package/dist/agents/codex-agents.d.ts +20 -0
  43. package/dist/agents/codex-agents.d.ts.map +1 -0
  44. package/dist/agents/codex-agents.js +36 -0
  45. package/dist/agents/codex-agents.js.map +1 -0
  46. package/dist/agents/document-writer.d.ts +11 -0
  47. package/dist/agents/document-writer.d.ts.map +1 -0
  48. package/dist/agents/document-writer.js +209 -0
  49. package/dist/agents/document-writer.js.map +1 -0
  50. package/dist/agents/frontend-engineer.d.ts +11 -0
  51. package/dist/agents/frontend-engineer.d.ts.map +1 -0
  52. package/dist/agents/frontend-engineer.js +115 -0
  53. package/dist/agents/frontend-engineer.js.map +1 -0
  54. package/dist/agents/librarian.d.ts +12 -0
  55. package/dist/agents/librarian.d.ts.map +1 -0
  56. package/dist/agents/librarian.js +103 -0
  57. package/dist/agents/librarian.js.map +1 -0
  58. package/dist/agents/metis.d.ts +12 -0
  59. package/dist/agents/metis.d.ts.map +1 -0
  60. package/dist/agents/metis.js +117 -0
  61. package/dist/agents/metis.js.map +1 -0
  62. package/dist/agents/momus.d.ts +12 -0
  63. package/dist/agents/momus.d.ts.map +1 -0
  64. package/dist/agents/momus.js +128 -0
  65. package/dist/agents/momus.js.map +1 -0
  66. package/dist/agents/multimodal-looker.d.ts +11 -0
  67. package/dist/agents/multimodal-looker.d.ts.map +1 -0
  68. package/dist/agents/multimodal-looker.js +70 -0
  69. package/dist/agents/multimodal-looker.js.map +1 -0
  70. package/dist/agents/oracle.d.ts +13 -0
  71. package/dist/agents/oracle.d.ts.map +1 -0
  72. package/dist/agents/oracle.js +191 -0
  73. package/dist/agents/oracle.js.map +1 -0
  74. package/dist/agents/orchestrator-sisyphus.d.ts +11 -0
  75. package/dist/agents/orchestrator-sisyphus.d.ts.map +1 -0
  76. package/dist/agents/orchestrator-sisyphus.js +115 -0
  77. package/dist/agents/orchestrator-sisyphus.js.map +1 -0
  78. package/dist/agents/prometheus.d.ts +12 -0
  79. package/dist/agents/prometheus.d.ts.map +1 -0
  80. package/dist/agents/prometheus.js +195 -0
  81. package/dist/agents/prometheus.js.map +1 -0
  82. package/dist/agents/sisyphus-junior.d.ts +12 -0
  83. package/dist/agents/sisyphus-junior.d.ts.map +1 -0
  84. package/dist/agents/sisyphus-junior.js +93 -0
  85. package/dist/agents/sisyphus-junior.js.map +1 -0
  86. package/dist/cli/analytics.js +0 -0
  87. package/dist/cli/components/CostDashboard.d.ts +15 -0
  88. package/dist/cli/components/CostDashboard.d.ts.map +1 -0
  89. package/dist/cli/components/CostDashboard.js +15 -0
  90. package/dist/cli/components/CostDashboard.js.map +1 -0
  91. package/dist/cli/components/LiveStats.d.ts +16 -0
  92. package/dist/cli/components/LiveStats.d.ts.map +1 -0
  93. package/dist/cli/components/LiveStats.js +16 -0
  94. package/dist/cli/components/LiveStats.js.map +1 -0
  95. package/dist/cli/components/SessionBrowser.d.ts +14 -0
  96. package/dist/cli/components/SessionBrowser.d.ts.map +1 -0
  97. package/dist/cli/components/SessionBrowser.js +14 -0
  98. package/dist/cli/components/SessionBrowser.js.map +1 -0
  99. package/dist/cli/index.js +0 -0
  100. package/dist/cli/tui.d.ts +21 -0
  101. package/dist/cli/tui.d.ts.map +1 -0
  102. package/dist/cli/tui.js +21 -0
  103. package/dist/cli/tui.js.map +1 -0
  104. package/dist/hooks/autopilot/signals.d.ts +20 -0
  105. package/dist/hooks/autopilot/signals.d.ts.map +1 -0
  106. package/dist/hooks/autopilot/signals.js +75 -0
  107. package/dist/hooks/autopilot/signals.js.map +1 -0
  108. package/dist/hooks/autopilot/summary.d.ts +27 -0
  109. package/dist/hooks/autopilot/summary.d.ts.map +1 -0
  110. package/dist/hooks/autopilot/summary.js +160 -0
  111. package/dist/hooks/autopilot/summary.js.map +1 -0
  112. package/dist/hooks/autopilot/transition.d.ts +39 -0
  113. package/dist/hooks/autopilot/transition.d.ts.map +1 -0
  114. package/dist/hooks/autopilot/transition.js +216 -0
  115. package/dist/hooks/autopilot/transition.js.map +1 -0
  116. package/dist/hooks/context-window-limit-recovery/constants.d.ts +28 -0
  117. package/dist/hooks/context-window-limit-recovery/constants.d.ts.map +1 -0
  118. package/dist/hooks/context-window-limit-recovery/constants.js +85 -0
  119. package/dist/hooks/context-window-limit-recovery/constants.js.map +1 -0
  120. package/dist/hooks/context-window-limit-recovery/index.d.ts +62 -0
  121. package/dist/hooks/context-window-limit-recovery/index.d.ts.map +1 -0
  122. package/dist/hooks/context-window-limit-recovery/index.js +201 -0
  123. package/dist/hooks/context-window-limit-recovery/index.js.map +1 -0
  124. package/dist/hooks/context-window-limit-recovery/parser.d.ts +31 -0
  125. package/dist/hooks/context-window-limit-recovery/parser.d.ts.map +1 -0
  126. package/dist/hooks/context-window-limit-recovery/parser.js +241 -0
  127. package/dist/hooks/context-window-limit-recovery/parser.js.map +1 -0
  128. package/dist/hooks/context-window-limit-recovery/types.d.ts +84 -0
  129. package/dist/hooks/context-window-limit-recovery/types.d.ts.map +1 -0
  130. package/dist/hooks/context-window-limit-recovery/types.js +34 -0
  131. package/dist/hooks/context-window-limit-recovery/types.js.map +1 -0
  132. package/dist/hooks/edit-error-recovery/index.d.ts +62 -0
  133. package/dist/hooks/edit-error-recovery/index.d.ts.map +1 -0
  134. package/dist/hooks/edit-error-recovery/index.js +89 -0
  135. package/dist/hooks/edit-error-recovery/index.js.map +1 -0
  136. package/dist/hooks/learned-skills/config.d.ts +53 -0
  137. package/dist/hooks/learned-skills/config.d.ts.map +1 -0
  138. package/dist/hooks/learned-skills/config.js +103 -0
  139. package/dist/hooks/learned-skills/config.js.map +1 -0
  140. package/dist/hooks/learned-skills/constants.d.ts +24 -0
  141. package/dist/hooks/learned-skills/constants.d.ts.map +1 -0
  142. package/dist/hooks/learned-skills/constants.js +26 -0
  143. package/dist/hooks/learned-skills/constants.js.map +1 -0
  144. package/dist/hooks/learned-skills/detection-hook.d.ts +39 -0
  145. package/dist/hooks/learned-skills/detection-hook.d.ts.map +1 -0
  146. package/dist/hooks/learned-skills/detection-hook.js +83 -0
  147. package/dist/hooks/learned-skills/detection-hook.js.map +1 -0
  148. package/dist/hooks/learned-skills/detector.d.ts +30 -0
  149. package/dist/hooks/learned-skills/detector.d.ts.map +1 -0
  150. package/dist/hooks/learned-skills/detector.js +150 -0
  151. package/dist/hooks/learned-skills/detector.js.map +1 -0
  152. package/dist/hooks/learned-skills/finder.d.ts +21 -0
  153. package/dist/hooks/learned-skills/finder.d.ts.map +1 -0
  154. package/dist/hooks/learned-skills/finder.js +117 -0
  155. package/dist/hooks/learned-skills/finder.js.map +1 -0
  156. package/dist/hooks/learned-skills/index.d.ts +62 -0
  157. package/dist/hooks/learned-skills/index.d.ts.map +1 -0
  158. package/dist/hooks/learned-skills/index.js +137 -0
  159. package/dist/hooks/learned-skills/index.js.map +1 -0
  160. package/dist/hooks/learned-skills/loader.d.ts +20 -0
  161. package/dist/hooks/learned-skills/loader.d.ts.map +1 -0
  162. package/dist/hooks/learned-skills/loader.js +107 -0
  163. package/dist/hooks/learned-skills/loader.js.map +1 -0
  164. package/dist/hooks/learned-skills/parser.d.ts +21 -0
  165. package/dist/hooks/learned-skills/parser.d.ts.map +1 -0
  166. package/dist/hooks/learned-skills/parser.js +190 -0
  167. package/dist/hooks/learned-skills/parser.js.map +1 -0
  168. package/dist/hooks/learned-skills/promotion.d.ts +29 -0
  169. package/dist/hooks/learned-skills/promotion.d.ts.map +1 -0
  170. package/dist/hooks/learned-skills/promotion.js +87 -0
  171. package/dist/hooks/learned-skills/promotion.js.map +1 -0
  172. package/dist/hooks/learned-skills/types.d.ts +109 -0
  173. package/dist/hooks/learned-skills/types.d.ts.map +1 -0
  174. package/dist/hooks/learned-skills/types.js +8 -0
  175. package/dist/hooks/learned-skills/types.js.map +1 -0
  176. package/dist/hooks/learned-skills/validator.d.ts +15 -0
  177. package/dist/hooks/learned-skills/validator.d.ts.map +1 -0
  178. package/dist/hooks/learned-skills/validator.js +87 -0
  179. package/dist/hooks/learned-skills/validator.js.map +1 -0
  180. package/dist/hooks/learned-skills/writer.d.ts +27 -0
  181. package/dist/hooks/learned-skills/writer.d.ts.map +1 -0
  182. package/dist/hooks/learned-skills/writer.js +126 -0
  183. package/dist/hooks/learned-skills/writer.js.map +1 -0
  184. package/dist/hooks/mnemosyne/config.d.ts +53 -0
  185. package/dist/hooks/mnemosyne/config.d.ts.map +1 -0
  186. package/dist/hooks/mnemosyne/config.js +103 -0
  187. package/dist/hooks/mnemosyne/config.js.map +1 -0
  188. package/dist/hooks/mnemosyne/constants.d.ts +24 -0
  189. package/dist/hooks/mnemosyne/constants.d.ts.map +1 -0
  190. package/dist/hooks/mnemosyne/constants.js +26 -0
  191. package/dist/hooks/mnemosyne/constants.js.map +1 -0
  192. package/dist/hooks/mnemosyne/detection-hook.d.ts +39 -0
  193. package/dist/hooks/mnemosyne/detection-hook.d.ts.map +1 -0
  194. package/dist/hooks/mnemosyne/detection-hook.js +83 -0
  195. package/dist/hooks/mnemosyne/detection-hook.js.map +1 -0
  196. package/dist/hooks/mnemosyne/detector.d.ts +30 -0
  197. package/dist/hooks/mnemosyne/detector.d.ts.map +1 -0
  198. package/dist/hooks/mnemosyne/detector.js +150 -0
  199. package/dist/hooks/mnemosyne/detector.js.map +1 -0
  200. package/dist/hooks/mnemosyne/finder.d.ts +21 -0
  201. package/dist/hooks/mnemosyne/finder.d.ts.map +1 -0
  202. package/dist/hooks/mnemosyne/finder.js +117 -0
  203. package/dist/hooks/mnemosyne/finder.js.map +1 -0
  204. package/dist/hooks/mnemosyne/index.d.ts +62 -0
  205. package/dist/hooks/mnemosyne/index.d.ts.map +1 -0
  206. package/dist/hooks/mnemosyne/index.js +137 -0
  207. package/dist/hooks/mnemosyne/index.js.map +1 -0
  208. package/dist/hooks/mnemosyne/loader.d.ts +20 -0
  209. package/dist/hooks/mnemosyne/loader.d.ts.map +1 -0
  210. package/dist/hooks/mnemosyne/loader.js +113 -0
  211. package/dist/hooks/mnemosyne/loader.js.map +1 -0
  212. package/dist/hooks/mnemosyne/parser.d.ts +21 -0
  213. package/dist/hooks/mnemosyne/parser.d.ts.map +1 -0
  214. package/dist/hooks/mnemosyne/parser.js +190 -0
  215. package/dist/hooks/mnemosyne/parser.js.map +1 -0
  216. package/dist/hooks/mnemosyne/promotion.d.ts +29 -0
  217. package/dist/hooks/mnemosyne/promotion.d.ts.map +1 -0
  218. package/dist/hooks/mnemosyne/promotion.js +87 -0
  219. package/dist/hooks/mnemosyne/promotion.js.map +1 -0
  220. package/dist/hooks/mnemosyne/types.d.ts +109 -0
  221. package/dist/hooks/mnemosyne/types.d.ts.map +1 -0
  222. package/dist/hooks/mnemosyne/types.js +8 -0
  223. package/dist/hooks/mnemosyne/types.js.map +1 -0
  224. package/dist/hooks/mnemosyne/validator.d.ts +15 -0
  225. package/dist/hooks/mnemosyne/validator.d.ts.map +1 -0
  226. package/dist/hooks/mnemosyne/validator.js +87 -0
  227. package/dist/hooks/mnemosyne/validator.js.map +1 -0
  228. package/dist/hooks/mnemosyne/writer.d.ts +27 -0
  229. package/dist/hooks/mnemosyne/writer.d.ts.map +1 -0
  230. package/dist/hooks/mnemosyne/writer.js +126 -0
  231. package/dist/hooks/mnemosyne/writer.js.map +1 -0
  232. package/dist/hooks/ralph-loop/index.d.ts +116 -0
  233. package/dist/hooks/ralph-loop/index.d.ts.map +1 -0
  234. package/dist/hooks/ralph-loop/index.js +322 -0
  235. package/dist/hooks/ralph-loop/index.js.map +1 -0
  236. package/dist/hooks/ralph-prd/index.d.ts +130 -0
  237. package/dist/hooks/ralph-prd/index.d.ts.map +1 -0
  238. package/dist/hooks/ralph-prd/index.js +310 -0
  239. package/dist/hooks/ralph-prd/index.js.map +1 -0
  240. package/dist/hooks/ralph-progress/index.d.ts +102 -0
  241. package/dist/hooks/ralph-progress/index.d.ts.map +1 -0
  242. package/dist/hooks/ralph-progress/index.js +408 -0
  243. package/dist/hooks/ralph-progress/index.js.map +1 -0
  244. package/dist/hooks/ralph-verifier/index.d.ts +72 -0
  245. package/dist/hooks/ralph-verifier/index.d.ts.map +1 -0
  246. package/dist/hooks/ralph-verifier/index.js +223 -0
  247. package/dist/hooks/ralph-verifier/index.js.map +1 -0
  248. package/dist/hooks/session-recovery/constants.d.ts +56 -0
  249. package/dist/hooks/session-recovery/constants.d.ts.map +1 -0
  250. package/dist/hooks/session-recovery/constants.js +78 -0
  251. package/dist/hooks/session-recovery/constants.js.map +1 -0
  252. package/dist/hooks/session-recovery/index.d.ts +53 -0
  253. package/dist/hooks/session-recovery/index.d.ts.map +1 -0
  254. package/dist/hooks/session-recovery/index.js +321 -0
  255. package/dist/hooks/session-recovery/index.js.map +1 -0
  256. package/dist/hooks/session-recovery/storage.d.ts +76 -0
  257. package/dist/hooks/session-recovery/storage.d.ts.map +1 -0
  258. package/dist/hooks/session-recovery/storage.js +383 -0
  259. package/dist/hooks/session-recovery/storage.js.map +1 -0
  260. package/dist/hooks/session-recovery/types.d.ts +145 -0
  261. package/dist/hooks/session-recovery/types.d.ts.map +1 -0
  262. package/dist/hooks/session-recovery/types.js +8 -0
  263. package/dist/hooks/session-recovery/types.js.map +1 -0
  264. package/dist/hooks/sisyphus-orchestrator/constants.d.ts +23 -0
  265. package/dist/hooks/sisyphus-orchestrator/constants.d.ts.map +1 -0
  266. package/dist/hooks/sisyphus-orchestrator/constants.js +142 -0
  267. package/dist/hooks/sisyphus-orchestrator/constants.js.map +1 -0
  268. package/dist/hooks/sisyphus-orchestrator/index.d.ts +113 -0
  269. package/dist/hooks/sisyphus-orchestrator/index.d.ts.map +1 -0
  270. package/dist/hooks/sisyphus-orchestrator/index.js +309 -0
  271. package/dist/hooks/sisyphus-orchestrator/index.js.map +1 -0
  272. package/dist/hooks/subagent-tracker/index.d.ts +83 -0
  273. package/dist/hooks/subagent-tracker/index.d.ts.map +1 -0
  274. package/dist/hooks/subagent-tracker/index.js +207 -0
  275. package/dist/hooks/subagent-tracker/index.js.map +1 -0
  276. package/dist/hooks/ultraqa-loop/index.d.ts +94 -0
  277. package/dist/hooks/ultraqa-loop/index.d.ts.map +1 -0
  278. package/dist/hooks/ultraqa-loop/index.js +216 -0
  279. package/dist/hooks/ultraqa-loop/index.js.map +1 -0
  280. package/dist/hooks/ultrawork-state/index.d.ts +62 -0
  281. package/dist/hooks/ultrawork-state/index.d.ts.map +1 -0
  282. package/dist/hooks/ultrawork-state/index.js +208 -0
  283. package/dist/hooks/ultrawork-state/index.js.map +1 -0
  284. package/dist/hud/sisyphus-state.d.ts +31 -0
  285. package/dist/hud/sisyphus-state.d.ts.map +1 -0
  286. package/dist/hud/sisyphus-state.js +163 -0
  287. package/dist/hud/sisyphus-state.js.map +1 -0
  288. package/docs/design/project-session-manager.md +1033 -0
  289. package/package.json +1 -1
  290. package/skills/project-session-manager/SKILL.md +410 -0
  291. package/skills/project-session-manager/lib/config.sh +86 -0
  292. package/skills/project-session-manager/lib/parse.sh +121 -0
  293. package/skills/project-session-manager/lib/session.sh +132 -0
  294. package/skills/project-session-manager/lib/tmux.sh +103 -0
  295. package/skills/project-session-manager/lib/worktree.sh +171 -0
  296. package/skills/project-session-manager/psm.sh +629 -0
  297. package/skills/project-session-manager/templates/feature.md +56 -0
  298. package/skills/project-session-manager/templates/issue-fix.md +57 -0
  299. package/skills/project-session-manager/templates/pr-review.md +65 -0
  300. package/skills/project-session-manager/templates/projects.json +19 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-claude-sisyphus",
3
- "version": "3.6.1",
3
+ "version": "3.6.2",
4
4
  "description": "Multi-agent orchestration system for Claude Code - Inspired by oh-my-opencode",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -0,0 +1,410 @@
1
+ ---
2
+ name: project-session-manager
3
+ description: Manage isolated dev environments with git worktrees and tmux sessions
4
+ aliases: [psm]
5
+ ---
6
+
7
+ # Project Session Manager (PSM) Skill
8
+
9
+ Automate isolated development environments using git worktrees and tmux sessions with Claude Code. Enables parallel work across multiple tasks, projects, and repositories.
10
+
11
+ ## Commands
12
+
13
+ | Command | Description | Example |
14
+ |---------|-------------|---------|
15
+ | `review <ref>` | PR review session | `/psm review omc#123` |
16
+ | `fix <ref>` | Issue fix session | `/psm fix omc#42` |
17
+ | `feature <proj> <name>` | Feature development | `/psm feature omc add-webhooks` |
18
+ | `list [project]` | List active sessions | `/psm list` |
19
+ | `attach <session>` | Attach to session | `/psm attach omc:pr-123` |
20
+ | `kill <session>` | Kill session | `/psm kill omc:pr-123` |
21
+ | `cleanup` | Clean merged/closed | `/psm cleanup` |
22
+ | `status` | Current session info | `/psm status` |
23
+
24
+ ## Project References
25
+
26
+ Supported formats:
27
+ - **Alias**: `omc#123` (requires `~/.psm/projects.json`)
28
+ - **Full**: `owner/repo#123`
29
+ - **URL**: `https://github.com/owner/repo/pull/123`
30
+ - **Current**: `#123` (uses current directory's repo)
31
+
32
+ ## Configuration
33
+
34
+ ### Project Aliases (`~/.psm/projects.json`)
35
+
36
+ ```json
37
+ {
38
+ "aliases": {
39
+ "omc": {
40
+ "repo": "Yeachan-Heo/oh-my-claudecode",
41
+ "local": "~/Workspace/oh-my-claudecode",
42
+ "default_base": "main"
43
+ }
44
+ },
45
+ "defaults": {
46
+ "worktree_root": "~/.psm/worktrees",
47
+ "cleanup_after_days": 14
48
+ }
49
+ }
50
+ ```
51
+
52
+ ## Directory Structure
53
+
54
+ ```
55
+ ~/.psm/
56
+ ├── projects.json # Project aliases
57
+ ├── sessions.json # Active session registry
58
+ └── worktrees/ # Worktree storage
59
+ └── <project>/
60
+ └── <type>-<id>/
61
+ ```
62
+
63
+ ## Session Naming
64
+
65
+ | Type | Tmux Session | Worktree Dir |
66
+ |------|--------------|--------------|
67
+ | PR Review | `psm:omc:pr-123` | `~/.psm/worktrees/omc/pr-123` |
68
+ | Issue Fix | `psm:omc:issue-42` | `~/.psm/worktrees/omc/issue-42` |
69
+ | Feature | `psm:omc:feat-auth` | `~/.psm/worktrees/omc/feat-auth` |
70
+
71
+ ---
72
+
73
+ ## Implementation Protocol
74
+
75
+ When the user invokes a PSM command, follow this protocol:
76
+
77
+ ### Parse Arguments
78
+
79
+ Parse `{{ARGUMENTS}}` to determine:
80
+ 1. **Subcommand**: review, fix, feature, list, attach, kill, cleanup, status
81
+ 2. **Reference**: project#number, URL, or session ID
82
+ 3. **Options**: --branch, --base, --no-claude, --no-tmux, etc.
83
+
84
+ ### Subcommand: `review <ref>`
85
+
86
+ **Purpose**: Create PR review session
87
+
88
+ **Steps**:
89
+
90
+ 1. **Resolve reference**:
91
+ ```bash
92
+ # Read project aliases
93
+ cat ~/.psm/projects.json 2>/dev/null || echo '{"aliases":{}}'
94
+
95
+ # Parse ref format: alias#num, owner/repo#num, or URL
96
+ # Extract: project_alias, repo (owner/repo), pr_number, local_path
97
+ ```
98
+
99
+ 2. **Fetch PR info**:
100
+ ```bash
101
+ gh pr view <pr_number> --repo <repo> --json number,title,author,headRefName,baseRefName,body,files,url
102
+ ```
103
+
104
+ 3. **Ensure local repo exists**:
105
+ ```bash
106
+ # If local path doesn't exist, clone
107
+ if [[ ! -d "$local_path" ]]; then
108
+ git clone "https://github.com/$repo.git" "$local_path"
109
+ fi
110
+ ```
111
+
112
+ 4. **Create worktree**:
113
+ ```bash
114
+ worktree_path="$HOME/.psm/worktrees/$project_alias/pr-$pr_number"
115
+
116
+ # Fetch PR branch
117
+ cd "$local_path"
118
+ git fetch origin "pull/$pr_number/head:pr-$pr_number-review"
119
+
120
+ # Create worktree
121
+ git worktree add "$worktree_path" "pr-$pr_number-review"
122
+ ```
123
+
124
+ 5. **Create session metadata**:
125
+ ```bash
126
+ cat > "$worktree_path/.psm-session.json" << EOF
127
+ {
128
+ "id": "$project_alias:pr-$pr_number",
129
+ "type": "review",
130
+ "project": "$project_alias",
131
+ "ref": "pr-$pr_number",
132
+ "branch": "<head_branch>",
133
+ "base": "<base_branch>",
134
+ "created_at": "$(date -Iseconds)",
135
+ "tmux_session": "psm:$project_alias:pr-$pr_number",
136
+ "worktree_path": "$worktree_path",
137
+ "source_repo": "$local_path",
138
+ "github": {
139
+ "pr_number": $pr_number,
140
+ "pr_title": "<title>",
141
+ "pr_author": "<author>",
142
+ "pr_url": "<url>"
143
+ },
144
+ "state": "active"
145
+ }
146
+ EOF
147
+ ```
148
+
149
+ 6. **Update sessions registry**:
150
+ ```bash
151
+ # Add to ~/.psm/sessions.json
152
+ ```
153
+
154
+ 7. **Create tmux session**:
155
+ ```bash
156
+ tmux new-session -d -s "psm:$project_alias:pr-$pr_number" -c "$worktree_path"
157
+ ```
158
+
159
+ 8. **Launch Claude Code** (unless --no-claude):
160
+ ```bash
161
+ tmux send-keys -t "psm:$project_alias:pr-$pr_number" "claude" Enter
162
+ ```
163
+
164
+ 9. **Output session info**:
165
+ ```
166
+ Session ready!
167
+
168
+ ID: omc:pr-123
169
+ Worktree: ~/.psm/worktrees/omc/pr-123
170
+ Tmux: psm:omc:pr-123
171
+
172
+ To attach: tmux attach -t psm:omc:pr-123
173
+ ```
174
+
175
+ ### Subcommand: `fix <ref>`
176
+
177
+ **Purpose**: Create issue fix session
178
+
179
+ **Steps**:
180
+
181
+ 1. **Resolve reference** (same as review)
182
+
183
+ 2. **Fetch issue info**:
184
+ ```bash
185
+ gh issue view <issue_number> --repo <repo> --json number,title,body,labels,url
186
+ ```
187
+
188
+ 3. **Create feature branch**:
189
+ ```bash
190
+ cd "$local_path"
191
+ git fetch origin main
192
+ branch_name="fix/$issue_number-$(echo "$title" | tr ' ' '-' | tr '[:upper:]' '[:lower:]' | head -c 30)"
193
+ git checkout -b "$branch_name" origin/main
194
+ ```
195
+
196
+ 4. **Create worktree**:
197
+ ```bash
198
+ worktree_path="$HOME/.psm/worktrees/$project_alias/issue-$issue_number"
199
+ git worktree add "$worktree_path" "$branch_name"
200
+ ```
201
+
202
+ 5. **Create session metadata** (similar to review, type="fix")
203
+
204
+ 6. **Update registry, create tmux, launch claude** (same as review)
205
+
206
+ ### Subcommand: `feature <project> <name>`
207
+
208
+ **Purpose**: Start feature development
209
+
210
+ **Steps**:
211
+
212
+ 1. **Resolve project** (from alias or path)
213
+
214
+ 2. **Create feature branch**:
215
+ ```bash
216
+ cd "$local_path"
217
+ git fetch origin main
218
+ branch_name="feature/$feature_name"
219
+ git checkout -b "$branch_name" origin/main
220
+ ```
221
+
222
+ 3. **Create worktree**:
223
+ ```bash
224
+ worktree_path="$HOME/.psm/worktrees/$project_alias/feat-$feature_name"
225
+ git worktree add "$worktree_path" "$branch_name"
226
+ ```
227
+
228
+ 4. **Create session, tmux, launch claude** (same pattern)
229
+
230
+ ### Subcommand: `list [project]`
231
+
232
+ **Purpose**: List active sessions
233
+
234
+ **Steps**:
235
+
236
+ 1. **Read sessions registry**:
237
+ ```bash
238
+ cat ~/.psm/sessions.json 2>/dev/null || echo '{"sessions":{}}'
239
+ ```
240
+
241
+ 2. **Check tmux sessions**:
242
+ ```bash
243
+ tmux list-sessions -F "#{session_name}" 2>/dev/null | grep "^psm:"
244
+ ```
245
+
246
+ 3. **Check worktrees**:
247
+ ```bash
248
+ ls -la ~/.psm/worktrees/*/ 2>/dev/null
249
+ ```
250
+
251
+ 4. **Format output**:
252
+ ```
253
+ Active PSM Sessions:
254
+
255
+ ID | Type | Status | Worktree
256
+ -------------------|---------|----------|---------------------------
257
+ omc:pr-123 | review | active | ~/.psm/worktrees/omc/pr-123
258
+ omc:issue-42 | fix | detached | ~/.psm/worktrees/omc/issue-42
259
+ ```
260
+
261
+ ### Subcommand: `attach <session>`
262
+
263
+ **Purpose**: Attach to existing session
264
+
265
+ **Steps**:
266
+
267
+ 1. **Parse session ID**: `project:type-number`
268
+
269
+ 2. **Verify session exists**:
270
+ ```bash
271
+ tmux has-session -t "psm:$session_id" 2>/dev/null
272
+ ```
273
+
274
+ 3. **Attach**:
275
+ ```bash
276
+ tmux attach -t "psm:$session_id"
277
+ ```
278
+
279
+ ### Subcommand: `kill <session>`
280
+
281
+ **Purpose**: Kill session and cleanup
282
+
283
+ **Steps**:
284
+
285
+ 1. **Kill tmux session**:
286
+ ```bash
287
+ tmux kill-session -t "psm:$session_id" 2>/dev/null
288
+ ```
289
+
290
+ 2. **Remove worktree**:
291
+ ```bash
292
+ worktree_path=$(jq -r ".sessions[\"$session_id\"].worktree" ~/.psm/sessions.json)
293
+ source_repo=$(jq -r ".sessions[\"$session_id\"].source_repo" ~/.psm/sessions.json)
294
+
295
+ cd "$source_repo"
296
+ git worktree remove "$worktree_path" --force
297
+ ```
298
+
299
+ 3. **Update registry**:
300
+ ```bash
301
+ # Remove from sessions.json
302
+ ```
303
+
304
+ ### Subcommand: `cleanup`
305
+
306
+ **Purpose**: Clean up merged PRs and closed issues
307
+
308
+ **Steps**:
309
+
310
+ 1. **Read all sessions**
311
+
312
+ 2. **For each PR session, check if merged**:
313
+ ```bash
314
+ gh pr view <pr_number> --repo <repo> --json merged,state
315
+ ```
316
+
317
+ 3. **For each issue session, check if closed**:
318
+ ```bash
319
+ gh issue view <issue_number> --repo <repo> --json closed,state
320
+ ```
321
+
322
+ 4. **Clean up merged/closed sessions**:
323
+ - Kill tmux session
324
+ - Remove worktree
325
+ - Update registry
326
+
327
+ 5. **Report**:
328
+ ```
329
+ Cleanup complete:
330
+ Removed: omc:pr-123 (merged)
331
+ Removed: omc:issue-42 (closed)
332
+ Kept: omc:feat-auth (active)
333
+ ```
334
+
335
+ ### Subcommand: `status`
336
+
337
+ **Purpose**: Show current session info
338
+
339
+ **Steps**:
340
+
341
+ 1. **Detect current session** from tmux or cwd:
342
+ ```bash
343
+ tmux display-message -p "#{session_name}" 2>/dev/null
344
+ # or check if cwd is inside a worktree
345
+ ```
346
+
347
+ 2. **Read session metadata**:
348
+ ```bash
349
+ cat .psm-session.json 2>/dev/null
350
+ ```
351
+
352
+ 3. **Show status**:
353
+ ```
354
+ Current Session: omc:pr-123
355
+ Type: review
356
+ PR: #123 - Add webhook support
357
+ Branch: feature/webhooks
358
+ Created: 2 hours ago
359
+ ```
360
+
361
+ ---
362
+
363
+ ## Error Handling
364
+
365
+ | Error | Resolution |
366
+ |-------|------------|
367
+ | Worktree exists | Offer: attach, recreate, or abort |
368
+ | PR not found | Verify URL/number, check permissions |
369
+ | No tmux | Warn and skip session creation |
370
+ | No gh CLI | Error with install instructions |
371
+
372
+ ## Requirements
373
+
374
+ - `git` with worktree support (v2.5+)
375
+ - `gh` CLI (authenticated)
376
+ - `tmux`
377
+ - `jq` for JSON parsing
378
+
379
+ ## Initialization
380
+
381
+ On first run, create default config:
382
+
383
+ ```bash
384
+ mkdir -p ~/.psm/worktrees ~/.psm/logs
385
+
386
+ # Create default projects.json if not exists
387
+ if [[ ! -f ~/.psm/projects.json ]]; then
388
+ cat > ~/.psm/projects.json << 'EOF'
389
+ {
390
+ "aliases": {
391
+ "omc": {
392
+ "repo": "Yeachan-Heo/oh-my-claudecode",
393
+ "local": "~/Workspace/oh-my-claudecode",
394
+ "default_base": "main"
395
+ }
396
+ },
397
+ "defaults": {
398
+ "worktree_root": "~/.psm/worktrees",
399
+ "cleanup_after_days": 14,
400
+ "auto_cleanup_merged": true
401
+ }
402
+ }
403
+ EOF
404
+ fi
405
+
406
+ # Create sessions.json if not exists
407
+ if [[ ! -f ~/.psm/sessions.json ]]; then
408
+ echo '{"version":1,"sessions":{},"stats":{"total_created":0,"total_cleaned":0}}' > ~/.psm/sessions.json
409
+ fi
410
+ ```
@@ -0,0 +1,86 @@
1
+ #!/bin/bash
2
+ # PSM Configuration Management
3
+
4
+ PSM_ROOT="${HOME}/.psm"
5
+ PSM_WORKTREES="${PSM_ROOT}/worktrees"
6
+ PSM_PROJECTS="${PSM_ROOT}/projects.json"
7
+ PSM_SESSIONS="${PSM_ROOT}/sessions.json"
8
+ PSM_LOGS="${PSM_ROOT}/logs"
9
+
10
+ # Initialize PSM directories and config files
11
+ psm_init() {
12
+ mkdir -p "$PSM_WORKTREES" "$PSM_LOGS"
13
+
14
+ # Create default projects.json if not exists
15
+ if [[ ! -f "$PSM_PROJECTS" ]]; then
16
+ cat > "$PSM_PROJECTS" << 'EOF'
17
+ {
18
+ "aliases": {
19
+ "omc": {
20
+ "repo": "Yeachan-Heo/oh-my-claudecode",
21
+ "local": "~/Workspace/oh-my-claudecode",
22
+ "default_base": "main"
23
+ }
24
+ },
25
+ "defaults": {
26
+ "worktree_root": "~/.psm/worktrees",
27
+ "cleanup_after_days": 14,
28
+ "auto_cleanup_merged": true
29
+ }
30
+ }
31
+ EOF
32
+ echo "Created default projects.json"
33
+ fi
34
+
35
+ # Create sessions.json if not exists
36
+ if [[ ! -f "$PSM_SESSIONS" ]]; then
37
+ echo '{"version":1,"sessions":{},"stats":{"total_created":0,"total_cleaned":0}}' > "$PSM_SESSIONS"
38
+ echo "Created sessions.json"
39
+ fi
40
+ }
41
+
42
+ # Get project config by alias
43
+ # Usage: psm_get_project "omc"
44
+ # Returns: repo|local|default_base
45
+ psm_get_project() {
46
+ local alias="$1"
47
+ if [[ ! -f "$PSM_PROJECTS" ]]; then
48
+ return 1
49
+ fi
50
+
51
+ local repo=$(jq -r ".aliases[\"$alias\"].repo // empty" "$PSM_PROJECTS")
52
+ local local_path=$(jq -r ".aliases[\"$alias\"].local // empty" "$PSM_PROJECTS")
53
+ local default_base=$(jq -r ".aliases[\"$alias\"].default_base // \"main\"" "$PSM_PROJECTS")
54
+
55
+ if [[ -z "$repo" ]]; then
56
+ return 1
57
+ fi
58
+
59
+ # Expand ~ to $HOME
60
+ local_path="${local_path/#\~/$HOME}"
61
+
62
+ echo "${repo}|${local_path}|${default_base}"
63
+ }
64
+
65
+ # Add or update project alias
66
+ psm_set_project() {
67
+ local alias="$1"
68
+ local repo="$2"
69
+ local local_path="$3"
70
+ local default_base="${4:-main}"
71
+
72
+ local tmp=$(mktemp)
73
+ jq ".aliases[\"$alias\"] = {\"repo\": \"$repo\", \"local\": \"$local_path\", \"default_base\": \"$default_base\"}" \
74
+ "$PSM_PROJECTS" > "$tmp" && mv "$tmp" "$PSM_PROJECTS"
75
+ }
76
+
77
+ # Get default worktree root
78
+ psm_get_worktree_root() {
79
+ local root=$(jq -r '.defaults.worktree_root // "~/.psm/worktrees"' "$PSM_PROJECTS")
80
+ echo "${root/#\~/$HOME}"
81
+ }
82
+
83
+ # Get cleanup days setting
84
+ psm_get_cleanup_days() {
85
+ jq -r '.defaults.cleanup_after_days // 14' "$PSM_PROJECTS"
86
+ }
@@ -0,0 +1,121 @@
1
+ #!/bin/bash
2
+ # PSM Reference Parser
3
+
4
+ # Parse a reference string into components
5
+ # Supports:
6
+ # omc#123 -> alias=omc, number=123
7
+ # owner/repo#123 -> repo=owner/repo, number=123
8
+ # https://... -> parsed from URL
9
+ # #123 -> number=123 (use current repo)
10
+ #
11
+ # Usage: psm_parse_ref "omc#123"
12
+ # Returns: type|alias|repo|number|local_path|base
13
+ psm_parse_ref() {
14
+ local ref="$1"
15
+ local type=""
16
+ local alias=""
17
+ local repo=""
18
+ local number=""
19
+ local local_path=""
20
+ local base="main"
21
+
22
+ # GitHub PR URL
23
+ if [[ "$ref" =~ ^https://github\.com/([^/]+)/([^/]+)/pull/([0-9]+) ]]; then
24
+ repo="${BASH_REMATCH[1]}/${BASH_REMATCH[2]}"
25
+ number="${BASH_REMATCH[3]}"
26
+ type="pr"
27
+ # Try to find alias for this repo
28
+ alias=$(psm_find_alias_for_repo "$repo")
29
+ if [[ -n "$alias" ]]; then
30
+ IFS='|' read -r _ local_path base <<< "$(psm_get_project "$alias")"
31
+ fi
32
+ echo "pr|${alias:-}|$repo|$number|${local_path:-}|$base"
33
+ return 0
34
+ fi
35
+
36
+ # GitHub Issue URL
37
+ if [[ "$ref" =~ ^https://github\.com/([^/]+)/([^/]+)/issues/([0-9]+) ]]; then
38
+ repo="${BASH_REMATCH[1]}/${BASH_REMATCH[2]}"
39
+ number="${BASH_REMATCH[3]}"
40
+ type="issue"
41
+ alias=$(psm_find_alias_for_repo "$repo")
42
+ if [[ -n "$alias" ]]; then
43
+ IFS='|' read -r _ local_path base <<< "$(psm_get_project "$alias")"
44
+ fi
45
+ echo "issue|${alias:-}|$repo|$number|${local_path:-}|$base"
46
+ return 0
47
+ fi
48
+
49
+ # alias#number format (e.g., omc#123)
50
+ if [[ "$ref" =~ ^([a-zA-Z][a-zA-Z0-9_-]*)#([0-9]+)$ ]]; then
51
+ alias="${BASH_REMATCH[1]}"
52
+ number="${BASH_REMATCH[2]}"
53
+
54
+ local project_info
55
+ project_info=$(psm_get_project "$alias")
56
+ if [[ $? -eq 0 ]]; then
57
+ IFS='|' read -r repo local_path base <<< "$project_info"
58
+ # Determine type from context (default to issue, caller specifies)
59
+ echo "ref|$alias|$repo|$number|$local_path|$base"
60
+ return 0
61
+ else
62
+ echo "error|Unknown project alias: $alias|||"
63
+ return 1
64
+ fi
65
+ fi
66
+
67
+ # owner/repo#number format
68
+ if [[ "$ref" =~ ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_.-]+)#([0-9]+)$ ]]; then
69
+ repo="${BASH_REMATCH[1]}/${BASH_REMATCH[2]}"
70
+ number="${BASH_REMATCH[3]}"
71
+ alias=$(psm_find_alias_for_repo "$repo")
72
+ if [[ -n "$alias" ]]; then
73
+ IFS='|' read -r _ local_path base <<< "$(psm_get_project "$alias")"
74
+ fi
75
+ echo "ref|${alias:-}|$repo|$number|${local_path:-}|$base"
76
+ return 0
77
+ fi
78
+
79
+ # Just #number (use current repo)
80
+ if [[ "$ref" =~ ^#([0-9]+)$ ]]; then
81
+ number="${BASH_REMATCH[1]}"
82
+ # Detect repo from current directory
83
+ if git rev-parse --git-dir > /dev/null 2>&1; then
84
+ local remote_url=$(git remote get-url origin 2>/dev/null)
85
+ if [[ "$remote_url" =~ github\.com[:/]([^/]+)/([^/.]+) ]]; then
86
+ repo="${BASH_REMATCH[1]}/${BASH_REMATCH[2]}"
87
+ local_path=$(git rev-parse --show-toplevel)
88
+ alias=$(psm_find_alias_for_repo "$repo")
89
+ fi
90
+ fi
91
+ echo "ref|${alias:-}|${repo:-}|$number|${local_path:-}|$base"
92
+ return 0
93
+ fi
94
+
95
+ echo "error|Cannot parse reference: $ref|||"
96
+ return 1
97
+ }
98
+
99
+ # Find project alias for a given repo
100
+ psm_find_alias_for_repo() {
101
+ local target_repo="$1"
102
+ if [[ ! -f "$PSM_PROJECTS" ]]; then
103
+ return 1
104
+ fi
105
+
106
+ jq -r ".aliases | to_entries[] | select(.value.repo == \"$target_repo\") | .key" "$PSM_PROJECTS" | head -1
107
+ }
108
+
109
+ # Sanitize a string for use in filenames/session names
110
+ psm_sanitize() {
111
+ local input="$1"
112
+ # Remove path traversal, convert to lowercase, replace spaces with dashes
113
+ echo "$input" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g' | sed 's/--*/-/g' | head -c 30
114
+ }
115
+
116
+ # Generate a slug from title
117
+ psm_slugify() {
118
+ local title="$1"
119
+ local max_len="${2:-30}"
120
+ echo "$title" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//' | sed 's/-$//' | head -c "$max_len"
121
+ }