agentlytics 0.2.5 → 0.2.6

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/editors/claude.js CHANGED
@@ -204,8 +204,18 @@ function extractAssistantContent(content) {
204
204
  // Usage / quota data from Anthropic OAuth API
205
205
  // ============================================================
206
206
 
207
+ function isKeychainAccessAllowed() {
208
+ try {
209
+ const configPath = path.join(os.homedir(), '.agentlytics', 'config.json');
210
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
211
+ return config.allowKeychainAccess === true;
212
+ } catch { return false; }
213
+ }
214
+
207
215
  function getClaudeCredentials() {
208
216
  // macOS: Keychain; Linux: secret-tool; Windows: not yet supported
217
+ // Requires explicit user permission (allowKeychainAccess in config)
218
+ if (!isKeychainAccessAllowed()) return null;
209
219
  try {
210
220
  const { execSync } = require('child_process');
211
221
  let raw;
package/index.js CHANGED
@@ -253,6 +253,39 @@ const BOT_STYLES = [
253
253
  ];
254
254
 
255
255
  (async () => {
256
+ // ── Ask for keychain access permission (first run only) ──
257
+ const CONFIG_DIR = path.join(os.homedir(), '.agentlytics');
258
+ const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
259
+ let agentConfig = {};
260
+ try { agentConfig = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf-8')); } catch {}
261
+
262
+ if (agentConfig.allowKeychainAccess === undefined) {
263
+ // Only relevant on macOS / Linux where keychain/secret-tool is used
264
+ if (process.platform === 'darwin' || process.platform === 'linux') {
265
+ const storeName = process.platform === 'darwin' ? 'Keychain' : 'secret store';
266
+ console.log(chalk.yellow(` ⚠ Some subscription details (e.g. Claude Code) require ${storeName} access.`));
267
+ console.log(chalk.dim(` This reads stored credentials to show plan/usage info.`));
268
+ console.log('');
269
+ const readline = require('readline');
270
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
271
+ const answer = await new Promise(r => {
272
+ rl.question(chalk.bold(` Allow ${storeName} access for subscription details? (y/N) `), (a) => {
273
+ rl.close();
274
+ r(a.trim().toLowerCase());
275
+ });
276
+ });
277
+ agentConfig.allowKeychainAccess = answer === 'y' || answer === 'yes';
278
+ if (!fs.existsSync(CONFIG_DIR)) fs.mkdirSync(CONFIG_DIR, { recursive: true });
279
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(agentConfig, null, 2));
280
+ if (agentConfig.allowKeychainAccess) {
281
+ console.log(chalk.green(` ✓ ${storeName} access enabled`));
282
+ } else {
283
+ console.log(chalk.dim(` – ${storeName} access skipped (subscription details won't be collected)`));
284
+ }
285
+ console.log('');
286
+ }
287
+ }
288
+
256
289
  let tick = 0;
257
290
  const startTime = Date.now();
258
291
  const result = await cache.scanAllAsync((p) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentlytics",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "Comprehensive analytics dashboard for AI coding agents — Cursor, Windsurf, Claude Code, VS Code Copilot, Zed, Antigravity, OpenCode, Command Code",
5
5
  "main": "index.js",
6
6
  "bin": {