What a command is
A command has four lifecycle pieces: initialize() (once at start), execute() (every loop), isFinished() (returns true to end), and end(boolean interrupted) (cleanup). A command runs from when it's scheduled until it finishes or is interrupted.
You can write a full command class, but modern WPILib strongly encourages lambdas and factory methods instead — they cover almost every use case with far less code.
Inline commands with factories
The Commands utility class and subsystem helper methods build commands inline:
// Run the intake until the button is released (runEnd: run, then stop)
Command intakeCmd = intake.runEnd(intake::run, intake::stop);
// A command that does one thing and finishes immediately
Command stopCmd = Commands.runOnce(intake::stop, intake);
// Run until a condition is met
Command raiseCmd = arm.run(arm::raise).until(arm::atTop);
Common building blocks:
run(...)— runs an action every loop (never finishes on its own).runOnce(...)— runs once and ends.runEnd(run, end)— runs an action, then runs an end action when it stops..until(condition)— adds an end condition to any command..withTimeout(seconds)— ends after a time limit.
Using the subsystem's own run/runEnd factory methods automatically adds that subsystem as a requirement.
Compositions: building bigger behavior
Commands are composable — you combine small commands into bigger ones. The main compositions:
- Sequential — run commands one after another:
Command auto = Commands.sequence( drivetrain.driveForward(2.0), arm.raiseToScore(), intake.eject()); - Parallel — run commands at the same time. Variants include
parallel()(waits for all),race()(ends when the first ends), anddeadline()(ends when one specific "deadline" command ends). - Decorators —
.andThen(...),.alongWith(...),.raceWith(...)chain commands fluently:arm.raiseToScore().andThen(intake.eject());
Because a composition is itself a command, you can nest compositions inside compositions — a full autonomous routine is just one big command.
A practical pattern
Keep command factories as methods on the subsystem that returns them:
public class Intake extends SubsystemBase {
public Command intakeCommand() { return runEnd(this::run, this::stop); }
}
Then wiring becomes a one-liner: driver.a().whileTrue(intake.intakeCommand()); (covered next). This keeps behavior close to the hardware it controls and keeps RobotContainer readable.
When to write a class
Write a dedicated command class only when logic is genuinely complex (lots of state, multiple phases) and a lambda would be unreadable. For most actions, inline factories are cleaner and less error-prone.
Key takeaways
- A command has initialize / execute / isFinished / end; most are built with lambdas instead.
- Use factory methods (run, runOnce, runEnd) and decorators (.until, .withTimeout, .andThen).
- Compositions (sequence, parallel, race, deadline) combine commands into bigger behavior.
- Subsystem factory methods auto-add the subsystem as a requirement.
- Write a full command class only for genuinely complex, multi-phase logic.
Keep going
Take the quiz · +10 XP with an accountMore in The Robot Program: Lifecycle and Command-Based Architecture
Sources & corrections
This lesson is AI-assisted: drafted from primary sources, then reviewed and edited by hand. Errors still get through. When one is reported we fix it and write down what changed — publicly, in the corrections log.
Sources and further reading
- Commandsdocs.wpilib.org
- Command Compositionsdocs.wpilib.org
- Organizing Command-Based Robot Projectsdocs.wpilib.org
Read next
Articles on this, for competition day
The lesson covers how it works. These cover what to do when it breaks.
- 9 min read
FRC Command-Based Programming: Subsystems, Commands, and the Scheduler
A beginner-friendly guide to WPILib command-based programming in Java: subsystems, commands, the CommandScheduler, triggers, and composing commands.
Read - 13 min read
FRC Code Structure Best Practices: Command-Based Project Architecture
How to structure an FRC command-based robot project the right way — subsystems, commands, RobotContainer, and Constants — verified against official WPILib docs.
Read - 15 min read
How to Design an FRC Intake: Rollers, Compression, and Motors
A primary-source FRC intake design guide: over-the-bumper vs under-bumper, roller vs wheel, compliance and durometer, compression and wrap, and motor selection.
Read
Lesson quiz
RequiredAll 3 right completes the lesson. Miss one and only that question comes back — anything you already answered correctly stays banked.
0 of 3 answered
01.In a Command's lifecycle, when is the execute() method called?
02.What does the boolean parameter in end(boolean interrupted) tell you?
03.Why is it a good pattern to keep command factory methods on the subsystem that returns them?
Answer every question to submit.
All 51 lessons in Programming, Controls & Sensors
- Not started:Mini-Project: A Closed-Loop Elevator with Motion Magic
- Not started:Mini-Project: A Velocity-Controlled Shooter on REVLib
- Not started:Mini-Project: A Teleop Swerve Drive Subsystem
- Not started:Mini-Project: An Autonomous Routine with PathPlanner
- Not started:Mini-Project: Vision-Aligned Scoring with Limelight
- Not started:State-Space Control and Kalman Filtering
- Not started:Log Replay Architecture with AdvantageKit
- Not started:Advanced Pose Estimation: Multi-Tag Fusion and Standard Deviations
- Not started:Robot Coordination, Alerts, and Operator Feedback
- Not started:Case Study: Hardening Software Before an Event