Skip to content

Overriding with Tags ​

Every tag in LuauDocs is a correction, never a requirement: you reach for one when the code says something other than what you mean, or when inference genuinely cannot see what you want documented. A library with no tags at all still gets a complete site. The handful below cover nearly every real case; Reference: Tags has the complete vocabulary: 24 tags, exactly Moonwave's set.

Tags go inside a doc comment, and prose can sit before or after them.

Describing parameters and returns ​

The signature already carries the types, so these tags exist to describe the values, not to declare them:

luau
--[[
Sends a request and waits for the response.

@param url -- where to send it
@param retries -- attempts after the first; defaults to 3
@return -- the decoded body
@error Timeout -- raised when the server does not answer in time
]]
function Http.get(url: string, retries: number?): Body

You can write a type after the name (@param url string -- ...), and it replaces the annotation in the rendered signature when you do, but usually the annotation already says it. @return tags apply in order. If you misspell a parameter name or write more @return tags than the function returns values, LuauDocs emits a warning rather than rendering inaccurate documentation.

In a multi-line signature, no tag is needed at all: a trailing comment on a parameter's line documents that parameter, the same way it documents a property or a type field.

luau
function Http.get(
	url: string, -- where to send it
	retries: number? -- attempts after the first; defaults to 3
): Body

An @param naming the same parameter overrides its trailing comment field by field: a type-only @param retries number replaces the type and keeps the trailing description.

Moving a member somewhere else ​

Sometimes a member is defined in one place and belongs, from a reader's point of view, in another. @within files it under a different class wherever it is defined:

luau
--[[
Formats a duration for display.

@within Timer
]]
local function formatDuration(seconds: number): string

@class Name documents a block as a class, which you need when the class is assembled in a way inference cannot follow. The other placement tags do the same for a single member or type; Reference: Tags lists them in full.

Only one of these placement tags belongs in a block. A second one is a conflict: the first wins and the later one is dropped and reported. @within is a data tag rather than a placement tag, so it combines freely with any of them.

Hiding things ​

luau
--[[ @ignore ]]
function M.experimentalThing() end
  • @ignore drops the item from the docs entirely, always.
  • @private marks it private, which hides it by default but renders it (badged) when you set [api] includePrivate = true.

An explicit tag takes precedence over the leading-underscore convention, so @private hides a member whose name has no underscore, and the convention decides only for members you never tagged.

Adding badges ​

Badges annotate a member without changing what it is, and the common ones need no tag, because LuauDocs reads the body. A function that waits (task.wait, signal:Wait(), a yielding engine method, or a call to something that does, in this module or one it requires) is badged Yields. Code only one realm can run (firing a remote, a realm-only service, the plugin global, a Studio-only member) is badged Server, Client, or Plugin. A property renders Read Only when its table is table.freezed or its field is marked read in the table's own type; a read field in a type imported from another module is not detected, so @readonly still applies there.

The example library's Queue shows both halves: push is tagged @since, while pop carries no tag at all, its badge detected from the task.wait() in its body:

examples/Flux/Util/Queue.luau
luau
--[[
Adds `item` to the back of the queue.

@since 1.1.0
]]
function Queue:push(item: any)
	table.insert(self.items, item)
end

--[[ Removes the front item and returns it, waiting when the queue is empty. ]]
function Queue:pop(): any
	while #self.items == 0 do
		task.wait()
	end
	return table.remove(self.items, 1)
end

Methods

push since 1.1.0

luau
Queue:push(item: any)

Adds item to the back of the queue.

pop Yields

luau
Queue:pop(): any

Removes the front item and returns it, waiting when the queue is empty.

These tags remain available when runtime behavior cannot be detected statically: @yields when yielding occurs within a callback passed as a value, and @server, @client, or @plugin when realm boundaries are conventions rather than calls. A realm tag replaces the detected realm entirely, so the tag wins when they disagree. @unreleased and @since track versioning, and @tag name badges anything else you want to call out. Badges render in a fixed order no matter which order you wrote them in.

@deprecated is the one that does more than badge. Writing @deprecated 2.0 -- states are collected once nothing references them on the example's State:Destroy badged the heading and added a callout under it:

Destroy Deprecated since 2.0

DEPRECATED

states are collected once nothing references them

luau
State:Destroy()

Drops every listener and releases the state.

The rest ​

The full vocabulary, @external and @field included, is cataloged in Reference: Tags, along with how a -- desc continues over several lines.