| name | add-bactopia-tool |
| description | Scaffold a complete Bactopia Tool across all three tiers -- module, subworkflow, and workflow entry point under workflows/bactopia-tools/. Creates all files (main.nf, module.config, schema.json, nextflow.config, tests) for the common single-tool pattern. Use when asked to add a new bactopia tool, create a bactopia tool, scaffold a complete tool, add a new analysis tool to bactopia-tools, or wire up a bioconda package as a bactopia-tool. This skill handles the full pipeline from package lookup through file generation -- do not use add-module or add-subworkflow separately when the goal is a complete bactopia-tool. |
Add Bactopia Tool
Scaffold a complete Bactopia Tool pipeline from a bioconda/conda-forge package. This creates all three tiers in one shot:
- Module (
modules/{tool}/) -- the Nextflow process that runs the tool
- Subworkflow (
subworkflows/{tool}/) -- orchestrates the module + aggregation
- Workflow (
workflows/bactopia-tools/{tool}/) -- user-facing entry point
This skill handles the common single-tool pattern which covers ~80% of bactopia-tools (abricate, mlst, bakta, quast, sistr, etc.). Multi-stage pipelines like snippy and pangenome should be hand-built.
Prerequisites
Before using this skill, read:
.agents/docs/standards/05-module-documentation.md -- Module GroovyDoc standards
.agents/docs/standards/04-subworkflow-documentation.md -- Subworkflow GroovyDoc standards
Interactive Questioning
This skill is interactive -- ask the user early and often, especially before creating files.
- Multiple questions at once: Use
AskUserQuestion popups (up to 4 questions per batch).
Mark the recommended option with "(Recommended)" at the end of its label and place it first.
- Single simple question: Just ask in chat, no popup needed.
- When in doubt: Ask. It's cheaper to clarify upfront than to regenerate files.
Phased Workflow
Follow these phases in order. When unsure about ANYTHING, ask the user rather than guess.
Phase 1: Package Verification
Goal: Confirm the package exists on bioconda and retrieve version/container information.
-
Ask the user for the bioconda package name (e.g., mlst, bakta, ssuissero).
-
Run the lookup command:
bash .agents/skills/add-bactopia-tool/scripts/run-bactopia-scaffold.sh lookup {package_name} --bactopia-path . --pretty
-
The output includes:
package, channel, version, build -- package identity
summary, home -- tool description and documentation URL
container_refs -- toolName, docker, image strings
existing_components -- which of module/subworkflow/workflow already exist
-
Present findings to the user and ask them to confirm before proceeding.
If any existing components are found, warn the user.
If the package is not found, ask the user to verify the name.
If the package does not exist on bioconda, inform the user you cannot proceed until a valid bioconda package is provided.
Phase 2: Tool Design
Goal: Gather all design decisions using interactive prompts so files can be generated coherently.
Important: Use the AskUserQuestion tool for structured choices throughout this phase.
Present up to 4 questions per batch. Mark the recommended option (based on WebFetch findings)
with "(Recommended)" at the end of its label and place it first in the options list.
-
Fetch the tool's documentation using WebFetch on the home URL from Phase 1.
- Extract: command-line options, input file types, output files, version command
- If WebFetch fails, ask the user directly
-
Batch 1: Core design choices (AskUserQuestion, up to 4 questions)
Based on WebFetch findings, ask these structured questions:
Question 1 -- Input type:
Determines which BACTOPIATOOL_INIT channel to use.
| Input Type | Channel | params.workflow.ext | Module record input |
|---|
| Assembly | assembly | ['fna'] | record(meta: Record, fna: Path) |
| Reads | reads | ['fastq'] | record(meta: Record, r1: Path?, r2: Path?, se: Path?, lr: Path?) |
| Assembly + reads | assembly_reads | ['fna', 'fastq'] | record(meta: Record, fna: Path, r1: Path?, r2: Path?, se: Path?, lr: Path?) |
| Proteins | proteins | ['faa'] | record(meta: Record, faa: Path) |
| GFF | gff | ['gff'] | record(meta: Record, gff: Path) |
| GenBank | gbff | ['gbk'] | record(meta: Record, gbff: Path) |
Options (pick top 3 most relevant, "Other" is auto-added for the rest):
- Assembly -- takes FASTA assembly files
- Reads -- takes FASTQ read files
- Assembly + Reads -- takes both FASTA and FASTQ
Question 2 -- Database requirement:
- No database needed
- Yes, requires a user-provided database
Question 3 -- Resource label:
- process_low -- 4 CPU, 8GB, 4h (default for most tools)
Phase 3: File Generation
Goal: Generate all 16 files across the three tiers using bactopia-scaffold.
-
Construct the JSON config from the design decisions. Write it to /tmp/scaffold-config.json:
{
"tool": "{tool_name}",
"display_name": "{DisplayName}",
"description": "{One-sentence description}",
"process_name": "{TOOL_NAME}",
"package": "{package_name}",
"version": "{version}",
"build": "{build}",
"home_url": "{github_url}",
"input_type": "{assembly|reads|assembly_reads|proteins|gff|genbank}",
"has_database": false,
"handles_gz": false,
"layout": "flat",
"resource_label":
Phase 4: Review & Customize
Goal: Review generated files and make tool-specific adjustments.
The templates produce correct scaffolds but many tools need customization:
-
Module main.nf -- the shell script block is a placeholder. Customize:
- The actual tool command, flags, and I/O handling
- Input decompression logic (if the tool doesn't handle .gz) -- use the standard
is_compressed pattern (see below)
- Database extraction logic (if database-dependent)
- Always preserve the
# Cleanup comment line -- even if empty, it marks where
cleanup steps go and keeps the shell block structure consistent across all modules
- Version extraction command
Standard decompression pattern (for tools that don't handle .gz natively):
In the Groovy script block, before the shell heredoc:
def is_compressed = fna.getName().endsWith(".gz") ? true : false
def fna_name = fna.getName().replace(".gz", "")
In the shell block:
if [ "${is_compressed}" == "true" ]; then
gzip -c -d ${fna} > ${fna_name}
fi
Then use ${fna_name} as the input filename for the tool command. This pattern is
used consistently across modules (e.g., staphopiasccmec, traitar). Prefer fna.getName();
it returns the task-relative staged path, which is what read-in-place tools need. Use
fna.fileName.name only when you copy/decompress to a fresh bare-named local file (explicit
if/else with cp -L) and this module stageAs's the input into a subdir, where a
staging/fna/ prefix would corrupt the output name (e.g., agrvate, gamma). Do NOT use
alternatives like fna.getName()[0..-4] or inline gunzip -c with if [[ ... == *.gz ]].
-
Module module.config -- review the ext.args construction:
- Verify boolean/string/integer flag handling is correct for each parameter
- Add any fixed flags (e.g.,
--threads ${task.cpus})
-
Phase 5: Integration & Next Steps
Goal: Wire up citations and inform the user about remaining steps.
-
Update data/citations.yml -- add the tool citation entry in alphabetical order:
{tool}:
name: "{ToolName}"
link: "{github_url}"
description: "{One-sentence description}"
cite: "{Full citation text}"
-
List all created files with full paths.
-
Remind the user to run these follow-up skills in order:
/run-tests {tool} module and subworkflow --generate -- generate snapshots and verify tests pass (new tools have no existing snapshots)
/update-catalog -- regenerate catalog.json and llms.txt (only after tests pass)
/merge-schemas on the new workflow -- generate nextflow_schema.json
/run-tests {tool} workflow --generate -- generate snapshots and verify the workflow test passes
The --generate flag is required because newly scaffolded tools have no
snapshot files yet. Without it, nf-test will fail immediately on missing
snapshots.
There is no point running /update-catalog or /merge-schemas if the
module/subworkflow tests are failing.
-
Note: nextflow_schema.json is NOT generated by this skill -- /merge-schemas handles it automatically from the module schema.json files.
Edge Cases
-
Package not found: The lookup command tries bioconda first, then conda-forge. If both fail, ask the user for version/build manually.
-
No build string: Container URLs will contain TODO_BUILD placeholders. Flag for manual review.
-
No --version CLI support: Use hardcoded VERSION pattern in the module main.nf.
-
Multi-package tools (mulled containers): Warn the user that container URLs cannot be auto-constructed. Flag for manual review.
-
Component already exists: The lookup output includes existing_components. Warn before proceeding.
Test Data Discovery
Test data paths are discovered dynamically from existing module tests using:
bash .agents/skills/add-bactopia-tool/scripts/run-bactopia-scaffold.sh test-data --input-type {type} --bactopia-path . --pretty
This scans modules/*/tests/main.nf.test for paths matching the input type and returns
pre-computed template variables. Always use the discovered paths -- never construct test
data paths manually. The output includes test_data_path (compressed, for subworkflow
tests), test_uncompressed_path (for module tests), test_species, and test_sample_id.
Supported input types: assembly, reads, assembly_reads, proteins, gff, genbank.