@vibe-cafe/vibe-usage 0.7.5 → 0.7.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/README.md CHANGED
@@ -4,19 +4,29 @@ Track your AI coding tool token usage and sync to [vibecafe.ai](https://vibecafe
4
4
 
5
5
  ## Quick Start
6
6
 
7
+ Get your API key at [vibecafe.ai/usage](https://vibecafe.ai/usage), then copy the one-liner shown there:
8
+
9
+ ```bash
10
+ npx @vibe-cafe/vibe-usage --key vbu_xxxxxxxxxxxx
11
+ ```
12
+
13
+ Or run without a key and paste it interactively:
14
+
7
15
  ```bash
8
16
  npx @vibe-cafe/vibe-usage
9
17
  ```
10
18
 
11
- This will:
12
- 1. Ask for your API key (get one at https://vibecafe.ai/usage/setup)
19
+ Either path will:
20
+ 1. Save your API key to `~/.vibe-usage/config.json`
13
21
  2. Detect installed AI coding tools
14
22
  3. Run an initial sync of your usage data
23
+ 4. Prompt you to enable the background daemon for continuous syncing (recommended)
15
24
 
16
25
  ## Commands
17
26
 
18
27
  ```bash
19
28
  npx @vibe-cafe/vibe-usage # Init (first run) or sync (subsequent runs)
29
+ npx @vibe-cafe/vibe-usage --key <vbu_...> # One-shot init with a pre-copied key
20
30
  npx @vibe-cafe/vibe-usage init # Re-run setup
21
31
  npx @vibe-cafe/vibe-usage sync # Manual sync
22
32
  npx @vibe-cafe/vibe-usage daemon # Continuous sync (every 30m, foreground)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-cafe/vibe-usage",
3
- "version": "0.7.5",
3
+ "version": "0.7.6",
4
4
  "description": "Track your AI coding tool token usage and sync to vibecafe.ai",
5
5
  "type": "module",
6
6
  "bin": {
package/src/index.js CHANGED
@@ -88,13 +88,26 @@ function handleConfig(args) {
88
88
  }
89
89
  }
90
90
 
91
- export async function run(args) {
91
+ function extractOption(args, name) {
92
+ const flag = `--${name}`;
93
+ const idx = args.findIndex(a => a === flag);
94
+ if (idx === -1) return { args, value: undefined };
95
+ const value = args[idx + 1];
96
+ if (value === undefined || value.startsWith('--')) {
97
+ console.error(`Option ${flag} requires a value.`);
98
+ process.exit(1);
99
+ }
100
+ return { args: [...args.slice(0, idx), ...args.slice(idx + 2)], value };
101
+ }
102
+
103
+ export async function run(rawArgs) {
104
+ const { args, value: apiKey } = extractOption(rawArgs, 'key');
92
105
  const command = args[0];
93
106
 
94
107
  switch (command) {
95
108
  case 'init': {
96
109
  const { runInit } = await import('./init.js');
97
- await runInit();
110
+ await runInit({ apiKey });
98
111
  break;
99
112
  }
100
113
  case 'sync': {
@@ -140,7 +153,9 @@ export async function run(args) {
140
153
 
141
154
  Usage:
142
155
  npx @vibe-cafe/vibe-usage Init (first run) or sync
143
- npx @vibe-cafe/vibe-usage init Set up API key
156
+ npx @vibe-cafe/vibe-usage --key <vbu_...> One-shot init with a pre-copied key
157
+ npx @vibe-cafe/vibe-usage init Set up API key (interactive)
158
+ npx @vibe-cafe/vibe-usage init --key <vbu_...> Init with key, skip paste prompt
144
159
  npx @vibe-cafe/vibe-usage sync Manually sync usage data
145
160
  npx @vibe-cafe/vibe-usage daemon Continuous sync (every 30m, foreground)
146
161
  npx @vibe-cafe/vibe-usage daemon install Install background service (systemd/launchd)
@@ -162,9 +177,10 @@ export async function run(args) {
162
177
  }
163
178
  default: {
164
179
  const config = loadConfig();
165
- if (!config?.apiKey) {
180
+ if (!config?.apiKey || apiKey) {
181
+ // First run OR user passed --key for a one-shot setup
166
182
  const { runInit } = await import('./init.js');
167
- await runInit();
183
+ await runInit({ apiKey });
168
184
  } else {
169
185
  const { runSync } = await import('./sync.js');
170
186
  await runSync();
package/src/init.js CHANGED
@@ -23,11 +23,22 @@ function openBrowser(url) {
23
23
  execFile(cmd, [url], () => {});
24
24
  }
25
25
 
26
- export async function runInit() {
26
+ function isDaemonPlatform() {
27
+ return process.platform === 'linux' || process.platform === 'darwin';
28
+ }
29
+
30
+ export async function runInit(options = {}) {
31
+ const { apiKey: providedKey } = options;
32
+
27
33
  console.log('\n vibe-usage - Vibe Usage Tracker by VibeCaf\u00e9\n');
28
34
 
29
35
  const existing = loadConfig();
30
36
  if (existing?.apiKey) {
37
+ if (providedKey && existing.apiKey === providedKey) {
38
+ console.log('Already configured with this key. Running sync...\n');
39
+ await runSync();
40
+ return;
41
+ }
31
42
  const answer = await prompt('Config already exists. Overwrite? (y/N) ');
32
43
  if (answer.toLowerCase() !== 'y') {
33
44
  console.log('Cancelled.');
@@ -36,14 +47,24 @@ export async function runInit() {
36
47
  }
37
48
 
38
49
  const apiUrl = process.env.VIBE_USAGE_API_URL || 'https://vibecafe.ai';
39
- console.log(`Get your API key at: ${apiUrl}/usage/setup\n`);
40
- openBrowser(`${apiUrl}/usage/setup`);
41
50
 
42
51
  let apiKey;
43
- while (true) {
44
- apiKey = await prompt('Paste your API key: ');
45
- if (apiKey.startsWith('vbu_')) break;
46
- console.log('Invalid key — must start with "vbu_". Try again.');
52
+ if (providedKey) {
53
+ if (!providedKey.startsWith('vbu_')) {
54
+ console.error('Invalid API key — must start with "vbu_".');
55
+ process.exit(1);
56
+ }
57
+ apiKey = providedKey;
58
+ console.log(`Using API key ${apiKey.slice(0, 8)}...`);
59
+ } else {
60
+ console.log(`Get your API key at: ${apiUrl}/usage\n`);
61
+ openBrowser(`${apiUrl}/usage`);
62
+
63
+ while (true) {
64
+ apiKey = await prompt('Paste your API key: ');
65
+ if (apiKey.startsWith('vbu_')) break;
66
+ console.log('Invalid key — must start with "vbu_". Try again.');
67
+ }
47
68
  }
48
69
 
49
70
  console.log(`\nVerifying key ${apiKey.slice(0, 8)}...`);
@@ -77,7 +98,20 @@ export async function runInit() {
77
98
 
78
99
  console.log(`\nSetup complete! View your dashboard at: ${apiUrl}/usage`);
79
100
 
80
- if (process.platform === 'linux' || process.platform === 'darwin') {
81
- console.log('\nTip: Run `npx @vibe-cafe/vibe-usage daemon install` to sync automatically in the background.');
101
+ if (isDaemonPlatform()) {
102
+ if (process.stdin.isTTY) {
103
+ console.log('');
104
+ const answer = await prompt('开启后台自动同步?(持续上报用量数据,推荐) [Y/n] ');
105
+ const normalized = answer.toLowerCase();
106
+ if (normalized === '' || normalized === 'y' || normalized === 'yes') {
107
+ const { manageDaemon } = await import('./daemon-service.js');
108
+ await manageDaemon('install');
109
+ } else {
110
+ console.log('\n可随时运行 `npx @vibe-cafe/vibe-usage daemon install` 开启后台同步。');
111
+ }
112
+ } else {
113
+ // Non-interactive shell (CI, pipe) — don't block on prompt
114
+ console.log('\nTip: Run `npx @vibe-cafe/vibe-usage daemon install` to sync automatically in the background.');
115
+ }
82
116
  }
83
117
  }