Yes, it does offer such a way - and actually it's stated in the manual just below where it says that the others are legacy.
So to quote the man page for
launchctl in the section for legacy subcommands - for the subcommands
unload it says:
Recommended alternative subcommands: bootstrap | bootout | enable |
So those are the newer subcommands, you want to look at.
Here's a few examples:
Before if you used
load like this:
launchctl load my.plist
You'll now write one of these:
sudo launchctl bootstrap system my.plist
launchctl bootstrap user/$(id -u) my.plist
launchctl bootstrap gui/$(id -u) my.plist
The difference being that you now have to specify the domain target. The difference here is that
system means that it going to be a system daemon that runs as the super user, compared to
user meaning that it will run as the given user, and
gui meaning that it will run as the given user, but only be active when the user is logged in to the graphical user interface. There's also a
pid target domain if you have more advanced needs.
$(id -u) is basically just a short hand for finding your own user's id. You can run
id -u in the Terminal to get it if you do not know it, and then you can just specificy it manually like for example so:
launchctl bootstrap gui/501 my.plist
The replacement for
unload is quite similar:
sudo launchctl bootout system my.plist
launchctl bootout user/$(id -u) my.plist
launchctl bootout gui/$(id -u) my.plist
So the above covers how to move away from the legacy subcommands to the recommended subcommands instead.
The second part of your question is whether you can do this without using a plist file. The answer is no. The
bootstrap subcommand requires you to specify a service-path, which can be either a plist, a XPC service bundle - or a directory of either of those. XPC service bundle are used by application developers, but they also include a plist file - so going that route is not going to save you from having a plist file.
You can of course do various sorts of work-arounds with scripts or utility programs so that you do not need to manually create and maintain plist files. You could even use for example a named pipe to avoid having to actually store the contents of the plist file on disk, but I cannot see the practical benefit of that.