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 v${VERSION} — dispatch AI research subagents
 32
 33Commands:
 34  web   Search the web and synthesize an answer
 35  repo  Clone and explore a git repository
 36
 37Usage:
 38  rumilo web <query> [-u <url>] [options]
 39  rumilo repo -u <uri> <query> [options]
 40
 41Options:
 42  -u <url>                 Seed URL to pre-fetch (web) or repository to clone (repo)
 43  --model <provider:model> Override the default model
 44  --ref <ref>              Checkout a specific ref after cloning (repo only)
 45  --full                   Full clone instead of shallow (repo only)
 46  --verbose                Show tool calls and results on stderr
 47  --no-cleanup             Preserve the workspace directory after exit
 48  -v, --version            Print version and exit
 49
 50Configuration:
 51  $XDG_CONFIG_HOME/rumilo/config.toml`);
 52    process.exit(0);
 53  }
 54
 55  try {
 56    if (command === "web") {
 57      const query = positional.join(" ");
 58      if (!query) {
 59        throw new RumiloError("Missing query. Usage: rumilo web <query>", "CLI_ERROR");
 60      }
 61
 62      await runWebCommand({
 63        query,
 64        url: options["uri"] ? String(options["uri"]) : undefined,
 65        model: options["model"] ? String(options["model"]) : undefined,
 66        verbose: Boolean(options["verbose"]),
 67        cleanup: !options["no-cleanup"],
 68      });
 69      return;
 70    }
 71
 72    if (command === "repo") {
 73      const query = positional.join(" ");
 74      const uri = options["uri"] ? String(options["uri"]) : undefined;
 75      if (!uri) {
 76        throw new RumiloError("Missing repository URI. Usage: rumilo repo -u <uri> <query>", "CLI_ERROR");
 77      }
 78      if (!query) {
 79        throw new RumiloError("Missing query. Usage: rumilo repo -u <uri> <query>", "CLI_ERROR");
 80      }
 81
 82      await runRepoCommand({
 83        query,
 84        uri,
 85        ref: options["ref"] ? String(options["ref"]) : undefined,
 86        full: Boolean(options["full"]),
 87        model: options["model"] ? String(options["model"]) : undefined,
 88        verbose: Boolean(options["verbose"]),
 89        cleanup: !options["no-cleanup"],
 90      });
 91      return;
 92    }
 93
 94    throw new RumiloError(`Unknown command: ${command}`, "CLI_ERROR");
 95  } catch (error: any) {
 96    const message = error instanceof Error ? error.message : String(error);
 97    console.error(message);
 98    process.exitCode = 1;
 99  }
100}
101
102main();