Add Module
Scaffold a complete Bactopia module for a bioconda/conda-forge package, creating all required files with GroovyDoc documentation and nf-test tests.
Prerequisites
Before using this skill, read:
.agents/docs/standards/05-module-documentation.md -- Module standards including module.config, schema.json, and test templates
.agents/docs/project/04-testing-framework.md -- Testing framework details
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 bioconda package exists and retrieve version/container information.
Ask the user for the bioconda package name (e.g., mlst, bakta, ssuissero).
Ask: Is this a standalone module or part of a multi-process set?
- Standalone: files go in
modules/{tool}/
- Multi-process: files go in
modules/{tool}/{process}/ (e.g., modules/bakta/run/)
- If multi-process: ask which process this is (run, download, summary, collate, etc.)
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.module -- whether the module already exists
Present findings to the user and ask them to confirm before proceeding.
If the module already exists, warn the user.
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:
| Input Type |
Record fields |
| Assembly |
record(meta: Record, fna: Path) |
| Reads |
record(meta: Record, r1: Path?, r2: Path?, se: Path?, lr: Path?) |
| Assembly + reads |
Assembly record + reads on separate lines |
| Alignment |
record(meta: Record, aln: Path) |
| Download / no input |
No record input |
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)
- process_medium -- 8 CPU, 32GB, 12h (BLAST-based, database searches)
- process_high -- 12 CPU, 64GB, 24h (memory-intensive)
- process_single -- 1 CPU, 4GB, 2h (single-threaded only)
Question 4 -- Compressed input:
- Yes, handles .gz natively
- No, needs decompression first
Run test-data discovery based on the input type selected in Batch 1:
bash .agents/skills/add-bactopia-tool/scripts/run-bactopia-scaffold.sh test-data --input-type {input_type} --bactopia-path . --pretty
This returns species/accession combinations already used by similar modules, with
pre-computed test_data_path, test_uncompressed_path, test_species, and
test_sample_id values. Use the returned paths directly in the scaffold config
(Phase 3) -- do NOT construct paths manually.
Batch 2: Outputs, parameters, and test data (AskUserQuestion, up to 3 questions)
Question 1 -- Output files:
Present what WebFetch found. Ask the user to confirm file extensions, descriptions,
and whether each is single (file()) or multiple (files()).
Question 2 -- User parameters:
Only flags representing user-meaningful analysis choices (identity thresholds, scheme
selection, algorithm toggles). Exclude infrastructure params (see below).
Question 3 -- Test data species:
Present top 3-4 species from the test-data discovery results. Recommend species that
exercise the tool's functionality. Include the accession in each option's description.
Present auto-detected details for confirmation.
After the structured choices, present these findings from WebFetch in a summary and
ask the user to confirm or request changes:
- Tool identity: name (snake_case), display name, one-sentence description
- Version command: how the tool reports its version
- Citation key and keywords for GroovyDoc
Infrastructure vs. user parameters (do NOT expose these):
| Tool flag |
Wired to |
Where |
--prefix, --label, --sample-name, etc. |
prefix variable (task.ext.prefix ?: "${_meta.name}") |
Shell block |
--threads, --cpus, -t, -p, etc. |
${task.cpus} |
Shell block or ext.args in module.config |
--output, --outdir, -o, etc. |
Usually . or ${prefix} |
Shell block |
These are written directly in the module's shell block (e.g., --prefix ${prefix},
--threads ${task.cpus}). The prefix variable is set in every module's script block
as prefix = task.ext.prefix ?: "${_meta.name}" and carries the sample name.
Only expose flags that represent user-meaningful analysis choices.
Every user parameter MUST be prefixed with the tool name: {tool}_{param}.
Parameter defaults:
- Do NOT assume a default is needed. Ask the user whether each parameter should have
a specific default value.
- If a string parameter needs a default, use an empty string
"", never null.
- Only include a parameter in the config's
"parameters" array if the user confirms
it should be exposed.
Final confirmation (AskUserQuestion, 1 question)
After presenting the summary, ask:
- Looks good, proceed to file generation
- I need to make changes (user provides details via "Other" or notes)
Phase 3: File Generation
Goal: Generate the 6 module files 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",
"has_database": false,
"handles_gz": false,
"layout": "flat",
"resource_label": "process_low",
"version_command": "{version_command}",
"citation_key": "{citation_key}",
"keywords": ["{keyword1}", "{keyword2}"],
"aggregation": {"strategy": "none"},
"outputs": [
{"name": "{field}", "extension": "{ext}", "description": "{desc}"}
],
"parameters": [
{"name": "{tool}_{param}", "type": "{type}", "default": "{default}", "description": "{desc}", "flag": "{--flag}"}
],
"container_refs": {
"toolName": "{from lookup}",
"docker": "{from lookup}",
"image": "{from lookup}"
},
"test_species": "{species}",
"test_sample_id": "{sample_id}",
"test_data_path": "{compressed_path}",
"test_uncompressed_path": "{uncompressed_path}"
}
Run the scaffold command:
bash .agents/skills/add-bactopia-tool/scripts/run-bactopia-scaffold.sh module --config /tmp/scaffold-config.json --bactopia-path . --pretty
The command creates 6 files:
modules/{tool}/main.nf
modules/{tool}/module.config
modules/{tool}/schema.json
modules/{tool}/tests/main.nf.test
modules/{tool}/tests/nextflow.config
modules/{tool}/tests/nf-test.config
Phase 4: Review & Customize
Goal: Review generated files and make tool-specific adjustments.
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)
- 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
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})
schema.json -- verify parameter types and defaults match module.config
Test files -- verify test data paths and snapshot fields
Run the linter to catch structural issues before proceeding:
bash .agents/skills/add-bactopia-tool/scripts/run-bactopia-lint.sh {tool} --bactopia-path .
This runs bactopia-lint scoped to the new module. Fix any FAILs before moving on.
Common issues:
- JS005: type/default mismatch in schema.json (e.g.,
type=string but default=null)
- M035: citation key not found in
data/citations.yml
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 steps in order:
/run-tests {tool} module --generate -- generate snapshots and verify the module test passes (new modules have no existing snapshots)
- If this module is part of a subworkflow, use
/add-subworkflow next
- If this is a standalone bactopia-tool, use
/add-bactopia-tool instead (it handles all tiers)
The --generate flag is required because newly scaffolded modules have no
snapshot files yet. Without it, nf-test will fail immediately on missing
snapshots.
Edge Cases
Multi-process modules: For nested layouts (modules/{tool}/run/, modules/{tool}/summary/), the scaffold command currently generates flat layout. Manually move files to the nested structure after generation.
No build string: Container URLs will contain TODO_BUILD placeholders.
Multi-package tools (mulled containers): Container URLs cannot be auto-constructed. Flag for manual review.
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.
1---2name: add-module3description: Scaffold a new Bactopia module from a bioconda/conda-forge package. Creates main.nf, module.config, schema.json, and test files following project standards. Use when asked to add a new module, create a new module, scaffold module files, or add a new tool's module.4---56# Add Module78Scaffold a complete Bactopia module for a bioconda/conda-forge package, creating all required files with GroovyDoc documentation and nf-test tests.910## Prerequisites1112Before using this skill, read:13- `.agents/docs/standards/05-module-documentation.md` -- Module standards including module.config, schema.json, and test templates14- `.agents/docs/project/04-testing-framework.md` -- Testing framework details1516## Interactive Questioning1718This skill is interactive -- ask the user early and often, especially before creating files.1920- **Multiple questions at once:** Use `AskUserQuestion` popups (up to 4 questions per batch).21 Mark the recommended option with "(Recommended)" at the end of its label and place it first.22- **Single simple question:** Just ask in chat, no popup needed.23- **When in doubt:** Ask. It's cheaper to clarify upfront than to regenerate files.2425## Phased Workflow2627Follow these phases in order. When unsure about ANYTHING, ask the user rather than guess.2829---3031### Phase 1: Package Verification3233**Goal:** Confirm the bioconda package exists and retrieve version/container information.34351. Ask the user for the **bioconda package name** (e.g., `mlst`, `bakta`, `ssuissero`).36372. Ask: **Is this a standalone module or part of a multi-process set?**38 - Standalone: files go in `modules/{tool}/`39 - Multi-process: files go in `modules/{tool}/{process}/` (e.g., `modules/bakta/run/`)40 - If multi-process: ask which process this is (run, download, summary, collate, etc.)41423. Run the lookup command:43 ```bash44 bash .agents/skills/add-bactopia-tool/scripts/run-bactopia-scaffold.sh lookup {package_name} --bactopia-path . --pretty45 ```46474. The output includes:48 - `package`, `channel`, `version`, `build` -- package identity49 - `summary`, `home` -- tool description and documentation URL50 - `container_refs` -- `toolName`, `docker`, `image` strings51 - `existing_components.module` -- whether the module already exists52535. **Present findings to the user** and ask them to confirm before proceeding.54 If the module already exists, warn the user.5556---5758### Phase 2: Tool Design5960**Goal:** Gather all design decisions using interactive prompts so files can be generated coherently.6162**Important:** Use the `AskUserQuestion` tool for structured choices throughout this phase.63Present up to 4 questions per batch. Mark the recommended option (based on WebFetch findings)64with "(Recommended)" at the end of its label and place it first in the options list.65661. **Fetch the tool's documentation** using WebFetch on the `home` URL from Phase 1.67 - Extract: command-line options, input file types, output files, version command68 - If WebFetch fails, ask the user directly69702. **Batch 1: Core design choices** (AskUserQuestion, up to 4 questions)7172 Based on WebFetch findings, ask these structured questions:7374 **Question 1 -- Input type:**75 | Input Type | Record fields |76 |---|---|77 | Assembly | `record(meta: Record, fna: Path)` |78 | Reads | `record(meta: Record, r1: Path?, r2: Path?, se: Path?, lr: Path?)` |79 | Assembly + reads | Assembly record + reads on separate lines |80 | Alignment | `record(meta: Record, aln: Path)` |81 | Download / no input | No record input |8283 Options (pick top 3 most relevant, "Other" is auto-added for the rest):84 - Assembly -- takes FASTA assembly files85 - Reads -- takes FASTQ read files86 - Assembly + Reads -- takes both FASTA and FASTQ8788 **Question 2 -- Database requirement:**89 - No database needed90 - Yes, requires a user-provided database9192 **Question 3 -- Resource label:**93 - process_low -- 4 CPU, 8GB, 4h (default for most tools)94 - process_medium -- 8 CPU, 32GB, 12h (BLAST-based, database searches)95 - process_high -- 12 CPU, 64GB, 24h (memory-intensive)96 - process_single -- 1 CPU, 4GB, 2h (single-threaded only)9798 **Question 4 -- Compressed input:**99 - Yes, handles .gz natively100 - No, needs decompression first1011023. **Run test-data discovery** based on the input type selected in Batch 1:103 ```bash104 bash .agents/skills/add-bactopia-tool/scripts/run-bactopia-scaffold.sh test-data --input-type {input_type} --bactopia-path . --pretty105 ```106 This returns species/accession combinations already used by similar modules, with107 pre-computed `test_data_path`, `test_uncompressed_path`, `test_species`, and108 `test_sample_id` values. Use the returned paths directly in the scaffold config109 (Phase 3) -- do NOT construct paths manually.1101114. **Batch 2: Outputs, parameters, and test data** (AskUserQuestion, up to 3 questions)112113 **Question 1 -- Output files:**114 Present what WebFetch found. Ask the user to confirm file extensions, descriptions,115 and whether each is single (`file()`) or multiple (`files()`).116117 **Question 2 -- User parameters:**118 Only flags representing user-meaningful analysis choices (identity thresholds, scheme119 selection, algorithm toggles). Exclude infrastructure params (see below).120121 **Question 3 -- Test data species:**122 Present top 3-4 species from the test-data discovery results. Recommend species that123 exercise the tool's functionality. Include the accession in each option's description.1241255. **Present auto-detected details for confirmation.**126127 After the structured choices, present these findings from WebFetch in a summary and128 ask the user to confirm or request changes:129130 - **Tool identity**: name (snake_case), display name, one-sentence description131 - **Version command**: how the tool reports its version132 - **Citation key** and **keywords** for GroovyDoc133134 **Infrastructure vs. user parameters (do NOT expose these):**135136 | Tool flag | Wired to | Where |137 |-----------|----------|-------|138 | `--prefix`, `--label`, `--sample-name`, etc. | `prefix` variable (`task.ext.prefix ?: "${_meta.name}"`) | Shell block |139 | `--threads`, `--cpus`, `-t`, `-p`, etc. | `${task.cpus}` | Shell block or `ext.args` in module.config |140 | `--output`, `--outdir`, `-o`, etc. | Usually `.` or `${prefix}` | Shell block |141142 These are written directly in the module's shell block (e.g., `--prefix ${prefix}`,143 `--threads ${task.cpus}`). The `prefix` variable is set in every module's script block144 as `prefix = task.ext.prefix ?: "${_meta.name}"` and carries the sample name.145146 Only expose flags that represent **user-meaningful analysis choices**.147148 Every user parameter MUST be prefixed with the tool name: `{tool}_{param}`.149150 **Parameter defaults:**151 - Do NOT assume a default is needed. Ask the user whether each parameter should have152 a specific default value.153 - If a string parameter needs a default, use an empty string `""`, never `null`.154 - Only include a parameter in the config's `"parameters"` array if the user confirms155 it should be exposed.1561576. **Final confirmation** (AskUserQuestion, 1 question)158159 After presenting the summary, ask:160 - Looks good, proceed to file generation161 - I need to make changes (user provides details via "Other" or notes)162163---164165### Phase 3: File Generation166167**Goal:** Generate the 6 module files using `bactopia-scaffold`.1681691. Construct the JSON config from the design decisions. Write it to `/tmp/scaffold-config.json`:170171 ```json172 {173 "tool": "{tool_name}",174 "display_name": "{DisplayName}",175 "description": "{One-sentence description}",176 "process_name": "{TOOL_NAME}",177 "package": "{package_name}",178 "version": "{version}",179 "build": "{build}",180 "home_url": "{github_url}",181 "input_type": "assembly",182 "has_database": false,183 "handles_gz": false,184 "layout": "flat",185 "resource_label": "process_low",186 "version_command": "{version_command}",187 "citation_key": "{citation_key}",188 "keywords": ["{keyword1}", "{keyword2}"],189 "aggregation": {"strategy": "none"},190 "outputs": [191 {"name": "{field}", "extension": "{ext}", "description": "{desc}"}192 ],193 "parameters": [194 {"name": "{tool}_{param}", "type": "{type}", "default": "{default}", "description": "{desc}", "flag": "{--flag}"}195 ],196 "container_refs": {197 "toolName": "{from lookup}",198 "docker": "{from lookup}",199 "image": "{from lookup}"200 },201 "test_species": "{species}",202 "test_sample_id": "{sample_id}",203 "test_data_path": "{compressed_path}",204 "test_uncompressed_path": "{uncompressed_path}"205 }206 ```2072082. Run the scaffold command:209 ```bash210 bash .agents/skills/add-bactopia-tool/scripts/run-bactopia-scaffold.sh module --config /tmp/scaffold-config.json --bactopia-path . --pretty211 ```2122133. The command creates 6 files:214 - `modules/{tool}/main.nf`215 - `modules/{tool}/module.config`216 - `modules/{tool}/schema.json`217 - `modules/{tool}/tests/main.nf.test`218 - `modules/{tool}/tests/nextflow.config`219 - `modules/{tool}/tests/nf-test.config`220221---222223### Phase 4: Review & Customize224225**Goal:** Review generated files and make tool-specific adjustments.2262271. **Module `main.nf`** -- the shell script block is a placeholder. Customize:228 - The actual tool command, flags, and I/O handling229 - Input decompression logic (if the tool doesn't handle .gz)230 - Database extraction logic (if database-dependent)231 - **Always preserve the `# Cleanup` comment line** -- even if empty, it marks where232 cleanup steps go and keeps the shell block structure consistent across all modules233 - Version extraction command2342352. **Module `module.config`** -- review the `ext.args` construction:236 - Verify boolean/string/integer flag handling is correct for each parameter237 - Add any fixed flags (e.g., `--threads ${task.cpus}`)2382393. **`schema.json`** -- verify parameter types and defaults match module.config2402414. **Test files** -- verify test data paths and snapshot fields2422435. **Run the linter** to catch structural issues before proceeding:244 ```bash245 bash .agents/skills/add-bactopia-tool/scripts/run-bactopia-lint.sh {tool} --bactopia-path .246 ```247 This runs `bactopia-lint` scoped to the new module. Fix any FAILs before moving on.248 Common issues:249 - JS005: type/default mismatch in schema.json (e.g., `type=string` but `default=null`)250 - M035: citation key not found in `data/citations.yml`2512526. **Update `data/citations.yml`** -- add the tool citation entry in alphabetical order:253 ```yaml254 {tool}:255 name: "{ToolName}"256 link: "{github_url}"257 description: "{One-sentence description}"258 cite: "{Full citation text}"259 ```2602617. **List all created files** with full paths.2622638. **Remind the user** to run these follow-up steps in order:264 1. `/run-tests {tool} module --generate` -- generate snapshots and verify the module test passes (new modules have no existing snapshots)265 2. If this module is part of a subworkflow, use `/add-subworkflow` next266 3. If this is a standalone bactopia-tool, use `/add-bactopia-tool` instead (it handles all tiers)267268 The `--generate` flag is required because newly scaffolded modules have no269 snapshot files yet. Without it, nf-test will fail immediately on missing270 snapshots.271272---273274## Edge Cases2752761. **Multi-process modules**: For nested layouts (`modules/{tool}/run/`, `modules/{tool}/summary/`), the scaffold command currently generates flat layout. Manually move files to the nested structure after generation.2772782. **No build string**: Container URLs will contain `TODO_BUILD` placeholders.2792803. **Multi-package tools** (mulled containers): Container URLs cannot be auto-constructed. Flag for manual review.281282## Test Data Discovery283284Test data paths are discovered dynamically from existing module tests using:285```bash286bash .agents/skills/add-bactopia-tool/scripts/run-bactopia-scaffold.sh test-data --input-type {type} --bactopia-path . --pretty287```288289This scans `modules/*/tests/main.nf.test` for paths matching the input type and returns290pre-computed template variables. Always use the discovered paths -- never construct test291data paths manually. The output includes `test_data_path` (compressed, for subworkflow292tests), `test_uncompressed_path` (for module tests), `test_species`, and `test_sample_id`.293294Supported input types: `assembly`, `reads`, `assembly_reads`, `proteins`, `gff`, `genbank`.