command1.andThen(command2, …) returns a SequentialCommand.
There are two key types of commands for determining order of execution, although there are others, and I highly recommend you go through all of them to find the right commands to fit your needs: SequentialCommands and ParallelCommands.
A SequentialCommand runs the commands one after another, such that in my above example, command1 must finish before command2 will be scheduled by the CommandScheduler, and as many commands that need to run in “sequence” can be strung together as arguments to the method call.
A ParallelCommand, which can be created by calling command1.alongWith(command2, …), runs all the commands all at the same time, and finishes only once each and every command has finished.
You can combine the two concepts, for example, creating a parallel command of intaking continuously and a sequential command that drives a path and then shoots the game piece.
var autoCommand = (driveOnGeneratedPath.andThen(shoot)).alongWith(intakeContinuously);
Does that help?
Another useful method is .repeatedly() which returns a RepeatCommand, allowing you to run a command over and over and combine repeatedly with an .until() with a lambda expression returning a boolean (which becomes the get() method of Supplier), that way, once you want it to stop repeating, you can have logic to do so. From the example I gave, we might want to repeat the command (leaving out the logic for actually switching to a new path to follow), we could drive and pick up multiple notes by doing the following:
var fullAutoCommand = autoCommand.repeatedly().until(() → noMoreNotesToGrab)
where noMoreNotesToGrab is some piece of logic defined elsewhere to say your autonomous should be done and stop finding paths to the next note.