@vibe-cafe/vibe-usage 0.3.0 → 0.4.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/README.md CHANGED
@@ -16,11 +16,13 @@ This will:
16
16
  ## Commands
17
17
 
18
18
  ```bash
19
- npx vibe-usage # Init (first run) or sync (subsequent runs)
20
- npx vibe-usage init # Re-run setup
21
- npx vibe-usage sync # Manual sync
22
- npx vibe-usage reset # Delete all data and re-upload from local logs
23
- npx vibe-usage status # Show config & detected tools
19
+ npx vibe-usage # Init (first run) or sync (subsequent runs)
20
+ npx vibe-usage init # Re-run setup
21
+ npx vibe-usage sync # Manual sync
22
+ npx vibe-usage daemon # Continuous sync (every 5 minutes)
23
+ npx vibe-usage reset # Delete all data and re-upload from local logs
24
+ npx vibe-usage reset --local # Delete this host's data only and re-upload
25
+ npx vibe-usage status # Show config & detected tools
24
26
  ```
25
27
 
26
28
  ## Supported Tools
@@ -39,12 +41,22 @@ npx vibe-usage status # Show config & detected tools
39
41
  - Aggregates token usage into 30-minute buckets
40
42
  - Uploads to your vibecafe.ai dashboard
41
43
  - Only syncs new data since last sync (incremental)
42
- - For continuous syncing, use the [Vibe Usage Mac app](https://github.com/vibe-cafe/vibe-usage-app) (auto-syncs every 5 minutes)
44
+ - For continuous syncing, use `npx vibe-usage daemon` or the [Vibe Usage Mac app](https://github.com/vibe-cafe/vibe-usage-app)
43
45
 
44
46
  ## Config
45
47
 
46
48
  Config stored at `~/.vibe-usage/config.json`. Contains your API key and last sync timestamp.
47
49
 
50
+ ## Daemon Mode
51
+
52
+ Run continuous syncing in the foreground (every 5 minutes):
53
+
54
+ ```bash
55
+ npx vibe-usage daemon
56
+ ```
57
+
58
+ Press Ctrl+C to stop. For background use: `nohup npx vibe-usage daemon &`
59
+
48
60
  ## License
49
61
 
50
62
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-cafe/vibe-usage",
3
- "version": "0.3.0",
3
+ "version": "0.4.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/daemon.js ADDED
@@ -0,0 +1,37 @@
1
+ import { loadConfig } from './config.js';
2
+ import { runSync } from './sync.js';
3
+
4
+ const INTERVAL = 5 * 60_000; // 5 minutes
5
+
6
+ function log(msg) {
7
+ const ts = new Date().toLocaleTimeString('en-US', { hour12: false });
8
+ process.stdout.write(`[${ts}] ${msg}\n`);
9
+ }
10
+
11
+ function sleep(ms) {
12
+ return new Promise(resolve => setTimeout(resolve, ms));
13
+ }
14
+
15
+ export async function runDaemon() {
16
+ const config = loadConfig();
17
+ if (!config?.apiKey) {
18
+ console.error('Not configured. Run `npx @vibe-cafe/vibe-usage init` first.');
19
+ process.exit(1);
20
+ }
21
+
22
+ log('Daemon started (sync every 5m, Ctrl+C to stop)');
23
+
24
+ // eslint-disable-next-line no-constant-condition
25
+ while (true) {
26
+ try {
27
+ await runSync({ throws: true, quiet: true });
28
+ } catch (err) {
29
+ if (err.message === 'UNAUTHORIZED') {
30
+ log('API key invalid. Exiting.');
31
+ process.exit(1);
32
+ }
33
+ log(`Sync error: ${err.message}`);
34
+ }
35
+ await sleep(INTERVAL);
36
+ }
37
+ }
package/src/index.js CHANGED
@@ -107,6 +107,12 @@ export async function run(args) {
107
107
  await runReset(args.slice(1));
108
108
  break;
109
109
  }
110
+ case 'daemon':
111
+ case '--daemon': {
112
+ const { runDaemon } = await import('./daemon.js');
113
+ await runDaemon();
114
+ break;
115
+ }
110
116
  case 'config': {
111
117
  handleConfig(args.slice(1));
112
118
  break;
@@ -125,8 +131,9 @@ export async function run(args) {
125
131
  npx vibe-usage Init (first run) or sync
126
132
  npx vibe-usage init Set up API key
127
133
  npx vibe-usage sync Manually sync usage data
134
+ npx vibe-usage daemon Continuous sync (every 5m)
128
135
  npx vibe-usage reset Delete all data and re-upload
129
- npx vibe-usage reset --host Delete data for this host only and re-upload
136
+ npx vibe-usage reset --local Delete data for this host only and re-upload
130
137
  npx vibe-usage status Show config and detected tools
131
138
  npx vibe-usage config show Show full config as JSON
132
139
  npx vibe-usage config get <key> Get a config value
package/src/reset.js CHANGED
@@ -21,7 +21,7 @@ function prompt(question) {
21
21
  }
22
22
 
23
23
  export async function runReset(args = []) {
24
- const hostOnly = args.includes('--host');
24
+ const hostOnly = args.includes('--local');
25
25
  const config = loadConfig();
26
26
  if (!config?.apiKey) {
27
27
  console.error('Not configured. Run `npx @vibe-cafe/vibe-usage init` first.');
package/src/sync.js CHANGED
@@ -11,10 +11,11 @@ function formatBytes(bytes) {
11
11
  return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
12
12
  }
13
13
 
14
- export async function runSync() {
14
+ export async function runSync({ throws = false, quiet = false } = {}) {
15
15
  const config = loadConfig();
16
16
  if (!config?.apiKey) {
17
17
  console.error('Not configured. Run `npx @vibe-cafe/vibe-usage init` first.');
18
+ if (throws) throw new Error('NOT_CONFIGURED');
18
19
  process.exit(1);
19
20
  }
20
21
 
@@ -38,7 +39,7 @@ export async function runSync() {
38
39
  }
39
40
 
40
41
  if (allBuckets.length === 0) {
41
- console.log('No new usage data found.');
42
+ if (!quiet) console.log('No new usage data found.');
42
43
  return 0;
43
44
  }
44
45
 
@@ -87,6 +88,7 @@ export async function runSync() {
87
88
  } catch (err) {
88
89
  if (err.message === 'UNAUTHORIZED') {
89
90
  console.error('Invalid API key. Run `npx @vibe-cafe/vibe-usage init` to reconfigure.');
91
+ if (throws) throw err;
90
92
  process.exit(1);
91
93
  }
92
94
  // Report partial success
@@ -95,6 +97,7 @@ export async function runSync() {
95
97
  } else {
96
98
  console.error(`Sync failed: ${err.message}`);
97
99
  }
100
+ if (throws) throw err;
98
101
  process.exit(1);
99
102
  }
100
103
  }