TinyMount
Summon mounts by id, not by name — short macros with a live action bar icon.
Why
A WoW macro is capped at 255 characters, and localised mount names are long — plenty run past thirty on their own, before you have written a single conditional. Four or five of those and the macro is full. You end up truncating names until it silently stops working, and a truncated name fails quietly, which is the worst kind of failure.
Numeric ids are three to five digits. This macro is 45 characters:
/mnt [af,nmnt]11111;[f,nmnt]22222;[nmnt]33333
The same three mounts spelled out by name do not fit at all.
Install
Copy the TinyMount folder — the one inside this repository, not the repository
folder itself — into Interface/AddOns/. The name has to stay TinyMount, which
is why it is already spelled that way here.
Usage
Make a normal macro and put it on your bar:
/mnt [m:cs]11111;[m:as]22222;[m:ac]33333;[m:c]44444;[m:s]55555;[m:a]66666;77777
That is it. No #showtooltip — it does nothing here, the client cannot read
custom commands. Pick any icon in the macro editor; TinyMount overwrites it.
Ids can be either spellIDs or mountIDs, whichever you have at hand.
A random favourite
One id is not an id. 000 summons a random mount out of your favourites —
the same thing Blizzard's own button does at the top of the mount journal, since
it is the same call underneath:
/mnt [m:a]11111;000
Alt for the one you picked, anything else for pot luck. The slot wears Blizzard's art for it and the tooltip is theirs too, in your own language.
Write it as three digits. 0 and 00 reach the same place — they are one
number by the time the macro is read — but 000 lines up with the ids around it
and reads as something you meant rather than something you half-typed.
It greys out where it will not work, the same as a named mount does — the answer
comes from Blizzard's own spell for it rather than from any one mount, since with
000 there is no one mount until you press the key.
What you get on the bar
- the icon changes as you hold a modifier, before you click anything
- the tooltip shows the mount that key would actually summon
- aboard anything, the slot turns into an exit button — same key, both ways
- it greys out where the mount will not come out — in combat, and in a room the game refuses to let you mount in — and the key goes quiet there rather than drawing a red line across your screen
- hover it while a room is the reason and the tooltip carries the client's own sentence for it, in your own language
- aboard something it stays lit either way: getting off works in a fight, and no room refuses to let you dismount in it
Getting off
While you are aboard something the command gets you off it. Conditions are
not consulted at all — no modifier, no [flyable], nothing in the macro can
change that, and the slot shows the exit icon to say so.
Two states count as aboard, and they are asked in this order:
| State | What the key does | Tooltip |
|---|---|---|
| in a vehicle — a passenger seat, a turret, a siege engine | leaves it | Leave Vehicle |
| on a mount | dismounts | Dismount |
The vehicle is asked first because the driver of a two-seater is both at once, and leaving the vehicle puts them on the ground either way.
Both work in combat and the slot stays lit for them, which is when getting off matters most. The icon is the same picture for both — it is Blizzard's own, and their exit-vehicle art and their dismount art have always been one file. The tooltip is what tells them apart.
Flight paths are not covered, and cannot be: the client locks your action bars for the whole flight, so there is no press to answer. Use Blizzard's own leave button if you want off early.
So one key does both directions and you never need a [mounted] branch or a
separate /dismount line. If you would rather keep riding while a modifier is
held, this is the one behaviour you cannot express in the macro — it is decided
before the macro is read.
Shapeshifted
Add one line above the command:
/cancelform
/mnt [m:cs]11111;22222
No condition on it. /cancelform out of a form is a no-op and says nothing, so
it will not draw the error that would stop the client reading the rest of the
macro. One keypress still does the whole thing — the form is down by the time
/mnt is read.
It goes at the very top, above a /click line too, since dropping the form is
also what lets the extra go off — most of them cannot be used shapeshifted
either:
/cancelform
/click tmt140309
/mnt [m:cs]11111;22222
Without it, /mnt from cat, bear, moonkin, travel form or ghost wolf answers
You must be in humanoid form and no mount comes out — while the very same
mount still summons fine from the mount journal.
That is not a bug in TinyMount and it cannot be fixed here. The journal calls
exactly the same function, C_MountJournal.SummonByID, on one bare line. The
function is not protected — TinyMount is built on that — but half of it is:
the client cancels your form when its own code is the caller and refuses to when
an addon is. There is no way around it from Lua either, because
CancelShapeshiftForm is protected outright and cancelling a form through the
buff functions is blocked by name, specifically so that addons cannot reach the
[form] conditional.
The macro can, though. /cancelform is run by the client under your own
keypress, which is secure, and that is the whole difference.
One thing to know if you share the macro across the account: /cancelform drops
a warrior's or monk's stance too, since the game files those under the same
mechanic. On a druid or a shaman there is nothing to lose.
One quirk in flight form. Pressed while you are flying, the extra draws a red you can't use that ability while pacified — but the mount still comes out, so it costs you nothing except the complaint.
The reason is a race you cannot arrange your way out of. /cancelform drops the
form instantly, but the client keeps you pacified for a moment longer, so by
the time the /click on the next line is read the form is gone, the extra looks
perfectly usable, and firing it still fails.
TinyMount does not try to silence it, and that is deliberate. That same moment
after /cancelform is when the extra legitimately fires on every ordinary press
out of cat, bear or moonkin form — suppressing it there to spare a rare flying
press would break the common case to tidy up the rare one.
Extras
An off-GCD toy or a cosmetic spell can go off together with the mount, on a
/click line above the command:
/click tmt140309
/mnt [m:cs]11111;22222
140309 is the Prismatic Bauble, so that macro shimmers you rainbow before it
puts you on a mount.
The name is the whole configuration — tm, one letter for the kind, then the
id. TinyMount builds a hidden secure button under that name the first time it
sees the macro, so there is nothing to set up and no settings file.
| Kind | Use it for | |
|---|---|---|
tmt |
toy | anything out of the toy box |
tms |
spell | a spell you know |
tmi |
item | something that really sits in your bags |
All three belong to the mount and are held back wherever it is — out of a /mnt
macro they do nothing at all. For a toy that fires on its own terms, in any
macro and in combat, see A toy on its own.
All lower case, and that is the only spelling — the name is looked up exactly as
written, so TMT140309 is a different button, and a button that does not exist
does nothing at all.
Pick the kind by what the id is, not by where you found it. A toy you have
learned is tmt, even though its id is an item id and the tooltip calls it an
item — the physical item is gone from your bags, so tmi has nothing to reach
for and the click does nothing at all.
/click takes conditionals of its own, and they are independent of the mount's.
Spell them out in full — the shorthand below is expanded by /mnt and nothing
else reads it:
/click [mod:shift]tms121183
/mnt [m:a]11111;22222
121183 is a paladin's Contemplation, held here to shift-clicks only.
It has to be /click, not /use or /cast. Two different reasons, and both
are hard:
- TinyMount cannot fire the extra for you. Casting a spell or using an item from
an addon is protected — the client checks who is calling, and an addon is
never a valid caller.
C_MountJournal.SummonByIDis the one exception this addon is built on, and it does not extend to anything else. A secure button sidesteps it honestly: your keypress drives the click, not TinyMount. - A
/useor/castline makes the client treat the whole slot as a spell action. It takes the icon over natively, repaints it faster than any addon can answer, and adds a proc glow for good measure — the live icon simply stops working./clickresolves to nothing, so the slot stays ours.
Where the button comes from
Worth reading before you copy a /click line somewhere else, because this is
the one thing about extras that surprises people.
TinyMount learns a name while it is repainting a slot. So it only ever sees
one that is written in a macro which is on a bar and carries a /mnt line —
those are the only macros it has any reason to read.
The button it then builds is a frame, and a frame's name is global. Once it
exists, any macro can click it: with no /mnt line, on any bar, out of any
macro at all. But something has to create it first, and only a mount macro on a
bar does that.
Which is why this does nothing whatsoever:
/use Healthstone
/click tmt140309
— if tmt140309 has never appeared in a mount macro on a bar. Clicking a button
that does not exist is not an error, so there is nothing to see: no red line, no
sound, no hint that the line was ever read. Put the name in your mount macro
once and press it, and the same name starts working everywhere.
The frame itself lives until you log out, because nothing in the client destroys
a frame. It stops firing, though, the moment the name is gone from every macro
TinyMount reads: editing any macro empties every button, and the macros fill
back in only the names they still spell. So taking a /click line out does what
you would expect it to, even though the frame behind it stays where it is,
doing nothing.
When the extra stays quiet
It is held back in four states, and in all four it is held back silently — no red line, no "not ready yet" out of the speakers:
- Aboard something. Mounted, or in a vehicle. The press is an exit and there is nothing to accompany.
- In combat. No mount can be summoned in combat at all, so the slot greys out and the key does nothing whatsoever — TinyMount does not even ask, because asking is what earns the client's complaint. Being aboard is the exception: the key still gets you off and the slot stays lit. The tooltip answers either way.
- On cooldown. The global cooldown does not count; an extra is meant to ride off it.
- Not yours. A spell this character has not learned, a toy that is in the box but locked to another class, an item you are out of.
Mounted and in combat are macro conditionals under the hood, so the client enforces them itself and goes on doing it through a fight. The rest have no conditional behind them and are applied by TinyMount out of combat, which is the only place they matter — in a fight the conditional has already emptied the button. Anything TinyMount cannot answer counts as held back, and a press that quietly does nothing is the cheap outcome.
The macro itself is never at risk. A line that fails stops nothing below it —
only /stopmacro and a condition matching nothing end a macro early — so the
mount comes out either way. What an unheld extra costs is the noise, and for
the lines TinyMount does not manage there is /tmq.
One macro, several characters
A macro can carry more than one /click line. Each is an ordinary line of the
macro, the client runs them in turn, and TinyMount builds a separate hidden
button for every name it finds — so they do not compete for anything:
/click tms121183
/click tmt140309
/mnt [m:cs]11111;22222
Because an extra this character does not have is quietly not armed, that macro needs no conditionals to sort itself out: the paladin gets Contemplation and the Bauble, the death knight gets the Bauble alone. Nothing to configure, and one macro for the account.
The one limit is the global cooldown, and it is the same limit any macro has: if the first line spends the GCD, the second may not get through. Extras are meant to be things that ride off it.
Extras fire whether or not the mount does, and they fire first, in the order they are written. If you need one without the other, use two keys.
A toy on its own
Everything above serves a mount, and is held back wherever the mount is. If what you want is just the toy — in any macro, with nothing deciding on your behalf — that is a different name:
/click ttoy140309
ttoy, then the id. No kind letter, because there is only one kind. It works in
any macro: one that hearths, one that opens a profession, one that carries
nothing else at all. TinyMount does not touch such a macro in any other way —
the icon, the tooltip and the greying all stay exactly as your bar addon drew
them. Only the button behind the name is ours.
It fires in combat. On a boss, mid-pull, wherever. That is the whole point of the separate name, and it is why there are no checks on it:
/click tmt140309 |
/click ttoy140309 |
|
|---|---|---|
Needs a /mnt in the macro |
yes | no |
| In combat | held back | fires |
| Mounted or in a vehicle | held back | fires |
| On cooldown | held back, silently | fires, client complains |
| Not yours | held back, silently | fires, client complains |
| Spells and items too | yes — tms, tmi |
toys only |
The two bottom rows are the trade, and it is a deliberate one rather than a corner cut. Filtering a button means writing an attribute to it, and writing an attribute is forbidden in combat — so a filtered button freezes on whatever it held when the fight started. A toy that came off cooldown mid-fight would stay dead until the fight ended, and say nothing about why. A button nobody touches cannot be wrong that way.
So on cooldown you get the client's own not ready yet, and it costs nothing
else — a /click that fails does not stop the lines below it. If the noise
bothers you, the addon already has an answer for exactly this:
/tmq
/click ttoy140309
One of several, at random
A colon and a list instead of a single id, and the press picks one:
/click ttoy:54452,64488,93672,142542,162973,163045,165669,165670,165802,166746,166747,168907,172179,180290,182773,183716,184353,188952,190196,193588,200630,206195,208704,209035,212337,228940,235016,236687,245970,246565,257736,263489,263933,264367,265100
Thirty-five hearthstone toys in 253 characters. A macro holds 255, so that one is full — there is no room for a thirty-sixth.
Every press rolls again, and it rolls in combat like the single-id form.
Toys you do not own are dropped from the list, along with any your class cannot use, so the roll never wastes a press on one of those. That list is rebuilt whenever the game says your collection changed.
Cooldowns are not, and the difference is worth a sentence. What you own changes when you learn a toy, which cannot happen mid-fight. A cooldown changes every few seconds and changes most during a fight — which is exactly when the list is frozen and cannot be rewritten. Bake a cooldown in and a toy that came off cooldown mid-pull would stay dead until the pull ended, silently. So a roll can still land on one that is not ready: the client says so, the press is spent, press again for a fresh roll.
Nothing else changes. No icon, no tooltip, no greying, and the two spellings can
sit in the same macro — they are separate buttons. So are ttoy:111,222 and
ttoy:222,111, which is harmless: both work, they simply cost two buttons
instead of one.
Why not the client's own /userandom. Because it makes you write item: in
front of every id, and those five characters are the whole budget:
| 10 toys | 20 toys | Fits at most | |
|---|---|---|---|
/userandom item:… |
130 | 250 | 20 |
/click ttoy:… |
81 | 151 | 34 |
A macro is capped at 255 characters, so twenty toys is where /userandom stops
and this form is still only half full. It also hands the roll off as a spell
name rather than the item, which leaves a toy that lives in your collection and
not your bags with nothing to fire it.
Those counts assume six-digit ids, which is what anything recent has. Older ones are five digits and buy you a character each — the example above fits thirty-five rather than thirty-four for exactly that reason.
The cap is on the whole macro, not the line, so anything you put above it —
#showtooltip, /tmq, another command — comes out of the same 255.
Conditionals on it
/click is the client's own command and it reads its own conditionals before it
ever looks the name up, so this needs nothing from TinyMount:
/click [nostealth] ttoy140309
Write them out in full. The shorthand further down ([m:cs], [nmnt], [sp:2])
is expanded by /mnt and read by nothing else — including /click.
Where a ttoy button comes from
TinyMount reads your macro list — all of it, account and character both — and
builds a button for every ttoy name it finds on a /click line. It does that at
login, across a loading screen, whenever you save a macro, and when you drop out
of combat. Never while repainting a slot, so none of it is on the path your bars
take when they redraw, and a ttoy button costs nothing at all while you play.
The button is a frame and a frame's name is global, so a name only ever has to be spelled somewhere — once it exists, any macro can click it. Clicking a button that does not exist is not an error, so a misspelled name is completely silent: no red line, no sound, no hint the line was read. If a toy does nothing whatsoever, check the spelling first.
Take the line out of every macro and the button stops firing — saving a macro empties them all, and the scan fills back in only the names still spelled somewhere.
One gap, the same one everything else here has: a macro written during a fight gets its button when the fight ends. Creating a secure button is barred in combat and there is no way around that.
Silencing a line
/tmq mutes the client's complaint about the line under it — the red text and
the spoken one both — and turns everything back on by itself a fraction of a
second later.
#showtooltip Divine Steed
/tmq
/use item:140309
/cast Divine Steed
The toy is off the global cooldown, so both lines go off. On the presses where it is still on cooldown you simply hear nothing about it, and the spell casts as usual.
One command, and no closing one. The complaint does not arrive in the frame
the macro is read in — it comes off the event queue a moment later — so /tmq
holds a short window open instead, a fraction of a second wide, and shuts it
itself. A closing line could not do that job: it would be read in the same frame
the opening one was, long before there was anything to catch, and one left
behind by an edit would mute you until the next reload. There is nothing to
switch back on afterwards — and so nothing that stays muted if you later edit
the line away.
Worth knowing:
- it silences everything the game sends you for that fraction of a second, not only cooldown errors. You asked for it by hand, on a line whose failure you already understand
- the sound goes with the text — the spoken line and the plain error blip both, because the client stops all three at the same switch. Nothing of yours is touched to do it: no setting is changed, so none can be left turned off
- it changes nothing about what the macro does. A line that fails still fails, it just does so without an audience
- you do not need it above a
/clickextra — those hold themselves back silently to begin with./tmqis for the ordinary/useand/castlines TinyMount has nothing to do with
Shorthand
Conditions are what a mount macro is mostly made of, so they have short forms.
The rule: a colon means the condition takes an argument. m: is the
modifier one, sp: is the specialisation one, and everything without a colon is
a plain state.
Modifiers
| Short | Expands to |
|---|---|
[m:c] |
[mod:ctrl] |
[m:s] |
[mod:shift] |
[m:a] |
[mod:alt] |
[m:cs] |
[mod:ctrl,mod:shift] |
[m:acs] |
[mod:alt,mod:ctrl,mod:shift] |
[nm:a] |
[nomod:alt] |
Letters are c ctrl, s shift, a alt, in any order. Combinations expand to
commas, which is AND — the only spelling of a modifier combination the client
actually documents.
States
| Short | Expands to | Short | Expands to | |
|---|---|---|---|---|
mnt / nmnt |
mounted / nomounted | sw / nsw |
swimming / noswimming | |
f / nf |
flyable / noflyable | in / out |
indoors / outdoors | |
af / naf |
advflyable / noadvflyable | c / nc |
combat / nocombat | |
fly / nfly |
flying / noflying | r / nr |
resting / noresting |
One caveat, and only one: sw is the single state the client announces
nowhere. Every other condition in that table has an event behind it, so the
icon follows it the moment it changes. Swimming has none, anywhere in the API, so
a slot branching on it repaints on the next thing that does happen — in practice
the modifier press, which is also the moment you are looking at the slot. The
command itself is never wrong; only the picture can lag.
Specialisation
| Short | Expands to |
|---|---|
[sp:2] |
[spec:2] |
[nsp:2] |
[nospec:2] |
[sp:1/2] |
[spec:1/2] |
Two characters a branch, which sounds like nothing until you are a druid: four
specialisations against af / f / nf is a dozen branches, and spec:
appears in every one of them.
/mnt [sp:1,af]11111;[sp:1]22222;[sp:2,af]33333;[sp:2]44444
Mixing
Anything not in the tables is passed through untouched, so full spellings and every other conditional keep working next to the short ones:
/mnt [m:a,nmnt,f]11111;[@mouseover,spec:2]22222;33333
To add your own shorthand, edit CONDITIONS at the top of TinyMount.lua for
plain states, or ARG_CONDITIONS just below it for ones that take an argument —
a line each.
Finding ids
Paste into chat to list your favourite mounts with their spellIDs:
/run for _,i in ipairs(C_MountJournal.GetMountIDs()) do local n,s,_,_,_,_,f=C_MountJournal.GetMountInfoByID(i) if f then print(s,n) end end
Or search by a fragment of the name:
/run for _,i in ipairs(C_MountJournal.GetMountIDs()) do local n,s=C_MountJournal.GetMountInfoByID(i) if n:find("Obsidian") then print(s,n) end end
A spellID from Wowhead's URL works just as well.
Compatibility
| Bars | Supported |
|---|---|
| Default Blizzard bars | yes |
| Dominos | yes — it builds from the Blizzard button template |
| Bartender4 and other LibActionButton-1.0 bars | yes |
| ElvUI | no — it ships a renamed fork of the library |
Notes
- Only mounts. The command works because
C_MountJournal.SummonByIDis not protected; the same approach with an ordinary spell would be blocked. - Dismounting mid-flight does exactly what you expect it to.
- If no branch of the macro matches — you are already mounted and everything is
behind
[nmnt], say — the slot falls back to the icon you picked in the macro editor rather than lying about the last mount shown. - The grey-when-you-cannot-mount check asks the client
(
C_MountJournal.GetMountUsabilityByID), not the map.IsIndoors()and[indoors]are a different question — a garrison, a cave and most buildings in a capital are indoors and let you mount anyway — so branching on those would grey the slot for no reason several times an evening. - When the slot is grey the key goes quiet too, rather than earning the client's complaint — the same way it already worked in combat. Nothing is given up by that: the summon the press would have asked for was already refused.
- There is no event for walking into a building —
ZONE_CHANGED_INDOORSdoes not fire for most of them. TinyMount watchesSPELL_UPDATE_USABLEinstead, which the client sends whenever what you can use changes, and repaints only when the answer is different from the last one it saw. - Nothing here polls. There is no
OnUpdateand no timer in the addon; the icon is repainted off the events that can change what the macro resolves to, and off the bar addon's own redraws so that it does not get overwritten. Measured withGetFunctionCPUUsage, the whole thing costs about 88 ms over a dungeon run. - If you go looking at the addon CPU list, expect TinyMount to appear far higher
than that.
hooksecurefuncbills the addon that installed a hook for the time spent inside the function it hooked, so an addon that follows your bars is charged for how your bar addon redraws them. The per-function numbers are the honest ones.
Built with
Written end to end with Claude (Opus 5) in Claude Code — the Lua, the comments in it, and this README. What the client actually permits was worked out the hard way, in game, one silent failure at a time.
License
MIT