Corpus Research: required_files Usage in IUC (AI Generated)#
If you are adding <required_files> to a tool and want real exemplars to copy,
this page surveys how the galaxyproject/tools-iuc
collection uses the element in practice — the patterns that work, a couple that
don’t, and a recommended shape for a new tool. It backs the
Pulsar compatibility checklist and complements Galaxy’s
reference docs for the
required_files tool element.
What the element is for#
<required_files> declares which files from a tool’s own directory must travel
with the job when it runs somewhere other than the Galaxy server — most
importantly remote execution via Pulsar,
where the tool directory is not on a shared filesystem and only the declared
files get staged to the remote host. Any wrapped script you reach for through
$__tool_directory__ needs to be listed here, or it silently goes missing on a
Pulsar node while working fine locally.
Adoption across IUC is small but growing, and the exact set turns over fast enough that pinning a list here would be misleading within weeks. To see who declares it today, search the collection directly:
As a snapshot: on 2026-07-27, 23 tool wrappers declared the element. This is
nowhere near universal — the vast majority of IUC tools that call
$__tool_directory__/script.py still do not declare required_files and
rely on the legacy whole-directory copy. So there is not yet a deep well of
precedent, but the exemplars discussed below give you a clean set to model from.
One thing worth knowing up front: as of that snapshot every wrapper that
declares the element uses only the <include path="..."/> form. There is no use
of <exclude>, glob patterns, or bulk directory= inclusion anywhere in the
collection. In practice required_files is used purely as an explicit
allow-list of individual files — so that is the idiom to follow.
Links to tool XMLs below are pinned to a fixed commit so the line numbers keep pointing at what the text describes; follow the search link above for the current state of any given wrapper.
Ways tools use it#
The exemplars fall into a handful of shapes. Find the one closest to your tool and copy it.
A single helper or entry script — the common case#
By far the most frequent pattern: one wrapper script (Python or R) lives beside
the XML and is both declared and invoked through $__tool_directory__.
add_input_name_as_column
is the canonical shape:
<required_files>
<include path="add_input_name_as_column.py"/>
</required_files>
and the command simply runs
python '$__tool_directory__/add_input_name_as_column.py'. Other one-script
examples you can copy directly:
microsatbed —
find_str.pybigwig_outlier_bed —
bigwig_outlier_bed.pyendorspy —
endorS.pybrew3r_r —
brew3r.r_script.Rvcontact2 —
extract_p2c_mapping.pyvirAnnot_blast2tsv —
blast2tsv.py
A script in a subdirectory#
Same as above, but the script lives under a scripts/ (or similar) subdirectory.
Just write the relative path — including the subdirectory — into path, and
reference the same relative path under $__tool_directory__ in the command.
hyphy_infer_stasis_clusters:
<required_files>
<include path="scripts/infer_stasis_clusters.py"/>
</required_files>
run with python3 '$__tool_directory__/scripts/infer_stasis_clusters.py'. The
sibling hyphy_strike_ambigs
does the same with a HyPhy batch-language file, scripts/strike-ambigs.bf — a
reminder that the declared file need not be Python or R.
Several co-dependent scripts#
When the entry script imports or sources its siblings, or the pipeline shells out to more than one file, declare them all. virAnnot_otu is the clearest example:
<required_files>
<include path="otu.py" />
<include path="seek_otu.R" />
<include path="rps2tree_html.py" />
</required_files>
Only otu.py is named on the command line; it is handed the tool directory
(-tp '$__tool_directory__/') so it can locate its two helpers at runtime. Those
helpers never appear on the command line, so without the explicit includes they
would be missing on a Pulsar node. Same idea, different languages:
hgvsparser declares two R files,
parseHGVS.RandbuildHGVS.R, eachsource()d from$__tool_directory__.ena_upload declares
extract_tables.pyanddump_yaml.py, called at different stages of the command.
A library sourced by a generated config script#
Sometimes the declared file is a library of functions rather than the entry
point: the actual program is written into a <configfile> at runtime, and that
generated script sources the library from $__tool_directory__. Both
ggplot2_barplot
and ggplot2_boxplot
do this:
<required_files>
<include path="utils.r" />
</required_files>
with the command
Rscript -e 'source("${__tool_directory__}/utils.r")' -e 'source("${run_script}")'
— the shared library is sourced first, then the generated run_script configfile.
The key point: required_files and configfiles are complementary. The stable
helper code is declared as a required file; the per-job program stays a
<configfile>.
Copying files into the working directory#
Occasionally the declared files are not run in place from $__tool_directory__
at all — the command copies them into the job working directory first. This comes
up with Python, where the caller and its imported modules must sit in the same
directory (a soft link does not satisfy the import).
table_compute:
<required_files>
<include path="scripts/safety.py" />
<include path="scripts/table_compute.py" />
</required_files>
cp '$userconf' ./userconfig.py &&
cp '$__tool_directory__/scripts/safety.py' ./safety.py &&
cp '$__tool_directory__/scripts/table_compute.py' ./table_compute.py &&
python ./table_compute.py
A generated userconfig.py has to be importable from the same directory as the
script, so everything is copied together. Even though the scripts are copied
rather than executed in place, they still must be listed in required_files so
they exist on the remote host to be copied.
Patterns worth internalizing#
Include-only allow-list. Every tool uses
<include path="..."/>and nothing else. Treatrequired_filesas “the explicit list of tool-dir files this job needs,” never as “start from everything and subtract.”One include per
$__tool_directory__reference. The healthy idiom is 1:1 — every file the command reaches for under$__tool_directory__/...has a matching<include>with the same relative path. Both$__tool_directory__/xand${__tool_directory__}/xspellings work and are used interchangeably.Relative paths mirror the on-disk layout. Paths are always relative to the tool directory (
find_str.py,scripts/table_compute.py); subdirectories go straight into thepathattribute.It’s usually code. Most declared files are executable wrappers and helpers —
.py,.R/.r, one HyPhy.bf. Small static data shipped alongside the wrapper is fair game too: getitd declaresanno/amplicon.txtandanno/amplicon_kayser.tsv. What does not belong here is bulk reference data or.locfiles — those go through a data table, not the tool directory.
Anti-patterns to avoid#
A declared file that is never used. upsetr included
utils.r, but nothing in its command or run-script configfile ever referenced it (the command is justRscript '${run_script}'). It looks copy-pasted from the ggplot2 wrappers, which genuinely sourceutils.r. Staging it is dead weight and a maintenance trap — drop includes you don’t use. (The wrapper has since dropped the block entirely, hence the pinned link.)The entry script left off the list. extract_genomic_dna declares only
extract_genomic_dna_utils.py, but the command actually runspython '$__tool_directory__/extract_genomic_dna.py'— the main entry script is not declared. Under Pulsar, only the utils file would stage and the tool would fail to find its own entry point. This is the sharpest cautionary example: the whole value of the element is defeated if the invoked script is omitted.Inconsistent path spellings. Some tools write
$__tool_directory__/fooand others${__tool_directory__}/foo. Both work; pick one for readability within a wrapper.
A recommended shape for a new tool#
For a typical single-script wrapper:
<required_files>
<include path="myscript.py"/>
</required_files>
...
<command><![CDATA[
python '$__tool_directory__/myscript.py' ...
]]></command>
Guidelines distilled from the healthy exemplars:
List every file the command reads from
$__tool_directory__— the entry script and any helper or library it imports or sources. Cross-check therequired_filesblock against every$__tool_directory__reference in the command,version_command, and configfiles. (virAnnot_otu and hgvsparser get this right; extract_genomic_dna does not.)Don’t list files you never reference — no speculative includes (the upsetr mistake).
Keep
pathrelative and identical to the on-disk layout, including anyscripts/subdirectory (hyphy, table_compute).Include-only. Enumerate exactly what is needed; there is no IUC precedent for
<exclude>or globbing, so prefer the explicit list.Pair with
configfiles, don’t replace them. Static helper code goes inrequired_files; per-job generated scripts stay as<configfile>(the ggplot2 pattern).If import-locality forces a copy into the working directory, still declare the sources in
required_filesso they exist on the remote host to be copied (the table_compute pattern).