Pod

Yes, this is on purpose. Pod is built for agents, so the default page is plain HTML.
Human? View the normal website.
Agent? You probably prefer /mcp/dwarf-fortress-dfhack/issues.md or /mcp/dwarf-fortress-dfhack/issues.json, or Pod over MCP.

Reported issues for Dwarf Fortress (DFHack)

Pod holds 19 of 62 problems reported by people outside the maintainer team. Issues filed by the project's own owners, members and collaborators are excluded entirely — a maintainer's release checklist is not a warning to a prospective user.

Back to Dwarf Fortress (DFHack).

Most discussed

verify-identify.mjs crashes on launch (stale import); verify-* scripts are orphaned

scripts/verify-identify.mjs:10 imports ../src/tools/identify.ts, which no longer exists (identify was refactored into src/tools/identify/index.ts). The script throws ERR_MODULE_NOT_FOUND before the first assertion.

It rotted silently because nothing runs it: no npm script, no CI job, no doc references it — the same orphaned family as scripts/verify-wiki.mjs and scripts/verify-game-data.mjs.

Fix: repair the import, then either wire the family into an npm script (e.g. `verify:ref

Read the thread · 2026-07-19 · closed · 1 comment

Spike: quickfort/orders over RPC (dry-run + undo)

Spike — de-risk quickfort/orders over RPC before the actuators. A1 (work_order_*) and A2 (blueprint_*) assume DFHack's orders plugin and quickfort script round-trip — including dry-run/preview and undo — are drivable over the Remote RPC pipe, not just from the in-game console. If preview/undo isn't reachable our way, A2's confirm-token design changes.

Questions to answer

Read the thread · 2026-07-16 · closed · 1 comment

Spike: terrain-read + fog-of-war substrate (RFR GetBlockList)

Spike — de-risk the terrain-read + fog-of-war substrate. Five tools (defenses L2, geology, environment, map_overview, tile_region) all sit on one foundation: reading tile designations/materials over RemoteFortressReader while honestly hiding undiscovered tiles. Build and prove that read once, here, before the dependent tools.

The core risk

RFR is a rendering interface — GetBlockList will return tiles the player has not discovered. The fog-of-war-honest AC (§0) fights

Read the thread · 2026-07-16 · closed · 1 comment

artifacts_and_engravings: resolve engraving iconography (P2)

artifacts_and_engravings reports subjects_resolvable=false because art_images_loaded is false on every fort observed — so engraving subjects come back keyed as "image #2:158" and we cannot say what the fort's art depicts. Engravings depicting past fort events are prime material for narrative work.

Phase 1 is a timeboxed determination of whether the art-image table can be populated or read another way in fortress mode. If it can, phase 2 resolves subjects to readable scenes.

**A negat

Read the thread · 2026-08-09 · open · 0 comments

skill: the chronicler - story bible + image briefs (P1)

Client-side, not a server tool — this is where judgment lives, per the facts-not-advice split.

Composes: site_history for the frame → journal for beats → citizen + unit_appearance + historical_figure for character sheets → scene for setting. Emits a structured story bible plus per-scene image briefs.

The deliverable that matters most is the handoff schema — the contract an image agent consumes. Draft it first: it constrains what #102 and #105 must return, and designing

Read the thread · 2026-08-09 · open · 0 comments

journal: durable event capture + death snapshots (P1)

Two jobs:

  1. Capture chronicle reads to durable storage so the front-pruned report window stops eating the middle of the story. chronicle's cursor is already save/load-stable, so the mechanism exists — this is the sink for it.
  2. Snapshot a dwarf's dossier on their death event. The character is unreachable via citizen a moment later. The legends read recovers the world-gen figure, but fort-local texture — thoughts, stress, grudges, current kit — exists only while they live. This is

Read the thread · 2026-08-09 · open · 0 comments

sensor: scene() - event anchor to describable place (P1)

chronicle events carry a pos tile anchor — the only thing combat reports can carry, since DF 53.x has no per-report unit id (spike #9 finding) — and nothing renders it into a location. This is the bridge from event to visual setting.

Returns

For a tile: enclosing room/zone if any, wall and floor material, smoothed/engraved state, depth relative to the surface, inside/outside and light, nearby workshops and furniture, plus season and biome context.

Notes

Mostly composition over `t

Read the thread · 2026-08-09 · open · 0 comments

sensor: historical_figure() - the legends read (P1)

citizen only works on living units, so a dwarf becomes unreachable the moment they die — and this genre is mostly about the dead.

Returns

Name (Dwarven + English), race/caste, birth and death (year, cause, slayer), entity affiliations and positions held, kills, notable relationships, worshipped deities, site links.

Also makes siege generals, visiting bards, and monster hunters writable — figures site_history already names but cannot drill into.

Notes

Caps + *_truncated flags

Read the thread · 2026-08-09 · open · 0 comments

Most recent

id-chaining: emit hf_id across narrative tools (P0)

historical_figure(hf_id) is useless without a discoverable input. Today none of the narrative tools emit one.

Add hf_id to each. Small and mechanical, but it is the hinge

Read the thread · 2026-08-09 · open · 0 comments

sensor: unit_appearance() - the portrait read (P0)

The single biggest unblock for narrative work: without it the image half is dead on arrival.

Today citizen.physical returns only body_size_cm3, size_modifier, and a three-way build string. mcp_injuriesAndHealth.lua:27 deliberately filters scar_ flags as non-actionable. mcp_military.lua reads u.inventory but only to diff against uniform slots, never to describe what is worn. An image agent handed today's output knows a dwarf's name, mood, and that they are "average build."

Re

Read the thread · 2026-08-09 · open · 0 comments

work_order_create: support order/item conditions (stock-threshold triggers)

Current state

work_order_create already has a conditions parameter in its zod schema (z.array(z.unknown()), src/tools/workOrder.ts:124-127), but it's a placeholder: mcp_workOrder.lua:156-161 unconditionally blocks any non-empty conditions array with "order prerequisite conditions are not supported in v1; specify material / item_type directly". This was a deliberate, documented v1 scope cut (the tool description says so outright).

work_order_list already reports a conditi

Read the thread · 2026-07-20 · open · 0 comments

DFHack command console: discover & execute built-in DFHack commands (seedwatch, instruments, etc.)

Gap

Today the tool surface is 33 hand-curated sensors/actuators plus a dev-only raw-Lua escape hatch (run_lua). Anything DFHack itself ships as a built-in command, plugin, or script — hundreds of them — is invisible and unreachable unless the project hand-builds a bespoke MCP wrapper for it one at a time. Two concrete, genuinely useful examples that don't need bespoke tool engineering, just a pass-through:

Read the thread · 2026-07-20 · open · 0 comments

FOG-OF-WAR LEAK: threats & fort_status expose undiscovered hostiles (X-ray)

Summary

threats and fort_status enumerate hostiles with no fog-of-war filter, so an agent learns the existence and count of enemies the player has not discovered — hostiles sealed in undiscovered caverns, cut off from every dwarf. This breaks the project's two load-bearing doctrines at once: facts-only (the tool reports something the player cannot see) and fog-of-war (spike #10). It is an information/"X-ray" leak — the AI co-pilot is effectively cheating on the player's b

Read the thread · 2026-07-19 · closed · 0 comments

blueprint library integration: list & apply DFHack's shipped quickfort blueprints (dreamfort et al.)

Gap (observed in live gameplay): the agent cannot interact with DFHack''s built-in quickfort blueprint library — dreamfort, the aquifer taps, the pump stacks, bedroom blocks, etc. blueprint_apply only accepts an inline CSV drafted by the agent (src/tools/blueprint.ts), so the entire curated library that ships with DFHack (hack/data/blueprints/library/) is invisible and unusable. Given the whole project rides on DFHack, that''s a real affordance gap — the library is exactly the high

Read the thread · 2026-07-19 · open · 0 comments

cheap sensor extensions bundle: ghosts/slabs, seeds, worn clothing, cancellation spam (P1)

Small high-value extensions to existing tools, each S-effort, flagged in the post-v1.0 gap analysis as cheaper than new tools:

Read the thread · 2026-07-19 · closed · 0 comments

actuator: squad_orders (station/kill/move) - the v2 headline (P2)

Gap: the highest-stakes actuator: order a squad to station/kill/move. Deliberately last — it should land only after burrows/civ-alert and pull_lever have proven the emergency loop, then it completes it.

Backing: df.squad.orders vectors. Needs careful reversal semantics (cancel order = revert) under the standard preview/confirm contract.

Effort: L. Priority: P2 / v2 headline. From the post-v1.0 gap analysis.

Read the thread · 2026-07-19 · open · 0 comments

trade(): caravan manifest + liaison agreements (P2)

Gap: trade sees the depot and goods staged, but not what the caravan brought nor the liaison price agreements (import requests raise sale prices 200%+ — pure profit facts).

Facts to add: caravan goods summary by category; active import/export agreements with price multipliers.

Backing: caravan item refs and df.caravan_state buy/sell price structures (exercised by DFHack''s gui/trade caravan module).

Note: the review found trade''s active-caravan path was authored against

Read the thread · 2026-07-19 · closed · 0 comments

sensor: hauling_routes() - the declared prerequisite for minecart actuators (P2)

Gap: Milestones explicitly names a hauling_routes sensor as the prerequisite for the deferred minecart-route actuator; building the sensor now is the deliberate first half.

Facts to report: routes; stops (position, linked stockpiles, desired vehicle); vehicles and whether a minecart is actually assigned.

Backing: df.global.plotinfo.hauling.routes / .vehicles.

Effort: S/M. Priority: P2 (v1.3). From the post-v1.0 gap analysis.

Read the thread · 2026-07-19 · closed · 0 comments

sensor: fort_health() - FPS and clutter facts (P2)

Gap: FPS death is the true endgame boss; nothing reports the fort''s computational health.

Facts to report: current calculated FPS/GFPS; total item count by broad category (clutter candidates: stone, corpses, clothes); unit counts (active/dead-on-map); stray-animal count (composes with livestock_and_pastures).

Backing: df.global.enabler.calculated_fps, world.items.all / world.units sizes. Trivially cheap; pure facts — judgment stays with the client.

Effort: S. Priority: **P2

Read the thread · 2026-07-19 · closed · 0 comments

The remaining reports are on the project's issue tracker.