getaimeter 0.7.1 → 0.7.3

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.
Files changed (3) hide show
  1. package/cli.js +2 -0
  2. package/package.json +1 -1
  3. package/service.js +61 -1
package/cli.js CHANGED
@@ -129,6 +129,8 @@ async function runSetup() {
129
129
  console.log(` ✓ Installed at: ${result.path}`);
130
130
  if (result.platform === 'windows') {
131
131
  console.log(' ✓ Will auto-start on login (Windows Startup folder)');
132
+ console.log(' ✓ Desktop shortcut created (double-click "AIMeter" to start)');
133
+ console.log(' ✓ Start Menu shortcut created');
132
134
  } else if (result.platform === 'macos') {
133
135
  console.log(' ✓ Will auto-start on login (launchd)');
134
136
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "getaimeter",
3
- "version": "0.7.1",
3
+ "version": "0.7.3",
4
4
  "description": "Track AI coding costs across Claude, Cursor, Codex, and Gemini. Optimization recommendations that cut costs by 30%.",
5
5
  "bin": {
6
6
  "aimeter": "cli.js"
package/service.js CHANGED
@@ -86,12 +86,72 @@ WshShell.Run """${nodePath}"" ""${script}"" watch", 0, False
86
86
 
87
87
  fs.mkdirSync(path.dirname(vbsPath), { recursive: true });
88
88
  fs.writeFileSync(vbsPath, vbs, 'utf8');
89
+
90
+ // Create Desktop and Start Menu shortcuts so users can launch without a terminal
91
+ createWindowsShortcuts(nodePath, script);
92
+
89
93
  return vbsPath;
90
94
  }
91
95
 
96
+ /**
97
+ * Create .lnk shortcuts on Desktop and Start Menu via PowerShell COM.
98
+ * These are proper Windows shortcuts with icon and description.
99
+ */
100
+ function createWindowsShortcuts(nodePath, script) {
101
+ const { execSync } = require('child_process');
102
+ const iconPath = path.join(__dirname, 'icon.ico');
103
+
104
+ const locations = [
105
+ path.join(os.homedir(), 'Desktop', 'AIMeter.lnk'),
106
+ path.join(os.homedir(), 'AppData', 'Roaming', 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'AIMeter.lnk'),
107
+ ];
108
+
109
+ // Write a temporary PS1 file to avoid all escaping issues
110
+ const ps1Path = path.join(os.tmpdir(), 'aimeter-shortcut.ps1');
111
+
112
+ for (const lnkPath of locations) {
113
+ // Use single quotes in PS1 with doubled single-quote escaping
114
+ const ps1Content = [
115
+ '$ws = New-Object -ComObject WScript.Shell',
116
+ `$s = $ws.CreateShortcut('${lnkPath.replace(/'/g, "''")}')`,
117
+ `$s.TargetPath = '${nodePath.replace(/\\\\/g, '\\').replace(/'/g, "''")}'`,
118
+ `$s.Arguments = [char]34 + '${script.replace(/\\\\/g, '\\').replace(/'/g, "''")}' + [char]34 + ' start'`,
119
+ `$s.WorkingDirectory = '${os.homedir().replace(/'/g, "''")}'`,
120
+ `$s.Description = 'AIMeter - AI coding cost optimizer'`,
121
+ `$s.WindowStyle = 7`,
122
+ `$icon = '${iconPath.replace(/'/g, "''")}'`,
123
+ `if (Test-Path $icon) { $s.IconLocation = $icon }`,
124
+ `$s.Save()`,
125
+ ].join('\n');
126
+
127
+ try {
128
+ fs.writeFileSync(ps1Path, ps1Content, 'utf8');
129
+ execSync(`powershell -NoProfile -ExecutionPolicy Bypass -File "${ps1Path}"`, {
130
+ stdio: 'ignore',
131
+ timeout: 10000,
132
+ });
133
+ } catch {
134
+ // Non-critical — shortcuts are convenience, not required
135
+ }
136
+ }
137
+
138
+ try { fs.unlinkSync(ps1Path); } catch {}
139
+ }
140
+
92
141
  function uninstallWindows() {
93
142
  const vbsPath = getWindowsVbsPath();
94
- try { fs.unlinkSync(vbsPath); return true; } catch { return false; }
143
+ try { fs.unlinkSync(vbsPath); } catch {}
144
+
145
+ // Remove Desktop and Start Menu shortcuts
146
+ const shortcuts = [
147
+ path.join(os.homedir(), 'Desktop', 'AIMeter.lnk'),
148
+ path.join(os.homedir(), 'AppData', 'Roaming', 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'AIMeter.lnk'),
149
+ ];
150
+ for (const lnk of shortcuts) {
151
+ try { fs.unlinkSync(lnk); } catch {}
152
+ }
153
+
154
+ return true;
95
155
  }
96
156
 
97
157
  function isInstalledWindows() {