magus-cli 0.0.0-placeholder → 7.0.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/README.md +309 -0
  2. package/bin/magus.js +170 -0
  3. package/package.json +67 -3
  4. package/scripts/build-binaries.ts +113 -0
  5. package/scripts/capture-builtin.ts +412 -0
  6. package/scripts/check-optional-deps.ts +49 -0
  7. package/scripts/test-isolated.ts +49 -0
  8. package/scripts/verify-binary.ts +95 -0
  9. package/scripts/verify-community-registry.ts +272 -0
  10. package/src/__tests__/active-closure.test.ts +184 -0
  11. package/src/__tests__/alias-adopt.test.ts +365 -0
  12. package/src/__tests__/alias-parser.test.ts +417 -0
  13. package/src/__tests__/alias-shell-writer.test.ts +681 -0
  14. package/src/__tests__/alias-store.test.ts +163 -0
  15. package/src/__tests__/binary-signing.test.ts +120 -0
  16. package/src/__tests__/blackbox-active-closure.test.ts +119 -0
  17. package/src/__tests__/blackbox-convergence.test.ts +334 -0
  18. package/src/__tests__/blackbox-parity.test.ts +684 -0
  19. package/src/__tests__/blackbox-plugin-state.test.ts +523 -0
  20. package/src/__tests__/blackbox-tool-state.test.ts +669 -0
  21. package/src/__tests__/cache-provenance.test.ts +84 -0
  22. package/src/__tests__/capture-builtin.test.ts +92 -0
  23. package/src/__tests__/catalog-cache-store.test.ts +309 -0
  24. package/src/__tests__/catalog-notice.test.ts +155 -0
  25. package/src/__tests__/cli-ansi.test.ts +297 -0
  26. package/src/__tests__/cli-apply-seams.test.ts +288 -0
  27. package/src/__tests__/cli-live.test.ts +391 -0
  28. package/src/__tests__/cli-router.test.ts +240 -0
  29. package/src/__tests__/cli-tool-commands.test.ts +239 -0
  30. package/src/__tests__/cli-tools-adapter.test.ts +294 -0
  31. package/src/__tests__/cli-update-view.test.ts +445 -0
  32. package/src/__tests__/community-fetch.test.ts +545 -0
  33. package/src/__tests__/community-registry.test.ts +269 -0
  34. package/src/__tests__/community-staleness.test.ts +720 -0
  35. package/src/__tests__/component-badge.test.ts +98 -0
  36. package/src/__tests__/component-icons.test.ts +94 -0
  37. package/src/__tests__/content-drift.test.ts +353 -0
  38. package/src/__tests__/conventions-integration.test.ts +830 -0
  39. package/src/__tests__/conventions-manager.test.ts +1236 -0
  40. package/src/__tests__/doctor-bins.test.ts +43 -0
  41. package/src/__tests__/doctor.test.ts +463 -0
  42. package/src/__tests__/dotenv.test.ts +195 -0
  43. package/src/__tests__/enabled-not-installed.test.ts +94 -0
  44. package/src/__tests__/file-locking.test.ts +208 -0
  45. package/src/__tests__/fixtures/tool-probe/brew-list-versions-tmux.txt +2 -0
  46. package/src/__tests__/fixtures/tool-probe/brew-outdated-behind-homebrew-spec.txt +29 -0
  47. package/src/__tests__/fixtures/tool-probe/brew-outdated-tmux-current.txt +7 -0
  48. package/src/__tests__/fixtures/tool-probe/brew-outdated-unknown-formula.txt +6 -0
  49. package/src/__tests__/fixtures/tool-probe/go-version-m-tmux-mcp.txt +27 -0
  50. package/src/__tests__/fixtures/tool-probe/npm-dist-tags-missing-scoped.txt +4 -0
  51. package/src/__tests__/fixtures/tool-probe/npm-dist-tags-openai-codex.txt +4 -0
  52. package/src/__tests__/fixtures/tool-probe/pypi-cowsay.txt +3 -0
  53. package/src/__tests__/fixtures/tool-probe/uv-receipt-browser-use.toml +10 -0
  54. package/src/__tests__/fixtures/tool-probe/uv-receipt-cowsay-git.toml +8 -0
  55. package/src/__tests__/fixtures/tool-probe/uv-receipt-cowsay-pinned.toml +8 -0
  56. package/src/__tests__/fixtures/tool-probe/uv-receipt-graphifyy.toml +7 -0
  57. package/src/__tests__/fixtures/tool-probe/uv-receipt-mcp.toml +6 -0
  58. package/src/__tests__/fixtures/tool-probe/uv-receipt-serena-agent.toml +9 -0
  59. package/src/__tests__/fixtures/tool-probe/uv-tool-list-outdated-pinned.txt +5 -0
  60. package/src/__tests__/fixtures/tool-probe/uv-tool-list-outdated.txt +11 -0
  61. package/src/__tests__/fixtures/tool-probe/uv-tool-list.txt +22 -0
  62. package/src/__tests__/footer-hints.test.ts +40 -0
  63. package/src/__tests__/format-command.test.ts +78 -0
  64. package/src/__tests__/git-worktree.test.ts +108 -0
  65. package/src/__tests__/github-budget.test.ts +206 -0
  66. package/src/__tests__/gitignore-check.test.ts +71 -0
  67. package/src/__tests__/gitignore-detector.test.ts +176 -0
  68. package/src/__tests__/gitignore-fixer.test.ts +317 -0
  69. package/src/__tests__/gitignore-resolver.test.ts +193 -0
  70. package/src/__tests__/gitignore-service.test.ts +137 -0
  71. package/src/__tests__/go-module.test.ts +43 -0
  72. package/src/__tests__/hook-import-policy.test.ts +90 -0
  73. package/src/__tests__/hook-process.test.ts +256 -0
  74. package/src/__tests__/hook-registration.test.ts +224 -0
  75. package/src/__tests__/install-command.test.ts +81 -0
  76. package/src/__tests__/install-plan.test.ts +104 -0
  77. package/src/__tests__/launcher-signal.test.ts +308 -0
  78. package/src/__tests__/local-marketplace-scan.test.ts +174 -0
  79. package/src/__tests__/manifest.test.ts +281 -0
  80. package/src/__tests__/markdown-renderer.test.ts +142 -0
  81. package/src/__tests__/marketplace-badge.test.ts +140 -0
  82. package/src/__tests__/marketplace-refresh.test.ts +335 -0
  83. package/src/__tests__/marketplace-version.test.ts +84 -0
  84. package/src/__tests__/marketplaces.test.ts +128 -0
  85. package/src/__tests__/mate-availability.test.ts +156 -0
  86. package/src/__tests__/mate-catalog.test.ts +295 -0
  87. package/src/__tests__/mcp-registry.test.ts +158 -0
  88. package/src/__tests__/model-visuals.test.tsx +2466 -0
  89. package/src/__tests__/models-adapter.test.ts +332 -0
  90. package/src/__tests__/models-cli.test.ts +273 -0
  91. package/src/__tests__/models-core.test.ts +802 -0
  92. package/src/__tests__/models-manager.test.ts +500 -0
  93. package/src/__tests__/models-presets-marketplace.test.ts +168 -0
  94. package/src/__tests__/models-screen-state.test.ts +315 -0
  95. package/src/__tests__/moved-marketplace.test.ts +86 -0
  96. package/src/__tests__/open-file.test.ts +59 -0
  97. package/src/__tests__/owned-marketplaces.test.ts +93 -0
  98. package/src/__tests__/plugin-checkout.test.ts +66 -0
  99. package/src/__tests__/plugin-cli-argv.test.ts +109 -0
  100. package/src/__tests__/plugin-contents.test.ts +371 -0
  101. package/src/__tests__/plugin-manager-fallback.test.ts +320 -0
  102. package/src/__tests__/plugin-releases.test.ts +98 -0
  103. package/src/__tests__/plugin-requires.test.ts +187 -0
  104. package/src/__tests__/plugin-row-text.test.ts +336 -0
  105. package/src/__tests__/plugin-setup.test.ts +1016 -0
  106. package/src/__tests__/profile-adopt.test.ts +177 -0
  107. package/src/__tests__/profile-command.test.ts +110 -0
  108. package/src/__tests__/profile-materializer.test.ts +238 -0
  109. package/src/__tests__/profile-sync.test.ts +154 -0
  110. package/src/__tests__/registry-version-resolution.test.ts +88 -0
  111. package/src/__tests__/resolve-executable.test.ts +42 -0
  112. package/src/__tests__/resolver.test.ts +351 -0
  113. package/src/__tests__/scope-action.test.ts +134 -0
  114. package/src/__tests__/scope-squares.test.tsx +164 -0
  115. package/src/__tests__/selection-scope.test.ts +100 -0
  116. package/src/__tests__/settings-file.test.ts +179 -0
  117. package/src/__tests__/shell-script-callers.test.ts +92 -0
  118. package/src/__tests__/skill-install-files.test.ts +136 -0
  119. package/src/__tests__/skills-catalog-client.test.ts +48 -0
  120. package/src/__tests__/style-wrap.test.ts +220 -0
  121. package/src/__tests__/styles-manager.test.ts +1098 -0
  122. package/src/__tests__/styles-origins.test.ts +414 -0
  123. package/src/__tests__/styles-screen-state.test.ts +457 -0
  124. package/src/__tests__/styles-status-line.test.ts +72 -0
  125. package/src/__tests__/styles-sync.test.ts +452 -0
  126. package/src/__tests__/symlink-manager.test.ts +180 -0
  127. package/src/__tests__/tabbar-layout.test.ts +100 -0
  128. package/src/__tests__/terminology-filler.test.ts +214 -0
  129. package/src/__tests__/theme-adaptive-colors.test.ts +354 -0
  130. package/src/__tests__/theme-env.test.ts +281 -0
  131. package/src/__tests__/theme-resolve.test.ts +380 -0
  132. package/src/__tests__/tool-probe.test.ts +1400 -0
  133. package/src/__tests__/toolchain.test.ts +232 -0
  134. package/src/__tests__/ui-version-writers.test.ts +88 -0
  135. package/src/__tests__/update-apply.test.ts +637 -0
  136. package/src/__tests__/update-plan.test.ts +1373 -0
  137. package/src/__tests__/uppercase-keybindings.test.ts +101 -0
  138. package/src/__tests__/useGitignoreModal.test.ts +79 -0
  139. package/src/__tests__/version-check-refresh.test.ts +45 -0
  140. package/src/__tests__/version-snapshot.test.ts +212 -0
  141. package/src/__tests__/version-unknown-state.test.ts +388 -0
  142. package/src/__tests__/worktree-registry-resolution.test.ts +107 -0
  143. package/src/cli/ansi.ts +520 -0
  144. package/src/cli/bootstrap.ts +134 -0
  145. package/src/cli/doctor.ts +218 -0
  146. package/src/cli/hook.ts +129 -0
  147. package/src/cli/install.ts +382 -0
  148. package/src/cli/live.ts +374 -0
  149. package/src/cli/models.ts +297 -0
  150. package/src/cli/profile.ts +197 -0
  151. package/src/cli/prompt.ts +32 -0
  152. package/src/cli/router.ts +207 -0
  153. package/src/cli/update-view.ts +526 -0
  154. package/src/cli/update.ts +613 -0
  155. package/src/cli/upgrade.ts +97 -0
  156. package/src/data/alias-flags.ts +301 -0
  157. package/src/data/cli-tools.ts +146 -0
  158. package/src/data/community-styles.ts +531 -0
  159. package/src/data/gitignore-defaults.ts +33 -0
  160. package/src/data/gitignore-reasons.ts +93 -0
  161. package/src/data/gitignore-templates.ts +25 -0
  162. package/src/data/marketplaces.ts +278 -0
  163. package/src/data/mcp-servers.ts +51 -0
  164. package/src/data/models-presets.ts +329 -0
  165. package/src/data/predefined-profiles.ts +252 -0
  166. package/src/data/settings-catalog.ts +714 -0
  167. package/src/data/skill-repos.ts +91 -0
  168. package/src/data/styles/asd-ste100.md +38 -0
  169. package/src/data/styles/calibrated.md +24 -0
  170. package/src/data/styles/direct.md +23 -0
  171. package/src/data/styles/evidence-first.md +22 -0
  172. package/src/data/styles/explanatory.md +23 -0
  173. package/src/data/styles/index.ts +57 -0
  174. package/src/data/styles/no-slop.md +32 -0
  175. package/src/data/styles/plain-language.md +23 -0
  176. package/src/data/styles/structured.md +30 -0
  177. package/src/data/styles/terminology.md +28 -0
  178. package/src/data/styles/terse.md +20 -0
  179. package/src/main.tsx +110 -0
  180. package/src/markdown.d.ts +13 -0
  181. package/src/opentui.d.ts +203 -0
  182. package/src/services/active-closure.ts +117 -0
  183. package/src/services/alias-settings.ts +60 -0
  184. package/src/services/alias-shell-writer.ts +1244 -0
  185. package/src/services/alias-store.ts +172 -0
  186. package/src/services/binary-signing.ts +78 -0
  187. package/src/services/catalog-cache-store.ts +316 -0
  188. package/src/services/claude-cli.ts +304 -0
  189. package/src/services/claude-runner.ts +31 -0
  190. package/src/services/claude-settings.ts +1589 -0
  191. package/src/services/cli-tool-commands.ts +133 -0
  192. package/src/services/community-fetcher.ts +90 -0
  193. package/src/services/community-styles.ts +1194 -0
  194. package/src/services/content-drift.ts +208 -0
  195. package/src/services/conventions-manager.ts +945 -0
  196. package/src/services/doctor-bins.ts +63 -0
  197. package/src/services/doctor.ts +570 -0
  198. package/src/services/dotenv.ts +181 -0
  199. package/src/services/git-worktree.ts +129 -0
  200. package/src/services/github-budget.ts +274 -0
  201. package/src/services/gitignore-check.ts +63 -0
  202. package/src/services/gitignore-detector.ts +167 -0
  203. package/src/services/gitignore-fixer.ts +280 -0
  204. package/src/services/gitignore-resolver.ts +208 -0
  205. package/src/services/gitignore-service.ts +167 -0
  206. package/src/services/hook-registration.ts +218 -0
  207. package/src/services/install-plan.ts +107 -0
  208. package/src/services/local-marketplace.ts +587 -0
  209. package/src/services/manifest.ts +250 -0
  210. package/src/services/marketplace-catalog-git.ts +173 -0
  211. package/src/services/marketplace-catalog.ts +129 -0
  212. package/src/services/marketplace-fetcher.ts +400 -0
  213. package/src/services/marketplace-refresh.ts +253 -0
  214. package/src/services/marketplace-sync.ts +145 -0
  215. package/src/services/mate-availability.ts +133 -0
  216. package/src/services/mate-catalog.ts +265 -0
  217. package/src/services/mcp-registry.ts +171 -0
  218. package/src/services/models-core.ts +969 -0
  219. package/src/services/models-manager.ts +606 -0
  220. package/src/services/plugin-checkout.ts +186 -0
  221. package/src/services/plugin-manager.ts +878 -0
  222. package/src/services/plugin-mcp-config.ts +242 -0
  223. package/src/services/plugin-releases.ts +47 -0
  224. package/src/services/plugin-requires.ts +227 -0
  225. package/src/services/plugin-setup.ts +965 -0
  226. package/src/services/profile-adopt.ts +206 -0
  227. package/src/services/profile-materializer.ts +133 -0
  228. package/src/services/profile-sync.ts +158 -0
  229. package/src/services/profiles.ts +225 -0
  230. package/src/services/resolver.ts +344 -0
  231. package/src/services/settings-file.ts +69 -0
  232. package/src/services/settings-manager.ts +307 -0
  233. package/src/services/skills-manager.ts +1111 -0
  234. package/src/services/skillsmp-client.ts +193 -0
  235. package/src/services/styles-manager.ts +1294 -0
  236. package/src/services/symlink-manager.ts +189 -0
  237. package/src/services/terminology-filler.ts +266 -0
  238. package/src/services/tool-probe.ts +1637 -0
  239. package/src/services/toolchain.ts +431 -0
  240. package/src/services/update-engine.ts +691 -0
  241. package/src/services/update-plan.ts +863 -0
  242. package/src/services/version-check.ts +127 -0
  243. package/src/services/version-snapshot.ts +189 -0
  244. package/src/tui.tsx +112 -0
  245. package/src/types/bun.d.ts +27 -0
  246. package/src/types/gitignore.ts +68 -0
  247. package/src/types/index.ts +447 -0
  248. package/src/ui/App.tsx +538 -0
  249. package/src/ui/adapters/catalogNotice.ts +122 -0
  250. package/src/ui/adapters/cliToolsAdapter.ts +176 -0
  251. package/src/ui/adapters/modelsAdapter.ts +213 -0
  252. package/src/ui/adapters/pluginsAdapter.ts +413 -0
  253. package/src/ui/adapters/settingsAdapter.ts +168 -0
  254. package/src/ui/adapters/skillsAdapter.ts +229 -0
  255. package/src/ui/adapters/stylesAdapter.ts +403 -0
  256. package/src/ui/components/CategoryHeader.tsx +64 -0
  257. package/src/ui/components/EmptyFilterState.tsx +32 -0
  258. package/src/ui/components/FlagDetailEditor.tsx +0 -0
  259. package/src/ui/components/ScopeIndicator.tsx +63 -0
  260. package/src/ui/components/ScrollableList.tsx +95 -0
  261. package/src/ui/components/SearchInput.tsx +57 -0
  262. package/src/ui/components/StyledText.tsx +75 -0
  263. package/src/ui/components/TabBar.tsx +101 -0
  264. package/src/ui/components/layout/FooterHints.tsx +78 -0
  265. package/src/ui/components/layout/Panel.tsx +63 -0
  266. package/src/ui/components/layout/ProgressBar.tsx +44 -0
  267. package/src/ui/components/layout/ScopeTabs.tsx +54 -0
  268. package/src/ui/components/layout/ScreenLayout.tsx +321 -0
  269. package/src/ui/components/layout/index.ts +9 -0
  270. package/src/ui/components/modals/ConfirmModal.tsx +62 -0
  271. package/src/ui/components/modals/InputModal.tsx +75 -0
  272. package/src/ui/components/modals/LoadingModal.tsx +51 -0
  273. package/src/ui/components/modals/MessageModal.tsx +66 -0
  274. package/src/ui/components/modals/ModalContainer.tsx +159 -0
  275. package/src/ui/components/modals/SelectModal.tsx +90 -0
  276. package/src/ui/components/modals/index.ts +6 -0
  277. package/src/ui/components/primitives/ActionHints.tsx +44 -0
  278. package/src/ui/components/primitives/DetailSection.tsx +23 -0
  279. package/src/ui/components/primitives/KeyValueLine.tsx +26 -0
  280. package/src/ui/components/primitives/ListCategoryRow.tsx +45 -0
  281. package/src/ui/components/primitives/MetaText.tsx +40 -0
  282. package/src/ui/components/primitives/ScopeDetail.tsx +67 -0
  283. package/src/ui/components/primitives/ScopeSquares.tsx +58 -0
  284. package/src/ui/components/primitives/SelectableRow.tsx +30 -0
  285. package/src/ui/components/primitives/index.ts +9 -0
  286. package/src/ui/hooks/index.ts +2 -0
  287. package/src/ui/hooks/useGitignoreModal.ts +95 -0
  288. package/src/ui/hooks/useKeyboard.ts +24 -0
  289. package/src/ui/hooks/useKeyboardHandler.ts +63 -0
  290. package/src/ui/registry.ts +33 -0
  291. package/src/ui/renderers/cliToolRenderers.tsx +326 -0
  292. package/src/ui/renderers/gitignoreRenderers.tsx +80 -0
  293. package/src/ui/renderers/markdownRenderer.tsx +302 -0
  294. package/src/ui/renderers/mcpRenderers.tsx +149 -0
  295. package/src/ui/renderers/modelRenderers.tsx +1309 -0
  296. package/src/ui/renderers/modelVisuals.tsx +1402 -0
  297. package/src/ui/renderers/pluginRenderers.tsx +1089 -0
  298. package/src/ui/renderers/pluginRowText.ts +70 -0
  299. package/src/ui/renderers/pluginStatusText.ts +56 -0
  300. package/src/ui/renderers/profileRenderers.tsx +406 -0
  301. package/src/ui/renderers/settingsRenderers.tsx +218 -0
  302. package/src/ui/renderers/skillRenderers.tsx +479 -0
  303. package/src/ui/renderers/styleRenderers.tsx +813 -0
  304. package/src/ui/screens/AliasScreen.tsx +1558 -0
  305. package/src/ui/screens/CliToolsScreen.tsx +367 -0
  306. package/src/ui/screens/EnvVarsScreen.tsx +221 -0
  307. package/src/ui/screens/GitignoreScreen.tsx +562 -0
  308. package/src/ui/screens/McpRegistryScreen.tsx +366 -0
  309. package/src/ui/screens/McpScreen.tsx +256 -0
  310. package/src/ui/screens/ModelsScreen.tsx +542 -0
  311. package/src/ui/screens/PluginsScreen.tsx +1464 -0
  312. package/src/ui/screens/ProfilesScreen.tsx +438 -0
  313. package/src/ui/screens/SkillsScreen.tsx +853 -0
  314. package/src/ui/screens/StylesScreen.tsx +1064 -0
  315. package/src/ui/screens/index.ts +11 -0
  316. package/src/ui/state/AppContext.tsx +233 -0
  317. package/src/ui/state/DimensionsContext.tsx +154 -0
  318. package/src/ui/state/reducer.ts +810 -0
  319. package/src/ui/state/types.ts +503 -0
  320. package/src/ui/theme-mode.ts +352 -0
  321. package/src/ui/theme-resolve.ts +147 -0
  322. package/src/ui/theme.ts +175 -0
  323. package/src/utils/clipboard.ts +58 -0
  324. package/src/utils/command-utils.ts +144 -0
  325. package/src/utils/config-dir.ts +45 -0
  326. package/src/utils/file-locking.ts +146 -0
  327. package/src/utils/fuzzy-search.ts +138 -0
  328. package/src/utils/go-module.ts +36 -0
  329. package/src/utils/open-file.ts +84 -0
  330. package/src/utils/run.ts +67 -0
  331. package/src/utils/string-utils.ts +88 -0
@@ -0,0 +1,97 @@
1
+ /**
2
+ * `magus upgrade` — self-update.
3
+ *
4
+ * This is what `magus update` used to do. `update` now means what it means
5
+ * in every package manager — bring THIS PROJECT's dependencies up to date —
6
+ * and advancing the tool itself moved here.
7
+ *
8
+ * Detects magus installs across bun + npm global, warns on duplicates
9
+ * (active vs shadowed), then re-installs `magus@latest` with whichever
10
+ * package manager owns the active binary. Resolves with the child's exit code.
11
+ */
12
+
13
+ import { spawn } from "node:child_process";
14
+ import { constants } from "node:os";
15
+
16
+ export async function runUpgradeCommand(): Promise<number> {
17
+ const { execSync } = await import("node:child_process");
18
+ const { existsSync } = await import("node:fs");
19
+
20
+ // Detect all installations of magus across package managers
21
+ const installations: Array<{ manager: "bun" | "npm"; path: string }> = [];
22
+
23
+ // Check bun global
24
+ try {
25
+ const bunGlobalBin = execSync("bun pm -g bin", {
26
+ encoding: "utf-8",
27
+ timeout: 5000,
28
+ }).trim();
29
+ const bunPath = `${bunGlobalBin}/magus`;
30
+ if (existsSync(bunPath))
31
+ installations.push({ manager: "bun", path: bunPath });
32
+ } catch {
33
+ // bun not installed or no global magus
34
+ }
35
+
36
+ // Check npm global
37
+ try {
38
+ const npmPrefix = execSync("npm prefix -g", {
39
+ encoding: "utf-8",
40
+ timeout: 5000,
41
+ }).trim();
42
+ const npmPath = `${npmPrefix}/bin/magus`;
43
+ if (existsSync(npmPath))
44
+ installations.push({ manager: "npm", path: npmPath });
45
+ } catch {
46
+ // npm not installed or no global magus
47
+ }
48
+
49
+ // Warn about duplicate installations
50
+ if (installations.length > 1) {
51
+ const activePath = execSync("which magus", {
52
+ encoding: "utf-8",
53
+ timeout: 5000,
54
+ }).trim();
55
+
56
+ console.log("⚠ magus is installed via multiple package managers:\n");
57
+ for (const inst of installations) {
58
+ const tag = inst.path === activePath ? " (active)" : " (shadowed)";
59
+ console.log(` ${inst.manager}: ${inst.path}${tag}`);
60
+ }
61
+ console.log("\nTo fix, keep one and remove the other:");
62
+ for (const inst of installations) {
63
+ console.log(` ${inst.manager} uninstall -g magus`);
64
+ }
65
+ console.log();
66
+ }
67
+
68
+ // Determine which package manager to use for the update
69
+ let usesBun = false;
70
+ try {
71
+ const magusPath = execSync("which magus", {
72
+ encoding: "utf-8",
73
+ }).trim();
74
+ usesBun = magusPath.includes(".bun") || magusPath.includes("bun/bin");
75
+ } catch {
76
+ // If which fails, default to npm
77
+ }
78
+
79
+ const pkgManager = usesBun ? "bun" : "npm";
80
+ console.log(`Updating magus using ${pkgManager}...`);
81
+
82
+ const installArgs = ["install", "-g", "magus@latest"];
83
+
84
+ return new Promise<number>((resolve) => {
85
+ const proc = spawn(pkgManager, installArgs, {
86
+ stdio: "inherit",
87
+ shell: false, // Avoid shell for security (fixes DEP0190 warning)
88
+ });
89
+ // `code ?? 0` is the same defect 6.8.1 removed from bin/magus.js: a
90
+ // package manager killed by a signal delivers code null, and reporting
91
+ // that upgrade as a success is the worst answer available.
92
+ proc.on("exit", (code, signal) =>
93
+ resolve(code ?? (signal ? 128 + (constants.signals[signal] ?? 0) : 1)),
94
+ );
95
+ proc.on("error", () => resolve(1));
96
+ });
97
+ }
@@ -0,0 +1,301 @@
1
+ /**
2
+ * Catalog of `claude` CLI flags that the Alias tab can compose into a managed
3
+ * shell alias. Verified against `claude --help` output and binary string scan
4
+ * of the shipped Claude Code 2.1.x binary.
5
+ *
6
+ * The catalog drives both the UI editor for each flag and the renderer that
7
+ * emits the final `alias claude='claude …'` string per shell.
8
+ */
9
+
10
+ export type FlagKind =
11
+ /** On/off. AliasFlagState: { enabled: boolean } */
12
+ | "boolean"
13
+ /** Three states: unset / on / off. Used for `--chrome` vs `--no-chrome`. */
14
+ | "tri-state"
15
+ /** Single value from a fixed list. AliasFlagState: { enabled, value }. */
16
+ | "select"
17
+ /** Free-form string. AliasFlagState: { enabled, value }. */
18
+ | "text"
19
+ /** Optional free-form string (flag works with or without a value). */
20
+ | "optional-text"
21
+ /** Repeatable list of strings. AliasFlagState: { enabled, values }. */
22
+ | "text-list"
23
+ /**
24
+ * Picklist of common tokens + free-form custom tokens, joined with commas.
25
+ * AliasFlagState: { enabled, picked: string[], custom: string[] }.
26
+ * Used for `--debug` because Claude Code's category set is dynamic.
27
+ */
28
+ | "multi-with-custom";
29
+
30
+ export interface FlagSelectOption {
31
+ label: string;
32
+ value: string;
33
+ }
34
+
35
+ export interface AliasFlag {
36
+ /** Stable identifier; used as JSON key in `~/.claude/magus-alias.json`. */
37
+ id: string;
38
+ /** Human label shown in the UI list. */
39
+ label: string;
40
+ /**
41
+ * The CLI flag as it appears on the command line. For tri-state, this is the
42
+ * "on" form (e.g. `--chrome`); the "off" form is in `triStateOff`.
43
+ */
44
+ flag: string;
45
+ /** Optional short flag (e.g. `-d` for `--debug`). Not currently rendered. */
46
+ shortFlag?: string;
47
+ kind: FlagKind;
48
+ /** One-line description shown in the detail panel. */
49
+ description: string;
50
+ /** Allowed values for `kind: "select"`. */
51
+ options?: FlagSelectOption[];
52
+ /** "Off" form for tri-state flags (e.g. `--no-chrome`). */
53
+ triStateOff?: string;
54
+ /** Picklist tokens for `kind: "multi-with-custom"`. */
55
+ picklist?: string[];
56
+ /** Default seed values for `text-list` and `multi-with-custom`. */
57
+ defaultValues?: string[];
58
+ /**
59
+ * Validation key. The renderer / UI consult this to grey out conflicting
60
+ * fields. Two flags with the same `xorGroup` are mutually exclusive.
61
+ */
62
+ xorGroup?: string;
63
+ /**
64
+ * The flag is only valid when another flag (by id) is enabled.
65
+ * UI greys out and shows "requires --xxx".
66
+ */
67
+ requires?: string;
68
+ /**
69
+ * If true, the value supports `{token}` placeholders that expand at shell
70
+ * eval time (not at write time). The renderer emits the value as a mix of
71
+ * literal segments and shell substitution segments instead of one quoted
72
+ * token. See `TEMPLATE_TOKENS` for the supported placeholder set.
73
+ */
74
+ templated?: boolean;
75
+ /** UI grouping; rendered as section headers in the list. */
76
+ group: FlagGroup;
77
+ }
78
+
79
+ /**
80
+ * Tokens supported in `templated: true` flag values. Description text is
81
+ * shown to the user; the actual shell-substitution code lives in the writer
82
+ * because it needs per-shell variants.
83
+ *
84
+ * Intentionally excludes `{hash}` for v1 — its only portable form is
85
+ * `od -An -N4 -tx1 /dev/urandom | tr -d ' \n'`, which looks frightening in a
86
+ * shell rc file. Users who want randomness can pair this prefix with bare
87
+ * `--remote-control` (which already auto-generates a unique suffix).
88
+ */
89
+ export const TEMPLATE_TOKENS: Array<{ token: string; description: string }> = [
90
+ { token: "{folder}", description: "current directory's basename" },
91
+ { token: "{day}", description: "day of month, zero-padded (01-31)" },
92
+ { token: "{month}", description: "month, zero-padded (01-12)" },
93
+ { token: "{year}", description: "4-digit year" },
94
+ ];
95
+
96
+ export type FlagGroup =
97
+ | "danger"
98
+ | "session"
99
+ | "context"
100
+ | "channels"
101
+ | "debug"
102
+ | "integration"
103
+ | "worktree";
104
+
105
+ export const FLAG_GROUPS: Array<{ id: FlagGroup; label: string }> = [
106
+ { id: "danger", label: "Permissions" },
107
+ { id: "session", label: "Session" },
108
+ { id: "context", label: "Context" },
109
+ { id: "channels", label: "Development channels" },
110
+ { id: "debug", label: "Debug" },
111
+ { id: "integration", label: "Integrations" },
112
+ { id: "worktree", label: "Worktree" },
113
+ ];
114
+
115
+ export const ALIAS_FLAGS: AliasFlag[] = [
116
+ {
117
+ id: "dangerously-skip-permissions",
118
+ label: "Skip permission checks",
119
+ flag: "--dangerously-skip-permissions",
120
+ kind: "boolean",
121
+ group: "danger",
122
+ description:
123
+ "Bypass all permission checks. Recommended only for sandboxes with no internet access.",
124
+ },
125
+ {
126
+ id: "allow-dangerously-skip-permissions",
127
+ label: "Allow skip-permissions opt-in",
128
+ flag: "--allow-dangerously-skip-permissions",
129
+ kind: "boolean",
130
+ group: "danger",
131
+ description:
132
+ "Enable the skip-permissions option without making it the default.",
133
+ },
134
+ {
135
+ id: "remote-control",
136
+ label: "Remote control",
137
+ flag: "--remote-control",
138
+ kind: "boolean",
139
+ group: "session",
140
+ description:
141
+ "Start an interactive session with Remote Control enabled. Claude Code auto-generates a unique session name; use --remote-control-session-name-prefix to customize it.",
142
+ },
143
+ {
144
+ id: "remote-control-session-name-prefix",
145
+ label: "Remote control name prefix",
146
+ flag: "--remote-control-session-name-prefix",
147
+ kind: "text",
148
+ templated: true,
149
+ group: "session",
150
+ description:
151
+ "Prefix for auto-generated Remote Control session names. Default: hostname. Supports template tokens that expand on each shell invocation: {folder} (basename of $PWD), {day}, {month}, {year}. Example: dev-{folder}-{day} → dev-myproject-15.",
152
+ },
153
+ {
154
+ id: "ide",
155
+ label: "Auto-connect to IDE",
156
+ flag: "--ide",
157
+ kind: "boolean",
158
+ group: "integration",
159
+ description:
160
+ "Automatically connect to IDE on startup if exactly one valid IDE is available.",
161
+ },
162
+ {
163
+ id: "chrome",
164
+ label: "Chrome integration",
165
+ flag: "--chrome",
166
+ triStateOff: "--no-chrome",
167
+ kind: "tri-state",
168
+ group: "integration",
169
+ description:
170
+ "Enable or disable Claude in Chrome integration. Unset leaves the project default in place.",
171
+ },
172
+ {
173
+ id: "effort",
174
+ label: "Effort level",
175
+ flag: "--effort",
176
+ kind: "select",
177
+ group: "session",
178
+ description: "Effort level for the current session.",
179
+ options: [
180
+ { label: "low", value: "low" },
181
+ { label: "medium", value: "medium" },
182
+ { label: "high", value: "high" },
183
+ { label: "xhigh", value: "xhigh" },
184
+ { label: "max", value: "max" },
185
+ ],
186
+ },
187
+ {
188
+ id: "system-prompt",
189
+ label: "System prompt",
190
+ flag: "--system-prompt",
191
+ kind: "text",
192
+ group: "context",
193
+ xorGroup: "system-prompt",
194
+ description:
195
+ "System prompt text to use for the session. Mutually exclusive with --system-prompt-file.",
196
+ },
197
+ {
198
+ id: "system-prompt-file",
199
+ label: "System prompt file",
200
+ flag: "--system-prompt-file",
201
+ kind: "text",
202
+ group: "context",
203
+ xorGroup: "system-prompt",
204
+ description:
205
+ "Path to a file whose contents replace the default system prompt. Mutually exclusive with --system-prompt.",
206
+ },
207
+ {
208
+ id: "append-system-prompt",
209
+ label: "Append system prompt",
210
+ flag: "--append-system-prompt",
211
+ kind: "text",
212
+ group: "context",
213
+ description:
214
+ "Text appended to the default system prompt. Composes with --system-prompt.",
215
+ },
216
+ {
217
+ id: "append-system-prompt-file",
218
+ label: "Append system prompt file",
219
+ flag: "--append-system-prompt-file",
220
+ kind: "text",
221
+ group: "context",
222
+ description:
223
+ "Path to a file whose contents are appended to the default system prompt.",
224
+ },
225
+ {
226
+ id: "channels",
227
+ label: "Channels (approved)",
228
+ flag: "--channels",
229
+ kind: "text-list",
230
+ group: "channels",
231
+ description:
232
+ "Approved channel plugins/MCP servers to run this session (the allowlist). Channels derived from --dangerously-load appear in a separate section here and are unioned in on write; add your own approved channels on top.",
233
+ defaultValues: [],
234
+ },
235
+ {
236
+ id: "dangerously-load-development-channels",
237
+ label: "Load development channels",
238
+ flag: "--dangerously-load-development-channels",
239
+ kind: "text-list",
240
+ group: "channels",
241
+ description:
242
+ "Sideload development channels not on the approved allowlist (local dev only). Also shown under --channels and unioned into it on write. Default seed: claudish (the only magus plugin currently shipping channels).",
243
+ defaultValues: ["plugin:claudish@magus"],
244
+ },
245
+ {
246
+ id: "debug",
247
+ label: "Debug categories",
248
+ flag: "--debug",
249
+ shortFlag: "-d",
250
+ kind: "multi-with-custom",
251
+ group: "debug",
252
+ description:
253
+ "Enable debug mode with optional category filter. Pick from common categories or add custom tokens (including negations like !file).",
254
+ picklist: [
255
+ "api",
256
+ "hooks",
257
+ "mcp",
258
+ "tools",
259
+ "plugins",
260
+ "skills",
261
+ "settings",
262
+ "permissions",
263
+ "auth",
264
+ "cache",
265
+ "statsig",
266
+ "file",
267
+ "1p",
268
+ ],
269
+ defaultValues: [],
270
+ },
271
+ {
272
+ id: "worktree",
273
+ label: "Use worktree",
274
+ flag: "--worktree",
275
+ kind: "boolean",
276
+ group: "worktree",
277
+ description:
278
+ "Create a git worktree for the session. Prerequisite for --tmux.",
279
+ },
280
+ {
281
+ id: "tmux",
282
+ label: "tmux session",
283
+ flag: "--tmux",
284
+ kind: "select",
285
+ group: "worktree",
286
+ requires: "worktree",
287
+ description:
288
+ "Create a tmux session for the worktree. Requires --worktree. iTerm2 native panes when available; classic for traditional tmux.",
289
+ options: [
290
+ { label: "auto (iTerm2 native)", value: "" },
291
+ { label: "classic", value: "classic" },
292
+ ],
293
+ },
294
+ ];
295
+
296
+ /** Look up a flag by id. Throws if missing — keeps callers honest. */
297
+ export function getFlagById(id: string): AliasFlag {
298
+ const f = ALIAS_FLAGS.find((flag) => flag.id === id);
299
+ if (!f) throw new Error(`Unknown alias flag id: ${id}`);
300
+ return f;
301
+ }
@@ -0,0 +1,146 @@
1
+ import type { BinInstaller } from "../types/index.js";
2
+
3
+ /**
4
+ * A CLI tool magus can install, check and update.
5
+ *
6
+ * There is deliberately NO `installCommand` field. Entries used to carry one
7
+ * alongside `packageManager` + `packageName`, which describe the same thing —
8
+ * so the two could disagree, and did: `aider` declared
9
+ * `packageName: "aider-chat"` while its `installCommand` installed
10
+ * `aider-install`, and the version check queried the former. The command is
11
+ * derived by `services/cli-tool-commands.ts` instead, which also means a
12
+ * catalogue entry can no longer smuggle shell syntax (that same entry's command
13
+ * was a `&&` chain) into something that gets executed.
14
+ */
15
+ export interface CliTool {
16
+ name: string;
17
+ displayName: string;
18
+ description: string;
19
+ checkCommand: string;
20
+ website: string;
21
+ category: "ai-coding" | "utility";
22
+ /**
23
+ * Reuses `BinInstaller` rather than restating its members, so the
24
+ * correspondence with the resolver in `services/toolchain.ts` — which is
25
+ * what turns this field into an actual command — is a compile-time fact.
26
+ */
27
+ packageManager: BinInstaller;
28
+ packageName: string;
29
+ }
30
+
31
+ export const cliTools: CliTool[] = [
32
+ {
33
+ name: "magus",
34
+ displayName: "magus",
35
+ description:
36
+ "TUI tool for managing Claude Code plugins, MCPs, and configuration",
37
+ checkCommand: "magus --version",
38
+ website: "https://github.com/MadAppGang/magus/tree/main/tools/magus",
39
+ category: "ai-coding",
40
+ packageManager: "bun",
41
+ packageName: "magus",
42
+ },
43
+ {
44
+ name: "mnemex",
45
+ displayName: "Mnemex",
46
+ description:
47
+ "AST-aware code search with PageRank, callers/callees, and semantic embeddings",
48
+ checkCommand: "mnemex --version",
49
+ website: "https://github.com/MadAppGang/mnemex",
50
+ category: "ai-coding",
51
+ packageManager: "bun",
52
+ packageName: "mnemex",
53
+ },
54
+ {
55
+ name: "claudish",
56
+ displayName: "Claudish",
57
+ description: "Run Claude Code with OpenRouter models (Grok, GPT-5, Gemini)",
58
+ checkCommand: "claudish --version",
59
+ website: "https://github.com/MadAppGang/claudish",
60
+ category: "ai-coding",
61
+ packageManager: "bun",
62
+ packageName: "claudish",
63
+ },
64
+ {
65
+ name: "claude",
66
+ displayName: "Claude Code",
67
+ description: "Anthropic official agentic coding tool",
68
+ checkCommand: "claude --version",
69
+ website: "https://claude.ai/code",
70
+ category: "ai-coding",
71
+ packageManager: "npm",
72
+ packageName: "@anthropic-ai/claude-code",
73
+ },
74
+ {
75
+ name: "codex",
76
+ displayName: "OpenAI Codex",
77
+ description:
78
+ "Lightweight coding agent from OpenAI that runs in your terminal",
79
+ checkCommand: "codex --version",
80
+ website: "https://github.com/openai/codex",
81
+ category: "ai-coding",
82
+ packageManager: "npm",
83
+ packageName: "@openai/codex",
84
+ },
85
+ {
86
+ name: "gemini",
87
+ displayName: "Gemini CLI",
88
+ description: "Google AI agent with 1M token context, free tier available",
89
+ checkCommand: "gemini --version",
90
+ website: "https://github.com/google-gemini/gemini-cli",
91
+ category: "ai-coding",
92
+ packageManager: "npm",
93
+ packageName: "@google/gemini-cli",
94
+ },
95
+ {
96
+ name: "qwen",
97
+ displayName: "Qwen Code",
98
+ description: "Alibaba coding agent optimized for Qwen3-Coder models",
99
+ checkCommand: "qwen --version",
100
+ website: "https://github.com/QwenLM/qwen-code",
101
+ category: "ai-coding",
102
+ packageManager: "npm",
103
+ packageName: "@qwen-code/qwen-code",
104
+ },
105
+ {
106
+ name: "cline",
107
+ displayName: "Cline",
108
+ description:
109
+ "Autonomous coding agent with plan & act, checkpoints, browser use",
110
+ checkCommand: "cline --version",
111
+ website: "https://cline.bot",
112
+ category: "ai-coding",
113
+ packageManager: "npm",
114
+ packageName: "cline",
115
+ },
116
+ {
117
+ name: "opencode",
118
+ displayName: "OpenCode",
119
+ description: "Open source AI coding agent trusted by 400k+ developers",
120
+ checkCommand: "opencode --version",
121
+ website: "https://opencode.ai",
122
+ category: "ai-coding",
123
+ packageManager: "npm",
124
+ packageName: "opencode-ai",
125
+ },
126
+ {
127
+ name: "aider",
128
+ displayName: "Aider",
129
+ description: "AI pair programming - works with Claude, GPT-4, local models",
130
+ checkCommand: "aider --version",
131
+ website: "https://aider.chat",
132
+ category: "ai-coding",
133
+ packageManager: "pip",
134
+ packageName: "aider-chat",
135
+ },
136
+ {
137
+ name: "crush",
138
+ displayName: "Crush",
139
+ description: "AI coding assistant from Charm with terminal-native UX",
140
+ checkCommand: "crush --version",
141
+ website: "https://github.com/charmbracelet/crush",
142
+ category: "ai-coding",
143
+ packageManager: "npm",
144
+ packageName: "@charmland/crush",
145
+ },
146
+ ];