grov 0.5.11 → 0.6.13

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 (190) hide show
  1. package/dist/cli/agents/registry.d.ts +17 -0
  2. package/dist/cli/agents/registry.js +132 -0
  3. package/dist/cli/commands/agents.d.ts +1 -0
  4. package/dist/cli/commands/agents.js +48 -0
  5. package/dist/cli/commands/disable.d.ts +1 -0
  6. package/dist/cli/commands/disable.js +179 -0
  7. package/dist/cli/commands/doctor.d.ts +1 -0
  8. package/dist/cli/commands/doctor.js +157 -0
  9. package/dist/{commands → cli/commands}/drift-test.js +39 -26
  10. package/dist/cli/commands/init.d.ts +1 -0
  11. package/dist/cli/commands/init.js +90 -0
  12. package/dist/{commands → cli/commands}/login.js +19 -18
  13. package/dist/{commands → cli/commands}/logout.js +1 -1
  14. package/dist/{commands → cli/commands}/proxy-status.js +1 -1
  15. package/dist/cli/commands/setup.d.ts +6 -0
  16. package/dist/cli/commands/setup.js +309 -0
  17. package/dist/{commands → cli/commands}/status.js +1 -1
  18. package/dist/{commands → cli/commands}/sync.d.ts +1 -0
  19. package/dist/{commands → cli/commands}/sync.js +59 -4
  20. package/dist/{commands → cli/commands}/uninstall.js +2 -2
  21. package/dist/cli/index.js +270 -0
  22. package/dist/{lib → core/cloud}/cloud-sync.d.ts +3 -3
  23. package/dist/{lib → core/cloud}/cloud-sync.js +10 -10
  24. package/dist/{lib → core/extraction}/correction-builder-proxy.d.ts +1 -1
  25. package/dist/{lib → core/extraction}/correction-builder-proxy.js +0 -4
  26. package/dist/{lib → core/extraction}/drift-checker-proxy.d.ts +13 -9
  27. package/dist/core/extraction/drift-checker-proxy.js +510 -0
  28. package/dist/{lib → core/extraction}/llm-extractor.d.ts +8 -38
  29. package/dist/{lib → core/extraction}/llm-extractor.js +132 -220
  30. package/dist/{lib → core}/store/sessions.js +3 -19
  31. package/dist/core/store/store.d.ts +1 -0
  32. package/dist/{lib → core/store}/store.js +1 -1
  33. package/dist/{lib → core}/store/types.d.ts +0 -4
  34. package/dist/integrations/mcp/cache.d.ts +27 -0
  35. package/dist/integrations/mcp/cache.js +106 -0
  36. package/dist/integrations/mcp/capture/antigravity-parser.d.ts +26 -0
  37. package/dist/integrations/mcp/capture/antigravity-parser.js +272 -0
  38. package/dist/integrations/mcp/capture/antigravity-scanner.d.ts +24 -0
  39. package/dist/integrations/mcp/capture/antigravity-scanner.js +153 -0
  40. package/dist/integrations/mcp/capture/antigravity-sync-tracker.d.ts +29 -0
  41. package/dist/integrations/mcp/capture/antigravity-sync-tracker.js +115 -0
  42. package/dist/integrations/mcp/capture/cli-extractor.d.ts +18 -0
  43. package/dist/integrations/mcp/capture/cli-extractor.js +258 -0
  44. package/dist/integrations/mcp/capture/cli-synced.d.ts +4 -0
  45. package/dist/integrations/mcp/capture/cli-synced.js +62 -0
  46. package/dist/integrations/mcp/capture/cli-transform.d.ts +30 -0
  47. package/dist/integrations/mcp/capture/cli-transform.js +62 -0
  48. package/dist/integrations/mcp/capture/cli-watcher.d.ts +31 -0
  49. package/dist/integrations/mcp/capture/cli-watcher.js +106 -0
  50. package/dist/integrations/mcp/capture/hook-handler.d.ts +2 -0
  51. package/dist/integrations/mcp/capture/hook-handler.js +157 -0
  52. package/dist/integrations/mcp/capture/sqlite-reader.d.ts +35 -0
  53. package/dist/integrations/mcp/capture/sqlite-reader.js +388 -0
  54. package/dist/integrations/mcp/capture/sync-tracker.d.ts +16 -0
  55. package/dist/integrations/mcp/capture/sync-tracker.js +102 -0
  56. package/dist/integrations/mcp/clients/cursor/rules-installer.d.ts +19 -0
  57. package/dist/integrations/mcp/clients/cursor/rules-installer.js +123 -0
  58. package/dist/integrations/mcp/index.d.ts +1 -0
  59. package/dist/integrations/mcp/index.js +94 -0
  60. package/dist/integrations/mcp/logger.d.ts +8 -0
  61. package/dist/integrations/mcp/logger.js +50 -0
  62. package/dist/integrations/mcp/server.d.ts +5 -0
  63. package/dist/integrations/mcp/server.js +58 -0
  64. package/dist/integrations/mcp/tools/expand.d.ts +1 -0
  65. package/dist/integrations/mcp/tools/expand.js +53 -0
  66. package/dist/integrations/mcp/tools/preview.d.ts +1 -0
  67. package/dist/integrations/mcp/tools/preview.js +64 -0
  68. package/dist/integrations/proxy/agents/base.d.ts +43 -0
  69. package/dist/integrations/proxy/agents/base.js +13 -0
  70. package/dist/{proxy/utils → integrations/proxy/agents/claude}/extractors.d.ts +4 -8
  71. package/dist/{proxy/utils → integrations/proxy/agents/claude}/extractors.js +4 -33
  72. package/dist/{proxy → integrations/proxy/agents/claude}/forwarder.d.ts +1 -1
  73. package/dist/{proxy → integrations/proxy/agents/claude}/forwarder.js +22 -6
  74. package/dist/integrations/proxy/agents/claude/index.d.ts +43 -0
  75. package/dist/integrations/proxy/agents/claude/index.js +386 -0
  76. package/dist/{proxy/action-parser.d.ts → integrations/proxy/agents/claude/parser.d.ts} +1 -1
  77. package/dist/integrations/proxy/agents/codex/extractors.d.ts +6 -0
  78. package/dist/integrations/proxy/agents/codex/extractors.js +49 -0
  79. package/dist/integrations/proxy/agents/codex/forwarder.d.ts +9 -0
  80. package/dist/integrations/proxy/agents/codex/forwarder.js +125 -0
  81. package/dist/integrations/proxy/agents/codex/index.d.ts +44 -0
  82. package/dist/integrations/proxy/agents/codex/index.js +371 -0
  83. package/dist/integrations/proxy/agents/codex/parser.d.ts +11 -0
  84. package/dist/integrations/proxy/agents/codex/parser.js +104 -0
  85. package/dist/integrations/proxy/agents/codex/patch.d.ts +12 -0
  86. package/dist/integrations/proxy/agents/codex/patch.js +40 -0
  87. package/dist/integrations/proxy/agents/codex/settings.d.ts +18 -0
  88. package/dist/integrations/proxy/agents/codex/settings.js +73 -0
  89. package/dist/integrations/proxy/agents/codex/types.d.ts +59 -0
  90. package/dist/integrations/proxy/agents/codex/types.js +2 -0
  91. package/dist/integrations/proxy/agents/index.d.ts +11 -0
  92. package/dist/integrations/proxy/agents/index.js +25 -0
  93. package/dist/integrations/proxy/agents/types.d.ts +77 -0
  94. package/dist/integrations/proxy/agents/types.js +2 -0
  95. package/dist/{proxy → integrations/proxy/cache}/extended-cache.js +2 -6
  96. package/dist/{proxy → integrations/proxy}/config.js +1 -1
  97. package/dist/{proxy → integrations/proxy}/handlers/preprocess.d.ts +3 -3
  98. package/dist/integrations/proxy/handlers/preprocess.js +194 -0
  99. package/dist/integrations/proxy/index.js +20 -0
  100. package/dist/integrations/proxy/injection/memory-injection.d.ts +56 -0
  101. package/dist/integrations/proxy/injection/memory-injection.js +252 -0
  102. package/dist/integrations/proxy/orchestrator.d.ts +30 -0
  103. package/dist/integrations/proxy/orchestrator.js +954 -0
  104. package/dist/integrations/proxy/request-processor.d.ts +14 -0
  105. package/dist/integrations/proxy/request-processor.js +68 -0
  106. package/dist/{proxy → integrations/proxy}/response-processor.d.ts +4 -3
  107. package/dist/{proxy → integrations/proxy}/response-processor.js +51 -43
  108. package/dist/{proxy → integrations/proxy}/server.d.ts +0 -1
  109. package/dist/integrations/proxy/server.js +146 -0
  110. package/dist/{proxy → integrations/proxy}/types.d.ts +4 -0
  111. package/dist/{proxy → integrations/proxy}/utils/logging.d.ts +1 -0
  112. package/dist/{proxy → integrations/proxy}/utils/logging.js +5 -0
  113. package/package.json +31 -10
  114. package/postinstall.js +62 -6
  115. package/dist/cli.js +0 -149
  116. package/dist/commands/capture.d.ts +0 -6
  117. package/dist/commands/capture.js +0 -324
  118. package/dist/commands/disable.d.ts +0 -1
  119. package/dist/commands/disable.js +0 -14
  120. package/dist/commands/doctor.d.ts +0 -1
  121. package/dist/commands/doctor.js +0 -89
  122. package/dist/commands/init.d.ts +0 -1
  123. package/dist/commands/init.js +0 -52
  124. package/dist/commands/inject.d.ts +0 -5
  125. package/dist/commands/inject.js +0 -88
  126. package/dist/commands/prompt-inject.d.ts +0 -4
  127. package/dist/commands/prompt-inject.js +0 -451
  128. package/dist/commands/unregister.d.ts +0 -1
  129. package/dist/commands/unregister.js +0 -28
  130. package/dist/lib/anchor-extractor.d.ts +0 -30
  131. package/dist/lib/anchor-extractor.js +0 -296
  132. package/dist/lib/correction-builder.d.ts +0 -10
  133. package/dist/lib/correction-builder.js +0 -226
  134. package/dist/lib/drift-checker-proxy.js +0 -373
  135. package/dist/lib/drift-checker.d.ts +0 -66
  136. package/dist/lib/drift-checker.js +0 -341
  137. package/dist/lib/hooks.d.ts +0 -38
  138. package/dist/lib/hooks.js +0 -291
  139. package/dist/lib/jsonl-parser.d.ts +0 -87
  140. package/dist/lib/jsonl-parser.js +0 -281
  141. package/dist/lib/session-parser.d.ts +0 -44
  142. package/dist/lib/session-parser.js +0 -256
  143. package/dist/lib/store.d.ts +0 -1
  144. package/dist/proxy/cache.d.ts +0 -32
  145. package/dist/proxy/cache.js +0 -47
  146. package/dist/proxy/handlers/preprocess.js +0 -186
  147. package/dist/proxy/index.js +0 -30
  148. package/dist/proxy/injection/delta-tracking.d.ts +0 -11
  149. package/dist/proxy/injection/delta-tracking.js +0 -94
  150. package/dist/proxy/injection/injectors.d.ts +0 -7
  151. package/dist/proxy/injection/injectors.js +0 -139
  152. package/dist/proxy/request-processor.d.ts +0 -27
  153. package/dist/proxy/request-processor.js +0 -233
  154. package/dist/proxy/server.js +0 -1289
  155. /package/dist/{commands → cli/commands}/drift-test.d.ts +0 -0
  156. /package/dist/{commands → cli/commands}/login.d.ts +0 -0
  157. /package/dist/{commands → cli/commands}/logout.d.ts +0 -0
  158. /package/dist/{commands → cli/commands}/proxy-status.d.ts +0 -0
  159. /package/dist/{commands → cli/commands}/status.d.ts +0 -0
  160. /package/dist/{commands → cli/commands}/uninstall.d.ts +0 -0
  161. /package/dist/{cli.d.ts → cli/index.d.ts} +0 -0
  162. /package/dist/{lib → core/cloud}/api-client.d.ts +0 -0
  163. /package/dist/{lib → core/cloud}/api-client.js +0 -0
  164. /package/dist/{lib → core/cloud}/credentials.d.ts +0 -0
  165. /package/dist/{lib → core/cloud}/credentials.js +0 -0
  166. /package/dist/{lib → core}/store/convenience.d.ts +0 -0
  167. /package/dist/{lib → core}/store/convenience.js +0 -0
  168. /package/dist/{lib → core}/store/database.d.ts +0 -0
  169. /package/dist/{lib → core}/store/database.js +0 -0
  170. /package/dist/{lib → core}/store/drift.d.ts +0 -0
  171. /package/dist/{lib → core}/store/drift.js +0 -0
  172. /package/dist/{lib → core}/store/index.d.ts +0 -0
  173. /package/dist/{lib → core}/store/index.js +0 -0
  174. /package/dist/{lib → core}/store/sessions.d.ts +0 -0
  175. /package/dist/{lib → core}/store/steps.d.ts +0 -0
  176. /package/dist/{lib → core}/store/steps.js +0 -0
  177. /package/dist/{lib → core}/store/tasks.d.ts +0 -0
  178. /package/dist/{lib → core}/store/tasks.js +0 -0
  179. /package/dist/{lib → core}/store/types.js +0 -0
  180. /package/dist/{proxy/action-parser.js → integrations/proxy/agents/claude/parser.js} +0 -0
  181. /package/dist/{lib → integrations/proxy/agents/claude}/settings.d.ts +0 -0
  182. /package/dist/{lib → integrations/proxy/agents/claude}/settings.js +0 -0
  183. /package/dist/{proxy → integrations/proxy/cache}/extended-cache.d.ts +0 -0
  184. /package/dist/{proxy → integrations/proxy}/config.d.ts +0 -0
  185. /package/dist/{proxy → integrations/proxy}/index.d.ts +0 -0
  186. /package/dist/{proxy → integrations/proxy}/types.js +0 -0
  187. /package/dist/{lib → utils}/debug.d.ts +0 -0
  188. /package/dist/{lib → utils}/debug.js +0 -0
  189. /package/dist/{lib → utils}/utils.d.ts +0 -0
  190. /package/dist/{lib → utils}/utils.js +0 -0
@@ -0,0 +1,90 @@
1
+ // grov init - Configure AI agent to use grov proxy/MCP
2
+ import { getAgentByName } from '../../integrations/proxy/agents/index.js';
3
+ import { setupMcpCursor, setupMcpAntigravity, setupMcpZed, setupCursorHooks } from './setup.js';
4
+ import { installProjectRules } from '../../integrations/mcp/clients/cursor/rules-installer.js';
5
+ const AGENT_INSTRUCTIONS = {
6
+ claude: {
7
+ envVar: 'ANTHROPIC_API_KEY',
8
+ command: 'claude',
9
+ keyUrl: 'https://console.anthropic.com/settings/keys',
10
+ },
11
+ codex: {
12
+ envVar: 'OPENAI_API_KEY',
13
+ command: 'codex',
14
+ keyUrl: 'https://platform.openai.com/api-keys',
15
+ },
16
+ };
17
+ export async function init(agentName = 'claude') {
18
+ // Cursor: MCP-based setup (different from proxy)
19
+ if (agentName === 'cursor') {
20
+ console.log('Configuring grov for Cursor...\n');
21
+ // 1. MCP registration (global)
22
+ await setupMcpCursor();
23
+ // 2. Stop hook registration (global)
24
+ await setupCursorHooks();
25
+ // 3. Project rules (per-project)
26
+ const projectDir = process.cwd();
27
+ const result = installProjectRules(projectDir);
28
+ if (result.grovRules) {
29
+ console.log(' + Created .grov/rules.mdc');
30
+ }
31
+ else {
32
+ console.log(' = .grov/rules.mdc already exists');
33
+ }
34
+ if (result.cursorPointer) {
35
+ console.log(' + Created .cursor/rules/90_grov.mdc');
36
+ }
37
+ else {
38
+ console.log(' = .cursor/rules/90_grov.mdc already exists');
39
+ }
40
+ console.log('\n--- Next Steps ---');
41
+ console.log('1. Restart Cursor');
42
+ console.log('2. Open this project in Cursor');
43
+ console.log('\nRun "grov doctor cursor" to verify setup.');
44
+ return;
45
+ }
46
+ // Antigravity: MCP-based setup
47
+ if (agentName === 'antigravity') {
48
+ console.log('Configuring grov for Antigravity...\n');
49
+ // MCP registration (global)
50
+ await setupMcpAntigravity();
51
+ console.log('\n--- Next Steps ---');
52
+ console.log('1. Restart Antigravity');
53
+ console.log('2. Open your project in Antigravity');
54
+ console.log('\nRun "grov doctor antigravity" to verify setup.');
55
+ return;
56
+ }
57
+ // Zed: MCP-based setup
58
+ if (agentName === 'zed') {
59
+ console.log('Configuring grov for Zed...\n');
60
+ // MCP registration (global)
61
+ await setupMcpZed();
62
+ console.log('\n--- Next Steps ---');
63
+ console.log('1. Restart Zed');
64
+ console.log('2. Open the Agent Panel in Zed');
65
+ console.log('\nRun "grov doctor zed" to verify setup.');
66
+ return;
67
+ }
68
+ // Claude/Codex: proxy-based setup
69
+ const agent = getAgentByName(agentName);
70
+ if (!agent) {
71
+ console.error(`Unknown agent: ${agentName}`);
72
+ console.error('Supported agents: claude, codex, cursor');
73
+ process.exit(1);
74
+ }
75
+ const instructions = AGENT_INSTRUCTIONS[agentName];
76
+ console.log(`Configuring grov for ${agentName}...\n`);
77
+ const settings = agent.getSettings();
78
+ const result = settings.setProxyEnabled(true);
79
+ if (result.action === 'added') {
80
+ console.log(` + Proxy configured for ${agentName}`);
81
+ }
82
+ else if (result.action === 'unchanged') {
83
+ console.log(` = Proxy already configured for ${agentName}`);
84
+ }
85
+ console.log(`\nConfig file: ${settings.getConfigPath()}`);
86
+ console.log('\n--- Next Steps (Claude/Codex) ---');
87
+ console.log('1. Terminal 1: grov proxy');
88
+ console.log(`2. Terminal 2: ${instructions.command}`);
89
+ console.log('\nRun "grov doctor" to verify your setup is complete.');
90
+ }
@@ -2,8 +2,9 @@
2
2
  // Authenticates CLI with Grov cloud using OAuth-like device flow
3
3
  import open from 'open';
4
4
  import * as readline from 'readline';
5
- import { writeCredentials, isAuthenticated, readCredentials, setTeamId, setSyncEnabled } from '../lib/credentials.js';
6
- import { startDeviceFlow, pollDeviceFlow, sleep, fetchTeams } from '../lib/api-client.js';
5
+ import { writeCredentials, isAuthenticated, readCredentials, setTeamId, setSyncEnabled } from '../../core/cloud/credentials.js';
6
+ import { startDeviceFlow, pollDeviceFlow, sleep, fetchTeams } from '../../core/cloud/api-client.js';
7
+ import { isAnyAgentConfigured } from '../agents/registry.js';
7
8
  /**
8
9
  * Prompt user for input
9
10
  */
@@ -38,6 +39,7 @@ function decodeTokenPayload(token) {
38
39
  }
39
40
  }
40
41
  export async function login() {
42
+ const autoMode = process.argv.includes('--auto');
41
43
  console.log('Logging in to Grov cloud...\n');
42
44
  // Check if already authenticated
43
45
  if (isAuthenticated()) {
@@ -119,8 +121,8 @@ export async function login() {
119
121
  return;
120
122
  }
121
123
  let selectedTeam = teams[0];
122
- // If multiple teams, let user choose
123
- if (teams.length > 1) {
124
+ // If multiple teams, let user choose (skip in auto mode)
125
+ if (teams.length > 1 && !autoMode) {
124
126
  console.log('\nYour teams:');
125
127
  teams.forEach((team, i) => {
126
128
  console.log(` ${i + 1}. ${team.name} (${team.slug})`);
@@ -131,8 +133,8 @@ export async function login() {
131
133
  selectedTeam = teams[index];
132
134
  }
133
135
  }
134
- // Ask to enable sync (default yes)
135
- const enableSync = await prompt(`Enable cloud sync to "${selectedTeam.name}"? [Y/n]: `);
136
+ // Ask to enable sync (default yes, skip in auto mode)
137
+ const enableSync = autoMode ? '' : await prompt(`Enable cloud sync to "${selectedTeam.name}"? [Y/n]: `);
136
138
  if (enableSync !== 'n' && enableSync !== 'no') {
137
139
  setTeamId(selectedTeam.id);
138
140
  setSyncEnabled(true);
@@ -142,21 +144,20 @@ export async function login() {
142
144
  console.log('║ ║');
143
145
  console.log('╚═════════════════════════════════════════╝');
144
146
  console.log(`\nSyncing to: ${selectedTeam.name}`);
145
- // Check API key and warn if not set
146
- if (!process.env.ANTHROPIC_API_KEY) {
147
- const shell = process.env.SHELL?.includes('zsh') ? '~/.zshrc' : '~/.bashrc';
148
- console.log('\n⚠️ WARNING: ANTHROPIC_API_KEY not set - memories will NOT sync!');
149
- console.log('\n Add PERMANENTLY to your shell (not just "export"):');
150
- console.log(` echo 'export ANTHROPIC_API_KEY=sk-ant-...' >> ${shell}`);
151
- console.log(` source ${shell}`);
152
- console.log('\n Get your key at: https://console.anthropic.com/settings/keys');
153
- }
154
- console.log('\nRun "grov doctor" to verify your setup is complete.');
155
- console.log('View memories at: https://app.grov.dev/memories\n');
156
147
  }
157
148
  else {
158
149
  console.log('\n✓ Logged in. Sync not enabled.');
159
- console.log('Run "grov sync --enable" later to start syncing.\n');
150
+ }
151
+ // Continue to agent setup if no agent configured
152
+ if (!isAnyAgentConfigured()) {
153
+ console.log('\n───────────────────────────────────────────────────────────\n');
154
+ console.log('Now let\'s configure your AI agent...\n');
155
+ const { runAgentSetup } = await import('./setup.js');
156
+ await runAgentSetup();
157
+ }
158
+ else {
159
+ console.log('\nRun "grov doctor" to verify your setup is complete.');
160
+ console.log('View memories at: https://app.grov.dev/memories\n');
160
161
  }
161
162
  }
162
163
  catch (err) {
@@ -1,5 +1,5 @@
1
1
  // Logout command - Clear stored credentials
2
- import { clearCredentials, readCredentials } from '../lib/credentials.js';
2
+ import { clearCredentials, readCredentials } from '../../core/cloud/credentials.js';
3
3
  export async function logout() {
4
4
  const creds = readCredentials();
5
5
  if (!creds) {
@@ -1,5 +1,5 @@
1
1
  // grov proxy-status - Show active proxy sessions
2
- import { getActiveSessionsForStatus } from '../lib/store.js';
2
+ import { getActiveSessionsForStatus } from '../../core/store/store.js';
3
3
  export async function proxyStatus() {
4
4
  const sessions = getActiveSessionsForStatus();
5
5
  if (sessions.length === 0) {
@@ -0,0 +1,6 @@
1
+ export declare function setupCursorHooks(): Promise<void>;
2
+ export declare function setupMcpCursor(): Promise<void>;
3
+ export declare function setupMcpAntigravity(): Promise<void>;
4
+ export declare function setupMcpZed(): Promise<void>;
5
+ export declare function runAgentSetup(): Promise<void>;
6
+ export declare function setup(): Promise<void>;
@@ -0,0 +1,309 @@
1
+ // Setup commands for grov integrations
2
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
3
+ import { homedir } from 'os';
4
+ import { join } from 'path';
5
+ import * as readline from 'readline';
6
+ import { getCliAgentsByType, isAnyAgentConfigured } from '../agents/registry.js';
7
+ const green = '\x1b[32m';
8
+ const yellow = '\x1b[33m';
9
+ const cyan = '\x1b[36m';
10
+ const dim = '\x1b[2m';
11
+ const reset = '\x1b[0m';
12
+ export async function setupCursorHooks() {
13
+ const hooksPath = join(homedir(), '.cursor', 'hooks.json');
14
+ const apiUrl = process.env.GROV_API_URL;
15
+ const command = apiUrl
16
+ ? `GROV_API_URL=${apiUrl} grov capture-hook`
17
+ : 'grov capture-hook';
18
+ const grovHook = { command };
19
+ let config = { version: 1, hooks: { stop: [] } };
20
+ if (existsSync(hooksPath)) {
21
+ try {
22
+ const content = readFileSync(hooksPath, 'utf-8');
23
+ config = JSON.parse(content);
24
+ if (!config.hooks)
25
+ config.hooks = {};
26
+ if (!config.hooks.stop)
27
+ config.hooks.stop = [];
28
+ }
29
+ catch {
30
+ config = { version: 1, hooks: { stop: [] } };
31
+ }
32
+ }
33
+ // Remove existing grov hook (if any) to replace with new one
34
+ const hadGrovHook = config.hooks.stop.some((h) => h.command?.includes('grov capture-hook'));
35
+ config.hooks.stop = config.hooks.stop.filter((h) => !h.command?.includes('grov capture-hook'));
36
+ // Add new grov hook
37
+ config.hooks.stop.push(grovHook);
38
+ try {
39
+ writeFileSync(hooksPath, JSON.stringify(config, null, 2));
40
+ if (hadGrovHook) {
41
+ console.log(`${green}✓${reset} Cursor stop hook updated.`);
42
+ }
43
+ else {
44
+ console.log(`${green}✓${reset} Cursor stop hook configured.`);
45
+ }
46
+ if (apiUrl) {
47
+ console.log(`${dim} API URL: ${apiUrl}${reset}`);
48
+ }
49
+ }
50
+ catch (err) {
51
+ const msg = err instanceof Error ? err.message : 'Unknown error';
52
+ console.error(`${yellow}⚠${reset} Could not write ${hooksPath}: ${msg}`);
53
+ }
54
+ }
55
+ export async function setupMcpCursor() {
56
+ const cursorDir = join(homedir(), '.cursor');
57
+ const mcpPath = join(cursorDir, 'mcp.json');
58
+ // Check if Cursor directory exists
59
+ if (!existsSync(cursorDir)) {
60
+ console.log(`${yellow}⚠${reset} Cursor not installed (~/.cursor not found)`);
61
+ console.log(`${dim}Install Cursor first, then run this command again.${reset}\n`);
62
+ return;
63
+ }
64
+ // Build grov entry - add env if GROV_API_URL is set
65
+ const apiUrl = process.env.GROV_API_URL;
66
+ const grovEntry = {
67
+ command: 'grov',
68
+ args: ['mcp'],
69
+ };
70
+ if (apiUrl) {
71
+ grovEntry.env = { GROV_API_URL: apiUrl };
72
+ }
73
+ let mcpConfig = { mcpServers: {} };
74
+ // Read existing config
75
+ if (existsSync(mcpPath)) {
76
+ try {
77
+ const content = readFileSync(mcpPath, 'utf-8');
78
+ mcpConfig = JSON.parse(content);
79
+ if (!mcpConfig.mcpServers) {
80
+ mcpConfig.mcpServers = {};
81
+ }
82
+ }
83
+ catch {
84
+ console.log(`${yellow}⚠${reset} Could not parse ${mcpPath}, creating new config.`);
85
+ mcpConfig = { mcpServers: {} };
86
+ }
87
+ }
88
+ const wasConfigured = !!mcpConfig.mcpServers?.grov;
89
+ // Always set/update grov entry
90
+ mcpConfig.mcpServers.grov = grovEntry;
91
+ // Write config
92
+ try {
93
+ writeFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2));
94
+ if (wasConfigured) {
95
+ console.log(`${green}✓${reset} Cursor MCP updated.`);
96
+ }
97
+ else {
98
+ console.log(`${green}✓${reset} Cursor MCP configured.`);
99
+ }
100
+ if (apiUrl) {
101
+ console.log(`${dim} API URL: ${apiUrl}${reset}`);
102
+ }
103
+ console.log(`${dim}Restart Cursor to apply changes.${reset}\n`);
104
+ }
105
+ catch (err) {
106
+ const msg = err instanceof Error ? err.message : 'Unknown error';
107
+ console.error(`${yellow}⚠${reset} Could not write ${mcpPath}: ${msg}`);
108
+ }
109
+ }
110
+ export async function setupMcpAntigravity() {
111
+ const antigravityDir = join(homedir(), '.gemini', 'antigravity');
112
+ const mcpConfigPath = join(antigravityDir, 'mcp_config.json');
113
+ // Check if Antigravity directory exists
114
+ if (!existsSync(antigravityDir)) {
115
+ console.log(`${yellow}⚠${reset} Antigravity not installed (~/.gemini/antigravity not found)`);
116
+ console.log(`${dim}Install Antigravity first, then run this command again.${reset}\n`);
117
+ return;
118
+ }
119
+ // Extract project name from cwd (Antigravity runs MCP with cwd="/")
120
+ const projectPath = process.cwd().split('/').filter(Boolean).pop() || 'unknown';
121
+ const grovEntry = {
122
+ command: 'grov',
123
+ args: ['mcp'],
124
+ env: {
125
+ GROV_PROJECT_PATH: projectPath,
126
+ },
127
+ };
128
+ let config = { mcpServers: {} };
129
+ // Read existing config
130
+ if (existsSync(mcpConfigPath)) {
131
+ try {
132
+ const content = readFileSync(mcpConfigPath, 'utf-8');
133
+ config = JSON.parse(content);
134
+ if (!config.mcpServers) {
135
+ config.mcpServers = {};
136
+ }
137
+ }
138
+ catch {
139
+ console.log(`${yellow}⚠${reset} Could not parse ${mcpConfigPath}, creating new config.`);
140
+ config = { mcpServers: {} };
141
+ }
142
+ }
143
+ // Check if already configured
144
+ if (config.mcpServers?.grov) {
145
+ console.log(`${green}✓${reset} Antigravity MCP already configured for grov.`);
146
+ console.log(`${dim}Restart Antigravity to apply any changes.${reset}\n`);
147
+ return;
148
+ }
149
+ // Add grov entry
150
+ config.mcpServers.grov = grovEntry;
151
+ // Write config
152
+ try {
153
+ writeFileSync(mcpConfigPath, JSON.stringify(config, null, 2));
154
+ console.log(`${green}✓${reset} Antigravity MCP configured.`);
155
+ console.log(`${dim}Restart Antigravity to activate grov.${reset}\n`);
156
+ }
157
+ catch (err) {
158
+ const msg = err instanceof Error ? err.message : 'Unknown error';
159
+ console.error(`${yellow}⚠${reset} Could not write ${mcpConfigPath}: ${msg}`);
160
+ }
161
+ }
162
+ export async function setupMcpZed() {
163
+ const zedConfigDir = join(homedir(), '.config', 'zed');
164
+ const settingsPath = join(zedConfigDir, 'settings.json');
165
+ // Check if Zed config directory exists
166
+ if (!existsSync(zedConfigDir)) {
167
+ console.log(`${yellow}⚠${reset} Zed not installed (~/.config/zed not found)`);
168
+ console.log(`${dim}Install Zed first, then run this command again.${reset}\n`);
169
+ return;
170
+ }
171
+ const grovEntry = {
172
+ command: 'grov',
173
+ args: ['mcp'],
174
+ };
175
+ let config = {};
176
+ // Read existing config (preserve all settings)
177
+ if (existsSync(settingsPath)) {
178
+ try {
179
+ // Zed settings.json may have comments, try to parse anyway
180
+ const content = readFileSync(settingsPath, 'utf-8');
181
+ // Remove single-line comments for parsing
182
+ const cleanContent = content.replace(/^\s*\/\/.*$/gm, '');
183
+ config = JSON.parse(cleanContent);
184
+ }
185
+ catch {
186
+ console.log(`${yellow}⚠${reset} Could not parse ${settingsPath}. Please add grov manually.`);
187
+ console.log(`\nAdd to your settings.json under "context_servers":`);
188
+ console.log(` "grov": { "command": "grov", "args": ["mcp"] }\n`);
189
+ return;
190
+ }
191
+ }
192
+ // Ensure context_servers object exists
193
+ if (!config.context_servers) {
194
+ config.context_servers = {};
195
+ }
196
+ const contextServers = config.context_servers;
197
+ // Check if already configured
198
+ if (contextServers.grov) {
199
+ console.log(`${green}✓${reset} Zed context_servers already configured for grov.`);
200
+ console.log(`${dim}Restart Zed to apply any changes.${reset}\n`);
201
+ return;
202
+ }
203
+ // Add grov entry
204
+ contextServers.grov = grovEntry;
205
+ // Write config
206
+ try {
207
+ writeFileSync(settingsPath, JSON.stringify(config, null, 2));
208
+ console.log(`${green}✓${reset} Zed context_servers configured.`);
209
+ console.log(`${dim}Restart Zed to activate grov.${reset}\n`);
210
+ }
211
+ catch (err) {
212
+ const msg = err instanceof Error ? err.message : 'Unknown error';
213
+ console.error(`${yellow}⚠${reset} Could not write ${settingsPath}: ${msg}`);
214
+ }
215
+ }
216
+ function prompt(question) {
217
+ const rl = readline.createInterface({
218
+ input: process.stdin,
219
+ output: process.stdout,
220
+ });
221
+ return new Promise((resolve) => {
222
+ rl.question(question, (answer) => {
223
+ rl.close();
224
+ resolve(answer.trim());
225
+ });
226
+ });
227
+ }
228
+ export async function runAgentSetup() {
229
+ const cliAgents = getCliAgentsByType('cli');
230
+ const ideAgents = getCliAgentsByType('ide');
231
+ const allAgents = [...cliAgents, ...ideAgents];
232
+ console.log('What AI tool do you use?\n');
233
+ console.log('CLI AGENTS (require proxy running)');
234
+ cliAgents.forEach((agent, i) => {
235
+ console.log(` ${i + 1}. ${agent.name} - ${agent.description}`);
236
+ });
237
+ console.log('\nIDE AGENTS (native integration, no proxy)');
238
+ ideAgents.forEach((agent, i) => {
239
+ console.log(` ${cliAgents.length + i + 1}. ${agent.name} - ${agent.description}`);
240
+ });
241
+ const choice = await prompt(`\nSelect agent [1-${allAgents.length}]: `);
242
+ const index = parseInt(choice, 10) - 1;
243
+ if (index < 0 || index >= allAgents.length || isNaN(index)) {
244
+ console.log('\nInvalid selection. Run "grov setup" to try again.\n');
245
+ return;
246
+ }
247
+ const selectedAgent = allAgents[index];
248
+ await configureAgent(selectedAgent);
249
+ showFinalInstructions(selectedAgent);
250
+ }
251
+ async function configureAgent(agent) {
252
+ console.log(`\nConfiguring ${agent.name}...\n`);
253
+ const { init } = await import('./init.js');
254
+ await init(agent.id);
255
+ }
256
+ function showFinalInstructions(agent) {
257
+ console.log('\n╔═════════════════════════════════════════════════════════╗');
258
+ console.log('║ ║');
259
+ console.log('║ ✓ Setup complete! ║');
260
+ console.log('║ ║');
261
+ console.log('╚═════════════════════════════════════════════════════════╝\n');
262
+ if (agent.type === 'cli') {
263
+ console.log('┌─────────────────────────────────────────────────────┐');
264
+ console.log('│ HOW TO USE GROV │');
265
+ console.log('│ │');
266
+ console.log('│ 1. Start proxy (keep running): │');
267
+ console.log('│ $ grov proxy │');
268
+ console.log('│ │');
269
+ console.log('│ 2. In another terminal, use your agent: │');
270
+ console.log(`│ $ ${agent.command}`.padEnd(54) + '│');
271
+ console.log('│ │');
272
+ console.log('│ 3. View your team\'s memories: │');
273
+ console.log('│ https://app.grov.dev │');
274
+ console.log('└─────────────────────────────────────────────────────┘');
275
+ }
276
+ else {
277
+ console.log('┌─────────────────────────────────────────────────────┐');
278
+ console.log('│ HOW TO USE GROV │');
279
+ console.log('│ │');
280
+ console.log(`│ 1. Restart ${agent.name}`.padEnd(54) + '│');
281
+ console.log('│ │');
282
+ console.log(`│ 2. Use ${agent.name} normally`.padEnd(54) + '│');
283
+ console.log('│ Grov runs automatically in the background │');
284
+ console.log('│ │');
285
+ console.log('│ 3. View your team\'s memories: │');
286
+ console.log('│ https://app.grov.dev │');
287
+ console.log('└─────────────────────────────────────────────────────┘');
288
+ }
289
+ console.log('\nTip: Run "grov doctor" anytime to check status\n');
290
+ }
291
+ export async function setup() {
292
+ const { isAuthenticated } = await import('../../core/cloud/credentials.js');
293
+ if (!isAuthenticated()) {
294
+ console.log('Let\'s get you set up with Grov.\n');
295
+ console.log('First, we\'ll connect to your team...\n');
296
+ const { login } = await import('./login.js');
297
+ await login();
298
+ return;
299
+ }
300
+ if (isAnyAgentConfigured()) {
301
+ console.log('An agent is already configured.\n');
302
+ const reconfigure = await prompt('Reconfigure? [y/N]: ');
303
+ if (reconfigure.toLowerCase() !== 'y' && reconfigure.toLowerCase() !== 'yes') {
304
+ console.log('\nRun "grov doctor" to check your setup.\n');
305
+ return;
306
+ }
307
+ }
308
+ await runAgentSetup();
309
+ }
@@ -1,5 +1,5 @@
1
1
  // grov status - Show stored reasoning for current project
2
- import { getTasksForProject, getTaskCount, getDatabasePath } from '../lib/store.js';
2
+ import { getTasksForProject, getTaskCount, getDatabasePath } from '../../core/store/store.js';
3
3
  export async function status(options) {
4
4
  const projectPath = process.cwd();
5
5
  console.log('Grov Status');
@@ -4,5 +4,6 @@ export interface SyncOptions {
4
4
  team?: string;
5
5
  status?: boolean;
6
6
  push?: boolean;
7
+ antigravity?: boolean;
7
8
  }
8
9
  export declare function sync(options: SyncOptions): Promise<void>;
@@ -1,14 +1,21 @@
1
1
  // Sync command - Configure cloud sync settings
2
- import { readCredentials, setTeamId, setSyncEnabled, getSyncStatus } from '../lib/credentials.js';
3
- import { fetchTeams, getApiUrl } from '../lib/api-client.js';
4
- import { syncTasks } from '../lib/cloud-sync.js';
5
- import { getUnsyncedTasks, markTaskSynced, setTaskSyncError } from '../lib/store.js';
2
+ import { readCredentials, setTeamId, setSyncEnabled, getSyncStatus } from '../../core/cloud/credentials.js';
3
+ import { fetchTeams, getApiUrl } from '../../core/cloud/api-client.js';
4
+ import { syncTasks } from '../../core/cloud/cloud-sync.js';
5
+ import { getUnsyncedTasks, markTaskSynced, setTaskSyncError } from '../../core/store/store.js';
6
+ import { scanOnce as scanAntigravity } from '../../integrations/mcp/capture/antigravity-scanner.js';
7
+ import { antigravityExists } from '../../integrations/mcp/capture/antigravity-parser.js';
6
8
  export async function sync(options) {
7
9
  const creds = readCredentials();
8
10
  if (!creds) {
9
11
  console.log('Not logged in. Run "grov login" first.\n');
10
12
  process.exit(1);
11
13
  }
14
+ // Sync Antigravity sessions
15
+ if (options.antigravity) {
16
+ await syncAntigravitySessions();
17
+ return;
18
+ }
12
19
  // Manual catch-up: push unsynced tasks for current project
13
20
  if (options.push) {
14
21
  const projectPath = process.cwd();
@@ -125,3 +132,51 @@ export async function sync(options) {
125
132
  }
126
133
  }
127
134
  }
135
+ // ─────────────────────────────────────────────────────────────
136
+ // Antigravity Sync
137
+ // ─────────────────────────────────────────────────────────────
138
+ async function syncAntigravitySessions() {
139
+ // Check prerequisites
140
+ if (!antigravityExists()) {
141
+ console.log('Antigravity not installed.\n');
142
+ console.log('Antigravity IDE stores its data in ~/.gemini/antigravity/');
143
+ console.log('Install Antigravity or check if the directory exists.\n');
144
+ process.exit(1);
145
+ }
146
+ const syncStatus = getSyncStatus();
147
+ if (!syncStatus?.enabled || !syncStatus.teamId) {
148
+ console.log('Cloud sync not configured.\n');
149
+ console.log('Enable sync first:');
150
+ console.log(' grov sync --enable --team <team-id>\n');
151
+ process.exit(1);
152
+ }
153
+ console.log('Scanning Antigravity sessions...\n');
154
+ try {
155
+ const result = await scanAntigravity();
156
+ console.log('Antigravity Sync Results\n');
157
+ console.log(` Sessions scanned: ${result.scanned}`);
158
+ console.log(` New memories: ${result.synced}`);
159
+ console.log(` Updated: ${result.updated}`);
160
+ console.log(` Skipped: ${result.skipped}`);
161
+ console.log(` Failed: ${result.failed}`);
162
+ console.log('');
163
+ if (result.errors.length > 0) {
164
+ console.log('Errors:');
165
+ for (const err of result.errors) {
166
+ console.log(` - ${err}`);
167
+ }
168
+ console.log('');
169
+ }
170
+ if (result.scanned === 0) {
171
+ console.log('No sessions found in ~/.gemini/antigravity/brain/');
172
+ console.log('Sessions are created when you use Antigravity IDE.\n');
173
+ }
174
+ else if (result.synced === 0 && result.updated === 0 && result.failed === 0) {
175
+ console.log('All sessions are already synced.\n');
176
+ }
177
+ }
178
+ catch (err) {
179
+ console.error(`Sync failed: ${err instanceof Error ? err.message : 'Unknown error'}\n`);
180
+ process.exit(1);
181
+ }
182
+ }
@@ -3,8 +3,8 @@ import { rmSync, existsSync } from 'fs';
3
3
  import { homedir } from 'os';
4
4
  import { join } from 'path';
5
5
  import * as readline from 'readline';
6
- import { setProxyEnv } from '../lib/settings.js';
7
- import { clearCredentials } from '../lib/credentials.js';
6
+ import { setProxyEnv } from '../../integrations/proxy/agents/claude/settings.js';
7
+ import { clearCredentials } from '../../core/cloud/credentials.js';
8
8
  const GROV_DIR = join(homedir(), '.grov');
9
9
  function prompt(question) {
10
10
  const rl = readline.createInterface({