{"id":51341133,"url":"https://github.com/kryptic-sh/hrdr","last_synced_at":"2026-07-02T08:00:26.146Z","repository":{"id":368338871,"uuid":"1284626215","full_name":"kryptic-sh/hrdr","owner":"kryptic-sh","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-30T07:01:36.000Z","size":93,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-30T07:08:11.198Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kryptic-sh.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["mxaddict"],"ko_fi":"mxaddict"}},"created_at":"2026-06-30T03:45:08.000Z","updated_at":"2026-06-30T07:01:40.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/kryptic-sh/hrdr","commit_stats":null,"previous_names":["kryptic-sh/hrdr"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/kryptic-sh/hrdr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kryptic-sh%2Fhrdr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kryptic-sh%2Fhrdr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kryptic-sh%2Fhrdr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kryptic-sh%2Fhrdr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kryptic-sh","download_url":"https://codeload.github.com/kryptic-sh/hrdr/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kryptic-sh%2Fhrdr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35038239,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-02T02:00:06.368Z","response_time":173,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-02T08:00:14.328Z","updated_at":"2026-07-02T08:00:26.133Z","avatar_url":"https://github.com/kryptic-sh.png","language":"Rust","funding_links":["https://github.com/sponsors/mxaddict","https://ko-fi.com/mxaddict"],"categories":[],"sub_categories":[],"readme":"# hrdr\n\n[![CI](https://github.com/kryptic-sh/hrdr/actions/workflows/ci.yml/badge.svg)](https://github.com/kryptic-sh/hrdr/actions/workflows/ci.yml)\n\n**Herder** — a fast, agentic coding harness for OpenAI-compatible models.\n\nhrdr drives a model through native tool calls to complete software-engineering\ntasks in a terminal. It is provider-agnostic: point it at any\n`/v1/chat/completions` endpoint — [`infr`](https://github.com/kryptic-sh/infr),\nOpenAI, llama.cpp, OpenRouter — and it streams tokens and runs tools until the\njob is done.\n\n\u003e Active development. The agent loop, adaptive tool set, sessions, file\n\u003e checkpoints, config hot-reload, and a rich TUI are in place. The default local\n\u003e backend is now [`infr`](https://github.com/kryptic-sh/infr) (with a\n\u003e `llama-server` fallback); see the roadmap for what's next.\n\n## Design\n\n- **Provider-agnostic client.** Speaks clean OpenAI chat-completions with native\n  `tools`/`tool_calls` and SSE streaming. The server owns chat-template\n  application; hrdr only ever sends structured `messages[]` + `tools[]`.\n- **Efficient, adaptive tool set.** Fewer, more powerful tools beat a big menu:\n  `read_file`, `write_file`, `edit`, `grep`, `glob`, `todo_write`, `web_fetch`,\n  `web_search`, plus a shell. Token-bounded outputs and line-numbered reads for\n  precise edits. Tools that shell out are **presence-aware**: the shell tool is\n  `bash` and/or `powershell` depending on what's installed, and `grep` uses\n  ripgrep → POSIX grep → a built-in walker — so the model is only ever offered\n  tools it can actually run.\n- **Pluggable input discipline.** Default is a plain, claude-style input (always\n  typing; `Enter` sends, `Shift+Enter` / `\\`+`Enter` insert a newline, `Ctrl+G`\n  opens `$EDITOR`, readline-ish `Ctrl+A`/`Ctrl+E`/`Ctrl+W`). `--vim` swaps in a\n  real [hjkl](https://github.com/kryptic-sh/hjkl) vim editor. Both are\n  `EditorEngine` impls behind an **FSM-agnostic** seam, so a future hjkl\n  VSCode/Helix discipline drops in with zero churn.\n- **Jinja prompt templating.** hrdr's own system prompt is assembled with\n  minijinja templates — editable without a recompile.\n\n## Workspace\n\n| Crate         | Role                                                            |\n| ------------- | --------------------------------------------------------------- |\n| `hrdr-llm`    | OpenAI-compatible client: types, streaming, tool-call assembly. |\n| `hrdr-tools`  | The tool set + registry + file checkpoints.                     |\n| `hrdr-agent`  | The agent loop + minijinja system prompt.                       |\n| `hrdr-editor` | FSM-agnostic hjkl embedding (`EditorEngine` seam).              |\n| `hrdr-tui`    | Ratatui UI: transcript + vim input pane, live streaming.        |\n| `hrdr`        | Binary: TUI by default, `hrdr run \u003ctask\u003e` for headless.         |\n\n## Usage\n\n```bash\n# interactive TUI (see keybindings + slash commands below)\nhrdr\n\n# vim keybindings in the input pane instead\nhrdr --vim\n\n# one-shot headless run, streamed to stdout\nhrdr run \"add a --json flag to the status command\"\n```\n\nIn the TUI, type a message and press `Enter` to send. `@path` attaches a file\n(with completion), and typing `/` opens a slash-command menu.\n\n### Keybindings\n\n| Key                       | Action                                                    |\n| ------------------------- | --------------------------------------------------------- |\n| `Enter`                   | Send (queues a follow-up if a reply is already running)   |\n| `Alt+Enter` / `\\`+`Enter` | Insert a newline (`Shift+Enter` too, where supported)     |\n| `Up` / `Down`             | Recall previous inputs (single-line); drive the `/` menu  |\n| `@path`                   | Attach a file to the message                              |\n| `Ctrl+G`                  | Edit the input in `$EDITOR` / `$VISUAL`                   |\n| `PageUp/Down`, mouse      | Scroll the transcript; `End` follows the newest output    |\n| `Ctrl+L`                  | Clear + repaint the screen                                |\n| `Esc` / `Ctrl+C`          | Interrupt the running turn                                |\n| `Ctrl+C` twice / `Ctrl+D` | Quit (`Ctrl+D` on an empty input); `Ctrl+Q` quits at once |\n\nPass `--vim` for a full [hjkl](https://github.com/kryptic-sh/hjkl) vim editor in\nthe input pane instead of the default plain input.\n\n### Slash commands\n\nType `/` to see the menu (fuzzy-matched, `Tab` to accept). Highlights:\n\n- **Session** — `/clear`, `/sessions`, `/resume \u003cid|name\u003e`, `/rename`,\n  `/compact`, `/info`, `/goto \u003cN|5m|top|end\u003e`, `/find \u003ctext\u003e` (`/next` `/prev`)\n- **Model** — `/model`, `/models`, `/provider`, `/temp`, `/effort`, `/reasoning`\n- **Files** — `/init` (write `AGENTS.md`), `/add`, `/edit \u003cfile\u003e`, `/diff`,\n  `/revert` + `/checkpoints` (file undo), `/tools`, `/expand`, `/paste`\n- **Reply** — `/copy [code|all|msg N]`, `/export [--json]`, `/retry [model]`,\n  `/undo`\n- **Appearance** — `/theme`, `/timestamps [none|relative|exact]`,\n  `/statusbar [none|truncate|wrap]`, `/todo-ttl [turns]`\n- **Other** — `/reload`, `/help`, `/exit`\n\nSessions auto-save per working directory and auto-resume on reopen. Project\ninstructions are read from `AGENTS.md` (the open [agents.md](https://agents.md)\nstandard) walking up from the cwd.\n\n### Local backend\n\nBy default hrdr **spawns a local backend** and shuts it down on exit. It's\n**presence-aware and infr-first**: if\n[`infr`](https://github.com/kryptic-sh/infr) is on `PATH` it's launched as\n`infr serve \u003cmodel\u003e` (native `tools`/`tool_calls`, SSE, GGUF Jinja chat\ntemplate); otherwise it falls back to **`llama-server`** (llama.cpp, started\nwith `--jinja` so tool calling works). If neither is installed, hrdr errors and\npoints you at `--no-backend`. See `apps/hrdr/src/backend.rs`.\n\n```bash\nhrdr                                   # spawns infr (or llama-server); default model Qwen3-8B\nhrdr --backend-model unsloth/Qwen3-14B-GGUF:Q4_K_M       # pick a bigger model (HF ref or .gguf path)\nhrdr --backend-arg=-ngl --backend-arg=99                 # GPU offload passthrough (llama.cpp fallback)\nhrdr --no-backend                      # use an endpoint you started yourself\n```\n\nIf a backend is already answering at `--base-url`, hrdr reuses it instead of\nspawning. Spawn logs go to `~/.cache/hrdr/infr-serve.log` (or\n`llama-server.log`). infr tuning (sampling, max tokens) is via `INFR_*` env\nvars; the same `--backend-model` ref works for both backends.\n\n### Providers\n\n`--provider \u003cname\u003e` (or `provider = \"...\"` in config, or `$HRDR_PROVIDER`)\nselects a preset endpoint + API-key env, and remote providers skip the local\nbackend:\n\nBuilt-in presets:\n\n| Provider               | Endpoint                       | API key env          | Backend |\n| ---------------------- | ------------------------------ | -------------------- | ------- |\n| `zen` / `opencode`     | `https://opencode.ai/zen/v1`   | `OPENCODE_API_KEY`   | remote  |\n| `openai`               | `https://api.openai.com/v1`    | `OPENAI_API_KEY`     | remote  |\n| `openrouter`           | `https://openrouter.ai/api/v1` | `OPENROUTER_API_KEY` | remote  |\n| `claude` / `anthropic` | `https://api.anthropic.com/v1` | `ANTHROPIC_API_KEY`  | remote  |\n| `local` / `infr`       | `http://localhost:8080/v1`     | `HRDR_API_KEY`       | spawned |\n\n(`claude` uses Anthropic's OpenAI-compatible endpoint.)\n\n```bash\nexport OPENCODE_API_KEY=sk-...\nhrdr models --provider zen                 # list OpenCode Zen models\nhrdr --provider zen --model grok-build-0.1 # chat against a Zen model\n```\n\n`--base-url` / `$HRDR_BASE_URL` still override a provider's endpoint.\n\n#### Custom providers\n\nDefine your own in `~/.config/hrdr/config.toml` under `[providers.\u003cname\u003e]` — a\ncustom entry shadows a built-in of the same name. Each can carry its own model\nand context window, so switching is a single `--provider \u003cname\u003e`:\n\n```toml\nprovider = \"mylocal\"            # default provider for this config\n\n[providers.mylocal]\nbase_url = \"http://localhost:8080/v1\"\nmodel = \"Qwen3-30B-A3B\"\nremote = false                  # hrdr may spawn/own a local backend\ncontext_window = 16384\n\n[providers.zen]\nbase_url = \"https://opencode.ai/zen/v1\"\nkey_env = \"OPENCODE_API_KEY\"    # or inline `api_key = \"...\"`\nmodel = \"grok-build-0.1\"\ncontext_window = 256000\n\n[providers.chatgpt]\nbase_url = \"https://api.openai.com/v1\"\nkey_env = \"OPENAI_API_KEY\"\nmodel = \"gpt-5.5\"\n```\n\n`context_window` is optional: if you omit it, hrdr probes the endpoint on\nstartup and uses what it advertises (vLLM's `max_model_len`, llama.cpp's\n`/props` `n_ctx`, etc.), falling back to the spawned backend's `--backend-ctx`\n(default 16384). Set it explicitly to override detection — the OpenAI API\ndoesn't expose context length, and some servers (including infr today) don't\nadvertise it. It drives the status bar's \"X of Y\" and the auto-compaction\nthreshold.\n\n### Theme\n\nThe TUI colors come from an [hjkl](https://github.com/kryptic-sh/hjkl) theme.\n`--theme \u003cpath\u003e` (or `theme = \"...\"` in config / `$HRDR_THEME`) points at an\nhjkl theme TOML (palette + `[ui]` styles); without one, hjkl's bundled dark\ntheme is used. hrdr maps the theme's palette onto its chat roles (user,\nassistant, dim chrome, tool/loader accent, success/error), so any hjkl theme\nworks.\n\nConfiguration (CLI flags override env):\n\n| Env             | Default                            | Meaning                     |\n| --------------- | ---------------------------------- | --------------------------- |\n| `HRDR_BASE_URL` | `http://localhost:8080/v1`         | OpenAI-compatible endpoint. |\n| `HRDR_MODEL`    | `default`                          | Model id.                   |\n| `HRDR_API_KEY`  | _(falls back to `OPENAI_API_KEY`)_ | Bearer token, if required.  |\n\n## Recommended companion tools\n\nhrdr works with zero extra tools installed, but the agent is more capable when\nthese are on `PATH`. It detects what's available and adapts.\n\n| Tool                           | Why                                                                                                          |\n| ------------------------------ | ------------------------------------------------------------------------------------------------------------ |\n| **bash** and/or **PowerShell** | The shell tool. At least one lets the model run builds/tests/commands. `bash` on unix; `pwsh` runs anywhere. |\n| **ripgrep** (`rg`)             | Fastest `grep` backend. Falls back to POSIX `grep`, then a built-in walker — but `rg` is best.               |\n| **git**                        | Repo awareness (branch in the status bar). In a git repo, file checkpoints auto-disable since git covers it. |\n| **`$EDITOR` / `$VISUAL`**      | Used by `Ctrl+G` and `/edit` (falls back to `vi`).                                                           |\n| A **Nerd Font**                | Status-bar icons. Otherwise set `icons = unicode` or `ascii` (config / `--icons` / `$HRDR_ICONS`).           |\n| **infr** or **llama.cpp**      | The managed local backend (infr preferred, `llama-server` fallback). Not needed with a remote provider.      |\n\n`SEARXNG_URL` (optional) points `web_search` at a SearXNG instance for more\nreliable results than the zero-config DuckDuckGo default.\n\n## Platform support\n\nBuilt and tested in CI on **Linux, macOS, and Windows** (fmt + clippy + tests on\nall three). The TUI, model streaming, web tools, theming, clipboard, config\nhot-reload, sessions, and file checkpoints are cross-platform.\n\nThe shell and search tools adapt to the host:\n\n- **Linux / macOS** — `bash` + ripgrep is the typical setup; everything works\n  out of the box.\n- **Windows** — PowerShell is always present, so the shell tool works, and the\n  built-in `grep` fallback means search works with nothing extra installed. For\n  parity with unix, optionally add **Git for Windows** (`bash`) and **ripgrep**\n  to `PATH`.\n\n## Status / roadmap\n\n- [x] OpenAI client (streaming + tool calls) + agent loop\n- [x] Adaptive tool set (files, `web_fetch`/`web_search`, presence-aware shell +\n      grep) with live output streaming\n- [x] TUI: markdown + syntax-highlighted code, diffs, `@file`, slash commands,\n      search/goto, timestamps, configurable status bar, themes\n- [x] Sessions (auto-save + auto-resume per cwd), `AGENTS.md` project\n      instructions\n- [x] File checkpoints + `/revert`; network retry + auto-compact on overflow\n- [x] Config file with persistence + OS-level hot-reload\n- [x] Cross-platform CI (Linux/macOS/Windows)\n- [x] Managed local backend — infr-first (native tool calls), `llama-server`\n      fallback\n- [x] hjkl deps via crates.io registry pins (standalone CI)\n- [ ] MCP client + LSP diagnostics feedback\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkryptic-sh%2Fhrdr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkryptic-sh%2Fhrdr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkryptic-sh%2Fhrdr/lists"}