superpowers-manager 0.9.0 → 0.10.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 (248) hide show
  1. package/README.md +35 -16
  2. package/dist/cli-arguments.js +2 -1
  3. package/dist/cli.js +12 -9
  4. package/dist/harnesses/codex/adapter.js +9 -1
  5. package/dist/harnesses/codex/hooks.js +17 -0
  6. package/dist/harnesses/hermes/harness.js +36 -0
  7. package/dist/harnesses/hermes/install.js +235 -0
  8. package/dist/harnesses/hermes/native.js +40 -0
  9. package/dist/harnesses/hermes/observe.js +178 -0
  10. package/dist/harnesses/hermes/paths.js +61 -0
  11. package/dist/harnesses/hermes/prepare.js +78 -0
  12. package/dist/harnesses/hermes/presentation.js +23 -0
  13. package/dist/harnesses/hermes/state.js +144 -0
  14. package/dist/snapshot-prepare.js +2 -0
  15. package/node_modules/yaml/LICENSE +13 -0
  16. package/node_modules/yaml/README.md +172 -0
  17. package/node_modules/yaml/bin.mjs +11 -0
  18. package/node_modules/yaml/browser/dist/compose/compose-collection.js +88 -0
  19. package/node_modules/yaml/browser/dist/compose/compose-doc.js +43 -0
  20. package/node_modules/yaml/browser/dist/compose/compose-node.js +109 -0
  21. package/node_modules/yaml/browser/dist/compose/compose-scalar.js +86 -0
  22. package/node_modules/yaml/browser/dist/compose/composer.js +219 -0
  23. package/node_modules/yaml/browser/dist/compose/resolve-block-map.js +115 -0
  24. package/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js +198 -0
  25. package/node_modules/yaml/browser/dist/compose/resolve-block-seq.js +49 -0
  26. package/node_modules/yaml/browser/dist/compose/resolve-end.js +37 -0
  27. package/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js +207 -0
  28. package/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +225 -0
  29. package/node_modules/yaml/browser/dist/compose/resolve-props.js +146 -0
  30. package/node_modules/yaml/browser/dist/compose/util-contains-newline.js +34 -0
  31. package/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js +26 -0
  32. package/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js +15 -0
  33. package/node_modules/yaml/browser/dist/compose/util-map-includes.js +13 -0
  34. package/node_modules/yaml/browser/dist/doc/Document.js +335 -0
  35. package/node_modules/yaml/browser/dist/doc/anchors.js +71 -0
  36. package/node_modules/yaml/browser/dist/doc/applyReviver.js +55 -0
  37. package/node_modules/yaml/browser/dist/doc/createNode.js +88 -0
  38. package/node_modules/yaml/browser/dist/doc/directives.js +176 -0
  39. package/node_modules/yaml/browser/dist/errors.js +57 -0
  40. package/node_modules/yaml/browser/dist/index.js +17 -0
  41. package/node_modules/yaml/browser/dist/log.js +11 -0
  42. package/node_modules/yaml/browser/dist/nodes/Alias.js +116 -0
  43. package/node_modules/yaml/browser/dist/nodes/Collection.js +147 -0
  44. package/node_modules/yaml/browser/dist/nodes/Node.js +38 -0
  45. package/node_modules/yaml/browser/dist/nodes/Pair.js +36 -0
  46. package/node_modules/yaml/browser/dist/nodes/Scalar.js +24 -0
  47. package/node_modules/yaml/browser/dist/nodes/YAMLMap.js +144 -0
  48. package/node_modules/yaml/browser/dist/nodes/YAMLSeq.js +113 -0
  49. package/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js +63 -0
  50. package/node_modules/yaml/browser/dist/nodes/identity.js +36 -0
  51. package/node_modules/yaml/browser/dist/nodes/toJS.js +37 -0
  52. package/node_modules/yaml/browser/dist/parse/cst-scalar.js +214 -0
  53. package/node_modules/yaml/browser/dist/parse/cst-stringify.js +61 -0
  54. package/node_modules/yaml/browser/dist/parse/cst-visit.js +97 -0
  55. package/node_modules/yaml/browser/dist/parse/cst.js +98 -0
  56. package/node_modules/yaml/browser/dist/parse/lexer.js +721 -0
  57. package/node_modules/yaml/browser/dist/parse/line-counter.js +39 -0
  58. package/node_modules/yaml/browser/dist/parse/parser.js +975 -0
  59. package/node_modules/yaml/browser/dist/public-api.js +102 -0
  60. package/node_modules/yaml/browser/dist/schema/Schema.js +37 -0
  61. package/node_modules/yaml/browser/dist/schema/common/map.js +17 -0
  62. package/node_modules/yaml/browser/dist/schema/common/null.js +15 -0
  63. package/node_modules/yaml/browser/dist/schema/common/seq.js +17 -0
  64. package/node_modules/yaml/browser/dist/schema/common/string.js +14 -0
  65. package/node_modules/yaml/browser/dist/schema/core/bool.js +19 -0
  66. package/node_modules/yaml/browser/dist/schema/core/float.js +43 -0
  67. package/node_modules/yaml/browser/dist/schema/core/int.js +38 -0
  68. package/node_modules/yaml/browser/dist/schema/core/schema.js +23 -0
  69. package/node_modules/yaml/browser/dist/schema/json/schema.js +62 -0
  70. package/node_modules/yaml/browser/dist/schema/tags.js +96 -0
  71. package/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js +58 -0
  72. package/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js +26 -0
  73. package/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js +46 -0
  74. package/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js +71 -0
  75. package/node_modules/yaml/browser/dist/schema/yaml-1.1/merge.js +67 -0
  76. package/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js +74 -0
  77. package/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js +78 -0
  78. package/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js +39 -0
  79. package/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js +93 -0
  80. package/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js +101 -0
  81. package/node_modules/yaml/browser/dist/stringify/foldFlowLines.js +146 -0
  82. package/node_modules/yaml/browser/dist/stringify/stringify.js +129 -0
  83. package/node_modules/yaml/browser/dist/stringify/stringifyCollection.js +153 -0
  84. package/node_modules/yaml/browser/dist/stringify/stringifyComment.js +20 -0
  85. package/node_modules/yaml/browser/dist/stringify/stringifyDocument.js +85 -0
  86. package/node_modules/yaml/browser/dist/stringify/stringifyNumber.js +25 -0
  87. package/node_modules/yaml/browser/dist/stringify/stringifyPair.js +150 -0
  88. package/node_modules/yaml/browser/dist/stringify/stringifyString.js +336 -0
  89. package/node_modules/yaml/browser/dist/util.js +11 -0
  90. package/node_modules/yaml/browser/dist/visit.js +233 -0
  91. package/node_modules/yaml/browser/index.js +5 -0
  92. package/node_modules/yaml/browser/package.json +3 -0
  93. package/node_modules/yaml/dist/cli.d.ts +8 -0
  94. package/node_modules/yaml/dist/cli.mjs +201 -0
  95. package/node_modules/yaml/dist/compose/compose-collection.d.ts +11 -0
  96. package/node_modules/yaml/dist/compose/compose-collection.js +90 -0
  97. package/node_modules/yaml/dist/compose/compose-doc.d.ts +7 -0
  98. package/node_modules/yaml/dist/compose/compose-doc.js +45 -0
  99. package/node_modules/yaml/dist/compose/compose-node.d.ts +29 -0
  100. package/node_modules/yaml/dist/compose/compose-node.js +112 -0
  101. package/node_modules/yaml/dist/compose/compose-scalar.d.ts +5 -0
  102. package/node_modules/yaml/dist/compose/compose-scalar.js +88 -0
  103. package/node_modules/yaml/dist/compose/composer.d.ts +63 -0
  104. package/node_modules/yaml/dist/compose/composer.js +224 -0
  105. package/node_modules/yaml/dist/compose/resolve-block-map.d.ts +6 -0
  106. package/node_modules/yaml/dist/compose/resolve-block-map.js +117 -0
  107. package/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts +11 -0
  108. package/node_modules/yaml/dist/compose/resolve-block-scalar.js +200 -0
  109. package/node_modules/yaml/dist/compose/resolve-block-seq.d.ts +6 -0
  110. package/node_modules/yaml/dist/compose/resolve-block-seq.js +51 -0
  111. package/node_modules/yaml/dist/compose/resolve-end.d.ts +6 -0
  112. package/node_modules/yaml/dist/compose/resolve-end.js +39 -0
  113. package/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts +7 -0
  114. package/node_modules/yaml/dist/compose/resolve-flow-collection.js +209 -0
  115. package/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts +10 -0
  116. package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +227 -0
  117. package/node_modules/yaml/dist/compose/resolve-props.d.ts +23 -0
  118. package/node_modules/yaml/dist/compose/resolve-props.js +148 -0
  119. package/node_modules/yaml/dist/compose/util-contains-newline.d.ts +2 -0
  120. package/node_modules/yaml/dist/compose/util-contains-newline.js +36 -0
  121. package/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts +2 -0
  122. package/node_modules/yaml/dist/compose/util-empty-scalar-position.js +28 -0
  123. package/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts +3 -0
  124. package/node_modules/yaml/dist/compose/util-flow-indent-check.js +17 -0
  125. package/node_modules/yaml/dist/compose/util-map-includes.d.ts +4 -0
  126. package/node_modules/yaml/dist/compose/util-map-includes.js +15 -0
  127. package/node_modules/yaml/dist/doc/Document.d.ts +141 -0
  128. package/node_modules/yaml/dist/doc/Document.js +337 -0
  129. package/node_modules/yaml/dist/doc/anchors.d.ts +24 -0
  130. package/node_modules/yaml/dist/doc/anchors.js +76 -0
  131. package/node_modules/yaml/dist/doc/applyReviver.d.ts +9 -0
  132. package/node_modules/yaml/dist/doc/applyReviver.js +57 -0
  133. package/node_modules/yaml/dist/doc/createNode.d.ts +17 -0
  134. package/node_modules/yaml/dist/doc/createNode.js +90 -0
  135. package/node_modules/yaml/dist/doc/directives.d.ts +49 -0
  136. package/node_modules/yaml/dist/doc/directives.js +178 -0
  137. package/node_modules/yaml/dist/errors.d.ts +21 -0
  138. package/node_modules/yaml/dist/errors.js +62 -0
  139. package/node_modules/yaml/dist/index.d.ts +25 -0
  140. package/node_modules/yaml/dist/index.js +50 -0
  141. package/node_modules/yaml/dist/log.d.ts +3 -0
  142. package/node_modules/yaml/dist/log.js +19 -0
  143. package/node_modules/yaml/dist/nodes/Alias.d.ts +29 -0
  144. package/node_modules/yaml/dist/nodes/Alias.js +118 -0
  145. package/node_modules/yaml/dist/nodes/Collection.d.ts +73 -0
  146. package/node_modules/yaml/dist/nodes/Collection.js +151 -0
  147. package/node_modules/yaml/dist/nodes/Node.d.ts +53 -0
  148. package/node_modules/yaml/dist/nodes/Node.js +40 -0
  149. package/node_modules/yaml/dist/nodes/Pair.d.ts +22 -0
  150. package/node_modules/yaml/dist/nodes/Pair.js +39 -0
  151. package/node_modules/yaml/dist/nodes/Scalar.d.ts +47 -0
  152. package/node_modules/yaml/dist/nodes/Scalar.js +27 -0
  153. package/node_modules/yaml/dist/nodes/YAMLMap.d.ts +53 -0
  154. package/node_modules/yaml/dist/nodes/YAMLMap.js +147 -0
  155. package/node_modules/yaml/dist/nodes/YAMLSeq.d.ts +60 -0
  156. package/node_modules/yaml/dist/nodes/YAMLSeq.js +115 -0
  157. package/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts +4 -0
  158. package/node_modules/yaml/dist/nodes/addPairToJSMap.js +65 -0
  159. package/node_modules/yaml/dist/nodes/identity.d.ts +23 -0
  160. package/node_modules/yaml/dist/nodes/identity.js +53 -0
  161. package/node_modules/yaml/dist/nodes/toJS.d.ts +29 -0
  162. package/node_modules/yaml/dist/nodes/toJS.js +39 -0
  163. package/node_modules/yaml/dist/options.d.ts +350 -0
  164. package/node_modules/yaml/dist/parse/cst-scalar.d.ts +64 -0
  165. package/node_modules/yaml/dist/parse/cst-scalar.js +218 -0
  166. package/node_modules/yaml/dist/parse/cst-stringify.d.ts +8 -0
  167. package/node_modules/yaml/dist/parse/cst-stringify.js +63 -0
  168. package/node_modules/yaml/dist/parse/cst-visit.d.ts +39 -0
  169. package/node_modules/yaml/dist/parse/cst-visit.js +99 -0
  170. package/node_modules/yaml/dist/parse/cst.d.ts +109 -0
  171. package/node_modules/yaml/dist/parse/cst.js +112 -0
  172. package/node_modules/yaml/dist/parse/lexer.d.ts +87 -0
  173. package/node_modules/yaml/dist/parse/lexer.js +723 -0
  174. package/node_modules/yaml/dist/parse/line-counter.d.ts +22 -0
  175. package/node_modules/yaml/dist/parse/line-counter.js +41 -0
  176. package/node_modules/yaml/dist/parse/parser.d.ts +84 -0
  177. package/node_modules/yaml/dist/parse/parser.js +980 -0
  178. package/node_modules/yaml/dist/public-api.d.ts +44 -0
  179. package/node_modules/yaml/dist/public-api.js +107 -0
  180. package/node_modules/yaml/dist/schema/Schema.d.ts +17 -0
  181. package/node_modules/yaml/dist/schema/Schema.js +39 -0
  182. package/node_modules/yaml/dist/schema/common/map.d.ts +2 -0
  183. package/node_modules/yaml/dist/schema/common/map.js +19 -0
  184. package/node_modules/yaml/dist/schema/common/null.d.ts +4 -0
  185. package/node_modules/yaml/dist/schema/common/null.js +17 -0
  186. package/node_modules/yaml/dist/schema/common/seq.d.ts +2 -0
  187. package/node_modules/yaml/dist/schema/common/seq.js +19 -0
  188. package/node_modules/yaml/dist/schema/common/string.d.ts +2 -0
  189. package/node_modules/yaml/dist/schema/common/string.js +16 -0
  190. package/node_modules/yaml/dist/schema/core/bool.d.ts +4 -0
  191. package/node_modules/yaml/dist/schema/core/bool.js +21 -0
  192. package/node_modules/yaml/dist/schema/core/float.d.ts +4 -0
  193. package/node_modules/yaml/dist/schema/core/float.js +47 -0
  194. package/node_modules/yaml/dist/schema/core/int.d.ts +4 -0
  195. package/node_modules/yaml/dist/schema/core/int.js +42 -0
  196. package/node_modules/yaml/dist/schema/core/schema.d.ts +1 -0
  197. package/node_modules/yaml/dist/schema/core/schema.js +25 -0
  198. package/node_modules/yaml/dist/schema/json/schema.d.ts +2 -0
  199. package/node_modules/yaml/dist/schema/json/schema.js +64 -0
  200. package/node_modules/yaml/dist/schema/json-schema.d.ts +69 -0
  201. package/node_modules/yaml/dist/schema/tags.d.ts +48 -0
  202. package/node_modules/yaml/dist/schema/tags.js +99 -0
  203. package/node_modules/yaml/dist/schema/types.d.ts +92 -0
  204. package/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts +2 -0
  205. package/node_modules/yaml/dist/schema/yaml-1.1/binary.js +70 -0
  206. package/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts +7 -0
  207. package/node_modules/yaml/dist/schema/yaml-1.1/bool.js +29 -0
  208. package/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts +4 -0
  209. package/node_modules/yaml/dist/schema/yaml-1.1/float.js +50 -0
  210. package/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts +5 -0
  211. package/node_modules/yaml/dist/schema/yaml-1.1/int.js +76 -0
  212. package/node_modules/yaml/dist/schema/yaml-1.1/merge.d.ts +9 -0
  213. package/node_modules/yaml/dist/schema/yaml-1.1/merge.js +71 -0
  214. package/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts +22 -0
  215. package/node_modules/yaml/dist/schema/yaml-1.1/omap.js +77 -0
  216. package/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts +10 -0
  217. package/node_modules/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
  218. package/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts +1 -0
  219. package/node_modules/yaml/dist/schema/yaml-1.1/schema.js +41 -0
  220. package/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts +28 -0
  221. package/node_modules/yaml/dist/schema/yaml-1.1/set.js +96 -0
  222. package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts +6 -0
  223. package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
  224. package/node_modules/yaml/dist/stringify/foldFlowLines.d.ts +34 -0
  225. package/node_modules/yaml/dist/stringify/foldFlowLines.js +151 -0
  226. package/node_modules/yaml/dist/stringify/stringify.d.ts +21 -0
  227. package/node_modules/yaml/dist/stringify/stringify.js +132 -0
  228. package/node_modules/yaml/dist/stringify/stringifyCollection.d.ts +17 -0
  229. package/node_modules/yaml/dist/stringify/stringifyCollection.js +155 -0
  230. package/node_modules/yaml/dist/stringify/stringifyComment.d.ts +10 -0
  231. package/node_modules/yaml/dist/stringify/stringifyComment.js +24 -0
  232. package/node_modules/yaml/dist/stringify/stringifyDocument.d.ts +4 -0
  233. package/node_modules/yaml/dist/stringify/stringifyDocument.js +87 -0
  234. package/node_modules/yaml/dist/stringify/stringifyNumber.d.ts +2 -0
  235. package/node_modules/yaml/dist/stringify/stringifyNumber.js +27 -0
  236. package/node_modules/yaml/dist/stringify/stringifyPair.d.ts +3 -0
  237. package/node_modules/yaml/dist/stringify/stringifyPair.js +152 -0
  238. package/node_modules/yaml/dist/stringify/stringifyString.d.ts +9 -0
  239. package/node_modules/yaml/dist/stringify/stringifyString.js +338 -0
  240. package/node_modules/yaml/dist/test-events.d.ts +4 -0
  241. package/node_modules/yaml/dist/test-events.js +134 -0
  242. package/node_modules/yaml/dist/util.d.ts +16 -0
  243. package/node_modules/yaml/dist/util.js +28 -0
  244. package/node_modules/yaml/dist/visit.d.ts +102 -0
  245. package/node_modules/yaml/dist/visit.js +236 -0
  246. package/node_modules/yaml/package.json +97 -0
  247. package/node_modules/yaml/util.js +2 -0
  248. package/package.json +27 -11
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Superpowers Manager
2
2
 
3
- Install [`obra/superpowers`](https://github.com/obra/superpowers) directly from upstream for Codex, the Pi coding agent, OpenCode, and Claude Code. Stay on a known-good release or commit, try a branch, and upgrade when you choose—without waiting for a marketplace copy to catch up.
3
+ Install [`obra/superpowers`](https://github.com/obra/superpowers) directly from upstream for Codex, the Pi coding agent, OpenCode, Claude Code, and Hermes Agent. Stay on a known-good release or commit, try a branch, and upgrade when you choose—without waiting for a marketplace copy to catch up.
4
4
 
5
5
  > Unofficial community integration. Not affiliated with the `obra/superpowers` maintainers.
6
6
 
@@ -21,7 +21,7 @@ npx superpowers-manager pin v6.1.1
21
21
  npx superpowers-manager install --harness codex
22
22
  ```
23
23
 
24
- Use `--harness pi` for Pi, `--harness opencode` for OpenCode, or `--harness claude-code` for Claude Code. The pin is shared by all harnesses, but each installation changes only when you run its `install` or `update` command. A saved pin keeps subsequent installs and updates on that version unless you change or override the selection.
24
+ Use `--harness pi` for Pi, `--harness opencode` for OpenCode, `--harness claude-code` for Claude Code, or `--harness hermes` for Hermes Agent. The pin is shared by all harnesses, but each installation changes only when you run its `install` or `update` command. A saved pin keeps subsequent installs and updates on that version unless you change or override the selection.
25
25
 
26
26
  To try a branch, replace `feature/foo` with an existing upstream branch:
27
27
 
@@ -42,7 +42,7 @@ See [version selection](https://github.com/j7an/superpowers-manager/blob/main/do
42
42
 
43
43
  ## Start with your agent
44
44
 
45
- The four harnesses share upstream selection, while each has independent prepared and installed state. Omitting `--harness` selects Codex.
45
+ The five harnesses share upstream selection, while each has independent prepared and installed state. Omitting `--harness` selects Codex.
46
46
 
47
47
  ### Codex
48
48
 
@@ -97,6 +97,18 @@ Restart Claude Code or run `/reload-plugins` after an install, activating update
97
97
  or removal. See the [Claude Code reference](https://github.com/j7an/superpowers-manager/blob/main/docs/claude-code.md)
98
98
  for conflicts, hooks, and recovery.
99
99
 
100
+ ### Hermes Agent
101
+
102
+ ```sh
103
+ npx superpowers-manager install --harness hermes
104
+ npx superpowers-manager probe --harness hermes
105
+ npx superpowers-manager update --harness hermes
106
+ ```
107
+
108
+ Restart Hermes sessions after an install, activating update, or removal. See
109
+ the [Hermes Agent reference](https://github.com/j7an/superpowers-manager/blob/main/docs/hermes.md)
110
+ for plugin layout, compatibility, route switching, and recovery.
111
+
100
112
  To remove a Manager-owned installation, choose one harness explicitly:
101
113
 
102
114
  ### Uninstall Codex
@@ -123,24 +135,31 @@ npx superpowers-manager uninstall --harness opencode
123
135
  npx superpowers-manager uninstall --harness claude-code
124
136
  ```
125
137
 
138
+ ### Uninstall Hermes Agent
139
+
140
+ ```sh
141
+ npx superpowers-manager uninstall --harness hermes
142
+ ```
143
+
126
144
  The manager never removes another Superpowers provider. See the [ownership guidance](https://github.com/j7an/superpowers-manager/blob/main/docs/usage.md#provider-ownership) before switching providers.
127
145
 
128
146
  ## Shared selection and lifecycle
129
147
 
130
- The [selection commands above](#choose-what-you-run) save shared upstream intent. They do not activate Codex, Pi, OpenCode, or Claude Code; run the selected harness's `install` or `update` to apply that choice. `unpin` restores the packaged fallback policy.
148
+ The [selection commands above](#choose-what-you-run) save shared upstream intent. They do not activate Codex, Pi, OpenCode, Claude Code, or Hermes Agent; run the selected harness's `install` or `update` to apply that choice. `unpin` restores the packaged fallback policy.
131
149
 
132
150
  See [targeted lifecycle commands](https://github.com/j7an/superpowers-manager/blob/main/docs/usage.md#targeted-lifecycle) for preparation, inspection, installation, updates, and removal.
133
151
 
134
- Use `--harness codex`, `--harness pi`, `--harness opencode`, or `--harness claude-code` with each targeted lifecycle command.
152
+ Use `--harness codex`, `--harness pi`, `--harness opencode`, `--harness claude-code`, or `--harness hermes` with each targeted lifecycle command.
135
153
 
136
154
  ```text
137
155
  shared selection -> prepare / inspect / activate Codex
138
156
  -> prepare / inspect / activate Pi
139
157
  -> prepare / inspect / activate OpenCode
140
158
  -> prepare / inspect / activate Claude Code
159
+ -> prepare / inspect / activate Hermes Agent
141
160
  ```
142
161
 
143
- The [usage reference](https://github.com/j7an/superpowers-manager/blob/main/docs/usage.md) covers version selection, precedence, offline behavior, `prepare`, validators, and every lifecycle command. The harness references cover [Codex registration and hooks](https://github.com/j7an/superpowers-manager/blob/main/docs/codex.md), [Pi snapshots and recovery](https://github.com/j7an/superpowers-manager/blob/main/docs/pi.md), [OpenCode snapshots](https://github.com/j7an/superpowers-manager/blob/main/docs/opencode.md), and [Claude Code marketplace registration](https://github.com/j7an/superpowers-manager/blob/main/docs/claude-code.md).
162
+ The [usage reference](https://github.com/j7an/superpowers-manager/blob/main/docs/usage.md) covers version selection, precedence, offline behavior, `prepare`, validators, and every lifecycle command. The harness references cover [Codex registration and hooks](https://github.com/j7an/superpowers-manager/blob/main/docs/codex.md), [Pi snapshots and recovery](https://github.com/j7an/superpowers-manager/blob/main/docs/pi.md), [OpenCode snapshots](https://github.com/j7an/superpowers-manager/blob/main/docs/opencode.md), [Claude Code marketplace registration](https://github.com/j7an/superpowers-manager/blob/main/docs/claude-code.md), and [Hermes Agent plugin support](https://github.com/j7an/superpowers-manager/blob/main/docs/hermes.md).
144
163
 
145
164
  ## Requirements and platforms
146
165
 
@@ -148,16 +167,16 @@ The installed package requires Node >=24. Native source, tests, and packaging to
148
167
 
149
168
  <!-- requirements:begin -->
150
169
 
151
- | Command | git | Codex CLI (default) | Pi CLI (`--harness pi`) | OpenCode CLI (`--harness opencode`) | Claude Code CLI (`--harness claude-code`) |
152
- | -------------- | --- | ------------------- | ----------------------- | ----------------------------------- | ----------------------------------------- |
153
- | `pin` | yes | no | no | no | no |
154
- | `track-latest` | no | no | no | no | no |
155
- | `unpin` | no | no | no | no | no |
156
- | `prepare` | yes | no | no | no | no |
157
- | `probe` | yes | yes | no | no | yes |
158
- | `install` | yes | yes | yes | yes | yes |
159
- | `update` | yes | yes | yes | yes | yes |
160
- | `uninstall` | no | yes | yes | no | yes |
170
+ | Command | git | Codex CLI (default) | Pi CLI (`--harness pi`) | OpenCode CLI (`--harness opencode`) | Claude Code CLI (`--harness claude-code`) | Hermes Agent CLI (`--harness hermes`) |
171
+ | -------------- | --- | ------------------- | ----------------------- | ----------------------------------- | ----------------------------------------- | ------------------------------------- |
172
+ | `pin` | yes | no | no | no | no | no |
173
+ | `track-latest` | no | no | no | no | no | no |
174
+ | `unpin` | no | no | no | no | no | no |
175
+ | `prepare` | yes | no | no | no | no | no |
176
+ | `probe` | yes | yes | no | no | yes | no |
177
+ | `install` | yes | yes | yes | yes | yes | yes |
178
+ | `update` | yes | yes | yes | yes | yes | yes |
179
+ | `uninstall` | no | yes | yes | no | yes | yes |
161
180
 
162
181
  <!-- requirements:end -->
163
182
 
@@ -23,7 +23,8 @@ export function extractHarnessOptions(command, argv) {
23
23
  if (value !== "codex" &&
24
24
  value !== "pi" &&
25
25
  value !== "opencode" &&
26
- value !== "claude-code")
26
+ value !== "claude-code" &&
27
+ value !== "hermes")
27
28
  throw new UsageError(`unknown harness: ${value}`);
28
29
  harness = value;
29
30
  }
package/dist/cli.js CHANGED
@@ -4,6 +4,7 @@ import * as path from "node:path";
4
4
  import { extractHarnessOptions, oneLine, UsageError } from "./cli-arguments.js";
5
5
  import { codexHarness } from "./harnesses/codex/harness.js";
6
6
  import { claudeCodeHarness } from "./harnesses/claude-code/harness.js";
7
+ import { hermesHarness } from "./harnesses/hermes/harness.js";
7
8
  import { piHarness } from "./harnesses/pi/harness.js";
8
9
  import { openCodeHarness } from "./harnesses/opencode/harness.js";
9
10
  import { createResourceCoordinator } from "./resource-lock.js";
@@ -214,7 +215,7 @@ function usage() {
214
215
  " install --harness opencode [--allow-experimental]",
215
216
  " update --harness opencode [--allow-experimental]",
216
217
  " uninstall --harness opencode",
217
- " --harness=codex, --harness=pi, --harness=opencode, and --harness=claude-code are also accepted after the command.",
218
+ " --harness=codex, --harness=pi, --harness=opencode, --harness=claude-code, and --harness=hermes are also accepted after the command.",
218
219
  "",
219
220
  "Environment overrides (used by in-process commands): SUPERPOWERS_REF,",
220
221
  "SUPERPOWERS_UPSTREAM_URL, SUPERPOWERS_CODEX, SUPERPOWERS_CACHE_DIR,",
@@ -222,7 +223,7 @@ function usage() {
222
223
  "SUPERPOWERS_PLUGIN_ROOT, SUPERPOWERS_MANIFEST_TEMPLATE,",
223
224
  "SUPERPOWERS_VALIDATOR_EXECUTABLE,",
224
225
  "SUPERPOWERS_INSTALLED_SEARCH_ROOT, SUPERPOWERS_INSTALL_REFRESH_MODE,",
225
- "SUPERPOWERS_OPENCODE, SUPERPOWERS_CLAUDE_CODE, CLAUDE_CONFIG_DIR",
226
+ "SUPERPOWERS_OPENCODE, SUPERPOWERS_CLAUDE_CODE, CLAUDE_CONFIG_DIR, SUPERPOWERS_HERMES, HERMES_HOME",
226
227
  "",
227
228
  "SUPERPOWERS_VALIDATOR is removed; unset it and use",
228
229
  "SUPERPOWERS_VALIDATOR_EXECUTABLE with an executable validator.",
@@ -252,13 +253,15 @@ async function main() {
252
253
  console.error(usage());
253
254
  process.exit(2);
254
255
  }
255
- const status = parsed.options.harness === "claude-code"
256
- ? await dispatch(claudeCodeHarness, parsed, root)
257
- : parsed.options.harness === "opencode"
258
- ? await dispatch(openCodeHarness, parsed, root)
259
- : parsed.options.harness === "pi"
260
- ? await dispatch(piHarness, parsed, root)
261
- : await dispatch(codexHarness, parsed, root);
256
+ const status = parsed.options.harness === "hermes"
257
+ ? await dispatch(hermesHarness, parsed, root)
258
+ : parsed.options.harness === "claude-code"
259
+ ? await dispatch(claudeCodeHarness, parsed, root)
260
+ : parsed.options.harness === "opencode"
261
+ ? await dispatch(openCodeHarness, parsed, root)
262
+ : parsed.options.harness === "pi"
263
+ ? await dispatch(piHarness, parsed, root)
264
+ : await dispatch(codexHarness, parsed, root);
262
265
  process.exit(status);
263
266
  }
264
267
  async function dispatch(adapter, parsed, root) {
@@ -182,12 +182,20 @@ async function runBuild(input, env, log) {
182
182
  ? "cannot copy upstream manifest into candidate"
183
183
  : "cannot copy fallback manifest into candidate");
184
184
  }
185
- let plan;
186
185
  let sourceRoot;
187
186
  let realCandidateRoot;
188
187
  try {
189
188
  sourceRoot = await realpath(upstreamRoot);
190
189
  realCandidateRoot = await realpath(candidateRoot);
190
+ }
191
+ catch {
192
+ // Kept out of the classification catch below, which re-emits its cause:
193
+ // a raw realpath error would carry Node's wording onto stderr.
194
+ log.appendText("stderr", `cannot resolve hook roots: ${upstreamRoot}, ${candidateRoot}`);
195
+ fail("build-failed", "failed to prepare upstream Codex hooks");
196
+ }
197
+ let plan;
198
+ try {
191
199
  const manifest = await readManifest(candidateManifest);
192
200
  plan = await classifyHooks(manifest, manifestSource, sourceRoot);
193
201
  }
@@ -240,7 +240,24 @@ async function validateMaterializedDestination(destination, candidateRoot) {
240
240
  throw hookError(message);
241
241
  }
242
242
  }
243
+ // The `hook materialization failed:` site in src/harnesses/codex/adapter.ts
244
+ // re-emits this module's messages, so a raw cp/copyFile/mkdir/readlink/symlink
245
+ // error must not escape: its message carries Node's own wording. Only an
246
+ // errno-shaped code is interpolated, matching
247
+ // `src/harnesses/codex/adapter.ts::const detail =`.
243
248
  export async function materializeHooks(plan, sourceRoot, candidateRoot) {
249
+ try {
250
+ await copyHookFiles(plan, sourceRoot, candidateRoot);
251
+ }
252
+ catch (cause) {
253
+ if (cause instanceof SafetyError && cause.module === "hooks")
254
+ throw cause;
255
+ const code = cause?.code ?? "";
256
+ const detail = /^E[A-Z0-9]+$/.test(code) ? `: ${code}` : "";
257
+ throw hookError(`cannot copy upstream hooks from ${sourceRoot} into ${candidateRoot}${detail}`, cause);
258
+ }
259
+ }
260
+ async function copyHookFiles(plan, sourceRoot, candidateRoot) {
244
261
  if (plan.copyHooksSubtree) {
245
262
  const sourceHooks = resolve(sourceRoot, "hooks");
246
263
  const candidateHooks = resolve(candidateRoot, "hooks");
@@ -0,0 +1,36 @@
1
+ import { displayPath } from "../../validator.js";
2
+ import { installHermes, removeHermes } from "./install.js";
3
+ import { hermesPaths } from "./paths.js";
4
+ import { hermesPreparationLocation, inspectHermesPrepared, prepareHermesCandidate, readHermesPrepared, validateHermesPreparationBeforeFetch, } from "./prepare.js";
5
+ import { hermesPresentation } from "./presentation.js";
6
+ import { inspectHermesControl, inspectHermesInstalled, inspectHermesOwnership, } from "./state.js";
7
+ function requirements(command, env) {
8
+ if (command !== "install" && command !== "update" && command !== "uninstall")
9
+ return [];
10
+ const executable = env.SUPERPOWERS_HERMES || "hermes";
11
+ return [
12
+ {
13
+ name: "hermes",
14
+ executable,
15
+ lookup: "explicit-path-or-path",
16
+ missingMessage: `required command not found: ${displayPath(executable)} — install Hermes Agent or set SUPERPOWERS_HERMES`,
17
+ },
18
+ ];
19
+ }
20
+ export const hermesHarness = {
21
+ preparationLocation: hermesPreparationLocation,
22
+ mutationRoots: async (ctx) => [
23
+ hermesPaths(ctx.env ?? {}, process.cwd()).hermesHome,
24
+ ],
25
+ validatePreparationBeforeFetch: validateHermesPreparationBeforeFetch,
26
+ prepareCandidate: prepareHermesCandidate,
27
+ inspectPrepared: inspectHermesPrepared,
28
+ readPrepared: readHermesPrepared,
29
+ inspectOwnership: inspectHermesOwnership,
30
+ inspectUpdateControl: inspectHermesControl,
31
+ inspectInstalled: inspectHermesInstalled,
32
+ install: installHermes,
33
+ remove: removeHermes,
34
+ requirements,
35
+ presentation: hermesPresentation,
36
+ };
@@ -0,0 +1,235 @@
1
+ import { cp, mkdir, mkdtemp, rename, rm } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { failureResult, successResult, } from "../../adapter-result.js";
4
+ import { assertNoFollowType } from "../../safe-path.js";
5
+ import { observeSnapshot } from "../../snapshot-package.js";
6
+ import { displayPath } from "../../validator.js";
7
+ import { runHermes } from "./native.js";
8
+ import { projectPluginsEnabled, readHermesStatus } from "./observe.js";
9
+ import { assertHermesStorageSafe, hermesPaths, } from "./paths.js";
10
+ import { readHermesPackageAssessment, readHermesReceipt } from "./prepare.js";
11
+ import { leftoverHermesPublication, observeHermesOwnership, otherSuperpowersManifests, } from "./state.js";
12
+ const DEFAULTS = { run: runHermes };
13
+ // Only hand-written diagnostics and bounded native exit statuses enter this type.
14
+ class HermesStep extends Error {
15
+ }
16
+ async function native(run, args, ctx) {
17
+ const result = await run(args, ctx);
18
+ if (!result.outcome.ok || result.status !== 0) {
19
+ const reported = result.outcome.ok
20
+ ? undefined
21
+ : /^Hermes command exited with status ([0-9]{1,3})$/.exec(result.outcome.error.message)?.[1];
22
+ const status = reported !== undefined && Number(reported) <= 255
23
+ ? ` (exit status ${reported})`
24
+ : "";
25
+ throw new HermesStep(`hermes ${args.join(" ")} did not complete${status}`);
26
+ }
27
+ }
28
+ async function checkPublicationState(paths) {
29
+ const leftovers = await leftoverHermesPublication(paths);
30
+ if (leftovers.length > 0)
31
+ throw new HermesStep(`Hermes recovery required; inspect leftover publication material at ${displayPath(leftovers[0])}`);
32
+ const conflicts = await otherSuperpowersManifests(paths);
33
+ if (conflicts.length > 0)
34
+ throw new HermesStep(`Hermes discovers another plugin named superpowers at ${displayPath(conflicts[0])}`);
35
+ }
36
+ async function requireSnapshot(root, digest) {
37
+ const snapshot = await observeSnapshot(root, readHermesReceipt);
38
+ if (snapshot.kind !== "owned" || snapshot.digest !== digest)
39
+ throw new HermesStep("the Hermes snapshot changed during publication");
40
+ }
41
+ async function verifyRemoved(paths, ctx) {
42
+ if ((await observeHermesOwnership(paths)).kind !== "absent" ||
43
+ (await readHermesStatus(paths, ctx.env ?? {})) !== "not enabled")
44
+ throw new HermesStep("Hermes still lists Superpowers or its plugin directory is still present after removal");
45
+ }
46
+ async function rollback(publication, identity, previouslyEnabled, paths, ctx, run) {
47
+ await assertHermesStorageSafe(paths);
48
+ await assertNoFollowType(publication.container, ["directory"]);
49
+ const status = await readHermesStatus(paths, ctx.env ?? {});
50
+ if (publication.priorDigest !== undefined) {
51
+ if (publication.movedBackup) {
52
+ await requireSnapshot(publication.backup, publication.priorDigest);
53
+ if (publication.published) {
54
+ await requireSnapshot(paths.pluginRoot, identity);
55
+ await assertNoFollowType(publication.stage, ["missing"]);
56
+ await rename(paths.pluginRoot, publication.stage);
57
+ publication.published = false;
58
+ }
59
+ await assertNoFollowType(paths.pluginRoot, ["missing"]);
60
+ await rename(publication.backup, paths.pluginRoot);
61
+ publication.movedBackup = false;
62
+ }
63
+ await requireSnapshot(paths.pluginRoot, publication.priorDigest);
64
+ if (!previouslyEnabled && status === "enabled") {
65
+ if ((await otherSuperpowersManifests(paths)).length > 0)
66
+ throw new HermesStep("Hermes discovers another plugin named superpowers during rollback");
67
+ await native(run, ["plugins", "disable", "superpowers"], ctx);
68
+ if ((await readHermesStatus(paths, ctx.env ?? {})) !== "disabled")
69
+ throw new HermesStep("Hermes still enables Superpowers after rollback");
70
+ }
71
+ }
72
+ else if (publication.published) {
73
+ await requireSnapshot(paths.pluginRoot, identity);
74
+ if ((await otherSuperpowersManifests(paths)).length > 0)
75
+ throw new HermesStep("Hermes discovers another plugin named superpowers during rollback");
76
+ await native(run, ["plugins", "remove", "superpowers"], ctx);
77
+ await verifyRemoved(paths, ctx);
78
+ publication.published = false;
79
+ }
80
+ await rm(publication.container, { recursive: true, force: false });
81
+ }
82
+ async function settle(operation, message, action) {
83
+ try {
84
+ await action();
85
+ return successResult(operation, null, []);
86
+ }
87
+ catch {
88
+ return failureResult(operation, "settlement-failed", message, [], []);
89
+ }
90
+ }
91
+ export async function installHermes(artifact, ctx, deps = DEFAULTS) {
92
+ const operation = "install-hermes";
93
+ const paths = hermesPaths(ctx.env ?? {}, process.cwd());
94
+ let publication;
95
+ let previouslyEnabled = false;
96
+ try {
97
+ const ownership = await observeHermesOwnership(paths);
98
+ if (ownership.kind === "foreign")
99
+ throw new HermesStep("refusing to replace a foreign Hermes plugin directory; remove it manually");
100
+ await checkPublicationState(paths);
101
+ if (projectPluginsEnabled(ctx.env ?? {}))
102
+ throw new HermesStep("HERMES_ENABLE_PROJECT_PLUGINS is set; unset it before installing Superpowers");
103
+ if (artifact.root !== paths.preparedRoot)
104
+ throw new HermesStep("unexpected Hermes prepared root");
105
+ const assessment = await readHermesPackageAssessment(artifact.root);
106
+ if (assessment.receipt.digest !== artifact.identity ||
107
+ assessment.receipt.commit !== artifact.commit ||
108
+ assessment.compatibility.kind !== "supported")
109
+ throw new HermesStep("the Hermes prepared artifact changed before activation");
110
+ previouslyEnabled =
111
+ (await readHermesStatus(paths, ctx.env ?? {})) === "enabled";
112
+ await mkdir(paths.pluginsRoot, { recursive: true });
113
+ await assertHermesStorageSafe(paths);
114
+ const container = await mkdtemp(join(paths.managerRoot, "publish."));
115
+ const pending = {
116
+ container,
117
+ stage: join(container, "stage"),
118
+ backup: join(container, "backup"),
119
+ priorDigest: ownership.kind === "owned" ? ownership.digest : undefined,
120
+ movedBackup: false,
121
+ published: false,
122
+ };
123
+ publication = pending;
124
+ await cp(artifact.root, pending.stage, {
125
+ recursive: true,
126
+ verbatimSymlinks: true,
127
+ force: false,
128
+ errorOnExist: true,
129
+ });
130
+ const staged = await readHermesPackageAssessment(pending.stage);
131
+ if (staged.receipt.digest !== artifact.identity ||
132
+ staged.receipt.commit !== artifact.commit ||
133
+ staged.compatibility.kind !== "supported")
134
+ throw new HermesStep("the staged Hermes artifact changed");
135
+ // Keep backups outside plugins so Hermes discovery sees only the live copy.
136
+ if (ownership.kind === "owned") {
137
+ await requireSnapshot(paths.pluginRoot, ownership.digest);
138
+ await rename(paths.pluginRoot, pending.backup);
139
+ pending.movedBackup = true;
140
+ }
141
+ else
142
+ await assertNoFollowType(paths.pluginRoot, ["missing"]);
143
+ await rename(pending.stage, paths.pluginRoot);
144
+ pending.published = true;
145
+ if (!previouslyEnabled)
146
+ await native(deps.run, ["plugins", "enable", "superpowers"], ctx);
147
+ let settled = false;
148
+ return successResult(operation, {
149
+ missingVerificationOutput: {
150
+ stdout: [],
151
+ stderr: [
152
+ "error: the Manager Hermes plugin is absent after activation",
153
+ ],
154
+ },
155
+ mismatchVerificationOutput: {
156
+ stdout: [],
157
+ stderr: [
158
+ "error: the installed Hermes plugin does not match the prepared artifact; run `hermes plugins list` to inspect load errors",
159
+ ],
160
+ },
161
+ transaction: {
162
+ finalize: () => settle(operation, `Hermes activation succeeded but backup cleanup failed at ${displayPath(container)}`, async () => {
163
+ if (settled)
164
+ return;
165
+ await assertHermesStorageSafe(paths);
166
+ await assertNoFollowType(container, ["directory"]);
167
+ await requireSnapshot(paths.pluginRoot, artifact.identity);
168
+ if (pending.movedBackup)
169
+ await requireSnapshot(pending.backup, pending.priorDigest);
170
+ await rm(container, { recursive: true, force: false });
171
+ settled = true;
172
+ }),
173
+ rollback: () => settle(operation, `Hermes rollback did not complete; the previous state may not be restored — inspect ${displayPath(container)}`, async () => {
174
+ if (settled)
175
+ return;
176
+ await rollback(pending, artifact.identity, previouslyEnabled, paths, ctx, deps.run);
177
+ settled = true;
178
+ }),
179
+ },
180
+ }, []);
181
+ }
182
+ catch (cause) {
183
+ const message = cause instanceof HermesStep
184
+ ? cause.message
185
+ : "cannot activate the Manager-owned Hermes installation";
186
+ let restored = true;
187
+ if (publication !== undefined) {
188
+ try {
189
+ if (publication.movedBackup || publication.published)
190
+ await rollback(publication, artifact.identity, previouslyEnabled, paths, ctx, deps.run);
191
+ else {
192
+ await assertNoFollowType(publication.container, ["directory"]);
193
+ await rm(publication.container, { recursive: true, force: false });
194
+ }
195
+ }
196
+ catch {
197
+ restored = false;
198
+ }
199
+ }
200
+ return failureResult(operation, "install-failed", restored
201
+ ? message
202
+ : `${message}; the previous Hermes state may not be restored — inspect ${displayPath(publication.container)}`, [], []);
203
+ }
204
+ }
205
+ export async function removeHermes(input, ctx, deps = DEFAULTS) {
206
+ const operation = "remove-hermes";
207
+ const paths = hermesPaths(ctx.env ?? {}, process.cwd());
208
+ try {
209
+ const ownership = await observeHermesOwnership(paths);
210
+ if (input.ownership === "foreign" || ownership.kind === "foreign")
211
+ throw new HermesStep("refusing to remove a foreign Hermes plugin directory; remove it manually");
212
+ await checkPublicationState(paths);
213
+ const listed = (await readHermesStatus(paths, ctx.env ?? {})) !== "not enabled";
214
+ if (input.ownership !== ownership.kind || input.listed !== listed)
215
+ return failureResult(operation, "stale-ownership", "Hermes plugin state changed before removal; inspect it and retry", [], []);
216
+ if (ownership.kind === "absent") {
217
+ if (listed)
218
+ throw new HermesStep("refusing to remove an unverified Hermes activation entry without an owned plugin directory");
219
+ return successResult(operation, null, []);
220
+ }
221
+ await native(deps.run, ["plugins", "remove", "superpowers"], ctx);
222
+ try {
223
+ await verifyRemoved(paths, ctx);
224
+ }
225
+ catch {
226
+ return failureResult(operation, "removal-unverified", "Hermes still lists Superpowers or its plugin directory is still present after removal", [], []);
227
+ }
228
+ return successResult(operation, null, []);
229
+ }
230
+ catch (cause) {
231
+ return failureResult(operation, "remove-failed", cause instanceof HermesStep
232
+ ? cause.message
233
+ : "cannot remove the Manager-owned Hermes plugin", [], []);
234
+ }
235
+ }
@@ -0,0 +1,40 @@
1
+ import { basename, dirname } from "node:path";
2
+ import { failureResult, } from "../../adapter-result.js";
3
+ import { runIsolatedNative, } from "../../harness-command-result.js";
4
+ import { BOUNDED_EXECUTABLE, runValidator } from "../../validator.js";
5
+ import { hermesPaths } from "./paths.js";
6
+ export async function runHermes(args, ctx, execute = runValidator) {
7
+ const invalidHome = () => failureResult("hermes-command", "invalid-home", "cannot resolve HERMES_HOME for Hermes command", [], []);
8
+ let home;
9
+ try {
10
+ home = hermesPaths(ctx.env ?? {}, process.cwd()).hermesHome;
11
+ }
12
+ catch {
13
+ return invalidHome();
14
+ }
15
+ let homeChanged = false;
16
+ const result = await runIsolatedNative("Hermes", (ctx.env ?? {}).SUPERPOWERS_HERMES || "hermes", ctx, async (executable, workspace, env, invocationCwd) => {
17
+ const childEnv = {
18
+ ...process.env,
19
+ ...env,
20
+ HERMES_HOME: home,
21
+ TMPDIR: workspace,
22
+ };
23
+ try {
24
+ if (hermesPaths(childEnv, invocationCwd).hermesHome !== home)
25
+ throw new Error("cannot resolve HERMES_HOME: child home changed");
26
+ }
27
+ catch {
28
+ homeChanged = true;
29
+ throw new Error("cannot resolve HERMES_HOME for Hermes command");
30
+ }
31
+ return await execute([
32
+ executable,
33
+ ...(basename(dirname(home)) === "profiles"
34
+ ? []
35
+ : ["--profile", "default"]),
36
+ ...args,
37
+ ], BOUNDED_EXECUTABLE, childEnv, workspace, invocationCwd);
38
+ });
39
+ return homeChanged ? invalidHome() : result;
40
+ }