emacsclient -c (or some other variation without
emacsclient to return as soon as it's contacted the running Emacs instance to tell it to edit the file. The program calling the editor (here, zsh, but this applies equally to any other program that invokes
$VISUAL) knows that you've finished editing because the program that it invoked has exited, which, with
-n, happens essentially immediately.
You need to arrange for the program invoked through
VISUAL to exit when you've finished editing, i.e. when you close the buffer in Emacs. That's exactly what
-n does: it contacts the running Emacs instance to tell it to open the file, then sits around until Emacs replies to tell emacsclient that the editing session is finished. The normal way to finish an editing session is to press
C-x # (
server-edit). This notifies emacsclient and closes the buffer, as well as the frame when it was opened by
emacsclient -c. Closing the buffer also notifies the emacsclient process that the session is finished, but you get a warning prompt (“Buffer … still has clients, kill it?”), which you can disable by overriding the function
server-kill-buffer-query-function (RMS thinks it's dangerous). In a frame opened by
emacsclient -c, pressing
C-x C-c (
save-buffers-kill-terminal) saves the file, closes it and closes the frame.