grov 0.5.5 → 0.5.7

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.
package/README.md CHANGED
@@ -166,6 +166,7 @@ grov proxy-status # Show active sessions
166
166
  grov status # Show captured tasks
167
167
  grov login # Login to cloud dashboard
168
168
  grov sync # Sync memories to team dashboard
169
+ grov doctor # Diagnose setup issues
169
170
  grov disable # Disable grov
170
171
  grov drift-test # Test drift detection
171
172
  ```
@@ -213,7 +214,7 @@ Browse, search, and manage your team's AI knowledge at [app.grov.dev](https://ap
213
214
  ## Environment Variables
214
215
 
215
216
  ```bash
216
- # Required for drift detection and LLM extraction
217
+ # Required for memory sync and drift detection
217
218
  export ANTHROPIC_API_KEY=sk-ant-...
218
219
 
219
220
  # Optional
@@ -222,7 +223,45 @@ export PROXY_HOST=127.0.0.1 # Proxy host
222
223
  export PROXY_PORT=8080 # Proxy port
223
224
  ```
224
225
 
225
- Without an API key, Grov uses basic extraction and disables drift detection.
226
+ Without an API key, Grov uses basic extraction and **memories will not sync**.
227
+
228
+ ---
229
+
230
+ ## Troubleshooting
231
+
232
+ ### Memories not syncing?
233
+
234
+ Run `grov doctor` to diagnose:
235
+
236
+ ```bash
237
+ grov doctor
238
+ ```
239
+
240
+ This checks your proxy, API key, login, sync status, and local database.
241
+
242
+ ### ⚠️ Common Issue: API Key Not Persisting
243
+
244
+ **Using `export ANTHROPIC_API_KEY=...` directly in terminal only works in THAT terminal session.** When you open a new terminal, the key is gone.
245
+
246
+ **Fix:** Add the key to your shell profile so it persists:
247
+
248
+ ```bash
249
+ # For zsh (macOS default):
250
+ echo 'export ANTHROPIC_API_KEY=sk-ant-...' >> ~/.zshrc
251
+ source ~/.zshrc
252
+
253
+ # For bash:
254
+ echo 'export ANTHROPIC_API_KEY=sk-ant-...' >> ~/.bashrc
255
+ source ~/.bashrc
256
+ ```
257
+
258
+ Then run `grov doctor` to verify:
259
+
260
+ ```
261
+ ✓ ANTHROPIC_API_KEY: Set
262
+ ```
263
+
264
+ Get your API key at: https://console.anthropic.com/settings/keys
226
265
 
227
266
  ---
228
267
 
package/dist/cli.js CHANGED
@@ -127,4 +127,12 @@ program
127
127
  const { sync } = await import('./commands/sync.js');
128
128
  await sync(options);
129
129
  }));
130
+ // grov doctor - Diagnose setup issues
131
+ program
132
+ .command('doctor')
133
+ .description('Check grov setup and diagnose issues')
134
+ .action(safeAction(async () => {
135
+ const { doctor } = await import('./commands/doctor.js');
136
+ await doctor();
137
+ }));
130
138
  program.parse();
@@ -0,0 +1 @@
1
+ export declare function doctor(): Promise<void>;
@@ -0,0 +1,89 @@
1
+ // grov doctor - Check setup and diagnose issues
2
+ import { existsSync, readFileSync } from 'fs';
3
+ import { homedir } from 'os';
4
+ import { join } from 'path';
5
+ import { request } from 'undici';
6
+ import { readCredentials, getSyncStatus } from '../lib/credentials.js';
7
+ import { initDatabase } from '../lib/store/database.js';
8
+ const CLAUDE_SETTINGS_PATH = join(homedir(), '.claude', 'settings.json');
9
+ const DB_PATH = join(homedir(), '.grov', 'memory.db');
10
+ export async function doctor() {
11
+ console.log('\nGrov Doctor');
12
+ console.log('===========\n');
13
+ // Check proxy
14
+ const proxyRunning = await checkProxy();
15
+ printCheck('Proxy', proxyRunning, 'Running on port 8080', 'Not running', 'grov proxy');
16
+ // Check Claude settings
17
+ const baseUrlConfigured = checkBaseUrl();
18
+ printCheck('ANTHROPIC_BASE_URL', baseUrlConfigured, 'Configured for proxy', 'Not configured', 'grov init');
19
+ // Check API key
20
+ const apiKey = process.env.ANTHROPIC_API_KEY;
21
+ const hasApiKey = !!(apiKey && apiKey.length > 10);
22
+ const shell = process.env.SHELL?.includes('zsh') ? '~/.zshrc' : '~/.bashrc';
23
+ const apiKeyFix = process.platform === 'win32'
24
+ ? 'setx ANTHROPIC_API_KEY "sk-ant-..." (permanent) or add to System Environment Variables'
25
+ : `Add to ${shell}: echo 'export ANTHROPIC_API_KEY=sk-ant-...' >> ${shell} && source ${shell}`;
26
+ printCheck('ANTHROPIC_API_KEY', hasApiKey, 'Set', 'NOT SET - memories will not sync!', apiKeyFix);
27
+ // Check login
28
+ const creds = readCredentials();
29
+ printCheck('Login', !!creds, creds ? `Logged in as ${creds.email}` : 'Not logged in', 'Not logged in', 'grov login');
30
+ // Check sync
31
+ const syncStatus = getSyncStatus();
32
+ const syncOk = syncStatus?.enabled && syncStatus?.teamId;
33
+ const syncMsg = syncOk
34
+ ? `Team ${syncStatus.teamId.substring(0, 8)}...`
35
+ : syncStatus?.teamId ? 'Disabled' : 'No team';
36
+ printCheck('Cloud Sync', !!syncOk, syncMsg, syncMsg, 'grov sync --enable --team <id>');
37
+ // Check database
38
+ const dbStats = checkDatabase();
39
+ const dbOk = dbStats.tasks > 0 || dbStats.sessions > 0;
40
+ const dbMsg = `${dbStats.tasks} tasks, ${dbStats.unsynced} unsynced, ${dbStats.sessions} active`;
41
+ printCheck('Local Database', dbOk, dbMsg, 'Empty', 'Use Claude Code with proxy running');
42
+ console.log('');
43
+ }
44
+ async function checkProxy() {
45
+ try {
46
+ const res = await request('http://127.0.0.1:8080/health', {
47
+ headersTimeout: 2000,
48
+ bodyTimeout: 2000
49
+ });
50
+ return res.statusCode === 200;
51
+ }
52
+ catch {
53
+ return false;
54
+ }
55
+ }
56
+ function checkBaseUrl() {
57
+ if (!existsSync(CLAUDE_SETTINGS_PATH))
58
+ return false;
59
+ try {
60
+ const settings = JSON.parse(readFileSync(CLAUDE_SETTINGS_PATH, 'utf-8'));
61
+ return settings.env?.ANTHROPIC_BASE_URL === 'http://127.0.0.1:8080';
62
+ }
63
+ catch {
64
+ return false;
65
+ }
66
+ }
67
+ function checkDatabase() {
68
+ if (!existsSync(DB_PATH)) {
69
+ return { tasks: 0, unsynced: 0, sessions: 0 };
70
+ }
71
+ try {
72
+ const db = initDatabase();
73
+ const tasks = db.prepare('SELECT COUNT(*) as c FROM tasks').get().c;
74
+ const unsynced = db.prepare('SELECT COUNT(*) as c FROM tasks WHERE synced_at IS NULL').get().c;
75
+ const sessions = db.prepare("SELECT COUNT(*) as c FROM session_states WHERE status = 'active'").get().c;
76
+ return { tasks, unsynced, sessions };
77
+ }
78
+ catch {
79
+ return { tasks: 0, unsynced: 0, sessions: 0 };
80
+ }
81
+ }
82
+ function printCheck(name, ok, successMsg, failMsg, fix) {
83
+ const icon = ok ? '\x1b[32m✓\x1b[0m' : '\x1b[31m✗\x1b[0m';
84
+ const msg = ok ? successMsg : failMsg;
85
+ console.log(`${icon} ${name}: ${msg}`);
86
+ if (!ok) {
87
+ console.log(` \x1b[90m→ ${fix}\x1b[0m`);
88
+ }
89
+ }
@@ -13,24 +13,28 @@ export async function init() {
13
13
  }
14
14
  console.log(`\nSettings file: ${getSettingsPath()}`);
15
15
  // Check for API key and provide helpful instructions
16
+ const shell = process.env.SHELL?.includes('zsh') ? '~/.zshrc' : '~/.bashrc';
16
17
  if (!process.env.ANTHROPIC_API_KEY) {
17
- console.log('\n' + '='.repeat(50));
18
- console.log(' ANTHROPIC_API_KEY not found');
19
- console.log('='.repeat(50));
20
- console.log('\nTo enable drift detection and smart extraction:\n');
21
- console.log(' 1. Get your API key at:');
18
+ console.log('\n╔═══════════════════════════════════════════════════════════╗');
19
+ console.log(' ⚠️ ANTHROPIC_API_KEY NOT SET - MEMORIES WILL NOT SYNC! ║');
20
+ console.log('╚═══════════════════════════════════════════════════════════╝');
21
+ console.log('\n 1. Get your API key at:');
22
22
  console.log(' https://console.anthropic.com/settings/keys\n');
23
- console.log(' 2. Add to your shell profile (~/.zshrc or ~/.bashrc):');
24
- console.log(' export ANTHROPIC_API_KEY=sk-ant-...\n');
25
- console.log(' 3. Restart terminal or run: source ~/.zshrc\n');
23
+ console.log(' 2. Add PERMANENTLY to your shell (not just "export" in terminal):');
24
+ console.log(` echo 'export ANTHROPIC_API_KEY=sk-ant-...' >> ${shell}\n`);
25
+ console.log(' 3. Apply changes:');
26
+ console.log(` source ${shell}\n`);
27
+ console.log(' ⚠️ Using "export" alone only works in THAT terminal!');
28
+ console.log(' The key will be gone when you open a new terminal.\n');
26
29
  }
27
30
  else {
28
- console.log('\n ANTHROPIC_API_KEY found');
31
+ console.log('\n ANTHROPIC_API_KEY found');
29
32
  }
30
33
  console.log('\n--- Next Steps ---');
31
34
  console.log('1. Terminal 1: grov proxy');
32
35
  console.log('2. Terminal 2: claude');
33
- console.log('\nGrov will automatically capture reasoning and inject context.');
36
+ console.log('\nRun "grov doctor" to verify your setup is complete.');
37
+ console.log('Grov will automatically capture reasoning and inject context.');
34
38
  }
35
39
  catch (error) {
36
40
  console.error('Failed to configure grov:', error instanceof Error ? error.message : 'Unknown error');
@@ -142,8 +142,17 @@ export async function login() {
142
142
  console.log('║ ║');
143
143
  console.log('╚═════════════════════════════════════════╝');
144
144
  console.log(`\nSyncing to: ${selectedTeam.name}`);
145
- console.log('\nYou\'re all set! Your AI sessions will now be saved.');
146
- console.log('View them at: https://app.grov.dev/memories\n');
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');
147
156
  }
148
157
  else {
149
158
  console.log('\n✓ Logged in. Sync not enabled.');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grov",
3
- "version": "0.5.5",
3
+ "version": "0.5.7",
4
4
  "description": "Collective AI memory for Claude Code - captures reasoning from sessions and injects context into future sessions",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",