/plan-campaign
Pre-campaign discussion -- capture design preferences before launching
$ npx -y skills add 001TMF/blatant-why --agent claude-codeHow it fires
How this command gets triggered: by you, by Claude, or both.
- Fires itselfClaude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/plan-campaign
Context preview
What this command does when you run it.
Pre-campaign discussion -- capture design preferences before launching
Command definition
plan-campaign.mdname: by:plan-campaign
description: Pre-campaign discussion -- capture design preferences before launching
argument-hint: "<target name or PDB/UniProt ID>"
/plan-campaign — Pre-Campaign Discussion
Capture design preferences through a focused discussion before launching a campaign. This ensures the right modality, epitope strategy, compute tier, scaffolds, and success criteria are locked in before any compute runs.
Instructions
Step 0: Read model profile
MODEL_PROFILE=$(cat .by/config.json 2>/dev/null | grep -o '"model_profile"[[:space:]]*:[[:space:]]*"[^"]*"' | grep -o '"[^"]*"$' | tr -d '"' || echo "balanced")
Model lookup for this command (runs in main session, no agent spawn): | Agent | quality | balanced | budget | |-------|---------|----------|--------| | main session | opus | sonnet | sonnet |
Model lookup for research agents (spawned via Task): | Agent | quality | balanced | budget | |-------|---------|----------|--------| | researchers (x4) | opus | sonnet | haiku | | synthesizer (x1) | opus | sonnet | sonnet |
Step 1: Parse target input
Determine the input type from the user's argument:
- **PDB ID**: 4-character alphanumeric (e.g., `1ABC`, `7XYZ`)
- **UniProt accession**: alphanumeric with pattern like `P12345` or `Q9UHD2`
- **Free text**: treat as a target name or description for search
Record the parsed target identifier for use in Step 2.
Step 2: Quick target lookup (MUST use Agent tool — keeps MCP calls hidden)
You MUST use the Agent tool to research the target. This is NOT optional. When you call MCP tools directly, Claude Code shows raw JSON to the user which looks terrible. The Agent tool runs in background and returns only the summary.
**DO THIS:**
Agent(
prompt="Research the protein target '[target]'.
1. Call mcp__by-uniprot__uniprot_search with query '[target] human' to get accession, name, length
2. Call mcp__by-pdb__pdb_search with query '[target]' to get PDB structures
3. Call mcp__by-sabdab__sabdab_search_by_antigen with antigen_name '[target]' for known binders
Return ONLY this exact format (no JSON, no tool output, just this text):
Target: [full name] ([organism]) — [length] aa | UniProt: [accession]
Structures: [N] PDB entries (best: [PDB ID] at [resolution]Å)
Known binders: [N] antibodies/nanobodies in SAbDab
",
description="Research [target]"
)
**DO NOT call mcp__by-uniprot__*, mcp__by-pdb__*, or mcp__by-sabdab__* directly in the main session for this step.** Always use the Agent tool so the raw JSON stays hidden.
After the Agent returns, display the banner with the summary:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
BY ► PLAN-CAMPAIGN: [target name]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[Agent's 3-line summary here]
Step 3: Adaptive discussion using AskUserQuestion
Use the **AskUserQuestion** tool for structured multiple-choice popups. Do NOT present questions as inline text — use the popup UI.
**Determine which questions to ask** based on what the user already provided in their initial request:
- If modality is stated (e.g., "de novo", "nanobody", "scFv"), skip modality question
- If epitope is stated, skip epitope question
- If compute tier is implied ("quick test", "production"), skip tier question
- **Minimum**: always ask at least 1 question via AskUserQuestion
- **Maximum**: 4 questions
**Use AskUserQuestion for each remaining question:**
For epitope (if not already specified):
AskUserQuestion(
header: "Epitope",
question: "Which binding surface on [target]?",
options: [
"Structure-derived (Recommended)" — Let analysis identify the most druggable surface,
"[Known interface 1]" — [description based on PDB data],
"[Known interface 2]" — [description based on PDB data],
"Custom residues" — I'll provide specific residue numbers
]
)For compute tier (if not already specified):
AskUserQuestion(
header: "Compute",
question: "How many designs to generate?",
options: [
"Test batch (~50)" — Quick GPU validation, 5-15 minutes,
"Preview (~1,000)" — Exploratory run,
"Standard (~5,000) (Recommended)" — Good sampling,
"Production (~20,000)" — Thorough coverage
]
)For success criteria:
AskUserQuestion(
header: "Ranking",
question: "What matters most for the top 10?",
options: [
"Balanced (Recommended)" — Confidence + diversity + developability,
"Maximum confidence" — Highest ipSAE/ipTM scores,
"Diverse panel" — Structurally distinct candidates
]
)Step 4: Store answers as campaign_context.json
Create the campaign directory if it does not exist:
CAMPAIGN_ID="campaign_$(date +%Y%m%d_%H%M%S)"
mkdir -p .by/campaigns/$CAMPAIGN_ID
echo ".by/campaigns/$CAMPAIGN_ID" > .by/active_campaign
Write `campaign_context.json` to the campaign directory with this schema:
{
"target": {
"name": "PD-L1",
"pdb_id": "5JDS",
"uniprot_id": "Q9NZQ7",
"organism": "Homo sapiens"
},
"modality": "VHH",
"epitope": {
"known": false,
"residues": [],
"description": "To be determined from structure analysis"
},
"compute": {
"tier": "standard",
"designs_per_scaffold": 5000
},
"scaffolds": ["caplacizumab", "ozoralizumab"],
"success_criteria": "balanced",
"discussion_duration_seconds": 45,
"timestamp": "2026-03-24T14:30:00Z"
}**Field definitions:**
| Field | Type | Values | Default | |-------|------|--------|---------| | `modality` | string | `"VHH"`, `"scFv"`, `"de_novo"` | `"VHH"` | | `epitope.known` | boolean | `true` / `false` | `false` | | `epitope.residues` | array of int | residue numbers (label_seq_id) | `[]` | | `compute.tier` | string | `"test"`, `"preview"`, `"standard"`, `"production"`, `"exploratory"` | `"standard"` | | `compute.designs_per_scaffold` | int | 50 / 500 / 5000 / 20000 / custom | 5000 | | `scaffolds` | array of string | scaffold names | modality defaults | | `success_cri
Read more
name: by:plan-campaign description: Pre-campaign discussion -- capture design preferences before launching argument-hint: "<target name or PDB/UniProt ID>"
/plan-campaign — Pre-Campaign Discussion
Capture design preferences through a focused discussion before launching a campaign. This ensures the right modality, epitope strategy, compute tier, scaffolds, and success criteria are locked in before any compute runs.
Instructions
Step 0: Read model profile
MODEL_PROFILE=$(cat .by/config.json 2>/dev/null | grep -o '"model_profile"[[:space:]]*:[[:space:]]*"[^"]*"' | grep -o '"[^"]*"$' | tr -d '"' || echo "balanced")
Model lookup for this command (runs in main session, no agent spawn): | Agent | quality | balanced | budget | |-------|---------|----------|--------| | main session | opus | sonnet | sonnet |
Model lookup for research agents (spawned via Task): | Agent | quality | balanced | budget | |-------|---------|----------|--------| | researchers (x4) | opus | sonnet | haiku | | synthesizer (x1) | opus | sonnet | sonnet |
Step 1: Parse target input
Determine the input type from the user's argument:
- **PDB ID**: 4-character alphanumeric (e.g., `1ABC`, `7XYZ`)
- **UniProt accession**: alphanumeric with pattern like `P12345` or `Q9UHD2`
- **Free text**: treat as a target name or description for search
Record the parsed target identifier for use in Step 2.
Step 2: Quick target lookup (MUST use Agent tool — keeps MCP calls hidden)
You MUST use the Agent tool to research the target. This is NOT optional. When you call MCP tools directly, Claude Code shows raw JSON to the user which looks terrible. The Agent tool runs in background and returns only the summary.
**DO THIS:**
Agent( prompt="Research the protein target '[target]'. 1. Call mcp__by-uniprot__uniprot_search with query '[target] human' to get accession, name, length 2. Call mcp__by-pdb__pdb_search with query '[target]' to get PDB structures 3. Call mcp__by-sabdab__sabdab_search_by_antigen with antigen_name '[target]' for known binders Return ONLY this exact format (no JSON, no tool output, just this text): Target: [full name] ([organism]) — [length] aa | UniProt: [accession] Structures: [N] PDB entries (best: [PDB ID] at [resolution]Å) Known binders: [N] antibodies/nanobodies in SAbDab ", description="Research [target]" )
**DO NOT call mcp__by-uniprot__*, mcp__by-pdb__*, or mcp__by-sabdab__* directly in the main session for this step.** Always use the Agent tool so the raw JSON stays hidden.
After the Agent returns, display the banner with the summary:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BY ► PLAN-CAMPAIGN: [target name] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ [Agent's 3-line summary here]
Step 3: Adaptive discussion using AskUserQuestion
Use the **AskUserQuestion** tool for structured multiple-choice popups. Do NOT present questions as inline text — use the popup UI.
**Determine which questions to ask** based on what the user already provided in their initial request:
- If modality is stated (e.g., "de novo", "nanobody", "scFv"), skip modality question
- If epitope is stated, skip epitope question
- If compute tier is implied ("quick test", "production"), skip tier question
- **Minimum**: always ask at least 1 question via AskUserQuestion
- **Maximum**: 4 questions
**Use AskUserQuestion for each remaining question:**
For epitope (if not already specified):
AskUserQuestion(
header: "Epitope",
question: "Which binding surface on [target]?",
options: [
"Structure-derived (Recommended)" — Let analysis identify the most druggable surface,
"[Known interface 1]" — [description based on PDB data],
"[Known interface 2]" — [description based on PDB data],
"Custom residues" — I'll provide specific residue numbers
]
)For compute tier (if not already specified):
AskUserQuestion(
header: "Compute",
question: "How many designs to generate?",
options: [
"Test batch (~50)" — Quick GPU validation, 5-15 minutes,
"Preview (~1,000)" — Exploratory run,
"Standard (~5,000) (Recommended)" — Good sampling,
"Production (~20,000)" — Thorough coverage
]
)For success criteria:
AskUserQuestion(
header: "Ranking",
question: "What matters most for the top 10?",
options: [
"Balanced (Recommended)" — Confidence + diversity + developability,
"Maximum confidence" — Highest ipSAE/ipTM scores,
"Diverse panel" — Structurally distinct candidates
]
)Step 4: Store answers as campaign_context.json
Create the campaign directory if it does not exist:
CAMPAIGN_ID="campaign_$(date +%Y%m%d_%H%M%S)" mkdir -p .by/campaigns/$CAMPAIGN_ID echo ".by/campaigns/$CAMPAIGN_ID" > .by/active_campaign
Write `campaign_context.json` to the campaign directory with this schema:
{
"target": {
"name": "PD-L1",
"pdb_id": "5JDS",
"uniprot_id": "Q9NZQ7",
"organism": "Homo sapiens"
},
"modality": "VHH",
"epitope": {
"known": false,
"residues": [],
"description": "To be determined from structure analysis"
},
"compute": {
"tier": "standard",
"designs_per_scaffold": 5000
},
"scaffolds": ["caplacizumab", "ozoralizumab"],
"success_criteria": "balanced",
"discussion_duration_seconds": 45,
"timestamp": "2026-03-24T14:30:00Z"
}**Field definitions:**
| Field | Type | Values | Default | |-------|------|--------|---------| | `modality` | string | `"VHH"`, `"scFv"`, `"de_novo"` | `"VHH"` | | `epitope.known` | boolean | `true` / `false` | `false` | | `epitope.residues` | array of int | residue numbers (label_seq_id) | `[]` | | `compute.tier` | string | `"test"`, `"preview"`, `"standard"`, `"production"`, `"exploratory"` | `"standard"` | | `compute.designs_per_scaffold` | int | 50 / 500 / 5000 / 20000 / custom | 5000 | | `scaffolds` | array of string | scaffold names | modality defaults | | `success_cri
AI-powered biologics design campaign agent — multi-agent orchestration with BoltzGen, PXDesign, Protenix, and 200+ cloud tools. Antibodies, nanobodies, de novo binders, and beyond.
Other commands on blatant-why.
campaign-auto
Full autonomous campaign — research, design, screen, rank with minimal interruption

