Make a named pipe then. Shells have built-in primitives for that. I.e. <() and >() subshells in bash, or psub in fish. Or have an option to read either a file descriptor or a file.
I can't understand why you keep inflating the difficulty of simple commandline parsing, which the tool needs to do anyway — we shouldn't even be talking about it. Commandline parsing code is done once (and read once per audit) while a hostile user interface that bad commandline creates takes effort to use each time someone invokes the tool. If the tool has 1000 users, then bad interface's overhead has 1000× weight when we measure it against the overhead of implementing commandline parsing. This is preposterous.
> Not involving argument parsing simplifies the interface
From interface perspective, how is `5>secretkey` simpler than `--sk secretkey`? The latter is descriptive, searchable and allows bash completion. I'll type `ed25519-keypair`, hit tab and recall what the argument called.
You can't justify poorly made interface that is unusable without opening the manual side by side. Moreover, the simplest shell scripts that call this tool are unreadable (and thus unauditable) without the the manual.
ed25519-keypair 5>secretkey 9>publickey
You see this line in a shell script. What does it do? Even before asking some deeper crypto-specific questions, you need to know what's written in "secretkey" and "publickey" files. You will end up spending your time (even a minute) and context-switch to check the descriptor numbers instead of doing something actually useful.