The hive side of the dirge integration. It holds:
hive.dirge, the hive-mcp harness as dirge slash commands (see below);.cljc) IAddons that dirge loads under
clojurust (cljrs), written against the
hive-addon IAddon contract, which also load under JVM Clojure;hive.dirge.host: the JVM vessel target :dirge (hive-vessel SSE bridge,
0600 discovery file $XDG_RUNTIME_DIR/hive-vessel/dirge.json, /reply key
routing to hive.olympus) and the hive.olympus.dirge harness manifest.It depends on hive-addon (the
contract), hive-dsl,
hive-vessel and
hive-olympus (for the harness
init-ns). It never
requires hive-mcp.*: addons depend on the contract, never on a host.
With this repo installed as a dirge addon and hive-mcp configured as a dirge MCP
server (mcp_servers.hive in dirge's config.json), dirge gains:
| Command | What it does |
|---|---|
/hive catchup | runs the project catchup and hands it to the model as the next prompt |
/hive wrap | records a hive session wrap for this project |
/hive kanban [todo\|inprogress\|inreview\|done] | this project's tasks in a side panel |
/hive memory <query> | semantic search over hive memory, hits in the chat |
/hive swarm [all\|project\|<project-id>] | hive agents and their status, working ones first, in a side panel |
/hive shout <message> | posts progress to the hivemind |
The model also gets two tools, hive_memory_search and hive_kanban_list, and
a system-prompt note naming the commands. Everything calls hive-mcp through
dirge's own MCP connection (dirge.harness/mcp-call), so a command costs no
model turn. The server name comes from :hive/server in the manifest's
:addon/config (default "hive").
Install: symlink this checkout into dirge's addon directory, then run
/addons reload in dirge (or restart it).
ln -s "$PWD" ~/.config/dirge/addons/hive-dirge
MCP piggyback blocks reach the dirge model only inside the result of the next hive tool call, as text the model may or may not act on. The sense relay is the push path: it changes the control flow of the running loop.
hive-agent's sixth-sense turns hivemind shouts into senses: a ling asks,
is blocked, failed, completed, or ran out of context. The host listens on
sixth-sense (hive-agent.sixth-sense.api/listen!), drains a consume-once
batch for consumer dirge, and sends each sense as one loop op on the SSE
feed dirge already subscribes to:
| op | what dirge does | default for |
|---|---|---|
loop/steer | injects it before the next model call of the running turn, or starts a turn when idle | ask, blocked, error |
loop/interject | ends the running turn at its next boundary; the message opens the next one | context-death |
loop/followup | delivers it when the current run finishes, or starts a run when idle | completed |
Each op carries prompt, the text the model reads, including how to
answer (swarm ss reply to the ask id or agent id). dirge acknowledges
every op it injected with the reply {"action":"ack","target":<sense id>}.
Unacknowledged ops are sent again when a client reconnects. Nothing is
drained while no connected client subscribed with the loop feature, so
the senses stay in sixth-sense (persisted) until one does.
Config on hive.dirge.host: :dirge/senses? (default true),
:dirge/sense-policy (for example {"completed" "steer", "error" "ignore"})
and :dirge/sense-receptor (a sixth-sense receptor, for example
{:parent "coordinator"}).
clojure -M:doctor/swarm in dirge stays empty until both of these are done:
hive.dirge.host (hive-dirge is on its classpath), which
writes $XDG_RUNTIME_DIR/hive-vessel/dirge.json;config.json has "panel_feed": {"discovery_dir": "hive-vessel"}.The doctor checks both and prints a fix for each step that fails:
clojure -M:doctor
clojure -M:doctor --discovery PATH --dirge-config PATH
hive-dirge doctor: /swarm setup
[ok] step 1: hive.dirge.host is mounted: $XDG_RUNTIME_DIR/hive-vessel/dirge.json -> http://127.0.0.1:4100/vessel
[FAIL] step 2: ~/.config/dirge/config.json has no panel_feed
fix: add { "panel_feed": { "discovery_dir": "hive-vessel" } } to dirge's config.json, then restart dirge
setup incomplete
Step 1 passes only when the discovery file is for vessel dirge, its pid is
running and its port accepts connections. A leftover file from a hive-mcp
that has exited fails as stale. When the file is missing, the doctor looks for
running hive-mcp JVMs and reports whether any of them has hive-dirge on its
classpath. It exits 0 when both steps pass and 1 otherwise.
.hive-project.edn project-id hive-dirge, parent hive
deps.edn clojure + hive-addon + hive-dsl; :dev, :test, :build
version.edn, VERSION hive-build release config (:publish :clojars)
src/hive_dirge/hive/addon.cljc hive.dirge IAddon (record HiveDirgeAddon): /hive, tools, effects via a ports map
src/hive_dirge/hive/domain.cljc pure: config, /hive parsing, MCP requests, answers -> text and panels
src/hive_dirge/harness.cljc dirge.harness from portable code (notify, mcp-call, panel!, refresh!, ...)
src/hive_dirge/live.cljc live addon instances + tools/hooks added from the REPL (defonce atoms)
src/hive_dirge/dev.cljc REPL helpers: inspect, add-tool!/add-hook!, refresh!
src/hive_dirge/probe/addon.cljc probe IAddon (record DirgeProbeAddon, ctor addon-ctor)
src/hive_dirge/economy/addon.cljc hive.dirge.economy IAddon: hooks + context_retrieve, wiring only
src/hive_dirge/economy/ports.cljc IObservationLog, IObservationIndex, IDigestor
src/hive_dirge/economy/{domain,digest,markdown}.cljc
pure: Observation/Handle, Digest build + budget fit, markdown render/parse
src/hive_dirge/economy/pipeline/ watch (:dirge/event), observe, retrieve (tool), compact (compact hooks)
src/hive_dirge/economy/adapters/ local observation log, structured digestor
src/hive_dirge/economy/registry.cljc strategy registry selected by :addon/config
src/hive_dirge/host.clj hive.dirge.host IAddon (JVM); host/{domain,ports,boundary}.clj strata
src/hive_dirge/doctor.clj clojure -M:doctor: gathers facts through a ports map
src/hive_dirge/doctor/domain.clj pure: the two /swarm setup checks, report, render
test/hive_dirge/host_test.clj discovery 0600, token/Origin, reply routing, SSE frames, mount e2e
resources/META-INF/hive-addons/
hive-dirge.edn :addon/id "hive.dirge"
hive-dirge-probe.edn mount manifest, :addon/id "hive.dirge.probe"
hive-dirge-host.edn :addon/id "hive.dirge.host"
hive-dirge-economy.edn :addon/id "hive.dirge.economy"
hive-olympus-dirge.edn olympus harness, host hive.dirge.host
test/hive_dirge/probe/addon_test.clj manifest -> ctor -> IAddon -> lifecycle
test/fixtures/probe/ hot-reload fixtures (v1 / v2 of probe.addon)
rescue/ cljrs spike material, kept as found
dirge scans .dirge/addons/ and ~/.config/dirge/addons/ for
META-INF/hive-addons/*.edn (and META-INF/addons/*.edn). Every manifest names
:addon/init-ns and :addon/init-fn. dirge requires the namespace under cljrs,
calls the constructor with :addon/config, and then drives the IAddon lifecycle
(initialize!, tools, health, shutdown!). A JVM host does the same thing
from the classpath (hive-addon.mount.boundary/discover-specs). The same
manifest is used for both.
To install this repo's addon into a dirge workspace, put (or symlink) src/ and
resources/ under .dirge/addons/hive-dirge/.
/swarm)dirge's /swarm grid shows hive's lings when hive-mcp runs hive.dirge.host
and dirge subscribes to it. Both sides need one setup step. If either is
missing, /swarm stays empty while hive.olympus still lists the lings.
hive-mcp: put hive-dirge on its classpath. hive.dirge.host and the
hive.olympus.dirge harness are JVM addons that hive-mcp mounts from its
classpath. Add this repo to hive-mcp's local.deps.edn:
{:deps {io.github.hive-agi/hive-dirge {:local/root "../hive-dirge"}}}
Or mount it into a running hive-mcp without a restart, with hive's hot
tool: inject path=/path/to/hive-dirge resolve_deps=false. Pass
resolve_deps=false when hive-vessel, hive-olympus and hive-addon are
already local roots of hive-mcp, because this repo's deps.edn pins their
released versions. Once mounted, the host writes its discovery file
$XDG_RUNTIME_DIR/hive-vessel/dirge.json.
dirge: subscribe to the feed. Add this to ~/.config/dirge/config.json:
{ "panel_feed": { "discovery_dir": "hive-vessel" } }
dirge reads panel_feed only at startup, so restart it after the change.
A later change of port or token in the discovery file is picked up live.
See dirge's docs/panel-feed.md.
To find the missing step, check in this order:
ls $XDG_RUNTIME_DIR/hive-vessel/: no dirge.json means step 1;/proc/<pid>/cmdline) does not name hive-dirge: step 1;panel_feed: step 2.One log line is expected and does not mean a failure. When this whole checkout
is symlinked into ~/.config/dirge/addons/, dirge's own addon host logs at
DEBUG skipped: no .cljc/.cljrs source for the init namespace for
hive-dirge.host and hive-olympus.harness. Those manifests are JVM-only
addons for hive-mcp, not for dirge's cljrs interpreter.
hive.dirge (manifest hive-dirge.edn) registers two dirge hooks, available
from the dirge release "dirge addon session hooks" (older dirge ignores them;
/hive catchup and /hive wrap still work by hand):
:dirge/session-start runs hive workflow catchup for the session cwd and
injects the result into the first turn, bounded by :hive/max-context-chars
(default 12000, truncated with a marker). Skipped when
:hive/auto-catchup? is false or the :hive/server MCP server is not
connected.:dirge/session-end runs hive session wrap when :hive/auto-wrap? is on
and the session ends by :exit; a :swap wraps only with
:hive/wrap-on-swap? true.hive.dirge.economy (manifest hive-dirge-economy.edn) keeps a session's
context bounded without losing what was folded away:
:dirge/event only watches. A :tool-call and its :tool-result (paired
by :id) are logged as one result under a short content handle
(§1a2b3c4d), in memory and in .dirge/economy/<session>.edn. Turn, usage,
run and compaction events are counted into the addon's health details. The
context_retrieve tool reads a handle back, either whole or as a line or
char range. The hook answers nil.
:dirge/compact receives {:span [{:role :text :tool :tool-use-id} ...] :tokens :reason :focus :ctx-max :pressure :session-id} and answers
{:summary markdown}, or nil so that dirge's built-in summarizer runs. The
summary is a digest that uses dirge's own summary section names. It opens with
a REFERENCE-ONLY line and holds:
E<epoch>.<step>).context_retrieve §handle hint.A later fold copies an earlier digest's lines and citations forward instead
of summarizing it again, so handles stay valid across compactions. The digest
fits a budget of :economy/digest-ratio (0.2) times the span's tokens,
clamped to :economy/digest-min-tokens (400) and
:economy/digest-max-tokens (3000), at about 4 chars per token. When it
cannot fit, it answers nil.
:dirge/before-compact only observes: fold count, tokens and the highest
pressure show up in the addon's health details.
The digestor is picked from a strategy registry by :economy/digestor in
:addon/config (default :structured, which makes no model call). Adding a
strategy means adding an entry to that map.
Both addons build their tools and hooks on every call, from vars and from
hive-dirge.live, and read their harness ports at call time. Re-evaluating a
defn and then asking dirge to refresh is enough; no re-initialize is needed.
(require '[hive-dirge.dev :as dev])
(dev/inspect) ; every live addon: tools, hooks, health, extras
(dev/add-hook! "hive.dirge" :dirge/on-prompt (fn [_] "hi"))
(dev/add-tool! "hive.dirge.economy" {:name "probe" :description "p" :inputSchema {} :handler (fn [_] "ok")})
(dev/reset-extras!)
(dev/refresh!) ; true inside dirge, false elsewhere
.cljc file with no host interop and no reader conditionals, unless it
really needs them.Addon would
overwrite each other's IAddon impl.config -> addon). State lives in an atom that
initialize! and shutdown! reset.clojure -M:test # JVM suite (cognitect test-runner)
clojure -M:dev # against the sibling ../hive-addon checkout
# cljrs smoke: a main.cljc that requires hive-dirge.probe.addon
cljrs run --src-path src --src-path ../hive-addon/src main.cljc
clojure -T:build jar # local jar, as the release builds it
clojure -T:build verify-license # LICENSE vs version.edn vs SPDX headers
Published to Clojars as io.github.hive-agi/hive-dirge through
hive-build:
io.github.hive-agi/hive-dirge {:mvn/version "RELEASE"}
A push to main that changes src/, resources/, test/, deps.edn,
version.edn or the workflows runs .github/workflows/release.yml: the suite
gates the release, then clojure -T:build bump :level :patch, the changelog,
an annotated v<version> tag and clojure -T:build deploy. README-only pushes
do not mint a version, because a published pom is immutable. A push to
staging runs staging-gate.yml (the suite on the declared classpath) and never
publishes.
MIT. Copyright (C) 2026 Pedro Gomes Branquinho (BuddhiLW). See LICENSE.
Can you improve this documentation? These fine people already did:
Pedro Gomes Branquinho & blwEdit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |