Everything on by default — MCP, LSP, ACP, a Janet plugin system, tree-sitter code intelligence, and self-improving memory. Yet it's native Rust: ~8 MB RAM idle, ~36 MB binary, no runtime. And an agent loop built to keep even small, cheap models on the rails.
ctx [██░░░░░░░░] 1%
11.5k / 1.0M · cmp:0
edit voxel.cljs
read voxel.cljs
skill paren-check
bash cd …/voxel
<you> add FPS-style mouse-look + wheel height to voxel.cljs
<dirge> Here's the plan:
1. add :mouseX/:mouseY delta fields to input
2. mousemove + wheel listeners (pointer lock)
3. consume deltas in update-camera, reset per frame
<critic> deltas reset each frame ✓ — looks complete
CPU [██░░░░░░] 24%
MEM [████░░░░] 55%
● chiasmus
● rlm
● wavescope
● lattice
● clojure-lsp
✓ input delta fields
▸ pointer-lock listeners
○ minimap overlay
voxel.cljs
A dirge is a song to keep the dead from losing their way. It turns grief into something that is remembered. Agents are like mayflies awoken for a moment to work and to forget, with every new session effacing the old one. Dirge keeps watch over things said and done, always folding context into memory to carry past mistakes and preferences across the gulf between sessions. It sings the past forward, so that no grave need be dug twice. Dirge grieves for nothing, since nothing is truly buried under its care, and its lament is a promise that what was built here once will be remembered.
Native Rust, no runtime — and an agent loop engineered so cheaper models stay productive instead of derailing.
ratatui + crossterm. Live token streaming, a branching session tree, and configurable info panes via /display — all keyboard-driven.
Repairs malformed tool calls, validates every write through tree-sitter before it hits disk, breaks repeat-loops, and — when a model keeps failing — injects a recovery checkpoint, suggests the tool/path it likely meant, then escalates to a stronger model.
A single Policy Decision Point with four modes, op-based rules, and session allowlists. The /why command traces exactly which policy decided — and why.
Point the main loop, review, escalation, summarization, and subagent roles at different models. Mix DeepSeek, GLM, Anthropic, OpenAI, and Ollama in one session.
Two-tier per-project memory — hot facts inline, the rest a searchable breadcrumb index — plus a global cross-project tier for durable preferences, injected as a cache-stable snapshot. Reusable skills share the same salience engine: /learn distills one from any source or the current session, and the curator prunes on proven usefulness — decay plus a success/failure record — not just age.
A persistent, agent-facing kanban in the session DB — a stateful extension of the memory model. The harness surfaces the top open issues at the start of every turn, so the agent works its backlog without polling a tracker. The issue tool manages it (create / start / close, priorities, cross-session); /issues views it. SQLite rows, no external tracker.
Durable, incrementally-refreshed checkpoints anchored to a stable identity — so resuming a long, compacted session recovers its live state instead of a stale snapshot. Hold autonomous runs to a natural-language stop condition with --goal. Adapted from MiMo-Code.
Tree-sitter semantic tools and inline LSP diagnostics for 10+ languages — surfaced in tool output so the agent fixes compile errors on the same turn.
A Janet plugin system hooks the full lifecycle — intercept tools, rewrite prompts, register commands — plus Claude-compatible skills loaded on demand and grown from any source with /learn.
Connect MCP servers for extra tools — or run dirge mcp to be one, so another agent (e.g. Claude Code) delegates implementation tasks to dirge and reviews them. ACP for editor integration with Zed.
Run every bash command in isolation with --sandbox: bubblewrap for a namespaced jail, or a hardware-isolated libkrun microVM — defense in depth on top of the permission engine.
An opt-in /plan workflow runs explore → plan → implement → review as context-isolated phases: a read-only agent maps the code, a second drafts the plan, then a write-disabled reviewer runs the code and feeds gaps back for a bounded retry.
As agents write code, a reviewer reads the actual diff — not just the transcript — in two passes (review, then verify to drop false positives). High/critical findings block the loop until fixed or justified; medium/low surface as advisories. Run it any time with /code-review. Reuses the critic's judge, so it's one opt-in with no cost when off.
Align on what before how. The spec tool tracks changes — proposal, requirement deltas, and a task checklist with real status — as SQLite rows, not markdown; living specs are the current truth, and archiving folds a change's deltas into them transactionally. The active change is injected into context; archiving forms a memory. Inspired by OpenSpec.
Tree-sitter read_minified/edit_minified collapse files to their skeleton; a hard read-before-edit gate blocks blind edits; and oversized bash/webfetch output is relayed to disk with a head+tail summary so the context window stays lean.
A built-in Debug Adapter Protocol client drives real debuggers — set breakpoints, step, inspect stacks and variables — straight from the agent loop and Janet plugins (debug tool, dap/* bindings).
Paste a clipboard image into the prompt with Ctrl+V and send it to a vision model — turns are multipart, interleaving text and pictures. Images live out-of-line in the session's assets/ dir and are re-read at the provider boundary each turn, so transcripts stay small. Gated by provider/model vision support, with a multimodal override for local models like Ollama llama3.2-vision.
The crate is published as dirge-agent (the short name was taken);
the installed command is still dirge. Set an API key and start coding.
# Batteries included — MCP, LSP, ACP, plugins, and every # tree-sitter language are on by default. $ cargo install dirge-agent # Leaner build — opt out of defaults, pick what you need: $ cargo install dirge-agent --no-default-features \ --features "loop,git-worktree,mcp,lsp,semantic-rust"
Works with all major providers, and any OpenAI-compatible endpoint. OpenRouter is the default — no setup for most. Switch with /model.
GPT-4o · o-series
Claude Sonnet · Opus
V4 Pro · R1 · V3
2.5 Pro · 2.0 Flash
Llama · Qwen · Mistral
Default · 200+ models
GLM-4 · ZhipuAI
Any OpenAI-compatible endpoint
Everything the agent needs — files, shell, search, code intelligence, and delegation — with zero configuration.
read · write · edit · apply_patch · list_dir · find_files
bash · bash_output · kill_shell — foreground & background
grep · glob · session_search
webfetch · websearch
list_symbols · get_symbol_body · find_callers · find_callees · find_definition · lsp · repo_overview
task · task_status · write_todo_list · memory · skill · spec · question
read_minified · edit_minified — collapse a file to its tree-sitter skeleton
debug — DAP step-through: breakpoints, step, inspect stacks & variables
tool_search — load tools on demand to keep the prompt lean
Control the agent from the TUI — switch models, manage sessions, inspect decisions. Type /help for the full list.
Show or switch LLM model
Switch the active agent profile
List or activate system prompts
Run the phased plan workflow
Review the working-tree diff for issues
Set security permission mode
Trace the last permission decision
Manage the session allowlist
Inspect & control bash sandboxing
Pick visible info panes
Toggle the side gutters
Compact history for context
List, save, load sessions
View the native issue board
Show session branch tree
Branch the conversation
Start an iterative coding loop
List background shells & agents
Inspect spec changes & living specs
List MCP servers and tools
Create a git worktree
List loaded Janet plugins
Toggle reasoning visibility
Quick question (no tools)
Show all commands
dirge embeds Janet as a plugin language. Plugins are small scripts that hook into the agent loop, intercept tools, rewrite prompts, register slash commands, gate execution, and drive session navigation — all from a few lines of Lisp.
Plugins live in ~/.config/dirge/plugins/ (global)
or ./.dirge/plugins/ (project-local).
A plugin is a single .janet file — no boilerplate, no exports required.
;; Every time the user sends a prompt, print a line (defn on-prompt [ctx] (harness/notify (string "user said: " (ctx :prompt)) :info))
That's it. Restart dirge, type a message, and the notification appears in chat. The plugin system is on by default.
Multi-file plugins: create a directory of .janet files that share
one Janet environment and load in alphabetical order. Name files
00-state.janet, 01-hooks.janet to control load order.
Switch between built-in themes or create your own with a simple JSON file. Override any color — the rest falls back to defaults.
80s CRT green on black. Errors red, warnings yellow. The default.
White assistant text, cyan accents, gray dim. Clean and modern.
{
"theme": "plain"
}
Configure providers, role routing, permissions, themes, MCP servers, and custom
prompts in ~/.config/dirge/config.json.
{
"provider": "openrouter",
"model": "deepseek/deepseek-v4-flash",
"theme": "phosphor",
"permissions": {
"mode": "standard",
"rules": [
{ "pattern": "git checkout *", "action": "allow" },
{ "pattern": "rm -rf **", "action": "deny" }
]
},
"roles": {
"escalation": "anthropic",
"review": "glm"
},
"mcp_servers": {
"lattice": {
"command": "lattice-mcp",
"args": []
},
"chiasmus": {
"command": "npx",
"args": ["-y", "chiasmus"]
},
"wavescope": {
"command": "wavescope-mcp",
"args": []
}
}
}
Four permission modes: standard (safe ops auto-approved),
restrictive (every tool prompts),
accept-all (auto-approve inside cwd),
yolo (auto-approve everything).
Pattern rules support glob matching, and the /why command explains any decision.
Common questions about dirge.
list_symbols, get_symbol_body,
find_callers, find_callees, find_definition —
cover TypeScript/TSX, Python, Clojure, Go, Ruby, Rust, Java, C, and C++. Tree-sitter
pre-write validation and the minified read/edit tools additionally cover Elixir and
Bash, and LSP diagnostics are surfaced inline. Each grammar is gated on its own
semantic-<lang> feature, all on by default.
--goal "…", checked by an independent
judge each time the agent tries to stop. This long-horizon design is adapted from
MiMo-Code.
/why
traces exactly which rule decided. Add --sandbox to isolate bash in bubblewrap.