groove-dev 0.8.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 (84) hide show
  1. package/CLAUDE.md +197 -0
  2. package/LICENSE +40 -0
  3. package/README.md +115 -0
  4. package/docs/GUI_DESIGN_SPEC.md +402 -0
  5. package/favicon.png +0 -0
  6. package/groove-logo-short.png +0 -0
  7. package/groove-logo.png +0 -0
  8. package/package.json +70 -0
  9. package/packages/cli/bin/groove.js +98 -0
  10. package/packages/cli/package.json +15 -0
  11. package/packages/cli/src/client.js +25 -0
  12. package/packages/cli/src/commands/agents.js +38 -0
  13. package/packages/cli/src/commands/approve.js +50 -0
  14. package/packages/cli/src/commands/config.js +35 -0
  15. package/packages/cli/src/commands/kill.js +15 -0
  16. package/packages/cli/src/commands/nuke.js +19 -0
  17. package/packages/cli/src/commands/providers.js +40 -0
  18. package/packages/cli/src/commands/rotate.js +16 -0
  19. package/packages/cli/src/commands/spawn.js +91 -0
  20. package/packages/cli/src/commands/start.js +31 -0
  21. package/packages/cli/src/commands/status.js +38 -0
  22. package/packages/cli/src/commands/stop.js +15 -0
  23. package/packages/cli/src/commands/team.js +77 -0
  24. package/packages/daemon/package.json +18 -0
  25. package/packages/daemon/src/adaptive.js +237 -0
  26. package/packages/daemon/src/api.js +533 -0
  27. package/packages/daemon/src/classifier.js +126 -0
  28. package/packages/daemon/src/credentials.js +121 -0
  29. package/packages/daemon/src/firstrun.js +93 -0
  30. package/packages/daemon/src/index.js +208 -0
  31. package/packages/daemon/src/introducer.js +238 -0
  32. package/packages/daemon/src/journalist.js +600 -0
  33. package/packages/daemon/src/lockmanager.js +58 -0
  34. package/packages/daemon/src/pm.js +108 -0
  35. package/packages/daemon/src/process.js +361 -0
  36. package/packages/daemon/src/providers/aider.js +72 -0
  37. package/packages/daemon/src/providers/base.js +38 -0
  38. package/packages/daemon/src/providers/claude-code.js +167 -0
  39. package/packages/daemon/src/providers/codex.js +68 -0
  40. package/packages/daemon/src/providers/gemini.js +62 -0
  41. package/packages/daemon/src/providers/index.js +38 -0
  42. package/packages/daemon/src/providers/ollama.js +94 -0
  43. package/packages/daemon/src/registry.js +89 -0
  44. package/packages/daemon/src/rotator.js +185 -0
  45. package/packages/daemon/src/router.js +132 -0
  46. package/packages/daemon/src/state.js +34 -0
  47. package/packages/daemon/src/supervisor.js +178 -0
  48. package/packages/daemon/src/teams.js +203 -0
  49. package/packages/daemon/src/terminal/base.js +27 -0
  50. package/packages/daemon/src/terminal/generic.js +27 -0
  51. package/packages/daemon/src/terminal/tmux.js +64 -0
  52. package/packages/daemon/src/tokentracker.js +124 -0
  53. package/packages/daemon/src/validate.js +122 -0
  54. package/packages/daemon/templates/api-builder.json +18 -0
  55. package/packages/daemon/templates/fullstack.json +18 -0
  56. package/packages/daemon/templates/monorepo.json +24 -0
  57. package/packages/gui/dist/assets/index-BO95Rm1F.js +73 -0
  58. package/packages/gui/dist/assets/index-CPzm9ZE9.css +1 -0
  59. package/packages/gui/dist/favicon.png +0 -0
  60. package/packages/gui/dist/groove-logo-short.png +0 -0
  61. package/packages/gui/dist/groove-logo.png +0 -0
  62. package/packages/gui/dist/index.html +13 -0
  63. package/packages/gui/index.html +12 -0
  64. package/packages/gui/package.json +22 -0
  65. package/packages/gui/public/favicon.png +0 -0
  66. package/packages/gui/public/groove-logo-short.png +0 -0
  67. package/packages/gui/public/groove-logo.png +0 -0
  68. package/packages/gui/src/App.jsx +215 -0
  69. package/packages/gui/src/components/AgentActions.jsx +347 -0
  70. package/packages/gui/src/components/AgentChat.jsx +479 -0
  71. package/packages/gui/src/components/AgentNode.jsx +117 -0
  72. package/packages/gui/src/components/AgentPanel.jsx +115 -0
  73. package/packages/gui/src/components/AgentStats.jsx +333 -0
  74. package/packages/gui/src/components/ApprovalQueue.jsx +156 -0
  75. package/packages/gui/src/components/EmptyState.jsx +100 -0
  76. package/packages/gui/src/components/SpawnPanel.jsx +515 -0
  77. package/packages/gui/src/components/TeamSelector.jsx +162 -0
  78. package/packages/gui/src/main.jsx +9 -0
  79. package/packages/gui/src/stores/groove.js +247 -0
  80. package/packages/gui/src/theme.css +67 -0
  81. package/packages/gui/src/views/AgentTree.jsx +148 -0
  82. package/packages/gui/src/views/CommandCenter.jsx +620 -0
  83. package/packages/gui/src/views/JournalistFeed.jsx +149 -0
  84. package/packages/gui/vite.config.js +19 -0
@@ -0,0 +1,402 @@
1
+ # Groove AI — GUI Design Specification
2
+ ### Terminal-Native Visual Control Plane
3
+
4
+ > The GUI should feel like a terminal that happens to have graphics in it — not a website pretending to be a terminal.
5
+
6
+ ---
7
+
8
+ ## Philosophy
9
+
10
+ This is a TUI-meets-browser hybrid. It runs at `localhost:3141` and is designed to sit inside a terminal multiplexer pane (cmux) alongside real terminal sessions. It should look like it belongs there. No rounded corners on containers, no card shadows, no hover animations, no gradient backgrounds. Think: htop with a React Flow node graph in the center.
11
+
12
+ ---
13
+
14
+ ## Color Palette
15
+
16
+ Based on One Dark Pro. Every color has a purpose.
17
+
18
+ ### Backgrounds
19
+ | Token | Hex | Usage |
20
+ |---|---|---|
21
+ | `--bg-base` | `#24282f` | Main content area / node graph background |
22
+ | `--bg-chrome` | `#282c34` | Sidebar, header bar, panels |
23
+ | `--bg-surface` | `#2c313a` | Buttons, input fields, card surfaces |
24
+ | `--bg-hover` | `#333842` | Button/row hover state |
25
+ | `--bg-active` | `#3a3f4b` | Active/selected button or tab |
26
+
27
+ ### Text
28
+ | Token | Hex | Usage |
29
+ |---|---|---|
30
+ | `--text-primary` | `#abb2bf` | Default body text, labels |
31
+ | `--text-bright` | `#e6e6e6` | Headings, active items, emphasis |
32
+ | `--text-dim` | `#5c6370` | Secondary info, timestamps, hints |
33
+ | `--text-muted` | `#3e4451` | Disabled text, decorative borders |
34
+
35
+ ### Accent / Status
36
+ | Token | Hex | Usage |
37
+ |---|---|---|
38
+ | `--accent` | `#33afbc` | Brand accent — active nav item, selected node border, primary action |
39
+ | `--green` | `#98c379` | Agent active, success states, healthy status |
40
+ | `--amber` | `#e5c07b` | Agent idle, warning, pending approval |
41
+ | `--red` | `#e06c75` | Agent blocked/error, kill actions, conflicts |
42
+ | `--purple` | `#c678dd` | Journalist activity, context rotation events |
43
+ | `--blue` | `#61afef` | Info badges, links, secondary accent |
44
+
45
+ ---
46
+
47
+ ## Typography
48
+
49
+ One font. Everywhere. No exceptions.
50
+
51
+ ```
52
+ font-family: 'JetBrains Mono', 'SF Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace;
53
+ ```
54
+
55
+ | Element | Size | Weight | Color |
56
+ |---|---|---|---|
57
+ | Header bar title | 13px | 600 | `--text-bright` |
58
+ | Nav buttons | 12px | 500 | `--text-primary` (inactive), `--text-bright` (active) |
59
+ | Node labels | 12px | 600 | `--text-bright` |
60
+ | Node metadata | 11px | 400 | `--text-dim` |
61
+ | Panel headings | 11px | 600 | `--text-dim`, uppercase, letter-spacing 1.5px |
62
+ | Panel body text | 12px | 400 | `--text-primary` |
63
+ | Timestamps | 10px | 400 | `--text-dim` |
64
+ | Status badges | 10px | 600 | Status color, uppercase |
65
+
66
+ ---
67
+
68
+ ## Layout
69
+
70
+ ```
71
+ ┌──────────────────────────────────────────────────────┐
72
+ │ HEADER BAR (--bg-chrome, 40px height) │
73
+ │ [logo] [Agents] [Tokens] [Teams] [Permissions] │
74
+ ├────────────────────────────────────┬─────────────────┤
75
+ │ │ │
76
+ │ NODE GRAPH │ DETAIL PANEL │
77
+ │ (--bg-base) │ (--bg-chrome) │
78
+ │ │ │
79
+ │ React Flow canvas with │ Context for │
80
+ │ agent nodes and edges │ selected node │
81
+ │ │ │
82
+ │ │ │
83
+ └────────────────────────────────────┴─────────────────┘
84
+ ```
85
+
86
+ ### Header Bar
87
+ - Height: 40px
88
+ - Background: `--bg-chrome`
89
+ - Bottom border: 1px `--text-muted`
90
+ - Logo: Groove infinity icon (16px), left side
91
+ - Nav buttons: right-aligned, evenly spaced
92
+
93
+ ### Node Graph Area
94
+ - Background: `--bg-base`
95
+ - Takes remaining viewport width/height
96
+ - Subtle dot grid pattern: `--text-muted` dots, 20px spacing, 1px size
97
+ - No border, no padding — edge to edge
98
+
99
+ ### Detail Panel (right sidebar)
100
+ - Width: 320px, collapsible
101
+ - Background: `--bg-chrome`
102
+ - Left border: 1px `--text-muted`
103
+ - Shows detail for whatever is selected in the graph
104
+
105
+ ---
106
+
107
+ ## Components
108
+
109
+ ### Nav Buttons (Header)
110
+
111
+ The four main views: **Agents**, **Tokens**, **Teams**, **Permissions**
112
+
113
+ ```
114
+ Inactive:
115
+ background: transparent
116
+ color: --text-primary
117
+ padding: 6px 14px
118
+ border: none
119
+
120
+ Hover:
121
+ background: --bg-hover
122
+ color: --text-bright
123
+
124
+ Active:
125
+ background: --bg-active
126
+ color: --text-bright
127
+ border-bottom: 2px --accent (or underline indicator)
128
+ ```
129
+
130
+ No border-radius. These are terminal tabs, not web buttons.
131
+
132
+ ### Agent Nodes (React Flow)
133
+
134
+ Each node represents one running agent.
135
+
136
+ ```
137
+ ┌─────────────────────────┐
138
+ │ ● backend-1 │ ← status dot + agent name
139
+ │ src/api/** │ ← file scope
140
+ │ claude-code · 45% │ ← provider + context usage
141
+ └─────────────────────────┘
142
+ ```
143
+
144
+ | Property | Value |
145
+ |---|---|
146
+ | Background | `--bg-surface` |
147
+ | Border | 1px `--text-muted` |
148
+ | Border (selected) | 1px `--accent` |
149
+ | Border-radius | 2px (barely rounded — terminal feel) |
150
+ | Padding | 10px 12px |
151
+ | Width | 200px |
152
+ | Font | 12px for name, 11px for metadata |
153
+
154
+ **Status dot** (6px circle, left of agent name):
155
+ - `--green` = active
156
+ - `--amber` = idle / waiting
157
+ - `--red` = blocked / error
158
+ - `--purple` = rotating context
159
+
160
+ **Context usage bar** (optional, bottom of node):
161
+ - Height: 2px
162
+ - Background: `--text-muted`
163
+ - Fill: `--green` (0-60%), `--amber` (60-80%), `--red` (80-100%)
164
+
165
+ ### Edges (connections between nodes)
166
+
167
+ - Stroke: `--text-muted`
168
+ - Stroke width: 1px
169
+ - Style: straight or step (not bezier — too soft)
170
+ - Animated dash when data is flowing (introduction events, journalist updates)
171
+
172
+ ### QC Supervisor Node (special)
173
+
174
+ Same structure as agent node but:
175
+ - Border: 1px `--purple`
176
+ - Label prefix: `[QC]`
177
+ - Always positioned at root/top of the tree
178
+
179
+ ### Status Badges
180
+
181
+ Small inline badges for agent states.
182
+
183
+ ```
184
+ background: rgba(color, 0.12)
185
+ color: status color
186
+ padding: 2px 6px
187
+ font-size: 10px
188
+ font-weight: 600
189
+ text-transform: uppercase
190
+ letter-spacing: 0.5px
191
+ border-radius: 2px
192
+ ```
193
+
194
+ Examples:
195
+ - `ACTIVE` — green bg tint, green text
196
+ - `IDLE` — amber bg tint, amber text
197
+ - `BLOCKED` — red bg tint, red text
198
+ - `ROTATING` — purple bg tint, purple text
199
+
200
+ ### Token Usage View
201
+
202
+ Replaces the node graph when "Tokens" tab is active.
203
+
204
+ ```
205
+ ┌──────────────────────────────────┐
206
+ │ TOKEN USAGE this session│
207
+ │ │
208
+ │ Total 1,247,893 │
209
+ │ Saved (routing) 412,500 (33%) │
210
+ │ Saved (rotation) 289,100 (23%) │
211
+ │ │
212
+ │ AGENT BREAKDOWN │
213
+ │ ─────────────────────────────── │
214
+ │ backend-1 482,100 38.6% │
215
+ │ ████████████████░░░░░░ │
216
+ │ frontend-1 391,200 31.3% │
217
+ │ ██████████████░░░░░░░░ │
218
+ │ database-1 374,593 30.0% │
219
+ │ █████████████░░░░░░░░░ │
220
+ └──────────────────────────────────┘
221
+ ```
222
+
223
+ Bar charts use block characters or thin divs:
224
+ - Fill: `--accent`
225
+ - Track: `--text-muted`
226
+ - Height: 3px
227
+
228
+ Numbers right-aligned, monospace tabular. This should look like a terminal stats output, not a web dashboard.
229
+
230
+ ### Teams View
231
+
232
+ List of saved team configurations.
233
+
234
+ ```
235
+ ┌──────────────────────────────────┐
236
+ │ SAVED TEAMS │
237
+ │ │
238
+ │ > fullstack 4 agents │
239
+ │ backend, frontend, db, qc │
240
+ │ saved 2026-04-05 │
241
+ │ │
242
+ │ > api-only 2 agents │
243
+ │ backend, database │
244
+ │ saved 2026-04-04 │
245
+ └──────────────────────────────────┘
246
+ ```
247
+
248
+ - `>` prefix for each team (terminal-style list marker)
249
+ - Selected team: `--text-bright` text, `--bg-hover` background
250
+ - Load button: inline, right side, `--accent` text
251
+
252
+ ### Permissions / Approvals View
253
+
254
+ Pending agent actions requiring human approval.
255
+
256
+ ```
257
+ ┌──────────────────────────────────┐
258
+ │ PENDING APPROVALS 2 │
259
+ │ │
260
+ │ backend-1 wants to: │
261
+ │ Edit src/middleware/auth.js │
262
+ │ "Refactoring auth to use JWT" │
263
+ │ [APPROVE] [REJECT] 2m ago │
264
+ │ │
265
+ │ frontend-1 wants to: │
266
+ │ Create src/components/Modal.jsx │
267
+ │ "Adding confirmation dialog" │
268
+ │ [APPROVE] [REJECT] 45s ago │
269
+ └──────────────────────────────────┘
270
+ ```
271
+
272
+ Action buttons:
273
+ ```
274
+ [APPROVE]:
275
+ background: rgba(--green, 0.12)
276
+ color: --green
277
+ border: 1px rgba(--green, 0.2)
278
+ padding: 4px 10px
279
+ font-size: 11px
280
+
281
+ [REJECT]:
282
+ background: rgba(--red, 0.12)
283
+ color: --red
284
+ border: 1px rgba(--red, 0.2)
285
+ padding: 4px 10px
286
+ font-size: 11px
287
+ ```
288
+
289
+ ---
290
+
291
+ ## Detail Panel (Right Sidebar)
292
+
293
+ Shows context for selected agent node.
294
+
295
+ ```
296
+ ┌─────────────────────┐
297
+ │ AGENT DETAIL │
298
+ │ │
299
+ │ backend-1 │
300
+ │ Status: ACTIVE │
301
+ │ Provider: claude │
302
+ │ Context: 45% │
303
+ │ ████████░░░░░░░░░░ │
304
+ │ Tokens: 482,100 │
305
+ │ Scope: │
306
+ │ src/api/** │
307
+ │ src/middleware/** │
308
+ │ Spawned: 14:20 │
309
+ │ Peers: frontend-1, │
310
+ │ database-1 │
311
+ │ │
312
+ │ RECENT ACTIVITY │
313
+ │ ───────────────── │
314
+ │ 14:32 editing │
315
+ │ auth.js │
316
+ │ 14:28 introduced to │
317
+ │ frontend-1 │
318
+ │ 14:20 spawned │
319
+ └─────────────────────┘
320
+ ```
321
+
322
+ - Section headers: `--text-dim`, 11px, uppercase, 1.5px letter-spacing
323
+ - Dividers: single line of `─` chars or 1px `--text-muted` border
324
+ - Key labels: `--text-dim`
325
+ - Values: `--text-primary`
326
+ - Agent name: `--text-bright`, 14px, 600 weight
327
+
328
+ ---
329
+
330
+ ## Interaction States
331
+
332
+ | State | Treatment |
333
+ |---|---|
334
+ | Default | `--bg-surface` background, `--text-primary` text |
335
+ | Hover | `--bg-hover` background, `--text-bright` text |
336
+ | Active/Selected | `--bg-active` background, `--text-bright` text |
337
+ | Focused | 1px `--accent` outline (no glow, no shadow) |
338
+ | Disabled | `--text-muted` text, no hover change |
339
+
340
+ No transitions longer than 100ms. No easing curves. Instant or near-instant state changes — like a terminal.
341
+
342
+ ---
343
+
344
+ ## What NOT To Do
345
+
346
+ - No border-radius > 2px anywhere
347
+ - No box-shadow anywhere
348
+ - No gradients anywhere
349
+ - No opacity transitions on hover
350
+ - No font-size larger than 14px (exception: token counter numbers)
351
+ - No sans-serif fonts
352
+ - No rounded buttons
353
+ - No icons — use text labels and ASCII where possible (`●`, `>`, `─`, `█`, `░`)
354
+ - No loading spinners — use text like `loading...` or `syncing...`
355
+ - No toast notifications — use inline status text
356
+ - No modals — use the detail panel or inline expansion
357
+
358
+ ---
359
+
360
+ ## CSS Variables (copy-paste ready)
361
+
362
+ ```css
363
+ :root {
364
+ /* Backgrounds */
365
+ --bg-base: #24282f;
366
+ --bg-chrome: #282c34;
367
+ --bg-surface: #2c313a;
368
+ --bg-hover: #333842;
369
+ --bg-active: #3a3f4b;
370
+
371
+ /* Text */
372
+ --text-primary: #abb2bf;
373
+ --text-bright: #e6e6e6;
374
+ --text-dim: #5c6370;
375
+ --text-muted: #3e4451;
376
+
377
+ /* Status */
378
+ --accent: #33afbc;
379
+ --green: #98c379;
380
+ --amber: #e5c07b;
381
+ --red: #e06c75;
382
+ --purple: #c678dd;
383
+ --blue: #61afef;
384
+
385
+ /* Typography */
386
+ --font: 'JetBrains Mono', 'SF Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace;
387
+ }
388
+ ```
389
+
390
+ ---
391
+
392
+ ## File Reference
393
+
394
+ - Logo (full): `/groove-logo.png` (800x254, cyan on transparent)
395
+ - Logo (icon): `/favicon.png` (500x500, infinity symbol)
396
+ - Brand accent: `#33afbc`
397
+ - Site: https://grooveai.dev
398
+ - Docs: https://docs.grooveai.dev
399
+
400
+ ---
401
+
402
+ *This spec is the single source of truth for GUI visual design. If it's not in here, don't add it. If it contradicts a mockup, this document wins.*
package/favicon.png ADDED
Binary file
Binary file
Binary file
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "groove-dev",
3
+ "version": "0.8.0",
4
+ "description": "Open-source agent orchestration layer for AI coding tools. GUI dashboard, multi-agent coordination, zero cold-start (Journalist), infinite sessions (adaptive context rotation), AI Project Manager, Quick Launch. Works with Claude Code, Codex, Gemini CLI, Aider, Ollama.",
5
+ "license": "FSL-1.1-Apache-2.0",
6
+ "author": "Groove Dev <hello@groovedev.ai> (https://groovedev.ai)",
7
+ "homepage": "https://groovedev.ai",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/grooveai-dev/groove"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/grooveai-dev/groove/issues"
14
+ },
15
+ "keywords": [
16
+ "ai",
17
+ "ai-agent",
18
+ "ai-coding",
19
+ "agent-orchestration",
20
+ "multi-agent",
21
+ "claude",
22
+ "claude-code",
23
+ "codex",
24
+ "gemini",
25
+ "aider",
26
+ "ollama",
27
+ "coding-assistant",
28
+ "developer-tools",
29
+ "devtools",
30
+ "context-window",
31
+ "token-savings",
32
+ "model-routing",
33
+ "orchestration",
34
+ "gui",
35
+ "dashboard",
36
+ "process-manager",
37
+ "llm",
38
+ "vscode",
39
+ "terminal"
40
+ ],
41
+ "bin": {
42
+ "groove": "./packages/cli/bin/groove.js"
43
+ },
44
+ "workspaces": [
45
+ "packages/daemon",
46
+ "packages/cli",
47
+ "packages/gui"
48
+ ],
49
+ "engines": {
50
+ "node": ">=20.0.0"
51
+ },
52
+ "scripts": {
53
+ "dev:daemon": "npm run dev -w packages/daemon",
54
+ "dev:gui": "npm run dev -w packages/gui",
55
+ "build": "npm run build -w packages/gui",
56
+ "build:gui": "npm run build -w packages/gui",
57
+ "test": "npm test -w packages/daemon",
58
+ "prepublishOnly": "npm run build:gui"
59
+ },
60
+ "bundledDependencies": [
61
+ "@groove-dev/daemon",
62
+ "@groove-dev/cli",
63
+ "@groove-dev/gui"
64
+ ],
65
+ "bundleDependencies": [
66
+ "@groove-dev/daemon",
67
+ "@groove-dev/cli",
68
+ "@groove-dev/gui"
69
+ ]
70
+ }
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+
3
+ // GROOVE CLI — Entry Point
4
+ // FSL-1.1-Apache-2.0 — see LICENSE
5
+
6
+ import { program } from 'commander';
7
+ import { start } from '../src/commands/start.js';
8
+ import { stop } from '../src/commands/stop.js';
9
+ import { spawn } from '../src/commands/spawn.js';
10
+ import { kill } from '../src/commands/kill.js';
11
+ import { agents } from '../src/commands/agents.js';
12
+ import { status } from '../src/commands/status.js';
13
+ import { nuke } from '../src/commands/nuke.js';
14
+ import { rotate } from '../src/commands/rotate.js';
15
+ import { teamSave, teamLoad, teamList, teamDelete, teamExport, teamImport } from '../src/commands/team.js';
16
+ import { approvals, approve, reject } from '../src/commands/approve.js';
17
+ import { providers, setKey } from '../src/commands/providers.js';
18
+ import { configShow, configSet } from '../src/commands/config.js';
19
+
20
+ program
21
+ .name('groove')
22
+ .description('Agent orchestration layer for AI coding tools')
23
+ .version('0.4.0');
24
+
25
+ program
26
+ .command('start')
27
+ .description('Start the GROOVE daemon')
28
+ .option('-p, --port <port>', 'Port to run on', '31415')
29
+ .action(start);
30
+
31
+ program
32
+ .command('stop')
33
+ .description('Stop the GROOVE daemon')
34
+ .action(stop);
35
+
36
+ program
37
+ .command('spawn')
38
+ .description('Spawn a new AI agent')
39
+ .option('-r, --role <role>', 'Agent role (e.g., backend, frontend, devops)')
40
+ .option('-s, --scope <patterns...>', 'File scope patterns')
41
+ .option('-p, --provider <provider>', 'AI provider', 'claude-code')
42
+ .option('-m, --model <model>', 'Model to use')
43
+ .option('--prompt <prompt>', 'Initial prompt for the agent')
44
+ .action(spawn);
45
+
46
+ program
47
+ .command('kill <id>')
48
+ .description('Kill a running agent')
49
+ .action(kill);
50
+
51
+ program
52
+ .command('agents')
53
+ .description('List all agents')
54
+ .action(agents);
55
+
56
+ program
57
+ .command('status')
58
+ .description('Show daemon status')
59
+ .action(status);
60
+
61
+ program
62
+ .command('nuke')
63
+ .description('Kill all agents and stop the daemon')
64
+ .action(nuke);
65
+
66
+ program
67
+ .command('rotate <id>')
68
+ .description('Rotate an agent (kill + respawn with fresh context)')
69
+ .action(rotate);
70
+
71
+ // Teams
72
+ const team = program.command('team').description('Manage saved agent teams');
73
+ team.command('save <name>').description('Save current agents as a team').action(teamSave);
74
+ team.command('load <name>').description('Load and spawn a saved team').action(teamLoad);
75
+ team.command('list').description('List saved teams').action(teamList);
76
+ team.command('delete <name>').description('Delete a saved team').action(teamDelete);
77
+ team.command('export <name>').description('Export team as JSON').action(teamExport);
78
+ team.command('import <file>').description('Import team from JSON file').action(teamImport);
79
+
80
+ // Approvals
81
+ program.command('approvals').description('List pending approvals').action(approvals);
82
+ program.command('approve <id>').description('Approve a pending request').action(approve);
83
+ program
84
+ .command('reject <id>')
85
+ .description('Reject a pending request')
86
+ .option('--reason <reason>', 'Rejection reason')
87
+ .action(reject);
88
+
89
+ // Providers
90
+ program.command('providers').description('List available AI providers').action(providers);
91
+ program.command('set-key <provider> <key>').description('Set API key for a provider').action(setKey);
92
+
93
+ // Config
94
+ const config = program.command('config').description('View and modify configuration');
95
+ config.command('show').description('Show current configuration').action(configShow);
96
+ config.command('set <key> <value>').description('Set a configuration value').action(configSet);
97
+
98
+ program.parse();
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "@groove-dev/cli",
3
+ "version": "0.8.0",
4
+ "description": "GROOVE CLI — manage AI coding agents from your terminal",
5
+ "license": "FSL-1.1-Apache-2.0",
6
+ "type": "module",
7
+ "bin": {
8
+ "groove": "./bin/groove.js"
9
+ },
10
+ "dependencies": {
11
+ "@groove-dev/daemon": "*",
12
+ "commander": "^12.1.0",
13
+ "chalk": "^5.3.0"
14
+ }
15
+ }
@@ -0,0 +1,25 @@
1
+ // GROOVE CLI — HTTP client for daemon communication
2
+ // FSL-1.1-Apache-2.0 — see LICENSE
3
+
4
+ const BASE_URL = process.env.GROOVE_URL || 'http://localhost:31415';
5
+
6
+ export async function apiCall(method, path, body) {
7
+ const url = `${BASE_URL}${path}`;
8
+ const options = {
9
+ method,
10
+ headers: { 'Content-Type': 'application/json' },
11
+ };
12
+
13
+ if (body) {
14
+ options.body = JSON.stringify(body);
15
+ }
16
+
17
+ const res = await fetch(url, options);
18
+
19
+ if (!res.ok) {
20
+ const err = await res.json().catch(() => ({ error: res.statusText }));
21
+ throw new Error(err.error || `HTTP ${res.status}`);
22
+ }
23
+
24
+ return res.json();
25
+ }
@@ -0,0 +1,38 @@
1
+ // GROOVE CLI — agents command
2
+ // FSL-1.1-Apache-2.0 — see LICENSE
3
+
4
+ import chalk from 'chalk';
5
+ import { apiCall } from '../client.js';
6
+
7
+ const STATUS_COLORS = {
8
+ running: 'green',
9
+ starting: 'yellow',
10
+ stopped: 'gray',
11
+ crashed: 'red',
12
+ completed: 'cyan',
13
+ };
14
+
15
+ export async function agents() {
16
+ try {
17
+ const list = await apiCall('GET', '/api/agents');
18
+
19
+ if (list.length === 0) {
20
+ console.log(chalk.dim('No agents running. Use `groove spawn` to start one.'));
21
+ return;
22
+ }
23
+
24
+ console.log(chalk.bold(`\n GROOVE Agents (${list.length})\n`));
25
+
26
+ for (const a of list) {
27
+ const color = STATUS_COLORS[a.status] || 'white';
28
+ const statusBadge = chalk[color](`[${a.status}]`);
29
+ console.log(` ${chalk.bold(a.name)} ${statusBadge} ${chalk.dim(a.id)}`);
30
+ console.log(` Role: ${a.role} Provider: ${a.provider} Scope: ${a.scope.join(', ') || '-'}`);
31
+ console.log(` Tokens: ${a.tokensUsed} Context: ${Math.round(a.contextUsage * 100)}%`);
32
+ console.log();
33
+ }
34
+ } catch {
35
+ console.error(chalk.red('Cannot connect to daemon. Is it running? Try: groove start'));
36
+ process.exit(1);
37
+ }
38
+ }