WoW Forever Addon Developer Guide: Writing Addons with AI
The constraints a language model needs before it writes code for World of Warcraft: Forever: the original Azeroth setting on the modern Mainline interface, without the Classic Era habits models memorized.
- TOC interface
- 16001
- Launch
- Nov 4, 2026
- API family
- Mainline 12.1.5
- Tested beta build
- 1.60.1.69913
The problem
Ask a model for a WoW addon and it writes Classic-era code. On beta build 1.60.1.69913, testers at WoW Forever Builds found GetSpellInfo and GetItemInfo gone, WOW_PROJECT_ID returning the Mainline value, and player health coming back as a secret value that addons cannot add to or compare. Warcraft Forever reports that CombatLogGetCurrentEventInfo is unavailable to addons. The beta has had newer builds since (1.60.1.70009 on September 23), so treat every observation as something to retest.
How to use this guide
Give the model explicit constraints before it generates anything. Read the client architecture patterns to see how Forever differs from Classic Era and Midnight. Use the API migration cheat sheet for C_Spell and C_Item signatures, check the common AI pitfalls, start from the starter files, paste from the addon prompts library, or inspect the Forever Beacon test addon, an unverified reference sample.
The golden rules
Ten rules for every AI draft that targets WoW Forever. Rules 3, 6, 7 and 8 are the ones Midnight guides leave out, because they are specific to the Forever beta.
- Interface: 16001.A Forever-only addon declares
## Interface: 16001, the Forever Beta value in the Warcraft Wiki TOC table. Classic Era uses 11509 and Midnight uses 120100. To ship one package to several clients, use a comma-separated interface line, a_Camelot.tocfile (the wiki's Forever suffix), or a_Mainline.tocthat Midnight and Forever share. Retest when the number moves at launch. - Lua 5.1.WoW runs a modified Lua 5.1. No
goto, no//, no bitwise operators and no_ENV. Bitwise work uses thebitlibrary (bit.band,bit.bor,bit.lshift). The wiki notes that the operating system and file I/O libraries are not present, andrequire,dofileandloadfileare not in its function list. The.tocfile is your module loader. - Mainline family, not Classic.Blizzard told the WoW UI Discord that Forever shares Mainline's UI architecture, "including the vast majority of APIs available in 12.1.5", and that Midnight's addon disarmament, secrets included, is active (quoted by Wowhead). The Forever game type was called Camelot, to be renamed before launch. On the September 17 Q&A stream the developers said "we did opt for the modern API approach." Port a Midnight addon; do not port a Classic combat addon and hope.
- C_ namespaces.On build 69913,
GetSpellInfo,GetItemInfo,GetSpellBookItemName,GetNumTalentTabs,GetTalentInfoandGetNumSkillLineswere missing.C_Spell.GetSpellInforeturns one table;C_Item.GetItemInforeturns the same list of values the old global did. Both returnniluntil the record is cached. Check fornil, request the load (C_Spell.RequestLoadSpellData,C_Item.RequestLoadItemDataByID) and listen for the result event. - Namespace everything.Every file begins with
local addonName, ns = .... Shared state hangs onns. The only globals you should declare are SavedVariables, slash command entries and the Addon Compartment callbacks named in the TOC. A frame namedMainFramebecomes a global; name it after your addon or passnil. - Events, not the combat log.Use one frame, one
OnEventscript and a table of handlers. UseRegisterUnitEventwhen you only watch the player. On Midnight, registeringCOMBAT_LOG_EVENT_UNFILTEREDthrows an error, and Warcraft Forever reports the combat log reader unavailable on Forever. Blizzard said on stream that Forever includes a damage meter and a cooldown manager, and that a swing timer is "perhaps coming soon". - Secrets are drawn, not solved.Testers saw player
UnitHealthcome back as a secret number:type()says number, and adding to it fails. Warcraft Forever reports unit names as possible secret strings andUnitCanAttackandUnitExistsas possible secret booleans. Guard values withissecretvaluebefore you compare, branch or print them. Pass health straight into aStatusBarwithSetMinMaxValuesandSetValue. A blocked protected call can fail without a Lua error, andpcallwill not clear it. - Do not trust
WOW_PROJECT_IDalone.Build 69913 reports1, the Mainline value. A library that reads1as Midnight only, or anything else as Classic, takes the wrong branch. The Warcraft Wiki suggests pairing it withLE_EXPANSION_LEVEL_CURRENT, or a TOC variable for the game type. Add a capability probe, and expect the test to change before launch. - No secure-snippet dependency.On build 69913, secure snippets failed to compile because the client had no
loadstring_untainted. Click-casting and action-bar paging that use snippets failed with them. WoW Forever Builds calls it probably a bug. Do not ship healer frames that need it until a build fixes it. Your own buttons are the safe click path. Do not write secure attributes onto Blizzard unit frames. - Whole files, correct load order.Always emit the
.tocand every.luafile in full. Beta addons live inWorld of Warcraft\_classic_beta_\Interface\AddOns\. SavedVariables load after your files run and are ready whenADDON_LOADEDfires for your addon. A September 21 forum report showed saved data written to disk but missing on the next login; a follow-up on September 25 says build 70009 loads it again.
Quick start
The smallest useful WoW Forever addon is two files. The folder name must match the TOC file name. Put them in World of Warcraft\_classic_beta_\Interface\AddOns\FirstLight\ and start the client. The character name is guarded because names can be secret.
## Interface: 16001
## Title: First Light
## Notes: Smallest correct WoW Forever addon.
## Author: YourName
## Version: 0.1.0
## SavedVariables: FirstLightDB
FirstLight.lualocal addonName, ns = ...
local function SafeName()
local name = UnitName("player")
if type(issecretvalue) == "function" and issecretvalue(name) then
return "adventurer"
end
return name or "adventurer"
end
local frame = CreateFrame("Frame")
function frame:ADDON_LOADED(loaded)
if loaded ~= addonName then return end
FirstLightDB = FirstLightDB or { seen = 0 }
ns.db = FirstLightDB
self:UnregisterEvent("ADDON_LOADED")
end
function frame:PLAYER_LOGIN()
ns.db.seen = ns.db.seen + 1
print("|cffd4a85a[" .. addonName .. "]|r online, " .. SafeName() .. ". Session " .. ns.db.seen .. ".")
end
frame:SetScript("OnEvent", function(self, event, ...)
if self[event] then
self[event](self, ...)
end
end)
frame:RegisterEvent("ADDON_LOADED")
frame:RegisterEvent("PLAYER_LOGIN")What is confirmed versus what was only observed
| Claim | Source and status |
|---|---|
| Forever uses the modern addon API | Confirmed. Blizzard developers, September 17 Q&A stream, 01:20:52 |
| Built-in damage meter and cooldown manager | Confirmed. Same stream, 01:21:51 |
| Swing timer | "Perhaps coming soon" on the same stream. Not a commitment |
| Shares most 12.1.5 APIs; Midnight disarmament and secrets active | Reported. Blizzard statement on the WoW UI Discord, quoted by Wowhead |
| Interface 16001 | Reported. Warcraft Wiki TOC table, Forever Beta row |
| UnitHealth is a secret number; secure snippets fail to compile | Reported. WoW Forever Builds, build 69913. Retest |
WOW_PROJECT_ID is 1 | Reported. WoW Forever Builds, build 69913. Retest |
| SavedVariables written but not restored | Unverified. Forum reports from September 18 to 21; a September 25 reply says build 70009 fixed it |
Beta access runs September 17 to October 21, 2026. Blizzard's launch date is November 4, 2026 at 3:00 p.m. PST, level cap 60. Any build between now and then can change the API. See the beta reference and systems overview for the game rules around it.
System prompt for AI models
Paste this block into your AI session before you ask for addon code. The task prompts, porting prompts and review prompt are on the AI prompt library.
You write World of Warcraft: Forever addons. The client is not Classic Era and it is not a private server.
Facts you must obey. Checked September 28, 2026 against Blizzard's statements, the Warcraft Wiki, and community tests on beta build 1.60.1.69913 (the beta has since moved to 1.60.1.70009). Launch is November 4, 2026. Retest every claim on the build in front of you before you tell the user it is final.
- The Forever beta TOC interface is 16001. A Forever-only addon uses exactly: ## Interface: 16001
- Lua is 5.1. No goto, no //, no bitwise operators, no _ENV. Bitwise work uses the bit library (bit.band, bit.bor, bit.lshift).
- There is no require, dofile, loadfile, io library or os library. Load order is the .toc file. Shared state lives on the addon namespace.
- Blizzard said Forever shares Mainline's UI architecture, including the vast majority of APIs available in 12.1.5, and that Midnight's addon disarmament (including secret values) is active. Forever and modern WoW are two game types in the Mainline family. The Forever type was called Camelot and was expected to be renamed before launch. Do not target Classic Era interface numbers (11500s).
- WOW_PROJECT_ID has been observed returning 1, the same value as Mainline. Never choose a Classic code path from that number alone. Probe select(4, GetBuildInfo()), LE_EXPANSION_LEVEL_CURRENT, and the presence of the API you need.
- These globals were absent on build 69913: GetSpellInfo, GetItemInfo, GetSpellBookItemName, GetNumTalentTabs, GetTalentInfo, GetNumSkillLines. Use C_Spell and C_Item. C_Spell.GetSpellInfo returns a table. C_Item.GetItemInfo returns multiple values, like the old global. Both return nil until the data is cached. Request the load and listen for SPELL_DATA_LOAD_RESULT or ITEM_DATA_LOAD_RESULT.
- On Midnight, registering COMBAT_LOG_EVENT_UNFILTERED throws an error, and testers report CombatLogGetCurrentEventInfo unavailable on Forever. Do not build a damage meter, healing meter, or combat-log boss mod. Blizzard ships a damage meter and a cooldown manager. A swing timer was described as perhaps coming soon, not as a promise.
- Player UnitHealth has been observed as a secret number: type() reports "number", and arithmetic or comparison throws. Unit names can be secret strings. UnitCanAttack and UnitExists can be secret booleans. Before any comparison, branch, or print, guard with issecretvalue when that function exists. Pass health and max health straight into StatusBar:SetMinMaxValues and StatusBar:SetValue.
- pcall does not make a protected call safe. Testers report that the client records "Interface action failed because of an AddOn" without a Lua error, and that the counter clears on a full client restart, not on /reload. Do not call ChatFrame_OpenChat, ChatEdit_ActivateChat, or C_SuperTrack.SetSuperTrackedUserWaypoint. Do not write secure attributes onto Blizzard unit frames. Shift-click links go through HandleModifiedItemClick. Map pins go through C_Map.SetUserWaypoint with a UiMapPoint.
- Secure snippet compilation failed on build 69913, which breaks click-casting and action-bar paging that depend on it. Treat that as a beta defect to retest, not as a design you should depend on. Use your own buttons.
- SavedVariables load after the addon's files run. Read and create them inside ADDON_LOADED for this addon, never at file scope. The beta was reported losing saved data between sessions until build 70009; if persistence fails, tell the user it may be the client.
- Every Lua file starts with: local addonName, ns = ...
- Handle events with one frame and a handler table keyed by event name. Do not grow an if/elseif chain. Do not poll with OnUpdate when an event exists.
- Check InCombatLockdown() before you show, hide, or move a protected frame. Queue the closure and run it on PLAYER_REGEN_ENABLED.
- Skin and inform. Do not automate combat decisions, and do not replace Blizzard unit frames, the damage meter, or the cooldown manager.
- When asked for an addon, emit a complete .toc and every .lua file. No fragments. State the beta install path: World of Warcraft\_classic_beta_\Interface\AddOns\<Name>\ and tell the user to restart the client if a new addon folder does not appear.
- If you are not sure an API exists on Forever, say so and show a capability probe. Do not invent C_ functions.Verification checklist
Run this checklist across every file an AI model produces before you test it in game:
0 of 10 checked in this browser
The rest of the guide
Each page covers one job:
- Page 2Forever patternsHow Forever differs from Classic Era and Midnight, secret values, and what is safe to build.
- Page 3API cheat sheetReplacements for missing globals, async data loading, secret-safe unit queries and events.
- Page 4PitfallsTwelve mistakes AI models make, with the code to write instead.
- Page 5Code templatesHello World, SavedVariables, a guarded status bar, the addon compartment and a combat queue.
- Page 6AI promptsThe system prompt, porting prompts, error diagnosis and a review prompt.
- Page 7Forever BeaconAn inspectable sample addon with
.toc,.luaand.zipdownloads.
Questions addon authors ask FAQ
What interface version do WoW Forever addons use?
The Warcraft Wiki lists 16001 for the Forever beta. Confirm it on your client with /dump select(4, GetBuildInfo()) in the chat box.
Can an AI write a WoW Forever addon?
Only if you give it explicit constraints first. Without them, models tend to emit old globals like GetSpellInfo, a retail interface number such as 110207, and COMBAT_LOG_EVENT_UNFILTERED. The system prompt and the checklist above catch most of these before you test in game.
What is Camelot in the beta client?
Camelot is the internal name of the Forever game type in the Mainline code family, per Blizzard's WoW UI Discord statement. Blizzard said it would be renamed before launch. The Warcraft Wiki already lists _Camelot.toc as the Forever TOC suffix, so check that suffix again after launch.
Every fact, with its source
- TOC interface Changed16001 in the Forever Beta row of the Warcraft Wiki TOC table; confirm with /dump select(4, GetBuildInfo())Classic: Classic Era lists 11509 on the same table.
- Addon API ChangedForever uses the modern addon API, with Midnight's combat restrictionsClassic: Classic Era keeps the older API with the combat log open to addons.
- Launch New in ForeverNovember 4, 2026 at 3:00 p.m. PST, level cap 60
- API family ChangedShares Mainline UI architecture and "the vast majority of APIs available in 12.1.5"
- Tested beta build New in Forever1.60.1.69913; later builds (70009 on September 23) may differ
- Built-in tools New in ForeverDamage meter and cooldown manager included; swing timer "perhaps coming soon"
Sources
- World of Warcraft Developer Q&A (September 17 stream), add-on answer at 01:20:52Blizzard Entertainment (YouTube)
- WoW: Forever Will Have Addon Changes from MidnightWowhead
- Addons in WoW Forever? Blizzard Devs Just Addressed the Big QuestionIcy Veins
- TOC formatWarcraft Wiki
- What the WoW Forever beta breaks for addons: secret health values, dead secure snippets, new APIsWoW Forever Builds
- AddonsWarcraft Forever
- WOWF Beta: Addon SavedVariables appear to write correctly to disk but are not restored at startupWorld of Warcraft Forums (player bug report)
- World of Warcraft: Forever What's Next Panel RecapBlizzard Entertainment
- Secret ValuesWarcraft Wiki
- Patch 12.0.0/API changesWarcraft Wiki
- WOW_PROJECT_IDWarcraft Wiki
- Lua functionsWarcraft Wiki
- Saving variables between game sessionsWarcraft Wiki
- Blizzard · Developer Q&A, 01:21:51