claude-maestro 0.1.16

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 (125) hide show
  1. package/README.md +130 -0
  2. package/bin/maestro.mjs +45 -0
  3. package/out/main/index.js +5293 -0
  4. package/out/preload/index.js +130 -0
  5. package/out/renderer/assets/apl-fqmucPXA.js +140 -0
  6. package/out/renderer/assets/asciiarmor-DucZyvP0.js +56 -0
  7. package/out/renderer/assets/asn1-BnOEsgAm.js +144 -0
  8. package/out/renderer/assets/asterisk-QAlztEwS.js +345 -0
  9. package/out/renderer/assets/brainfuck-DZVCuF_t.js +53 -0
  10. package/out/renderer/assets/clike-xqXYL6ge.js +805 -0
  11. package/out/renderer/assets/clojure-BhXMqnxz.js +849 -0
  12. package/out/renderer/assets/cmake-BGaNd9E7.js +71 -0
  13. package/out/renderer/assets/cobol-4yqQntpt.js +120 -0
  14. package/out/renderer/assets/coffeescript-D2dXvhEc.js +308 -0
  15. package/out/renderer/assets/commonlisp-CF_VNHQR.js +130 -0
  16. package/out/renderer/assets/crystal-DyuLTqLs.js +398 -0
  17. package/out/renderer/assets/css-c-jst79C.js +1783 -0
  18. package/out/renderer/assets/cypher-Dlu_3r4V.js +121 -0
  19. package/out/renderer/assets/d-UURgV0Ux.js +179 -0
  20. package/out/renderer/assets/diff-B_Bi2Crb.js +25 -0
  21. package/out/renderer/assets/dockerfile-Bvk733Ga.js +201 -0
  22. package/out/renderer/assets/dtd-Dy74G54E.js +114 -0
  23. package/out/renderer/assets/dylan-TSb-Nfix.js +314 -0
  24. package/out/renderer/assets/ebnf-4fKAGW3a.js +140 -0
  25. package/out/renderer/assets/ecl-B59qGGVg.js +178 -0
  26. package/out/renderer/assets/eiffel-Dze7nlu3.js +134 -0
  27. package/out/renderer/assets/elm-DG7jkhNZ.js +176 -0
  28. package/out/renderer/assets/erlang-BO6gOnGA.js +674 -0
  29. package/out/renderer/assets/factor-CMxFHDqz.js +65 -0
  30. package/out/renderer/assets/fcl-CDDUNjTj.js +141 -0
  31. package/out/renderer/assets/forth-B9D2JCeE.js +116 -0
  32. package/out/renderer/assets/fortran-CAG2BFbe.js +467 -0
  33. package/out/renderer/assets/gas-d3KEcW3x.js +294 -0
  34. package/out/renderer/assets/gherkin-DhZlEZiy.js +115 -0
  35. package/out/renderer/assets/groovy-CpwJiBl7.js +223 -0
  36. package/out/renderer/assets/haskell-ySd-OUo8.js +459 -0
  37. package/out/renderer/assets/haxe-7MlzfeYV.js +514 -0
  38. package/out/renderer/assets/http-BqypyemW.js +79 -0
  39. package/out/renderer/assets/idl-4HIGJlDI.js +985 -0
  40. package/out/renderer/assets/index-2SQReYbL.js +117 -0
  41. package/out/renderer/assets/index-B4G_DF7l.js +178 -0
  42. package/out/renderer/assets/index-BJ7HHtlW.css +4015 -0
  43. package/out/renderer/assets/index-BLk1t3tc.js +151 -0
  44. package/out/renderer/assets/index-BLtm0KYA.js +157 -0
  45. package/out/renderer/assets/index-BPgGZ4iY.js +82 -0
  46. package/out/renderer/assets/index-BQE9vCdv.js +332 -0
  47. package/out/renderer/assets/index-BYr39Do3.js +61 -0
  48. package/out/renderer/assets/index-Ba0sUbhl.js +47177 -0
  49. package/out/renderer/assets/index-BewSkGJT.js +1041 -0
  50. package/out/renderer/assets/index-BnId7J8H.js +1021 -0
  51. package/out/renderer/assets/index-Btn996gP.js +406 -0
  52. package/out/renderer/assets/index-C7i4WyfA.js +311 -0
  53. package/out/renderer/assets/index-CW9SAu99.js +385 -0
  54. package/out/renderer/assets/index-CXmk7jHk.js +291 -0
  55. package/out/renderer/assets/index-CyQp9UDR.js +82 -0
  56. package/out/renderer/assets/index-Da2gJ_Wd.js +704 -0
  57. package/out/renderer/assets/index-DkFO-IXC.js +2488 -0
  58. package/out/renderer/assets/index-DqrDpNqn.js +689 -0
  59. package/out/renderer/assets/index-Dw7p19YD.js +327 -0
  60. package/out/renderer/assets/index-QPm3UFYR.js +97 -0
  61. package/out/renderer/assets/index-RGiHNShF.js +1768 -0
  62. package/out/renderer/assets/index-RgZE5T_I.js +642 -0
  63. package/out/renderer/assets/index-t8kJBumF.js +312 -0
  64. package/out/renderer/assets/javascript-C_OHM9hj.js +994 -0
  65. package/out/renderer/assets/julia-Bs6JJhYG.js +407 -0
  66. package/out/renderer/assets/livescript-DmzgM3Yt.js +296 -0
  67. package/out/renderer/assets/lua-Cvg8VrAA.js +256 -0
  68. package/out/renderer/assets/mathematica-DNLOL9PQ.js +110 -0
  69. package/out/renderer/assets/mbox-Ga7d4MMN.js +117 -0
  70. package/out/renderer/assets/mirc-Dma3B8rS.js +107 -0
  71. package/out/renderer/assets/mllike-DHn7xckP.js +334 -0
  72. package/out/renderer/assets/modelica-0d55jYY0.js +147 -0
  73. package/out/renderer/assets/mscgen-DdqZYINH.js +135 -0
  74. package/out/renderer/assets/mumps-Btr8VblO.js +93 -0
  75. package/out/renderer/assets/nginx-DTDtBDVN.js +141 -0
  76. package/out/renderer/assets/nsis-3zG7tgur.js +62 -0
  77. package/out/renderer/assets/ntriples-CvgOYMpL.js +153 -0
  78. package/out/renderer/assets/octave-DYBj3-tl.js +200 -0
  79. package/out/renderer/assets/oz-R_e8WMIi.js +231 -0
  80. package/out/renderer/assets/pascal-GD8iposT.js +105 -0
  81. package/out/renderer/assets/perl-DL9mHpoi.js +1105 -0
  82. package/out/renderer/assets/pig-C_4T4YIV.js +101 -0
  83. package/out/renderer/assets/powershell-B0suO7Vd.js +328 -0
  84. package/out/renderer/assets/properties-BR-vP1aU.js +58 -0
  85. package/out/renderer/assets/protobuf-BxgpyhoW.js +77 -0
  86. package/out/renderer/assets/pug-CTXt1f8z.js +405 -0
  87. package/out/renderer/assets/puppet-Bdao66PW.js +137 -0
  88. package/out/renderer/assets/python-CvWbmiX4.js +427 -0
  89. package/out/renderer/assets/q-CrbCVq4a.js +131 -0
  90. package/out/renderer/assets/r-V7nswm59.js +170 -0
  91. package/out/renderer/assets/rpm-C-DLY-If.js +109 -0
  92. package/out/renderer/assets/ruby-JDKLJNK0.js +330 -0
  93. package/out/renderer/assets/sas-D2UG-yhZ.js +207 -0
  94. package/out/renderer/assets/scheme-BKzrkGJD.js +222 -0
  95. package/out/renderer/assets/shell-BlsXDxCn.js +222 -0
  96. package/out/renderer/assets/sieve-CjwBwOY5.js +135 -0
  97. package/out/renderer/assets/simple-mode-DMneyfDu.js +130 -0
  98. package/out/renderer/assets/smalltalk-BOIGQuhN.js +121 -0
  99. package/out/renderer/assets/solr-CwD7U71z.js +69 -0
  100. package/out/renderer/assets/sparql-DYskk2vE.js +249 -0
  101. package/out/renderer/assets/spreadsheet-Bgtt3oLP.js +87 -0
  102. package/out/renderer/assets/sql-BSrOzCRI.js +354 -0
  103. package/out/renderer/assets/stex-B6LNC55o.js +231 -0
  104. package/out/renderer/assets/stylus-BkS-boTH.js +565 -0
  105. package/out/renderer/assets/swift-FRZi1uvB.js +291 -0
  106. package/out/renderer/assets/tcl-CUcaCdmq.js +114 -0
  107. package/out/renderer/assets/textile-BnFpjsrl.js +414 -0
  108. package/out/renderer/assets/tiddlywiki-CjprD-Qp.js +218 -0
  109. package/out/renderer/assets/tiki-DK9DOeWn.js +268 -0
  110. package/out/renderer/assets/toml-BOuWGMcf.js +76 -0
  111. package/out/renderer/assets/troff-E1bJ0PPL.js +61 -0
  112. package/out/renderer/assets/ttcn-cfg-Dc39-fIP.js +133 -0
  113. package/out/renderer/assets/ttcn-tKd4HLu4.js +192 -0
  114. package/out/renderer/assets/turtle-Dq7-1WAf.js +124 -0
  115. package/out/renderer/assets/vb-Dp90gtsv.js +196 -0
  116. package/out/renderer/assets/vbscript-CI6_mxxU.js +479 -0
  117. package/out/renderer/assets/velocity-BwIZK1TH.js +149 -0
  118. package/out/renderer/assets/verilog-DDCYnHN8.js +430 -0
  119. package/out/renderer/assets/vhdl-DCkMIyT9.js +158 -0
  120. package/out/renderer/assets/webidl-BTLTThCm.js +204 -0
  121. package/out/renderer/assets/xquery-BrBUuxMR.js +525 -0
  122. package/out/renderer/assets/yacas-b5lAVEIl.js +130 -0
  123. package/out/renderer/assets/z80-BZV19vqv.js +93 -0
  124. package/out/renderer/index.html +16 -0
  125. package/package.json +109 -0
package/README.md ADDED
@@ -0,0 +1,130 @@
1
+ # Maestro
2
+
3
+ > ⚠️ **Disclaimer: this is a vibe-coded app.** Maestro was built almost entirely by Claude Code
4
+ > (including by Maestro driving itself), with light human steering. Treat it as an experiment —
5
+ > expect rough edges, review before relying on it, and use at your own risk.
6
+
7
+ One window to run and **conduct** multiple Claude Code CLI sessions, each in its own repo, with a
8
+ live file explorer per session and git-worktree parallel tasks. See [PLAN.md](./PLAN.md) and
9
+ [SPECS.md](./SPECS.md).
10
+
11
+ Each session embeds the **real, unmodified `claude` CLI** in a real pseudo-terminal (ConPTY on
12
+ Windows, forkpty on macOS) — all CLI features (permission prompts, slash commands, `!` shell,
13
+ paste, vim mode) work exactly as in a normal terminal. The app adds the frame: session registry,
14
+ switching, status badges, file tree, viewer, parallel tasks, and restore-on-restart.
15
+
16
+ Requires the `claude` CLI on PATH (`npm i -g @anthropic-ai/claude-code`).
17
+
18
+ ## Install
19
+
20
+ **Windows** — grab either from the [latest release](https://github.com/pedroferreira1142/maestro/releases/latest):
21
+
22
+ - `Maestro-<version>-portable.exe` — single file, run from anywhere, **no install, no admin rights**
23
+ - `Maestro-Setup-<version>.exe` — per-user installer (Start menu + uninstaller, no admin rights)
24
+
25
+ **macOS** — from the same release page:
26
+
27
+ - `Maestro-<version>-arm64.dmg` (Apple Silicon) or `Maestro-<version>-x64.dmg` (Intel)
28
+ - The app is unsigned: on first launch, right-click the app → **Open** (or
29
+ `xattr -d com.apple.quarantine /Applications/Maestro.app`).
30
+
31
+ **npx / npm** (any OS with Node 20+; downloads Electron on first run):
32
+
33
+ ```bash
34
+ npx claude-maestro
35
+ # or install the command globally:
36
+ npm i -g claude-maestro && claude-maestro
37
+ ```
38
+
39
+ (Published to npm as [`claude-maestro`](https://www.npmjs.com/package/claude-maestro). You can also
40
+ run the unpublished tip with `npx github:pedroferreira1142/maestro`.)
41
+
42
+ ## Develop
43
+
44
+ ```powershell
45
+ npm install
46
+ npm run dev # development with HMR
47
+ npm run build # production bundles into out/
48
+ npm run package # build installers/portables into release/
49
+ node bin/maestro.mjs # run the built app
50
+ ```
51
+
52
+ Cutting a release: see [RELEASING.md](RELEASING.md) for the SemVer policy and the
53
+ `npm run release:patch|minor|major` scripts.
54
+
55
+ ## Use
56
+
57
+ On macOS, `Cmd` works wherever `Ctrl` is listed (except `Ctrl+Tab`, which stays `Ctrl`).
58
+
59
+ | Action | How |
60
+ |---|---|
61
+ | New session | `+` in the sidebar, or `Ctrl+Shift+N` → pick a repo folder |
62
+ | **New parallel task (worktree)** | `⑂` on a session, or `Ctrl+Shift+T` |
63
+ | New terminal in session | `+▾` in the tab strip, or `Ctrl+T` |
64
+ | Switch session | Click in sidebar, `Ctrl+Tab` / `Ctrl+Shift+Tab`, or `Ctrl+1…9` |
65
+ | Close session | ✕ on hover, or `Ctrl+Shift+W` |
66
+ | Rename session | Double-click its name |
67
+ | Toggle file explorer | `Ctrl+B` |
68
+ | View a file | Single-click in the tree (read-only viewer tab) |
69
+ | Open in editor | Double-click in the tree (default: VS Code) |
70
+ | Context menu | Right-click a file/folder: open, reveal, copy path |
71
+ | Terminal search | `Ctrl+F` in the terminal |
72
+ | Copy / paste in terminal | `Ctrl+Shift+C` / `Ctrl+Shift+V`, right-click toggles copy/paste, `Ctrl+C` with selection copies |
73
+
74
+ Sessions keep running in the background when not visible; scrollback is preserved. Status
75
+ glyphs in the sidebar: `⟳` working · `●` needs your input · `○` idle · `✕` exited (with
76
+ restart-resume buttons in the pane).
77
+
78
+ On app restart, all sessions are restored and conversations resumed via `claude --continue`.
79
+
80
+ ## Parallel tasks (git worktrees)
81
+
82
+ While Claude works on task A in a repo, spin off task B **on the same repo** without waiting:
83
+
84
+ 1. Click `⑂` on the session (or `Ctrl+Shift+T`). Name the task and pick its type — a branch
85
+ (`parallel/<slug>`, `feature/<slug>` or `bug/<slug>`) and a worktree folder
86
+ (`<repo>.worktrees/<slug>`, sibling of the repo) are created.
87
+ 2. A linked session appears indented under the parent, running its own `claude` in the
88
+ worktree — optionally pre-typed with your first prompt (you press Enter to send).
89
+ 3. When the task is done, click **Merge** on the task entry: the branch is merged
90
+ (`--no-ff`) into the base branch. Clean merge → offers to remove the worktree and
91
+ branch. Conflicts → you land in the terminal to resolve them like a normal merge.
92
+
93
+ Any number of tasks can run side by side; each is isolated in its own working tree.
94
+
95
+ ### Reliable "needs input" detection
96
+
97
+ Claude Code rings the terminal bell on prompts when configured to:
98
+
99
+ ```powershell
100
+ claude config set --global preferredNotifChannel terminal_bell
101
+ ```
102
+
103
+ With that set, background sessions flag themselves (badge + OS notification + taskbar flash)
104
+ the moment Claude asks for permission or input. Without it, detection falls back to output
105
+ heuristics.
106
+
107
+ ## State
108
+
109
+ Session list, window bounds, and settings persist in `sessions.json` under the app's user-data
110
+ dir (`%APPDATA%\maestro` on Windows, `~/Library/Application Support/maestro` on macOS). The tail
111
+ of each terminal's output (~200 KB) is persisted under `scrollback/` in the same dir and replayed
112
+ on restart above a dim `── restored from previous session ──` divider, while Claude's own
113
+ `--continue` restores the conversation itself.
114
+
115
+ ## Architecture (short)
116
+
117
+ - **Main process** (`src/main/`): `SessionManager` owns one `PtySession` (node-pty ConPTY
118
+ running `claude`) per session — PTYs live in main, so a renderer reload never kills sessions.
119
+ `StatusDetector` classifies the output stream; `FsService` does bounded chokidar watching
120
+ (root + expanded dirs, ignore-list at watcher level) and path-validated file reads.
121
+ - **Preload** (`src/preload/`): typed `window.api` bridge, contextIsolation on.
122
+ - **Renderer** (`src/renderer/`): React + zustand. One persistent xterm.js instance per
123
+ session (hidden, never unmounted ⇒ instant switching), lazy file tree with live updates and
124
+ changed-file flashes, CodeMirror 6 read-only viewer with auto language detection.
125
+
126
+ ## Acknowledgements
127
+
128
+ This wouldn't have been possible without the help of
129
+ [Tim Pieters](https://www.linkedin.com/in/tim-pieters/) and
130
+ [Sven De Pickere](https://www.linkedin.com/in/svendepickere/).
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * npx/CLI launcher for Maestro.
4
+ *
5
+ * Resolves the electron binary and boots the built app (out/ + package.json
6
+ * `main`). When the package was installed without electron (it's a devDep so
7
+ * electron-builder accepts it), falls back to running electron via npx, which
8
+ * downloads it into the npx cache on first use — no admin rights needed.
9
+ */
10
+ import { spawn } from 'node:child_process'
11
+ import { existsSync } from 'node:fs'
12
+ import { createRequire } from 'node:module'
13
+ import { dirname, join } from 'node:path'
14
+ import { fileURLToPath } from 'node:url'
15
+
16
+ const appDir = join(dirname(fileURLToPath(import.meta.url)), '..')
17
+
18
+ if (!existsSync(join(appDir, 'out', 'main', 'index.js'))) {
19
+ console.error('Maestro: built app not found (out/main/index.js missing). Run "npm run build" first.')
20
+ process.exit(1)
21
+ }
22
+
23
+ const require = createRequire(import.meta.url)
24
+ let electronPath = null
25
+ try {
26
+ // In plain Node, require('electron') resolves to the binary's path.
27
+ const resolved = require('electron')
28
+ if (typeof resolved === 'string') electronPath = resolved
29
+ } catch {
30
+ // electron not installed alongside the package — use the npx fallback below
31
+ }
32
+
33
+ // Windows needs shell:true to run npx.cmd; pass one pre-quoted string there
34
+ // (args arrays + shell:true are deprecated, DEP0190).
35
+ const child = electronPath
36
+ ? spawn(electronPath, [appDir], { stdio: 'inherit' })
37
+ : process.platform === 'win32'
38
+ ? spawn(`npx -y "electron@^33.3.0" "${appDir}"`, { stdio: 'inherit', shell: true })
39
+ : spawn('npx', ['-y', 'electron@^33.3.0', appDir], { stdio: 'inherit' })
40
+
41
+ child.on('error', (err) => {
42
+ console.error('Maestro: failed to launch electron:', err.message)
43
+ process.exit(1)
44
+ })
45
+ child.on('close', (code) => process.exit(code ?? 0))