index.ts

 1#!/usr/bin/env bun
 2import { runWebCommand } from "./commands/web.js";
 3import { runRepoCommand } from "./commands/repo.js";
 4import { RumiloError } from "../util/errors.js";
 5import { parseArgs } from "./parse-args.js";
 6import { readFileSync } from "node:fs";
 7import { join } from "node:path";
 8import { fileURLToPath } from "node:url";
 9
10const VERSION = "0.1.0";
11
12async function main() {
13  const { command, options, positional } = parseArgs(process.argv);
14
15  // Handle version flag coming before any command (e.g., rumilo -v)
16  // When short flags come right after process.argv, they end up in 'command'
17  if (command && (command === "-v" || command === "--version") && Object.keys(options).length === 0 && positional.length === 0) {
18    console.log(`rumilo v${VERSION}`);
19    process.exit(0);
20  }
21
22  const actualCommand = command?.startsWith("-") ? undefined : command;
23
24  // Handle version/short version as flag (before command) or as command
25  if (options["version"] || actualCommand === "version" || actualCommand === "v") {
26    console.log(`rumilo v${VERSION}`);
27    process.exit(0);
28  }
29
30  if (!actualCommand || actualCommand === "help" || actualCommand === "--help" || actualCommand === "-h" || options["help"]) {
31    console.log("rumilo web <query> [-u URL] [--model <provider:model>] [--verbose] [--no-cleanup]");
32    console.log("rumilo repo -u <uri> <query> [--ref <ref>] [--full] [--model <provider:model>] [--verbose] [--no-cleanup]");
33    process.exit(0);
34  }
35
36  try {
37    if (command === "web") {
38      const query = positional.join(" ");
39      if (!query) {
40        throw new RumiloError("Missing query", "CLI_ERROR");
41      }
42
43      await runWebCommand({
44        query,
45        url: options["uri"] ? String(options["uri"]) : undefined,
46        model: options["model"] ? String(options["model"]) : undefined,
47        verbose: Boolean(options["verbose"]),
48        cleanup: !options["no-cleanup"],
49      });
50      return;
51    }
52
53    if (command === "repo") {
54      const query = positional.join(" ");
55      const uri = options["uri"] ? String(options["uri"]) : undefined;
56      if (!uri) {
57        throw new RumiloError("Missing repo URI", "CLI_ERROR");
58      }
59      if (!query) {
60        throw new RumiloError("Missing query", "CLI_ERROR");
61      }
62
63      await runRepoCommand({
64        query,
65        uri,
66        ref: options["ref"] ? String(options["ref"]) : undefined,
67        full: Boolean(options["full"]),
68        model: options["model"] ? String(options["model"]) : undefined,
69        verbose: Boolean(options["verbose"]),
70        cleanup: !options["no-cleanup"],
71      });
72      return;
73    }
74
75    throw new RumiloError(`Unknown command: ${command}`, "CLI_ERROR");
76  } catch (error: any) {
77    const message = error instanceof Error ? error.message : String(error);
78    console.error(message);
79    process.exitCode = 1;
80  }
81}
82
83main();