@jonaskahn/relo 0.2.0 → 0.2.1-beta.60.90c6f7c6

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
@@ -41,6 +41,8 @@ that output under the install: npm otherwise runs it in the background and
41
41
  shows nothing until the command ends, which makes a slow download look stuck.
42
42
 
43
43
  State lives in `~/.relo` (`$RELO_HOME`), shared with every other installer.
44
+ On Windows the install also adds a Desktop "Relo" shortcut that restarts the
45
+ daemon without opening a terminal.
44
46
  Never installed twice: if another Relo is on your PATH, this one refuses and
45
47
  tells you where it found it.
46
48
 
package/lib/install.mjs CHANGED
@@ -42,6 +42,7 @@ import {
42
42
  warn
43
43
  } from './progress.mjs';
44
44
  import { target } from './platform.mjs';
45
+ import { createDesktopShortcut } from './shortcut.mjs';
45
46
  import { assets, checksumsUrl, pinnedTag, selectBundle, tagFromArgs, url } from './release.mjs';
46
47
  import { extractBinary } from './archive.mjs';
47
48
 
@@ -211,6 +212,11 @@ try {
211
212
  done(`${label('CONFLICT')} no other relo install`);
212
213
 
213
214
  const destination = await fromRelease(tag, asset, startedAt);
215
+ if (createDesktopShortcut(destination)) {
216
+ done(`${label('SHORTCUT')} Desktop\\Relo`);
217
+ } else if (asset.os === 'windows') {
218
+ note('no Desktop shortcut was created; run: relo daemon restart --force');
219
+ }
214
220
  if (startNow === 'yes') {
215
221
  closeScreen();
216
222
  // The daemon's error goes into the result block rather than through
@@ -0,0 +1,41 @@
1
+ // The Desktop shortcut a Windows install leaves, the same one Relo-Setup
2
+ // creates: it restarts the daemon through the GUI-subsystem relo.exe, so
3
+ // opening it shows no terminal. Other platforms have no such shortcut.
4
+ import { spawnSync } from 'node:child_process';
5
+
6
+ const NAME = 'Relo.lnk';
7
+
8
+ // run executes a PowerShell script with the values passed through the
9
+ // environment, so a path never needs quoting.
10
+ function run(script, env) {
11
+ const result = spawnSync('powershell', ['-NoProfile', '-NonInteractive', '-Command', script], {
12
+ env: { ...process.env, ...env },
13
+ stdio: 'ignore'
14
+ });
15
+ return result.status === 0;
16
+ }
17
+
18
+ const DESKTOP = "$desktop = [Environment]::GetFolderPath('Desktop'); $link = Join-Path $desktop '" + NAME + "';";
19
+
20
+ // createDesktopShortcut writes the shortcut for binary and reports whether it
21
+ // exists afterwards. The working directory is the profile, because the
22
+ // install directory is not a place to write.
23
+ export function createDesktopShortcut(binary, { nodePlatform = process.platform } = {}) {
24
+ if (nodePlatform !== 'win32') return false;
25
+ return run(
26
+ DESKTOP +
27
+ '$s = (New-Object -ComObject WScript.Shell).CreateShortcut($link);' +
28
+ '$s.TargetPath = $env:RELO_BINARY;' +
29
+ "$s.Arguments = 'daemon restart --force';" +
30
+ '$s.IconLocation = $env:RELO_BINARY;' +
31
+ '$s.WorkingDirectory = $env:USERPROFILE;' +
32
+ '$s.Save()',
33
+ { RELO_BINARY: binary }
34
+ );
35
+ }
36
+
37
+ // removeDesktopShortcut deletes the shortcut; a missing one is fine.
38
+ export function removeDesktopShortcut({ nodePlatform = process.platform } = {}) {
39
+ if (nodePlatform !== 'win32') return false;
40
+ return run(DESKTOP + 'Remove-Item -LiteralPath $link -Force -ErrorAction SilentlyContinue', {});
41
+ }
package/lib/uninstall.mjs CHANGED
@@ -15,12 +15,14 @@ import { spawnSync } from 'node:child_process';
15
15
 
16
16
  import { quiesce, reloHome } from './daemon.mjs';
17
17
  import { target } from './platform.mjs';
18
+ import { removeDesktopShortcut } from './shortcut.mjs';
18
19
 
19
20
  const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
20
21
  const binary = resolve(packageRoot, 'bin', target().name);
21
22
  const home = reloHome();
22
23
 
23
24
  try {
25
+ removeDesktopShortcut();
24
26
  if (existsSync(binary)) {
25
27
  spawnSync(binary, ['--home', home, 'uninstall', '--prepare'], { stdio: 'inherit' });
26
28
  } else {
@@ -28,4 +30,4 @@ try {
28
30
  }
29
31
  } catch (error) {
30
32
  console.warn(`relo: could not stop the running daemon; ${error.message}`);
31
- }
33
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jonaskahn/relo",
3
- "version": "0.2.0",
3
+ "version": "0.2.1-beta.60.90c6f7c6",
4
4
  "description": "One local proxy that lets Codex, Claude Code, Cursor and Grok, etc. Talk to any model, any provider with no config changes",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",
@@ -49,6 +49,7 @@
49
49
  "lib/platform.mjs",
50
50
  "lib/progress.mjs",
51
51
  "lib/release.mjs",
52
+ "lib/shortcut.mjs",
52
53
  "lib/uninstall.mjs",
53
54
  "README.md"
54
55
  ],