An attribute is a @name written on the line above something, saying what it's for or how it should be treated: @main makes a function the program's start, @test makes it a test, @get("/todos") makes it an HTTP route. They're Refingere's replacement for frameworks and configuration files - the code stays ordinary functions and structs, and the attributes say what's special about them. This page is a tour; the Attributes reference describes each one exactly.
Attributes go directly above what they apply to - a definition, a statement, a field - or right before a parameter. Several can be stacked. Some take arguments in parentheses, by position or by name, and some arguments are optional, so @test and @test(e2e) both work. See Attributes in the syntax reference.
@main is where a program starts, one per folder - and it can take a struct marked @args, whose fields are the program's command-line flags (see Command-line Programs). @test marks a test, and @testHelper marks code only tests may use. @bench marks a function to time rather than test. See Testing.
@inject, @injectLocally and @injectGlobally on a const provide a context value to every call in its file, folder or project, and @require on a function declares one it reads, optionally with a default. See Context and Dependency Injection.
Four attributes describe what calling a function can do, each allowing everything the ones before it do: @pure (only its arguments matter), @reads (context values too), @writes (it changes what a parameter or a context value holds) and @effects (I/O). A target narrows one: @reads(&clock) reads no other context value, @writes(self) changes nothing but what self holds. A context value named this way is required too, as if by @require - so currentPrices needs no @require(&clock).
The checker works out every function's effects from its body and from what it calls, so the compiler knows them whether or not they're written. Writing one is a promise it checks: a @pure function that reads &clock - itself, or through a function it calls - is an error saying so. A function given another as a parameter doesn't take on that one's effects by calling it; what passes it does, so xs.map(f) is as pure as f. Calling a function value from anywhere else - a field, a local - could do anything, and counts as @effects. On an interface member, the attribute binds every implementation, and calling through the interface relies on it.
@memoize caches a function's results, so it has to be pure, and is checked as @pure. @slow marks an expensive function - the optimizer never inlines it or computes a call to it twice, and moves a pure one's call out of a loop that gives it the same arguments each time. @inline copies a function, lambda or block into each place it's used, and can't go with @slow.
@derive writes implement blocks for interfaces with an obvious implementation - see Interfaces. @singleton makes a struct have a single instance. @deprecated makes every use a warning, with an optional message pointing to the replacement.
@parallel runs a function on another thread: calling it gives a Promise at once, and several calls run at the same time. What it's given and gives back is copied, and it has to be self-contained - it reads no context value it doesn't inject itself. See Threads.
@serve makes a function an HTTP server, and @get, @post, @put, @patch, @delete and @route make functions its routes - each reads &request and answers with a Response. @app, @component and @state build an app that runs in the browser. See Servers and Browser Apps.
@js on a function without a body makes it call a JavaScript or TypeScript export, and on a function with one makes it callable from JavaScript. See JavaScript and TypeScript.
@onError, @onReturn, @onYield and @onBlockEnd choose when a defer runs - see Resources and Memory. @bodyMacro, @stringMacro, @deriveMacro, @attributeMacro, @programMacro and @phase define macros - see Macros.
Any other @name is allowed, and does nothing by itself: it's metadata for something else to read. #comptime.definitionsWith("command") finds every definition marked @command, anywhere in the project, with the attribute's arguments - so marking a function is enough to register it, with no list to keep up to date. Program macros can select definitions by attribute in the same way.
To make an attribute that changes what it's on - wraps a function, checks a struct - write an attribute macro.