Is it really bad to use \makeatletter and \makeatother in a package or class file?

First of all, \makeatletter is unnecessary in .sty or .cls files, as the default catcode regime includes it; this is presumably to encourage package writers to hide their macros using @-laden names. For this reason, I believe that using this command is harmless in package files.

However, using the pair of commands together is harmful, because unlike in a document, you do not want to return to the @ = other setup within the package. These are document commands and the standard ordering \makeatletter \makeatother assumes that \makeatother is actually undoing the previous change, whereas in packages, it is the one making the change.

Edit: Here is a more informed answer. According to source2e.pdf, the following scheme is used to load packages and classes:

  1. First, the options and such are gathered.
  2. Then the name of the current file (i.e. mypackage.sty), along with the catcode of @, are saved on a stack.
  3. Then \makeatletter is run and, if appropriate, the requested file is loaded.
  4. Afterwards, the stack is popped and the pre-package-load state restored.

In other words, the following ignorant code has no effect at all:

\documentclass{article}
\usepackage{bad}
\begin{document}
\end{document}

bad.sty:

\makeatletter
\makeatother
\RequirePackage{unsuspecting}

However, it is quite possible that a package does not use \RequirePackage, but just \input. In that case, the catcode is not protected and indeed, errors can arise, as you can check yourself by making bad.sty, for example:

\makeatletter
\makeatother
\input{pgfkeys.sty}

If that seems artificial, have a look at pgfkeys.sty itself: it \inputs pgfkeys.code.tex, and that file, in turn, \inputs pgfkeysfiltered.code.tex. Presumably, the author felt himself safe once within his own package, but did not suspect that someone else might circumvent the package-loading protection mechanisms also!


This was a lot more serious in LaTeX2.09 as there LaTeX just executed \makeatletter once before handling all the .sty files (LaTeX2.09 didn't gave the .cls/.sty distinction). So it was a common problem, almost a FAQ, that packages were released that executed \makeatother at the end of the file and they worked in isolation but broke any following "style files" (aka packages).

So one of the first things done for 2e was to reset the catcode of @ on loading each package, maintaining a stack so that the catcode is restored at the end of the package to what it was before. Thus by design it is hard to find an example where a rogue \makeatother at the end of a package does harm.

That said, it's better practice not to fall than to rely on a safety net.


As long as you're aware not to do bad things inside your own package (like Ryan Reich's example), you seem to be safe within the bounds of what LaTeX offers.

But still dangers lurk around the corner.

If I say

\usepackage{afterpackage}

\AfterPackage{foo}{\input{bar}}

\usepackage{foo}

and inside foo.sty

\makeatother

and inside bar.tex

\protected@edef\baz{quux}

then I get an error because @ is not a letter (which doesn't happen without the \makeatother).

(the main point of this answer is of course that the (unsuspecting) person using \AfterPackage is not neccessarily the same as the package author)