Examples
Complete, runnable strategies with commentary. All but the last ship with the suite as example files — copy one into your strategy folder to try it. The last is a pattern worth having even though it is not one of the shipped files.
Every example below is reproduced exactly as it ships, including the rough edges, which are called out where they matter.
Minimal
Ships as pass-only.yaml.
$schema: https://scm.kebab.sh/strat/config.json
name: pass-only
description: Minimal example that always passes.
phases:
default:
actions:
- pass
Useful as a smoke test — load it, enable it, and confirm the runner engages and passes. If this does not work, the problem is not your strategy.
Farm nuke
Ships as storm_cp.yml.
name: storm_cp
phases:
main:
priority: 100
actions:
- cast:
name: 'Tempest'
enchant: none
Three lines of behaviour: cast Tempest, unenchanted, every round. This is what a farm bot actually wants against low-health trash — no blade setup, no enchant spend, just the cheapest AOE that clears the board.
enchant: none is deliberate. Enchanting a Tempest you are throwing at a 200-health mob wastes
a card you would rather keep.
There is no fallback, so a round with no Tempest in hand does nothing. Adding
fallback: pass would be strictly better.
Farm with a blade
Ships as storm_cp_sm.yml.
name: storm_cp_sm
phases:
main:
priority: 100
actions:
- cast:
name: 'StormBlade'
- cast:
name: 'Mass Storm Trap'
- cast:
name: 'Tempest'
enchant: none
Order does the work. Round one has a StormBlade in hand, so it blades. Round two has no blade left to cast, the first action fails to resolve, it tries the trap, and eventually falls through to Tempest.
No condition needed — action ordering plus resolution failure gives you the sequencing for free.
Note that the first two actions omit enchant: entirely, which here means "cast plain": there
is no enchant: block in this file, so the round-start auto pass has no policy and does
nothing.
Boss and mob in one file
Ships as storm_quest.yml.
name: storm_quest
clients:
- p1
phases:
boss:
priority: 100
when:
boss_present: true
actions:
- cast:
name: 'StormBlade'
enchant: none
- cast:
name: 'Tempest'
enchant: none
mob:
priority: 50
when:
boss_present: false
actions:
- cast:
name: 'Tempest'
enchant: none
Blade only when there is a boss worth blading for; otherwise go straight to the AOE. Scoped to
p1, so on the console a second hooked client is left alone — on the desktop app clients: is
ignored, and the strategy runs wherever you point it.
The two boss_present phases between them do not cover every round: if the enemy list
cannot be read, both are false and nothing runs. There is no fallback: here either, so such a
round does nothing at all. Adding fallback: pass would be strictly better.
Storm hitter
Ships as storm-hitter.yaml.
$schema: https://scm.kebab.sh/strat/config.json
name: storm-hitter
description: Example storm hitter for a secondary window.
school: storm
clients:
- p2
enchant:
prefer: epic
fallback: colossal
auto: true
targets:
default_enemy: boss
default_ally: self
fallback: pass
phases:
setup:
priority: 50
when:
no_blade: storm
actions:
- blade:
school: storm
target: self
execute:
priority: 10
actions:
- cast:
type: damage
school: storm
aoe: true
min_pips: 4
enchant: required
- cast:
type: damage
school: storm
target: boss
- wand_hit:
target: first
A proper hitter. no_blade: storm at priority 50 means it blades once and stops — as soon as
a storm blade is on the board the setup phase stops matching and execute takes over.
The execute list is ordered by value: an enchanted AOE of at least 4 pips first, then any
storm damage at the boss, then a wand hit. enchant: required on the first means it only fires
when it can be buffed; otherwise the plain single-target spell goes out.
This file uses the legacy top-level prefer/fallback rather than a damage: block, which is
what makes both auto: true and the enchant: required action work — with a blade:-only
policy neither would have anything to reach for.
fallback: pass covers the round where nothing at all resolves.
Balance support
Ships as balance-support.yaml.
$schema: https://scm.kebab.sh/strat/config.json
name: balance-support
description: Example support strategy shared by two windows.
school: balance
clients:
- p1
- p3
targets:
default_enemy: boss
default_ally: lowest_health_ally
fallback: pass
phases:
emergency:
priority: 100
when:
any_ally_health_below: 35
actions:
- heal:
school: life
target: lowest_health_ally
- pass
support:
priority: 50
when:
no_blade: true
actions:
- blade:
school: balance
target: self
pressure:
priority: 10
actions:
- trap:
school: balance
target: boss
- cast:
type: damage
school: balance
target: boss
- pass
Three tiers. The emergency phase ends in pass — if someone is below 35% and there is no heal
in hand, this deliberately does nothing rather than falling through to attack. That is a real
choice: at 35% you would rather not pull more aggro.
"Ally" includes you, so any_ally_health_below: 35 also fires on your own health, and
lowest_health_ally will pick you if you are the most hurt. For a support character that is
the behaviour you want.
Scoped to two clients that both run the same behaviour, which is the case where a shared
strategy beats a team file — on the console, at least; the desktop app ignores clients:.
Shadow-mutated nuke
Ships as storm.yml. The only shipped example that uses an enchant chain.
name: storm
clients:
- p1
enchant:
damage:
prefer: epic
mutation:
prefer: shadow
blade:
prefer: sharpen
trap:
prefer: potent
phases:
boss:
priority: 100
when:
all:
- boss_present: true
- round_above: 1
actions:
- blade:
target: self
school: storm
enchant: required
- cast:
name: 'Glowbug Squall'
enchant: required
enchants:
- type: mutation
- type: damage
when:
shadow_pips_above: 0
main:
priority: 100
actions:
- blade:
target: self
school: storm
enchant: required
when:
no_blade:
target: self
school: storm
enchanted: true
- blade:
target: self
school: storm
enchant: none
when:
no_blade:
target: self
school: storm
enchanted: false
- cast:
name: 'Frenzy'
enchant: none
- cast:
name: 'Storm Lord'
enchant: required
- cast:
name: 'Bunyip'
enchant: required
The chain is the interesting part. Neither step names a card, so each one takes its prefer
from the matching policy: type: mutation pulls shadow, type: damage pulls epic. The
mutation lands first, then the damage enchant goes on top of it — a second step is allowed to
enchant an already-enchanted card, which the single-policy path is not.
The main phase is a good model for blade layering: sharpened blade first, plain blade only
once the sharpened one is down, each guarded on the board rather than on a round counter.
boss and main both sit at priority 100. They only resolve in that order because boss sorts
before main alphabetically. Rename the phases and the behaviour changes. Give the boss phase a
higher number instead — this is exactly the mistake
Phases → priority warns about.
Non-healing support
Ships as blade-fire.yaml.
$schema: https://scm.kebab.sh/strat/config.json
name: blade-fire
description: Non-healing support example that buffs p1 directly.
school: balance
clients:
- p2
enchant:
blade:
prefer: sharpen
trap:
prefer: potent
targets:
default_ally: p1
default_enemy: boss
fallback: pass
phases:
main:
priority: 75
actions:
- cast:
name: Fire Blade
target: p1
enchant: required
- blade:
school: balance
target: p1
enchant: required
- trap:
school: balance
target: boss
- pass
A balance character buffing a fire hitter. The action list is a priority order: the fire blade is worth more to a fire hitter than a balance blade, so it goes first; the balance blade is the fallback; the trap is what happens when both blades are already down.
The enchant.blade policy is what makes the second action's enchant: required produce a
sharpened blade rather than whatever enchant happened to be nearest. The trap: policy is
inert here — the trap action carries no enchant: key, so nothing ever consults it.
The first action never fires as written. cast: picks its enchant policy from the spell
type of the card it matched, and Fire Blade is a charm — so it looks for enchant.support, not
enchant.blade. There is no support: block here, no top-level prefer, and no enchants:
chain, so enchant: required has nothing to reach for and the action is skipped every round.
The blade: action below it works, because blade: does consult enchant.blade.
Add support: { prefer: sharpen } to the enchant: block, or spell the chain out on the
action:
- cast:
name: Fire Blade
target: p1
enchant: required
enchants:
- prefer: sharpen
It is console-only. target: p1 and default_ally: p1 do not resolve in the desktop app,
so both blade actions are skipped there and the strategy degrades to "trap the boss, then
pass". See Targeting → client aliases.
Boss and mob split
Not a shipped file, but the pattern is worth having:
$schema: https://scm.kebab.sh/strat/config.json
name: fire-adaptive
school: fire
targets:
default_enemy: boss
enchant:
damage: { prefer: epic, fallback: colossal }
blade: { prefer: sharpen }
fallback: pass
phases:
emergency:
priority: 200
when:
health_below: 30
actions:
- heal: { school: life, target: self }
boss-setup:
priority: 120
when:
all:
- boss_present: true
- no_blade: fire
actions:
- blade: { school: fire, target: self, enchant: required }
boss-hit:
priority: 100
when:
boss_present: true
actions:
- cast: { name: 'Fire Dragon', enchant: required }
- cast: { type: damage, school: fire, target: boss }
mob-clear:
priority: 50
when:
all:
- boss_present: false
- enemies_at_least: 2
actions:
- cast: { type: damage, school: fire, aoe: true, enchant: none }
single:
priority: 10
actions:
- cast: { type: damage, school: fire }
- wand_hit: { target: first }
Blades and enchants only get spent on boss fights. Trash gets an unenchanted AOE, and anything
else falls through to a plain hit. The emergency heal sits above everything at 200 and, having
no trailing pass, falls through to normal play when no heal is in hand.
The blade: policy is not optional here. enchant: required on the boss-setup blade needs
enchant.blade (or enchant.support, or a top-level prefer) to have anything to reach for —
a damage:-only policy would leave that action permanently skipped.
Team
See Teams for life_fire.yml, a two-character strategy
where a life support character lays sharpened blades and potent feints for a fire hitter.