Several of those documented exit codes are primarily for copy/sync and similar commands, I think. But yes, I agree that returning exit code 1 may be misleading. I think it would be pretty easy to improve this, the main challenge is to pick a number..
Exit code 2 I don't think is even in use. It is documented as "Error not otherwise categorised", but can't find any traces of it ever being returned in code.
We could go all-in robocopy exit code style... or like I remember FSUM checksum tool did, which was to indicate actual number of errors (file mismatches) in the exit code. Would be doable, but probably not necessary, too much effort for too little gain? And I see a risk of it ending up in a can of worms.
So, should we try to turn those exit codes up to eleven then (I mean pick next unused exit code, 11)? Or any better ideas?
Yes, we return exit code 1 for both usage errors, like unknown flags or invalid number of arguments, as well as for general errors. I think exit code 1 definitively makes sense to use as a default, i.e. for "error not otherwise categorised", but then as you say, exit code 2 may be appropriate to use for usage errors.
The documentation currently states:
0 - success
1 - Syntax or usage error
2 - Error not otherwise categorised
What we actually do, currently:
0 - success
1 - Syntax or usage error, and errors not otherwise categorised
So from that I think we can make up something different if we want!
Note that there are quite a few places where we do log.Fatal - I think these exit with error code 1 which is where those are coming from. (I'm trying to root out all the log.Fatal as they don't play nice with librclone though!)
This makes sense if we are using log.Fatal - leave it as the catch all then we can specifically use 2 for Syntax or usage error.