README.md

  1<!--
  2SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  3
  4SPDX-License-Identifier: CC0-1.0
  5-->
  6
  7# Rúmilo
  8
  9_Dedicated CLI research agent_
 10
 11[![REUSE](https://api.reuse.software/badge/git.secluded.site/rumilo)](https://api.reuse.software/info/git.secluded.site/rumilo)
 12![License: GPL-3.0-or-later](https://img.shields.io/badge/license-GPL--3.0--or--later-blue)
 13![Runtime: Bun](https://img.shields.io/badge/runtime-Bun-f9f1e1?logo=bun)
 14![TypeScript](https://img.shields.io/badge/TypeScript-3178c6?logo=typescript&logoColor=white)
 15
 16Query `rumilo` (or make an `rml` alias) in `web` or `repo` mode to have an LLM
 17find an answer. Ask about ... anything! It knows the current date/time so it
 18_can_ do a reasonable job at finding the latest version of `$thing`. It can find
 19some tool's docs and provide usage instructions. It can read a library's source
 20code to provide usage instructions.
 21
 22Use `web` mode to search the internet and read webpages. Provide a URL with `-u`
 23to pre-fetch and attach that page. Rúmilo can still search/fetch if it decides
 24that page isn't enough to answer the query.
 25
 26Use `repo` mode with a provided clone URI to clone the repo into a temporary
 27directory and let the LLM do basic searching/listing/reading/etc. inside. If you
 28or the main agent don't know the clone URI, use `web` mode to find it.
 29
 30You can use any model from any provider, remote or local. In theory. Rúmilo
 31relies on [Pi] for all the LLM agenty things. Web search is _currently_ only
 32through [Kagi] using [kagi-ken]. Kagi normally charge for API access, kagi-ken
 33uses your existing subscription. Webpage fetching is _currently_ only handled by
 34Mozilla's [Tabstack] service. It prefers cached copies if available, avoiding
 35additional load on the destination site when possible. I intend to add some sort
 36of extension system so it's easier to add support for any search/fetch provider.
 37
 38[Pi]: https://github.com/badlogic/pi-mono
 39[Kagi]: https://kagi.com
 40[kagi-ken]: https://github.com/czottmann/kagi-ken
 41[Tabstack]: https://tabstack.ai
 42
 43## Usage
 44
 45```bash
 46rumilo web "how do llm model loop werk?"
 47rumilo web -u https://dev.synthetic.new/docs/openai/models "how should my client parse reasoning content?"
 48rumilo repo -u https://github.com/synthetic-lab/octofriend "how does octo apply edits?"
 49```
 50
 51## Requirements
 52
 53- [Bun]
 54- [Git] (for repo mode)
 55- Kagi session token (copy session link from [user details][kagi user details]
 56  page, paste somewhere, your token is after `token=`)
 57- Tabstack API key (log into [the console][tabstack console], and create a new
 58  API key)
 59
 60[Bun]: https://bun.com
 61[Git]: https://git-scm.com
 62[kagi user details]: https://kagi.com/settings/user_details
 63[tabstack console]: https://console.tabstack.ai
 64
 65## Configuration
 66
 67Rúmilo reads configuration from `$XDG_CONFIG_HOME/rumilo/config.toml`.
 68
 69Example:
 70
 71```toml
 72[defaults]
 73model = "anthropic:claude-sonnet-4-5"
 74cleanup = true
 75
 76[web]
 77model = "anthropic:claude-haiku-4-5"
 78```
 79
 80### Custom Models
 81
 82You can define custom OpenAI-compatible endpoints like Ollama, vLLM, or
 83self-hosted models in the `[custom_models]` section:
 84
 85```toml
 86[custom_models.syn_glm47]
 87provider = "synthetic"
 88api = "openai-completions"
 89base_url = "https://api.synthetic.new/openai/v1"
 90api_key = "!fnox get SYNTHETIC_API_KEY"
 91id = "hf:zai-org/GLM-4.7"
 92name = "GLM 4.7"
 93reasoning = true
 94input = ["text"]
 95cost = { input = 0, output = 0 }
 96context_window = 198000
 97max_tokens = 64000
 98```
 99
100Use custom models with the `custom:` prefix:
101
102```bash
103rumilo web "query" --model custom:syn_glm47
104rumilo repo -u <uri> "query" --model custom:syn_glm47
105```
106
107#### Custom Model Fields
108
109All custom model fields — including provider/API configuration, value resolution
110for `api_key` and `headers`, and OpenAI compatibility flags — are documented in
111[pi-mono's model configuration
112docs](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/models.md).
113That doc uses JSON; in Rúmilo's TOML config, field names use `snake_case`
114instead of `camelCase` (e.g. `base_url` instead of `baseUrl`, `context_window`
115instead of `contextWindow`).
116
117Compatibility flags go in a `[custom_models.<name>.compat]` sub-table:
118
119```toml
120[custom_models.mistral.compat]
121max_tokens_field = "max_tokens"
122requires_tool_result_name = true
123requires_thinking_as_text = true
124requires_mistral_tool_ids = true
125```
126
127**Note on `supports_developer_role`:** OpenAI's Responses API uses `role:
128"developer"` instead of `"system"` for reasoning models. Most OpenAI-compatible
129endpoints do not support this and will return "Incorrect role information"
130errors. If your custom model has `reasoning = true` and you encounter this
131error, set `supports_developer_role = false` in the compat section to use
132`"system"` instead.
133
134### Credentials
135
136Set credentials either via config (above) or environment:
137
138- `KAGI_SESSION_TOKEN`: Kagi session token
139- `TABSTACK_API_KEY`: Tabstack API key