DFHack Core

Command Implementation

DFHack commands can be implemented in three ways, all of which are used in the same way:

builtin:commands are implemented by the core of DFHack. They manage other DFHack tools, interpret commands, and control basic aspects of DF (force pause or quit).
plugins:are stored in hack/plugins/ and must be compiled with the same version of DFHack. They are less flexible than scripts, but used for complex or ongoing tasks because they run faster.
scripts:are Ruby or Lua scripts stored in hack/scripts/. Because they don’t need to be compiled, scripts are more flexible about versions, and easier to distribute. Most third-party DFHack addons are scripts.

Using DFHack Commands

DFHack commands can be executed in a number of ways:

  1. Typing the command into the DFHack console (see below)
  2. From the OS terminal (see below)
  3. Pressing a key combination set up with keybinding
  4. From one of several Init Files, automatically
  5. Using script to run a batch of commands from a file

The DFHack Console

The command line has some nice line editing capabilities, including history that’s preserved between different runs of DF - use and to go through the history.

To include whitespace in the argument/s to some command, quote it in double quotes. To include a double quote character, use \".

If the first non-whitespace character is :, the command is parsed in an alternative mode. The non-whitespace characters following the : are the command name, and the remaining part of the line is used verbatim as the first argument. This is very useful for the lua and ruby commands. As an example, the following two command lines are exactly equivalent:

:foo a b "c d" e f
foo "a b \"c d\" e f"

Using an OS terminal

DFHack commands can be run from an OS terminal at startup, using ‘+ args’, or at any other time using the dfhack-run executable.

If DF/DFHack is started with arguments beginning with +, the remaining text is treated as a command in the DFHack console. It is possible to use multiple such commands, which are split on +. For example:

./dfhack +load-save region1
"Dwarf Fortress.exe" +devel/print-args Hello! +enable workflow

The first example (*nix), load-save, skips the main menu and loads region1 immediately. The second (Windows) example prints Hello! in the DFHack console, and enables workflow. Note that the :foo syntax for whitespace in arguments is not compatible with ‘+ args’.

dfhack-run

If DF and DFHack are already running, calling dfhack-run my command in an external terminal is equivalent to calling my command in the DFHack console. Direct use of the DFHack console is generally easier, but dfhack-run can be useful in a variety of circumstances:

  • if the console is unavailable
    • with the init setting PRINT_MODE:TEXT
    • while running an interactive command (e.g. liquids or tiletypes)
  • from external programs or scripts
  • if DF or DFHack are not responding

Examples:

./dfhack-run cursecheck
dfhack-run kill-lua

The first (*nix) example checks for vampires; the second (Windows) example uses kill-lua to stop a Lua script.

Note

dfhack-run attempts to connect to a server on TCP port 5000. If DFHack was unable to start this server, dfhack-run will not be able to connect. This could happen if you have other software listening on port 5000, or if you have multiple copies of DF running simultaneously. To assign a different port, see Server configuration.

Built-in Commands

The following commands are provided by the ‘core’ components of DFHack, rather than plugins or scripts.

alias

The alias command allows configuring aliases to other DFHack commands. Aliases are resolved immediately after built-in commands, which means that an alias cannot override a built-in command, but can override a command implemented by a plugin or script.

Usage:

alias list:lists all configured aliases
alias add <name> <command> [arguments...]:
 adds an alias
alias replace <name> <command> [arguments...]:
 replaces an existing alias with a new command, or adds the alias if it does not already exist
alias delete <name>:
 removes the specified alias

Aliases can be given additional arguments when created and invoked, which will be passed to the underlying command in order. An example with devel/print-args:

[DFHack]# alias add pargs devel/print-args example
[DFHack]# pargs text
example
text

cls

Clear the terminal. Does not delete command history.

die

Instantly kills DF without saving.

enable

Many plugins can be in a distinct enabled or disabled state. Some of them activate and deactivate automatically depending on the contents of the world raws. Others store their state in world data. However a number of them have to be enabled globally, and the init file is the right place to do it.

Most such plugins or scripts support the built-in enable and disable commands. Calling them at any time without arguments prints a list of enabled and disabled plugins, and shows whether that can be changed through the same commands. Passing plugin names to these commands will enable or disable the specified plugins. For example, to enable the manipulator plugin:

enable manipulator

It is also possible to enable or disable multiple plugins at once:

enable manipulator search

fpause

Forces DF to pause. This is useful when your FPS drops below 1 and you lose control of the game.

help

Most commands support using the help <command> built-in command to retrieve further help without having to look at this document. ? <cmd> and man <cmd> are aliases.

Some commands (including many scripts) instead take help or ? as an option on their command line - ie <cmd> help.

hide

Hides the DFHack terminal window. Only available on Windows.

keybinding

To set keybindings, use the built-in keybinding command. Like any other command it can be used at any time from the console, but bindings are not remembered between runs of the game unless re-created in dfhack*.init.

Currently, any combinations of Ctrl/Alt/Shift with A-Z, 0-9, F1-F12 or ` are supported.

Possible ways to call the command:

keybinding list <key>
List bindings active for the key combination.
keybinding clear <key> <key>...
Remove bindings for the specified keys.
keybinding add <key> "cmdline" "cmdline"...
Add bindings for the specified key.
keybinding set <key> "cmdline" "cmdline"...
Clear, and then add bindings for the specified key.

The <key> parameter above has the following case-sensitive syntax:

[Ctrl-][Alt-][Shift-]KEY[@context[|context...]]

where the KEY part can be any recognized key and [] denote optional parts.

When multiple commands are bound to the same key combination, DFHack selects the first applicable one. Later add commands, and earlier entries within one add command have priority. Commands that are not specifically intended for use as a hotkey are always considered applicable.

The context part in the key specifier above can be used to explicitly restrict the UI state where the binding would be applicable. If called without parameters, the keybinding command among other things prints the current context string.

Only bindings with a context tag that either matches the current context fully, or is a prefix ending at a / boundary would be considered for execution, i.e. when in context foo/bar/baz, keybindings restricted to any of @foo/bar/baz, @foo/bar, @foo or none will be active.

Multiple contexts can be specified by separating them with a pipe (|) - for example, @foo|bar|baz/foo would match anything under @foo, @bar, or @baz/foo.

Interactive commands like liquids cannot be used as hotkeys.

kill-lua

Stops any currently-running Lua scripts. By default, scripts can only be interrupted every 256 instructions. Use kill-lua force to interrupt the next instruction.

load

load, unload, and reload control whether a plugin is loaded into memory - note that plugins are loaded but disabled unless you do something. Usage:

load|unload|reload PLUGIN|(-a|--all)

Allows dealing with plugins individually by name, or all at once.

Note that plugins do not maintain their enabled state if they are reloaded, so you may need to use enable to re-enable a plugin after reloading it.

ls

ls does not list files like the Unix command, but rather available commands - first built in commands, then plugins, and scripts at the end. Usage:

ls -a:Also list scripts in subdirectories of hack/scripts/, which are generally not intended for direct use.
ls <plugin>:List subcommands for the given plugin.

plug

Lists available plugins, including their state and detailed description.

plug
Lists available plugins (not commands implemented by plugins)
plug [PLUGIN] [PLUGIN] ...
List state and detailed description of the given plugins, including commands implemented by the plugin.

sc-script

Allows additional scripts to be run when certain events occur (similar to onLoad*.init scripts)

script

Reads a text file, and runs each line as a DFHack command as if it had been typed in by the user - treating the input like an init file.

Some other tools, such as autobutcher and workflow, export their settings as the commands to create them - which are later loaded with script

show

Shows the terminal window after it has been hidden. Only available on Windows. You’ll need to use it from a keybinding set beforehand, or the in-game command-prompt.

type

type command shows where command is implemented.

Other Commands

The following commands are not built-in, but offer similarly useful functions.

Configuration Files

Most DFHack settings can be changed by modifying files in the dfhack-config folder (which is in the DF folder). The default versions of these files, if they exist, are in dfhack-config/default and are installed when DFHack starts if necessary.

Init Files

DFHack allows users to automatically run commonly-used DFHack commands when DF is first loaded, when a world is loaded, when a map is loaded, when a map is unloaded, and when a world is unloaded.

Init scripts function the same way they would if the user manually typed in their contents, but are much more convenient. In order to facilitate savegave portability, mod merging, and general organization of init files, DFHack supports multiple init files both in the main DF directory and save-specific init files in the save folders.

DFHack looks for init files in three places each time they could be run:

  1. The dfhack-config/init subdirectory in the main DF directory
  2. data/save/world/raw, where world is the current save, and
  3. data/save/world/raw/objects

For each of those directories, all matching init files will be executed in alphabetical order.

Before running matched init scripts in any of those locations, the dfhack-config/init/default.* file that matches the event will be run to load DFHack defaults. Only the dfhack-config/init directory is checked for this file, not any raw directories. If you want DFHack to load without running any of its default configuration commands, edit the dfhack-config/init/default.* files and comment out the commands you see there.

When reading commands from the init files or with the script command, if the final character on a line is a backslash then the next uncommented line is considered a continuation of that line, with the backslash deleted. Commented lines are skipped, so it is possible to comment out parts of a command with the # character.

dfhack*.init

On startup, DFHack looks for files of the form dfhack*.init (where * is a placeholder for any string, including the empty string).

These files are best used for keybindings and enabling persistent plugins which do not require a world to be loaded.

onLoad*.init

When a world is loaded, DFHack looks for files of the form onLoad*.init, where * can be any string, including the empty string.

A world being loaded can mean a fortress, an adventurer, or legends mode.

These files are best used for non-persistent commands, such as setting a fix script to run on repeat.

onMapLoad*.init

When a map is loaded, either in adventure or fort mode, DFHack looks for files of the form onMapLoad*.init, where * can be any string, including the empty string.

These files are best used for commands that are only relevant once there is a game map loaded.

onMapUnload*.init and onUnload*.init

When a map or world is unloaded, DFHack looks for files of the form onMapUnload*.init or onUnload*.init, respectively.

Modders often use unload init scripts to disable tools which should not run after a modded save is unloaded.

raw/init.d/*.lua

Any lua script named raw/init.d/*.lua, in the save or main DF directory, will be run when any world or that save is loaded.

Script paths

Script paths are folders that DFHack searches to find a script when a command is run. By default, the following folders are searched, in order (relative to the root DF folder):

  1. data/save/<region folder>/raw/scripts (only if a save is loaded)
  2. raw/scripts
  3. hack/scripts

For example, if teleport is run, these folders are searched in order for teleport.lua or teleport.rb, and the first matching file is run.

Script paths can be added by modifying dfhack-config/script-paths.txt. Each line should start with one of these characters:

  • +: adds a script path that is searched before the default paths (above)
  • -: adds a script path that is searched after the default paths
  • #: a comment (the line is ignored)

Paths can be absolute or relative - relative paths are interpreted relative to the root DF folder.

Tip

When developing scripts in the dfhack/scripts repo, it may be useful to add the path to your local copy of the repo with +. This will allow you to make changes in the repo and have them take effect immediately, without needing to re-install or copy scripts over manually.

Note that script-paths.txt is only read at startup, but the paths can also be modified programmatically at any time through the Lua API.

Environment Variables

DFHack’s behavior can be adjusted with some environment variables. For example, on UNIX-like systems:

DFHACK_SOME_VAR=1 ./dfhack
  • DFHACK_PORT: the port to use for the RPC server (used by dfhack-run and remotefortressreader among others) instead of the default 5000. As with the default, if this port cannot be used, the server is not started. See DFHack Remote Interface for more details.
  • DFHACK_DISABLE_CONSOLE: if set, the DFHack console is not set up. This is the default behavior if PRINT_MODE:TEXT is set in data/init/init.txt. Intended for situations where DFHack cannot run in a terminal window.
  • DFHACK_HEADLESS: if set, and PRINT_MODE:TEXT is set, DF’s display will be hidden, and the console will be started unless DFHACK_DISABLE_CONSOLE is also set. Intended for non-interactive gameplay only.
  • DFHACK_NO_GLOBALS, DFHACK_NO_VTABLES: ignores all global or vtable addresses in symbols.xml, respectively. Intended for development use - e.g. to make sure tools do not crash when these addresses are missing.
  • DFHACK_NO_DEV_PLUGINS: if set, any plugins from the plugins/devel folder that are built and installed will not be loaded on startup.
  • DFHACK_LOG_MEM_RANGES (macOS only): if set, logs memory ranges to stderr.log. Note that devel/lsmem can also do this.
  • DFHACK_ENABLE_LUACOV: if set, enables coverage analysis of Lua scripts. Use the devel/luacov script to generate coverage reports from the collected metrics.

Other (non-DFHack-specific) variables that affect DFHack:

  • TERM: if this is set to dumb or cons25 on *nix, the console will not support any escape sequences (arrow keys, etc.).
  • LANG, LC_CTYPE: if either of these contain “UTF8” or “UTF-8” (not case sensitive), DF2CONSOLE() will produce UTF-8-encoded text. Note that this should be the case in most UTF-8-capable *nix terminal emulators already.

Miscellaneous Notes

This section is for odd but important notes that don’t fit anywhere else.

  • If a DF H hotkey is named with a DFHack command, pressing the corresponding Fx button will run that command, instead of zooming to the set location. This feature will be removed in a future version. (see Issue 731)
  • The binaries for 0.40.15-r1 to 0.34.11-r4 are on DFFD. Older versions are available here. These files will eventually be migrated to GitHub. (see Issue 473)