Download-and-copy is the way. A single binary CLI can just copy over itself and exec into the new version. You can preserve the permissions of the original file.
With scripting-language CLIs, you either have to deal with the module install process or use an external packaging solution.