@vibe-cafe/vibe-usage 0.1.11 → 0.2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-cafe/vibe-usage",
3
- "version": "0.1.11",
3
+ "version": "0.2.0",
4
4
  "description": "Track your AI coding tool token usage and sync to vibecafe.ai",
5
5
  "type": "module",
6
6
  "bin": {
package/src/config.js CHANGED
@@ -3,7 +3,8 @@ import { join } from 'node:path';
3
3
  import { homedir } from 'node:os';
4
4
 
5
5
  const CONFIG_DIR = join(homedir(), '.vibe-usage');
6
- const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
6
+ const isDev = process.env.VIBE_USAGE_DEV === '1';
7
+ const CONFIG_FILE = join(CONFIG_DIR, isDev ? 'config.dev.json' : 'config.json');
7
8
 
8
9
  export function getConfigPath() {
9
10
  return CONFIG_FILE;
package/src/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { loadConfig, getConfigPath } from './config.js';
1
+ import { loadConfig, saveConfig, getConfigPath } from './config.js';
2
2
  import { detectInstalledTools, TOOLS } from './hooks.js';
3
3
  import { existsSync } from 'node:fs';
4
4
 
@@ -36,6 +36,60 @@ async function showStatus() {
36
36
  console.log();
37
37
  }
38
38
 
39
+ const VALID_CONFIG_KEYS = ['apiKey', 'apiUrl', 'lastSync'];
40
+
41
+ function handleConfig(args) {
42
+ const sub = args[0];
43
+
44
+ switch (sub) {
45
+ case 'get': {
46
+ const key = args[1];
47
+ if (!key) {
48
+ console.error('Usage: vibe-usage config get <key>');
49
+ process.exit(1);
50
+ }
51
+ const config = loadConfig();
52
+ if (!config || !(key in config)) {
53
+ // Output nothing — caller checks exit code or empty output
54
+ process.exit(0);
55
+ }
56
+ // Output raw value (no formatting) for machine parsing
57
+ console.log(config[key] ?? '');
58
+ break;
59
+ }
60
+ case 'set': {
61
+ const key = args[1];
62
+ const value = args[2];
63
+ if (!key || value === undefined) {
64
+ console.error('Usage: vibe-usage config set <key> <value>');
65
+ process.exit(1);
66
+ }
67
+ if (!VALID_CONFIG_KEYS.includes(key)) {
68
+ console.error(`Unknown config key: ${key}`);
69
+ console.error(`Valid keys: ${VALID_CONFIG_KEYS.join(', ')}`);
70
+ process.exit(1);
71
+ }
72
+ const config = loadConfig() || {};
73
+ config[key] = value;
74
+ saveConfig(config);
75
+ break;
76
+ }
77
+ case 'show': {
78
+ const config = loadConfig();
79
+ if (!config) {
80
+ console.log('{}');
81
+ } else {
82
+ console.log(JSON.stringify(config, null, 2));
83
+ }
84
+ break;
85
+ }
86
+ default:
87
+ console.error(`Unknown config subcommand: ${sub || '(none)'}`);
88
+ console.error('Usage: vibe-usage config <get|set|show>');
89
+ process.exit(1);
90
+ }
91
+ }
92
+
39
93
  export async function run(args) {
40
94
  const command = args[0];
41
95
 
@@ -50,6 +104,10 @@ export async function run(args) {
50
104
  await runSync();
51
105
  break;
52
106
  }
107
+ case 'config': {
108
+ handleConfig(args.slice(1));
109
+ break;
110
+ }
53
111
  case 'status': {
54
112
  await showStatus();
55
113
  break;
@@ -58,14 +116,17 @@ export async function run(args) {
58
116
  case '--help':
59
117
  case '-h': {
60
118
  console.log(`
61
- vibe-usage - Vibe Usage Tracker by VibeCaf\u00e9
119
+ vibe-usage - Vibe Usage Tracker by VibeCafé
62
120
 
63
121
  Usage:
64
- npx vibe-usage Init (first run) or sync
65
- npx vibe-usage init Set up API key and hooks
66
- npx vibe-usage sync Manually sync usage data
67
- npx vibe-usage status Show config and detected tools
68
- npx vibe-usage help Show this help
122
+ npx vibe-usage Init (first run) or sync
123
+ npx vibe-usage init Set up API key and hooks
124
+ npx vibe-usage sync Manually sync usage data
125
+ npx vibe-usage status Show config and detected tools
126
+ npx vibe-usage config show Show full config as JSON
127
+ npx vibe-usage config get <key> Get a config value
128
+ npx vibe-usage config set <key> <value> Set a config value
129
+ npx vibe-usage help Show this help
69
130
  `);
70
131
  break;
71
132
  }
package/src/sync.js CHANGED
@@ -1,3 +1,7 @@
1
+ import { hostname as osHostname } from 'node:os';
2
+ import { existsSync, readFileSync, unlinkSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { homedir } from 'node:os';
1
5
  import { loadConfig, saveConfig } from './config.js';
2
6
  import { ingest } from './api.js';
3
7
  import { parsers } from './parsers/index.js';
@@ -34,6 +38,12 @@ export async function runSync() {
34
38
  return 0;
35
39
  }
36
40
 
41
+ // Tag every bucket with this machine's hostname
42
+ const host = osHostname().replace(/\.local$/, '');
43
+ for (const b of allBuckets) {
44
+ b.hostname = host;
45
+ }
46
+
37
47
  const apiUrl = config.apiUrl || 'https://vibecafe.ai';
38
48
  let totalIngested = 0;
39
49
  const totalBatches = Math.ceil(allBuckets.length / BATCH_SIZE);
@@ -83,6 +93,24 @@ export async function runSync() {
83
93
  * Runs silently — meant as a self-healing side effect of sync.
84
94
  */
85
95
  function ensureHooks() {
96
+ // Skip hook injection if Vibe Usage Mac app is running
97
+ const markerPath = join(homedir(), '.vibe-usage', 'mac-app-active');
98
+ if (existsSync(markerPath)) {
99
+ try {
100
+ const marker = JSON.parse(readFileSync(markerPath, 'utf-8'));
101
+ if (marker.pid) {
102
+ try {
103
+ process.kill(marker.pid, 0);
104
+ return;
105
+ } catch {
106
+ try { unlinkSync(markerPath); } catch { /* ignore */ }
107
+ }
108
+ }
109
+ } catch {
110
+ // Malformed marker file — ignore
111
+ }
112
+ }
113
+
86
114
  for (const tool of TOOLS) {
87
115
  if (!tool.inject) continue;
88
116
  try {