@seedvault/cli 0.1.3 → 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.
Files changed (3) hide show
  1. package/bin/sv.mjs +2 -7
  2. package/dist/sv.js +375 -80
  3. package/package.json +1 -1
package/bin/sv.mjs CHANGED
@@ -1,10 +1,5 @@
1
- #!/usr/bin/env node
2
- import { execFileSync } from "child_process";
1
+ #!/usr/bin/env bun
3
2
  import { join, dirname } from "path";
4
3
  import { fileURLToPath } from "url";
5
4
  const __dirname = dirname(fileURLToPath(import.meta.url));
6
- try {
7
- execFileSync("bun", [join(__dirname, "..", "dist", "sv.js"), ...process.argv.slice(2)], { stdio: "inherit" });
8
- } catch (e) {
9
- process.exit(e.status || 1);
10
- }
5
+ await import(join(__dirname, "..", "dist", "sv.js"));
package/dist/sv.js CHANGED
@@ -12,12 +12,25 @@ import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
12
12
  var CONFIG_DIR = join(homedir(), ".config", "seedvault");
13
13
  var CONFIG_PATH = join(CONFIG_DIR, "config.json");
14
14
  var PID_PATH = join(CONFIG_DIR, "daemon.pid");
15
- function getConfigDir() {
16
- return CONFIG_DIR;
17
- }
15
+ var DAEMON_LOG_PATH = join(CONFIG_DIR, "daemon.log");
16
+ var LAUNCHD_PLIST_PATH = join(homedir(), "Library", "LaunchAgents", "ai.seedvault.daemon.plist");
17
+ var SYSTEMD_UNIT_PATH = join(homedir(), ".config", "systemd", "user", "seedvault.service");
18
+ var SCHTASKS_XML_PATH = join(CONFIG_DIR, "seedvault-task.xml");
18
19
  function getPidPath() {
19
20
  return PID_PATH;
20
21
  }
22
+ function getDaemonLogPath() {
23
+ return DAEMON_LOG_PATH;
24
+ }
25
+ function getLaunchdPlistPath() {
26
+ return LAUNCHD_PLIST_PATH;
27
+ }
28
+ function getSystemdUnitPath() {
29
+ return SYSTEMD_UNIT_PATH;
30
+ }
31
+ function getSchtasksXmlPath() {
32
+ return SCHTASKS_XML_PATH;
33
+ }
21
34
  function ensureConfigDir() {
22
35
  if (!existsSync(CONFIG_DIR)) {
23
36
  mkdirSync(CONFIG_DIR, { recursive: true });
@@ -402,7 +415,7 @@ async function collections() {
402
415
  }
403
416
 
404
417
  // src/commands/start.ts
405
- import { writeFileSync as writeFileSync2, unlinkSync } from "fs";
418
+ import { writeFileSync as writeFileSync2, unlinkSync as unlinkSync2 } from "fs";
406
419
 
407
420
  // ../node_modules/.bun/chokidar@4.0.3/node_modules/chokidar/esm/index.js
408
421
  import { stat as statcb } from "fs";
@@ -2271,13 +2284,350 @@ async function walkDirRecursive(dir, results) {
2271
2284
  }
2272
2285
  }
2273
2286
 
2287
+ // src/daemon/service.ts
2288
+ import { resolve as resolve5, dirname as dirname3 } from "path";
2289
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, unlinkSync } from "fs";
2290
+ var TASK_NAME = "SeedvaultDaemon";
2291
+ function detectPlatform() {
2292
+ if (process.platform === "darwin")
2293
+ return "macos";
2294
+ if (process.platform === "linux")
2295
+ return "linux";
2296
+ if (process.platform === "win32")
2297
+ return "windows";
2298
+ throw new Error(`Unsupported platform: ${process.platform}. Only macOS, Linux, and Windows are supported.`);
2299
+ }
2300
+ function resolveBunPath() {
2301
+ const which = Bun.which("bun");
2302
+ if (which)
2303
+ return which;
2304
+ if (process.platform === "win32") {
2305
+ const fallback = resolve5(process.env.USERPROFILE || process.env.HOME || "~", ".bun", "bin", "bun.exe");
2306
+ if (existsSync3(fallback))
2307
+ return fallback;
2308
+ } else {
2309
+ const fallback = resolve5(process.env.HOME || "~", ".bun", "bin", "bun");
2310
+ if (existsSync3(fallback))
2311
+ return fallback;
2312
+ }
2313
+ throw new Error("Cannot find bun executable. Ensure bun is in your PATH.");
2314
+ }
2315
+ function resolveSvPath() {
2316
+ return resolve5(process.argv[1]);
2317
+ }
2318
+ async function runCommand(cmd, args) {
2319
+ const proc = Bun.spawn([cmd, ...args], {
2320
+ stdout: "pipe",
2321
+ stderr: "pipe"
2322
+ });
2323
+ const [stdout2, stderr] = await Promise.all([
2324
+ new Response(proc.stdout).text(),
2325
+ new Response(proc.stderr).text()
2326
+ ]);
2327
+ const exitCode = await proc.exited;
2328
+ if (exitCode !== 0) {
2329
+ throw new Error(`Command failed: ${cmd} ${args.join(" ")}
2330
+ ${stderr.trim() || stdout2.trim()}`);
2331
+ }
2332
+ return { stdout: stdout2.trim(), stderr: stderr.trim() };
2333
+ }
2334
+ function generatePlist(bunPath, svPath, logPath) {
2335
+ return `<?xml version="1.0" encoding="UTF-8"?>
2336
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
2337
+ <plist version="1.0">
2338
+ <dict>
2339
+ <key>Label</key>
2340
+ <string>ai.seedvault.daemon</string>
2341
+ <key>ProgramArguments</key>
2342
+ <array>
2343
+ <string>${bunPath}</string>
2344
+ <string>${svPath}</string>
2345
+ <string>start</string>
2346
+ <string>--foreground</string>
2347
+ </array>
2348
+ <key>KeepAlive</key>
2349
+ <dict>
2350
+ <key>SuccessfulExit</key>
2351
+ <false/>
2352
+ </dict>
2353
+ <key>RunAtLoad</key>
2354
+ <true/>
2355
+ <key>ThrottleInterval</key>
2356
+ <integer>5</integer>
2357
+ <key>StandardOutPath</key>
2358
+ <string>${logPath}</string>
2359
+ <key>StandardErrorPath</key>
2360
+ <string>${logPath}</string>
2361
+ </dict>
2362
+ </plist>
2363
+ `;
2364
+ }
2365
+ function generateUnit(bunPath, svPath, logPath) {
2366
+ return `[Unit]
2367
+ Description=Seedvault Sync Daemon
2368
+
2369
+ [Service]
2370
+ ExecStart=${bunPath} ${svPath} start --foreground
2371
+ Restart=on-failure
2372
+ RestartSec=5
2373
+ StandardOutput=append:${logPath}
2374
+ StandardError=append:${logPath}
2375
+
2376
+ [Install]
2377
+ WantedBy=default.target
2378
+ `;
2379
+ }
2380
+ function escapeXml(s) {
2381
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
2382
+ }
2383
+ function generateTaskXml(bunPath, svPath, logPath) {
2384
+ const eBun = escapeXml(bunPath);
2385
+ const eSv = escapeXml(svPath);
2386
+ const eLog = escapeXml(logPath);
2387
+ return `<?xml version="1.0" encoding="UTF-16"?>
2388
+ <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
2389
+ <RegistrationInfo>
2390
+ <Description>Seedvault Sync Daemon</Description>
2391
+ </RegistrationInfo>
2392
+ <Triggers>
2393
+ <LogonTrigger>
2394
+ <Enabled>true</Enabled>
2395
+ </LogonTrigger>
2396
+ </Triggers>
2397
+ <Settings>
2398
+ <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
2399
+ <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
2400
+ <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
2401
+ <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
2402
+ <RestartOnFailure>
2403
+ <Interval>PT5S</Interval>
2404
+ <Count>999</Count>
2405
+ </RestartOnFailure>
2406
+ </Settings>
2407
+ <Actions>
2408
+ <Exec>
2409
+ <Command>cmd</Command>
2410
+ <Arguments>/c "${eBun}" "${eSv}" start --foreground &gt;&gt; "${eLog}" 2&gt;&amp;1</Arguments>
2411
+ </Exec>
2412
+ </Actions>
2413
+ </Task>
2414
+ `;
2415
+ }
2416
+ async function installService() {
2417
+ const platform = detectPlatform();
2418
+ const bunPath = resolveBunPath();
2419
+ const svPath = resolveSvPath();
2420
+ const logPath = getDaemonLogPath();
2421
+ ensureConfigDir();
2422
+ if (platform === "macos") {
2423
+ await installMacos(bunPath, svPath, logPath);
2424
+ } else if (platform === "linux") {
2425
+ await installLinux(bunPath, svPath, logPath);
2426
+ } else {
2427
+ await installWindows(bunPath, svPath, logPath);
2428
+ }
2429
+ }
2430
+ async function installMacos(bunPath, svPath, logPath) {
2431
+ const plistPath = getLaunchdPlistPath();
2432
+ const plistDir = dirname3(plistPath);
2433
+ if (!existsSync3(plistDir)) {
2434
+ mkdirSync2(plistDir, { recursive: true });
2435
+ }
2436
+ if (existsSync3(plistPath)) {
2437
+ try {
2438
+ await runCommand("launchctl", ["unload", plistPath]);
2439
+ } catch {}
2440
+ }
2441
+ await Bun.write(plistPath, generatePlist(bunPath, svPath, logPath));
2442
+ await runCommand("launchctl", ["load", plistPath]);
2443
+ console.log("Seedvault daemon registered with launchd.");
2444
+ console.log(` Service: ai.seedvault.daemon`);
2445
+ console.log(` Log: ${logPath}`);
2446
+ console.log(` The daemon will auto-restart on crash and start on login.`);
2447
+ console.log(` Run 'sv status' to check, 'sv stop' to unregister.`);
2448
+ }
2449
+ async function installLinux(bunPath, svPath, logPath) {
2450
+ const unitPath = getSystemdUnitPath();
2451
+ const unitDir = dirname3(unitPath);
2452
+ if (!existsSync3(unitDir)) {
2453
+ mkdirSync2(unitDir, { recursive: true });
2454
+ }
2455
+ if (existsSync3(unitPath)) {
2456
+ try {
2457
+ await runCommand("systemctl", ["--user", "disable", "--now", "seedvault.service"]);
2458
+ } catch {}
2459
+ }
2460
+ await Bun.write(unitPath, generateUnit(bunPath, svPath, logPath));
2461
+ await runCommand("systemctl", ["--user", "daemon-reload"]);
2462
+ await runCommand("systemctl", ["--user", "enable", "--now", "seedvault.service"]);
2463
+ console.log("Seedvault daemon registered with systemd.");
2464
+ console.log(` Service: seedvault.service`);
2465
+ console.log(` Log: ${logPath}`);
2466
+ console.log(` The daemon will auto-restart on crash and start on login.`);
2467
+ console.log(` Run 'sv status' to check, 'sv stop' to unregister.`);
2468
+ }
2469
+ async function installWindows(bunPath, svPath, logPath) {
2470
+ const xmlPath = getSchtasksXmlPath();
2471
+ try {
2472
+ await runCommand("schtasks", ["/Delete", "/TN", TASK_NAME, "/F"]);
2473
+ } catch {}
2474
+ await Bun.write(xmlPath, generateTaskXml(bunPath, svPath, logPath));
2475
+ await runCommand("schtasks", ["/Create", "/TN", TASK_NAME, "/XML", xmlPath, "/F"]);
2476
+ await runCommand("schtasks", ["/Run", "/TN", TASK_NAME]);
2477
+ console.log("Seedvault daemon registered with Windows Task Scheduler.");
2478
+ console.log(` Task: ${TASK_NAME}`);
2479
+ console.log(` Log: ${logPath}`);
2480
+ console.log(` The daemon will auto-restart on failure and start on login.`);
2481
+ console.log(` Run 'sv status' to check, 'sv stop' to unregister.`);
2482
+ }
2483
+ async function uninstallService() {
2484
+ const platform = detectPlatform();
2485
+ if (platform === "macos") {
2486
+ await uninstallMacos();
2487
+ } else if (platform === "linux") {
2488
+ await uninstallLinux();
2489
+ } else {
2490
+ await uninstallWindows();
2491
+ }
2492
+ }
2493
+ async function uninstallMacos() {
2494
+ const plistPath = getLaunchdPlistPath();
2495
+ if (!existsSync3(plistPath)) {
2496
+ console.log("No daemon service is registered.");
2497
+ return;
2498
+ }
2499
+ try {
2500
+ await runCommand("launchctl", ["unload", plistPath]);
2501
+ } catch {}
2502
+ unlinkSync(plistPath);
2503
+ cleanupPidFile();
2504
+ console.log("Daemon stopped and service unregistered.");
2505
+ }
2506
+ async function uninstallLinux() {
2507
+ const unitPath = getSystemdUnitPath();
2508
+ if (!existsSync3(unitPath)) {
2509
+ console.log("No daemon service is registered.");
2510
+ return;
2511
+ }
2512
+ try {
2513
+ await runCommand("systemctl", ["--user", "disable", "--now", "seedvault.service"]);
2514
+ } catch {}
2515
+ unlinkSync(unitPath);
2516
+ try {
2517
+ await runCommand("systemctl", ["--user", "daemon-reload"]);
2518
+ } catch {}
2519
+ cleanupPidFile();
2520
+ console.log("Daemon stopped and service unregistered.");
2521
+ }
2522
+ async function uninstallWindows() {
2523
+ let taskExists = false;
2524
+ try {
2525
+ await runCommand("schtasks", ["/Query", "/TN", TASK_NAME]);
2526
+ taskExists = true;
2527
+ } catch {}
2528
+ if (!taskExists) {
2529
+ console.log("No daemon service is registered.");
2530
+ return;
2531
+ }
2532
+ try {
2533
+ await runCommand("schtasks", ["/End", "/TN", TASK_NAME]);
2534
+ } catch {}
2535
+ try {
2536
+ await runCommand("schtasks", ["/Delete", "/TN", TASK_NAME, "/F"]);
2537
+ } catch {}
2538
+ const xmlPath = getSchtasksXmlPath();
2539
+ if (existsSync3(xmlPath)) {
2540
+ try {
2541
+ unlinkSync(xmlPath);
2542
+ } catch {}
2543
+ }
2544
+ cleanupPidFile();
2545
+ console.log("Daemon stopped and service unregistered.");
2546
+ }
2547
+ function cleanupPidFile() {
2548
+ const pidPath = getPidPath();
2549
+ if (existsSync3(pidPath)) {
2550
+ try {
2551
+ unlinkSync(pidPath);
2552
+ } catch {}
2553
+ }
2554
+ }
2555
+ async function getServiceStatus() {
2556
+ const platform = detectPlatform();
2557
+ if (platform === "macos") {
2558
+ return getStatusMacos();
2559
+ } else if (platform === "linux") {
2560
+ return getStatusLinux();
2561
+ } else {
2562
+ return getStatusWindows();
2563
+ }
2564
+ }
2565
+ async function getStatusMacos() {
2566
+ const plistPath = getLaunchdPlistPath();
2567
+ if (!existsSync3(plistPath)) {
2568
+ return { installed: false, running: false, pid: null };
2569
+ }
2570
+ try {
2571
+ const { stdout: stdout2 } = await runCommand("launchctl", ["list", "ai.seedvault.daemon"]);
2572
+ const pidMatch = stdout2.match(/"PID"\s*=\s*(\d+)/);
2573
+ const pid = pidMatch ? parseInt(pidMatch[1], 10) : null;
2574
+ return { installed: true, running: pid !== null, pid };
2575
+ } catch {
2576
+ return { installed: true, running: false, pid: null };
2577
+ }
2578
+ }
2579
+ async function getStatusLinux() {
2580
+ const unitPath = getSystemdUnitPath();
2581
+ if (!existsSync3(unitPath)) {
2582
+ return { installed: false, running: false, pid: null };
2583
+ }
2584
+ let running = false;
2585
+ try {
2586
+ const { stdout: stdout2 } = await runCommand("systemctl", ["--user", "is-active", "seedvault.service"]);
2587
+ running = stdout2 === "active";
2588
+ } catch {}
2589
+ let pid = null;
2590
+ if (running) {
2591
+ try {
2592
+ const { stdout: stdout2 } = await runCommand("systemctl", ["--user", "show", "--property=MainPID", "seedvault.service"]);
2593
+ const match = stdout2.match(/MainPID=(\d+)/);
2594
+ if (match) {
2595
+ const parsed = parseInt(match[1], 10);
2596
+ if (parsed > 0)
2597
+ pid = parsed;
2598
+ }
2599
+ } catch {}
2600
+ }
2601
+ return { installed: true, running, pid };
2602
+ }
2603
+ async function getStatusWindows() {
2604
+ try {
2605
+ const { stdout: stdout2 } = await runCommand("schtasks", ["/Query", "/TN", TASK_NAME, "/FO", "CSV", "/NH"]);
2606
+ const installed = true;
2607
+ const running = stdout2.toLowerCase().includes("running");
2608
+ let pid = null;
2609
+ const pidPath = getPidPath();
2610
+ if (running && existsSync3(pidPath)) {
2611
+ try {
2612
+ const content = await Bun.file(pidPath).text();
2613
+ const parsed = parseInt(content.trim(), 10);
2614
+ if (!isNaN(parsed) && parsed > 0)
2615
+ pid = parsed;
2616
+ } catch {}
2617
+ }
2618
+ return { installed, running, pid };
2619
+ } catch {
2620
+ return { installed: false, running: false, pid: null };
2621
+ }
2622
+ }
2623
+
2274
2624
  // src/commands/start.ts
2275
2625
  async function start(args) {
2276
- const daemonize = args.includes("-d") || args.includes("--daemon");
2277
- if (daemonize) {
2278
- return startBackground();
2626
+ const foreground = args.includes("-f") || args.includes("--foreground");
2627
+ if (foreground) {
2628
+ return startForeground();
2279
2629
  }
2280
- return startForeground();
2630
+ return installService();
2281
2631
  }
2282
2632
  async function startForeground() {
2283
2633
  let config = loadConfig();
@@ -2398,31 +2748,13 @@ async function startForeground() {
2398
2748
  watcher.close();
2399
2749
  syncer.stop();
2400
2750
  try {
2401
- unlinkSync(getPidPath());
2751
+ unlinkSync2(getPidPath());
2402
2752
  } catch {}
2403
2753
  process.exit(0);
2404
2754
  };
2405
2755
  process.on("SIGINT", shutdown);
2406
2756
  process.on("SIGTERM", shutdown);
2407
2757
  }
2408
- async function startBackground() {
2409
- loadConfig();
2410
- const entryPoint = import.meta.dir + "/../index.ts";
2411
- const logPath = getConfigDir() + "/daemon.log";
2412
- const child = Bun.spawn({
2413
- cmd: ["bun", "run", entryPoint, "start"],
2414
- stdin: "ignore",
2415
- stdout: Bun.file(logPath),
2416
- stderr: Bun.file(logPath),
2417
- env: { ...process.env }
2418
- });
2419
- const pid = child.pid;
2420
- writeFileSync2(getPidPath(), String(pid));
2421
- console.log(`Daemon started in background (PID ${pid}).`);
2422
- console.log(` Log: ${logPath}`);
2423
- console.log(` Run 'sv status' to check, 'sv stop' to stop.`);
2424
- child.unref();
2425
- }
2426
2758
  function keyByName(collections2) {
2427
2759
  const map = new Map;
2428
2760
  for (const collection of collections2) {
@@ -2455,46 +2787,11 @@ function reconcileCollections(prev, next) {
2455
2787
  }
2456
2788
 
2457
2789
  // src/commands/stop.ts
2458
- import { readFileSync as readFileSync2, unlinkSync as unlinkSync2, existsSync as existsSync3 } from "fs";
2459
2790
  async function stop() {
2460
- const pidPath = getPidPath();
2461
- if (!existsSync3(pidPath)) {
2462
- console.log("No daemon is running (no PID file found).");
2463
- return;
2464
- }
2465
- const pid = parseInt(readFileSync2(pidPath, "utf-8").trim(), 10);
2466
- if (isNaN(pid)) {
2467
- console.error("Invalid PID file. Removing it.");
2468
- unlinkSync2(pidPath);
2469
- return;
2470
- }
2471
- try {
2472
- process.kill(pid, 0);
2473
- } catch {
2474
- console.log(`Daemon (PID ${pid}) is not running. Cleaning up PID file.`);
2475
- unlinkSync2(pidPath);
2476
- return;
2477
- }
2478
- try {
2479
- process.kill(pid, "SIGTERM");
2480
- console.log(`Sent SIGTERM to daemon (PID ${pid}).`);
2481
- await Bun.sleep(500);
2482
- try {
2483
- process.kill(pid, 0);
2484
- console.log("Daemon still running. Send SIGKILL with: kill -9 " + pid);
2485
- } catch {
2486
- console.log("Daemon stopped.");
2487
- try {
2488
- unlinkSync2(pidPath);
2489
- } catch {}
2490
- }
2491
- } catch (e) {
2492
- console.error(`Failed to stop daemon: ${e.message}`);
2493
- }
2791
+ await uninstallService();
2494
2792
  }
2495
2793
 
2496
2794
  // src/commands/status.ts
2497
- import { readFileSync as readFileSync3, existsSync as existsSync4 } from "fs";
2498
2795
  async function status() {
2499
2796
  if (!configExists()) {
2500
2797
  console.log("Not configured. Run 'sv init' first.");
@@ -2505,21 +2802,19 @@ async function status() {
2505
2802
  `);
2506
2803
  console.log(` Server: ${config.server}`);
2507
2804
  console.log(` Contributor: ${config.contributorId}`);
2508
- const pidPath = getPidPath();
2509
- if (existsSync4(pidPath)) {
2510
- const pid = parseInt(readFileSync3(pidPath, "utf-8").trim(), 10);
2511
- let alive = false;
2512
- try {
2513
- process.kill(pid, 0);
2514
- alive = true;
2515
- } catch {}
2516
- if (alive) {
2517
- console.log(` Daemon: running (PID ${pid})`);
2805
+ try {
2806
+ const platform = detectPlatform();
2807
+ const serviceName = platform === "macos" ? "launchd" : platform === "linux" ? "systemd" : "Task Scheduler";
2808
+ const svc = await getServiceStatus();
2809
+ if (!svc.installed) {
2810
+ console.log(` Daemon: not registered (run 'sv start' to register)`);
2811
+ } else if (svc.running) {
2812
+ console.log(` Daemon: running via ${serviceName}${svc.pid ? ` (PID ${svc.pid})` : ""}`);
2518
2813
  } else {
2519
- console.log(` Daemon: not running (stale PID file)`);
2814
+ console.log(` Daemon: registered via ${serviceName} but not running`);
2520
2815
  }
2521
- } else {
2522
- console.log(" Daemon: not running");
2816
+ } catch {
2817
+ console.log(" Daemon: unsupported platform");
2523
2818
  }
2524
2819
  if (config.collections.length === 0) {
2525
2820
  console.log(" Collections: none configured");
@@ -2644,9 +2939,9 @@ Collections:
2644
2939
  collections List configured collections
2645
2940
 
2646
2941
  Daemon:
2647
- start Start syncing (foreground)
2648
- start -d Start syncing (background)
2649
- stop Stop the daemon
2942
+ start Register OS service and start syncing
2943
+ start -f Start syncing in foreground (debug)
2944
+ stop Stop daemon and unregister service
2650
2945
  status Show sync status
2651
2946
 
2652
2947
  Files:
@@ -2664,7 +2959,7 @@ async function main() {
2664
2959
  return;
2665
2960
  }
2666
2961
  if (cmd === "--version" || cmd === "-v") {
2667
- console.log("0.1.3");
2962
+ console.log("0.2.0");
2668
2963
  return;
2669
2964
  }
2670
2965
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seedvault/cli",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "sv": "bin/sv.mjs"