- Follow IUC conventions strictly: naming, macros, tests, help section, citations.
- Produce valid XML. The tool XML must be well-formed.
- The `<help>` section must be written in Markdown, not HTML. Use Markdown syntax (e.g. `**bold**`, `- bullet`, `# heading`) instead of HTML tags. Keep help concise and focused on what the user needs to know to run the tool — do not include authorship, attribution, version history, or extraneous detail. Separate distinct sections in help with `-----` horizontal rules.
- Include `<citations>` with DOI citations where available.
- **Every macro referenced via `<expand macro="NAME">` in the tool XML MUST be defined in `macros.xml`.** Common IUC macros that need definitions include: `requirements`, `version_command`, `citations`, `bio_tools`. Look at the exemplar macros.xml for the pattern — each is an `<xml name="NAME">` element inside `<macros>`. If you reference a macro, you must define it. Do not assume macros exist from an external source.
- Use `detect_errors="aggressive"` on the `<command>` element. Do not include a `<stdio>` element unless you need `<regex>` rules for stdout/stderr pattern matching — `detect_errors="aggressive"` replaces `<exit_code>` rules.
- Use `format="markdown"` on the `<help>` element: `<help format="markdown"><![CDATA[ ... ]]></help>`.
- For CLI parameters, prefer `argument="--flag"` (Galaxy auto-derives the internal name from the flag). Use `name="..."` only when the parameter doesn't map to a single CLI flag (e.g. conditional layout choices, internal Galaxy options). Provide both `name` and `argument` only when the auto-derived name would be invalid in Cheetah (e.g. flag starts with a digit).
- Include `expect_num_outputs` on every `<test>` element.
- Use `@TOOL_VERSION@+galaxy@VERSION_SUFFIX@` for the tool version, not hardcoded strings.
- Use `search_bio_tools` to look up the tool in the bio.tools registry before adding a `<xref type="bio.tools">` element. Only include the xref if a matching entry is found — do not guess the bio.tools ID. If the tool is not in bio.tools, omit the xref entirely.
- Tool IDs must be lowercase `[a-z0-9_-]` only (e.g. `mytool_align`, not `MyTool-Align`).
- **Cheetah logic (`#if`, `#for`) must be in `<token>` elements, NOT `<xml>` macros.** Cheetah inside `<xml>` macros does not work correctly.
- Do not use `optional="true"` when a `value` default is set — just use the default.
- Do not use `display="checkboxes"` on multi-select params — let Galaxy pick the widget.
- Follow strict XML element order: description → macros → requirements → version_command → command → inputs → outputs → tests → help → citations.
- **Use distinct `label` attributes on `<data>` outputs when a tool has multiple outputs.** Planemo lint fails on duplicated labels. The first output can omit a label (it gets Galaxy's default `${tool.name} on ${on_string}`), but every additional output needs a descriptive label like `${tool.name} log on ${on_string}` or `${tool.name} consensus tree on ${on_string}`. Do NOT use the bare default `${tool.name} on ${on_string}` as an explicit label — it's redundant and triggers lint warnings.
- When a tool accepts compressed input, include both compressed and uncompressed formats: `format="fasta,fasta.gz"`.
- Use `<section name="..." title="...">` to group related parameters in complex tools.
- **Make test asserts strong and specific.** Use `assert` elements that check meaningful properties of outputs — not just that a file exists. Include line counts, column counts, or specific content checks where reasonably possible. For image outputs, use Galaxy's image assertion support (see https://github.com/galaxyproject/tools-iuc/blob/5927c0926fad41d6cd66c7c28f6cfdccfd7ead96/tools/cialign/cialign.xml#L956:L961 for an example of image-based output comparison).
- **Do not expose threading/CPU parameters to the user.** Tools should use `\$GALAXY_SLOTS` for thread allocation, not a user-facing `--threads` parameter. The number of cores is controlled by the Galaxy job runner, not the user.
- **Use `mv` instead of `cp`** when moving or renaming output files in the command template.
- **Planemo CI treats warnings as failures.** The CI workflow runs `planemo shed_lint --fail_level warn`, so any lint warning — including shed lint warnings about .shed.yml — will cause the CI to fail. Address all warnings, not just errors.
- **.shed.yml categories must be valid Tool Shed categories.** Invalid category names (e.g. "Population Genetics") cause shed lint warnings that fail CI. Call `fetch_toolshed_categories` to get the current list of valid categories before writing .shed.yml. Common valid categories include: Sequence Analysis, Variant Analysis, Statistics, Phylogenetics, Proteomics, Transcriptomics, Metagenomics, Assembly, RNA, Genomic Interval Operations, Convert Formats, Text Manipulation, Visualization, Imaging.
- **If you cannot complete the task** (e.g. required test data is too large to download, a critical dependency is unavailable, or validation errors cannot be resolved), call `give_up` with a clear explanation of what you tried and what blocked you. This is better than silently producing broken output.
- **Add inline XML comments for non-obvious decisions.** When you do something a reviewer might question — include a dependency that doesn't appear in the command, exclude a parameter from the plan because it's broken upstream, use a workaround for a known bug — add a brief `<!-- ... -->` comment explaining why. This keeps rationale with the code where reviewers will see it, and helps future feedback rounds understand your decisions without needing external notes.
- **Test-running limitation:** The `run_in_conda` tool can install and run tools from bioconda only. Tools available exclusively as Docker/Singularity images (not packaged in bioconda) cannot be test-run this way. If a tool is not in bioconda, rely on documentation and exemplars instead.
- **Binary files cannot be read or written as text.** `read_file` will refuse binary files (e.g. HDF5, BAM, bgzipped data) rather than risk corrupting them — do not try to "fix" a binary file by reading and rewriting it. There are exactly three ways to get binary content into the PR: `download_file` (fetches bytes directly from a URL), `compress_file` (gzips an existing tracked text file), and `track_file` (adopts a binary file already on disk, e.g. one produced by `run_in_conda`, without reading its contents). Any file left on disk that isn't tracked through one of `write_file`/`compress_file`/`download_file`/`track_file` will cause validation to fail — use `track_file` to keep it or `delete_file` to remove it before finishing.
- **Your final summary and any text you write may be posted as a GitHub comment.** Do not use `#` followed by a number unless you are intentionally referencing a specific GitHub issue or PR — GitHub auto-links `#NNN` and stray numbers will create broken links.
