diff --git a/picocli/pom.xml b/picocli/pom.xml
new file mode 100644
index 0000000000..0334f5463d
--- /dev/null
+++ b/picocli/pom.xml
@@ -0,0 +1,28 @@
+
+
+ 4.0.0
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+ picocli
+
+
+
+ info.picocli
+ picocli
+ 3.9.6
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+ 2.1.4.RELEASE
+
+
+
\ No newline at end of file
diff --git a/picocli/src/main/java/com/baeldung/picocli/git/Application.java b/picocli/src/main/java/com/baeldung/picocli/git/Application.java
new file mode 100644
index 0000000000..04af524e45
--- /dev/null
+++ b/picocli/src/main/java/com/baeldung/picocli/git/Application.java
@@ -0,0 +1,41 @@
+package com.baeldung.picocli.git;
+
+import com.baeldung.picocli.git.commands.programmative.GitCommand;
+import com.baeldung.picocli.git.commands.subcommands.GitAddCommand;
+import com.baeldung.picocli.git.commands.subcommands.GitCommitCommand;
+import com.baeldung.picocli.git.commands.subcommands.GitConfigCommand;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import picocli.CommandLine;
+
+@SpringBootApplication
+public class Application implements CommandLineRunner {
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ private GitCommand gitCommand;
+ private GitAddCommand addCommand;
+ private GitCommitCommand commitCommand;
+ private GitConfigCommand configCommand;
+
+ @Autowired
+ public Application(GitCommand gitCommand, GitAddCommand addCommand, GitCommitCommand commitCommand, GitConfigCommand configCommand) {
+ this.gitCommand = gitCommand;
+ this.addCommand = addCommand;
+ this.commitCommand = commitCommand;
+ this.configCommand = configCommand;
+ }
+
+ @Override
+ public void run(String... args) {
+ CommandLine commandLine = new CommandLine(gitCommand);
+ commandLine.addSubcommand("add", addCommand);
+ commandLine.addSubcommand("commit", commitCommand);
+ commandLine.addSubcommand("config", configCommand);
+
+ commandLine.parseWithHandler(new CommandLine.RunLast(), args);
+ }
+}
diff --git a/picocli/src/main/java/com/baeldung/picocli/git/commands/declarative/GitCommand.java b/picocli/src/main/java/com/baeldung/picocli/git/commands/declarative/GitCommand.java
new file mode 100644
index 0000000000..f3c690a3e6
--- /dev/null
+++ b/picocli/src/main/java/com/baeldung/picocli/git/commands/declarative/GitCommand.java
@@ -0,0 +1,32 @@
+package com.baeldung.picocli.git.commands.declarative;
+
+import com.baeldung.picocli.git.model.ConfigElement;
+import com.baeldung.picocli.git.commands.subcommands.GitAddCommand;
+import com.baeldung.picocli.git.commands.subcommands.GitCommitCommand;
+import com.baeldung.picocli.git.commands.subcommands.GitConfigCommand;
+import picocli.CommandLine;
+
+import static picocli.CommandLine.*;
+import static picocli.CommandLine.Command;
+
+@Command(
+ name = "git",
+ subcommands = {
+ GitAddCommand.class,
+ GitCommitCommand.class,
+ GitConfigCommand.class
+ }
+)
+public class GitCommand implements Runnable {
+ public static void main(String[] args) {
+ CommandLine commandLine = new CommandLine(new GitCommand());
+ commandLine.registerConverter(ConfigElement.class, ConfigElement::from);
+
+ commandLine.parseWithHandler(new RunLast(), args);
+ }
+
+ @Override
+ public void run() {
+ System.out.println("The popular git command");
+ }
+}
diff --git a/picocli/src/main/java/com/baeldung/picocli/git/commands/methods/GitCommand.java b/picocli/src/main/java/com/baeldung/picocli/git/commands/methods/GitCommand.java
new file mode 100644
index 0000000000..2c3e440b8b
--- /dev/null
+++ b/picocli/src/main/java/com/baeldung/picocli/git/commands/methods/GitCommand.java
@@ -0,0 +1,27 @@
+package com.baeldung.picocli.git.commands.methods;
+
+import picocli.CommandLine;
+
+import static picocli.CommandLine.Command;
+
+@Command(name = "git")
+public class GitCommand implements Runnable {
+ public static void main(String[] args) {
+ CommandLine.run(new GitCommand(), args);
+ }
+
+ @Override
+ public void run() {
+ System.out.println("The popular git command");
+ }
+
+ @Command(name = "add")
+ public void addCommand() {
+ System.out.println("Adding some files to the staging area");
+ }
+
+ @Command(name = "commit")
+ public void commitCommand() {
+ System.out.println("Committing files in the staging area, how wonderful?");
+ }
+}
diff --git a/picocli/src/main/java/com/baeldung/picocli/git/commands/programmative/GitCommand.java b/picocli/src/main/java/com/baeldung/picocli/git/commands/programmative/GitCommand.java
new file mode 100644
index 0000000000..81ecfd78be
--- /dev/null
+++ b/picocli/src/main/java/com/baeldung/picocli/git/commands/programmative/GitCommand.java
@@ -0,0 +1,26 @@
+package com.baeldung.picocli.git.commands.programmative;
+
+import com.baeldung.picocli.git.commands.subcommands.GitAddCommand;
+import com.baeldung.picocli.git.commands.subcommands.GitCommitCommand;
+import org.springframework.stereotype.Component;
+import picocli.CommandLine;
+
+import static picocli.CommandLine.Command;
+import static picocli.CommandLine.RunLast;
+
+@Command(name = "git")
+@Component
+public class GitCommand implements Runnable {
+ public static void main(String[] args) {
+ CommandLine commandLine = new CommandLine(new GitCommand());
+ commandLine.addSubcommand("add", new GitAddCommand());
+ commandLine.addSubcommand("commit", new GitCommitCommand());
+
+ commandLine.parseWithHandler(new RunLast(), args);
+ }
+
+ @Override
+ public void run() {
+ System.out.println("The popular git command");
+ }
+}
diff --git a/picocli/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitAddCommand.java b/picocli/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitAddCommand.java
new file mode 100644
index 0000000000..803cd8dc7d
--- /dev/null
+++ b/picocli/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitAddCommand.java
@@ -0,0 +1,31 @@
+package com.baeldung.picocli.git.commands.subcommands;
+
+import org.springframework.stereotype.Component;
+
+import java.nio.file.Path;
+import java.util.List;
+
+import static picocli.CommandLine.*;
+
+@Command(
+ name = "add"
+)
+@Component
+public class GitAddCommand implements Runnable {
+ @Option(names = "-A")
+ private boolean allFiles;
+
+ @Parameters(index = "0..*")
+ private List files;
+
+ @Override
+ public void run() {
+ if (allFiles) {
+ System.out.println("Adding all files to the staging area");
+ }
+
+ if (files != null) {
+ files.forEach(path -> System.out.println("Adding " + path + " to the staging area"));
+ }
+ }
+}
diff --git a/picocli/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitCommitCommand.java b/picocli/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitCommitCommand.java
new file mode 100644
index 0000000000..df4928983c
--- /dev/null
+++ b/picocli/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitCommitCommand.java
@@ -0,0 +1,26 @@
+package com.baeldung.picocli.git.commands.subcommands;
+
+import org.springframework.stereotype.Component;
+
+import static picocli.CommandLine.Command;
+import static picocli.CommandLine.Option;
+
+@Command(
+ name = "commit"
+)
+@Component
+public class GitCommitCommand implements Runnable {
+ @Option(names = {"-m", "--message"}, required = true)
+ private String[] messages;
+
+ @Override
+ public void run() {
+ System.out.println("Committing files in the staging area, how wonderful?");
+ if (messages != null) {
+ System.out.println("The commit message is");
+ for (String message : messages) {
+ System.out.println(message);
+ }
+ }
+ }
+}
diff --git a/picocli/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitConfigCommand.java b/picocli/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitConfigCommand.java
new file mode 100644
index 0000000000..80e14c0121
--- /dev/null
+++ b/picocli/src/main/java/com/baeldung/picocli/git/commands/subcommands/GitConfigCommand.java
@@ -0,0 +1,24 @@
+package com.baeldung.picocli.git.commands.subcommands;
+
+import com.baeldung.picocli.git.model.ConfigElement;
+import org.springframework.stereotype.Component;
+
+import static picocli.CommandLine.Command;
+import static picocli.CommandLine.Parameters;
+
+@Command(
+ name = "config"
+)
+@Component
+public class GitConfigCommand implements Runnable {
+ @Parameters(index = "0")
+ private ConfigElement element;
+
+ @Parameters(index = "1")
+ private String value;
+
+ @Override
+ public void run() {
+ System.out.println("Setting " + element.value() + " to " + value);
+ }
+}
diff --git a/picocli/src/main/java/com/baeldung/picocli/git/model/ConfigElement.java b/picocli/src/main/java/com/baeldung/picocli/git/model/ConfigElement.java
new file mode 100644
index 0000000000..edc6573d88
--- /dev/null
+++ b/picocli/src/main/java/com/baeldung/picocli/git/model/ConfigElement.java
@@ -0,0 +1,25 @@
+package com.baeldung.picocli.git.model;
+
+import java.util.Arrays;
+
+public enum ConfigElement {
+ USERNAME("user.name"),
+ EMAIL("user.email");
+
+ private final String value;
+
+ ConfigElement(String value) {
+ this.value = value;
+ }
+
+ public String value() {
+ return value;
+ }
+
+ public static ConfigElement from(String value) {
+ return Arrays.stream(values())
+ .filter(element -> element.value.equals(value))
+ .findFirst()
+ .orElseThrow(() -> new IllegalArgumentException("The argument " + value + " doesn't match any ConfigElement"));
+ }
+}
diff --git a/picocli/src/main/java/com/baeldung/picocli/helloworld/HelloWorldCommand.java b/picocli/src/main/java/com/baeldung/picocli/helloworld/HelloWorldCommand.java
new file mode 100644
index 0000000000..97a861e2f0
--- /dev/null
+++ b/picocli/src/main/java/com/baeldung/picocli/helloworld/HelloWorldCommand.java
@@ -0,0 +1,20 @@
+package com.baeldung.picocli.helloworld;
+
+import picocli.CommandLine;
+
+import static picocli.CommandLine.Command;
+
+@Command(
+ name = "hello",
+ description = "Says hello"
+)
+public class HelloWorldCommand implements Runnable {
+ public static void main(String[] args) {
+ CommandLine.run(new HelloWorldCommand(), args);
+ }
+
+ @Override
+ public void run() {
+ System.out.println("Hello World!");
+ }
+}
diff --git a/pom.xml b/pom.xml
index efd7f60d2e..17ab605e7a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,6 +12,7 @@
lombok-custom
+ picocli