Usually a return code of 0 indicates success and a return code of 1 indicates a problem, but not always. Granted, many of the GNU core utilities have been ported from way back before the day. Even those rewritten from scratch are probably based on a previous incarnation, so it’s understandable that the maintainers wanted to keep return code the same as their historical counterparts. Millions of well written scripts depend on them, after all.
The GNU coreutils make heavy use of Texinfo pages for detailed information. I have no idea why the GNU authors abhor man pages so much. To be honest, I don’t really care. But I was sick and tired of digging around for the return codes.
The following utilities return 0 upon success.
grep returns 0 if the pattern is found, 1 if not found, and 2 on error (such as a file not being readable).
gzip returns 0 upon success, 1 on error, and 2 on warning.
tar returns 0 if all went well (except for some –compare options), non-zero (usually 2, except for remote operations which may be 128) means something went wrong.
None of this matters if your scripts don’t check return codes of external routines, in which case I’d suggest that you’re doing it wrong. How else would you know if something failed? Regardless of whether your own scripts exit with a return code or not, you ought to be checking.
When writing scripts, I make an effort to use the same return codes as gzip. That’s me. Just another person’s standard if not somewhat consistent with most of the GNU utilities, I guess.