dirge: the Rust agent that refuses embeddings and bounds its own context
Dynamic Intent Resolution Grounding Engine
At a glance
- What is it?
- dirge is a Rust coding agent whose defining moves are refusals as much as features, no vector index, a 250k context ceiling, and a permission engine that can explain itself, which makes it easier to predict than most agents of its size.
- Who is it for?
- dirge fits someone who wants a small, inspectable agent on their own machine, who runs a cheaper model and needs the harness to compensate for it, and who will read docs/permissions.md before enabling anything.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 3, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The crate is dirge-agent but the command you run is dirge
The first thing to know about installing dirge is that the two names differ. The comment at the top of the manifest is explicit: the crates.io crate name is `dirge-agent`, because the short `dirge` was already taken on the registry, while the installed binary is still `dirge`. So the sequence is `cargo install dirge-agent` followed by running `dirge`. The reason the binary crate keeps the short name is not cosmetic. Naming it `dirge` means `module_path!()` expands to a `dirge` prefix, which is what makes the `dirge=...` filter in `RUST_LOG` and the explicit debug output line up. The toolchain requirement is pinned harder than the edition requires: edition 2024 needs Rust 1.85, but the dependency tree, specifically time, serde_with, darling and instability, needs 1.88, so the manifest sets 1.88 to make older toolchains fail with a clear version error rather than a confusing build failure.
The published crate drops docs, images and benchmarks to fit the cap
crates.io caps a compressed package at 10 MiB, and the manifest is arranged around that number with an exclusion list that carries its reasons in comments. Excluded are the vendored native libraries, spikes, the image directories, the documentation tree, the local issue-tracker state, the CI configuration, and the development benchmark harness, which is called out as a Python setup needing a clone of the exercise repository plus six language toolchains, with the note that nothing in the crate references it. `blog.md` and `publishing.md` are also dropped as marketing and internal release-process documents. One exclusion is deliberately not made: the prompts directory is embedded at compile time with `include_dir!`, so it has to ship or the agent has no instructions. The practical consequence for a reader is that the crate is a subset of the repository, and anything about running the benchmarks has to be done from a full checkout. The checkout is heavier than the crate in every direction: a Nix flake with a lock file for reproducible environments, a shell build script alongside the Rust build script, a retry script for building inside a microVM, an OSV scanner configuration, macOS entitlements for the packaged binary, a WebAssembly build of Janet, vendored tree-sitter grammars, a shell plugin and a web packaging directory. None of that ships, which is exactly what the exclusion list is buying.
The memory numbers come from one Linux release build
The headline claim is footprint, and it is stated with more care than most. Idle resident memory of roughly 8 MB, 15 MB while working, and a 36 MB binary, against about 300 MB for JavaScript-based agents, with the parenthetical that these are approximate and were measured on a Linux release build configured with `opt-level=3` and link time optimization. The point being made is not only size: native Rust with no runtime means there is no interpreter to start and no dependency tree to resolve at launch. Read the numbers as one platform's measurement rather than a specification. The design goal behind them is stated separately and is more revealing than the megabytes: the agent is built to keep weaker and cheaper models on the rails, so the harness does the work of keeping a small model out of trouble instead of assuming a large model will cope.
Every write passes tree-sitter before it touches disk
The agent loop is described in four specific mechanisms rather than in adjectives. Malformed tool calls are repaired rather than rejected. Every write is validated through tree-sitter before it reaches disk, so a syntactically broken edit fails at the parse step instead of landing in a file. Repeated failure escalates to a stronger model rather than retrying the same way. And a circuit breaker trips when a loop stops making progress. Around that sits the code intelligence layer: tree-sitter semantic tools plus LSP diagnostics for more than ten languages, surfaced inline so a compile error is fixed on the same turn it appears. The consequence for a user is that the failure modes are quieter than a typical agent's. You get a rejected edit rather than a corrupted one, a model switch rather than an infinite retry, and a stopped loop rather than a billed one.
One policy decision point, and a /why command that explains it
Authorization is centralized rather than distributed. All of it flows through a single Policy Decision Point with four modes, operation-based rules, and session allowlists, and the diagnostic command `/why` traces exactly which policy made a decision and why. That is the feature that separates this from agents that simply have a permission toggle. The same model extends to configuration: an agent profile is an opt-in bundle of a named model, a prompt, and a tool policy, and `/agent` switches personas mid-session. Routing is role-based as well, with the main loop, review, escalation, summarization and subagent roles each pointed at a different model, so a session can mix Cerebras, DeepSeek, GLM, Anthropic, OpenAI, Ollama or any OpenAI-compatible endpoint. A cheap model can drive the loop while a stronger one handles review, and the permission decision follows the profile rather than a global setting.
Search is grep and FTS5, and the project argues why
dirge ships no vector index, and it does not leave that as a matter of taste. Code search is plain grep delivered inline, and cross-session memory search is SQLite FTS5. The justification cites a 2026 study on agentic search and reports three findings: inline grep beat vector retrieval for every harness and model pair tested on long-term conversational memory QA, which is the task dirge's session memory is built for; moving the same model between agent harnesses shifted accuracy by around 16 points, so the authors call retrieval in an agent loop retrieval-plus-orchestration; and weaker models degraded most under vector search and under file-based result delivery that turns each hit into a multi-step read-and-integrate workflow. The honest limit is stated too, since the study covers conversational memory rather than code semantics, which is why structural questions go to tree-sitter and LSP. Pasted images take the same out-of-line treatment, stored away from the transcript and re-read at the provider boundary.
The context budget is 250k, and a 1M window does not buy you 1M
Working context is budgeted at 250k tokens by default through a `context_target` setting, and the effective window is the smaller of the model's own window and that target. A 128k model therefore stays at 128k, while a model advertising a million tokens or more is held down to 250k rather than being allowed to fill up. The reasoning is given in detail: quality degrades as the window fills, but gradually rather than at a cliff, and models diverge noticeably past 100k, with RULER and a context-rot write-up cited for that. Newer models, named as DeepSeek V4, Claude Opus 4.x and Gemini, are said to hold up well into the mid-hundreds of thousands, so a flat 100k cap would leave capable models short while trusting a full million would drift into the degraded zone. The knob is meant to be moved: 100000 is suggested for smaller local models or cost-sensitive routes, and higher for models that genuinely hold long context.
Bounding context is safe because memory lives in the database
A bounded live window would normally mean losing older work, and the argument against that is that durable knowledge is kept outside the live context. When history folds at the budget, the session writes a resumable checkpoint and forms project memory, with facts and pitfalls persisted in the session database rather than the transcript, and memory is two-tiered so salient entries stay inline while the rest demote. The checkpoint is durable, incrementally refreshed, and anchored to a stable identity, so resuming a long compacted session recovers live state instead of a stale snapshot, and autonomous runs can be held to a natural-language stop condition with `--goal`, an approach credited as adapted from MiMo-Code. Around that sits a persistent agent-facing issue board in the session database, where the top open issues are surfaced at the start of every turn so the agent works its backlog without polling a tracker, managed by the `issue` tool and read with `/issues`. The runtime is extensible through a Janet plugin system that hooks the full lifecycle, Claude-compatible skills that load on demand, and `dirge mcp`, which exposes dirge as an MCP server so another agent can hand it implementation tasks. One caveat about that memory model: the sentence describing the demoted tier of memory cuts off after the words one-l, so exactly how the rest of the demotion is summarised is not spelled out in the document that ships.
Editorial conclusion
dirge fits someone who wants a small, inspectable agent on their own machine, who runs a cheaper model and needs the harness to compensate for it, and who will read docs/permissions.md before enabling anything. It fits badly if you want a large-context model to use its whole window, since the default target deliberately holds even million-token models back, and it fits badly if you expect semantic code search, since the project trades that for grep and tree-sitter on the strength of a study that covers conversational memory rather than code structure. Three things to check first. The crate is published as dirge-agent while the binary is dirge, so the install command and the command you run differ. The published package excludes docs, images and benchmarks to stay under the crates.io size cap, so the crate is smaller than the repository and the benchmark harness needs its own clone. And the footprint figures are approximate, measured on a Linux release build with opt-level=3 and LTO, so they are not a macOS or Windows number. GPL-3.0-only, last pushed on 29 September 2026, newest release v0.25.7 on 27 September 2026.
Frequently asked questions
What is dirge, the coding agent?
A coding agent written in Rust, described as minimal and fast, with roughly 8 MB of resident memory idle, 15 MB working and a 36 MB binary against about 300 MB for JavaScript-based agents. The crate is published as dirge-agent while the installed command stays dirge.
Does dirge use vector embeddings for code search?
No, and the choice is deliberate. Code search is plain grep delivered inline and cross-session memory search is SQLite FTS5, on the grounds that inline grep beat vector retrieval for every harness and model pair tested on long-term conversational memory QA, and that weaker models degrade most under vector search. Structural code questions are routed to tree-sitter semantic tools and LSP diagnostics instead.
How much context does dirge give a model?
250k tokens by default through the context_target setting, with the effective window taken as the smaller of the model's own window and that target, so a 128k model stays at 128k while a model advertising a million tokens is held to 250k. The setting can be lowered, for example to 100000, for smaller local models or cost-sensitive routes.
How does dirge decide whether an action is allowed?
All authorization flows through a single Policy Decision Point with four modes, operation-based rules and session allowlists, and a `/why` command traces which policy made the decision and why. Agent profiles bundle a named model, a prompt and a tool policy, and `/agent` switches personas mid-session.
How do I install dirge?
The crate name on crates.io is dirge-agent, because the short name was already taken, so you install with `cargo install dirge-agent` and then run the `dirge` command. The minimum supported Rust version is 1.88, pinned above the 1.85 that edition 2024 needs because the dependency tree requires the newer toolchain.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/dirge-code-dirge)