A cross-platform command-line shell built in pure Java, designed around the WORE principle
(Write Once, Run Everywhere).
Note: Jcmdshell is not affiliated with Oracle or the Java® trademark.
- Works on Windows, Linux, macOS, and Windows on ARM
- Uses JLine for modern terminal input and editing
- Can be built with or without Maven
- Supports both standard JAR and fat JAR builds
- No native dependencies
- JDK 25 or newer
- Maven (optional, but recommended)
Maven automatically downloads dependencies and produces two JAR files:
| Output | Description |
|---|---|
target/Jcmdshell.jar |
Standard JAR — requires a lib/ folder with dependencies |
target/Jcmdshell-fat.jar |
Fat JAR — includes JLine and runs anywhere |
Build command:
mvn clean packageclean is optional, but recommended when a target/ directory already exists.
-
Download JLine 3.30.6
https://mvnrepository.com/artifact/org.jline/jline/3.30.6 -
Create a
lib/directory and place the downloaded JAR inside:
mkdir libUsing a
lib/folder is recommended, but optional if you provide a manifest with the classpath.
The following manual build uses thelib/setup.
javac -cp "lib/*" -d target (Get-ChildItem -Recurse -Filter *.java src/main/java/xyz/stackpancakes).FullNamedir /B /S "src\main\java\xyz\stackpancakes\*.java" > java_files.txt
javac -cp "lib\*" -d target @java_files.txt
del java_files.txtjavac -cp "lib/*" -d target $(find src/main/java/xyz/stackpancakes -name "*.java")target/ act as compilation output directories.
On Unix-like systems, a POSIX-compatible
shis assumed to be available.
If you have Nix installed, you can build and run Jcmdshell without manually managing Java or Maven dependencies:
nix run github:StackPancakes/JcmdshellYour project already includes a MANIFEST.MF with:
Manifest-Version: 1.0
Created-By: StackPancakes
Main-Class: xyz.stackpancakes.Main
Class-Path: lib/jline-3.30.6.jar
Sealed: true
Specification-Title: Jcmdshell
Specification-Version: 0.1.0
Specification-Vendor: StackPancakes
Implementation-Title: Jcmdshell
Implementation-Version: 0.1.0
Implementation-Vendor: StackPancakes
Because of this, creating a new manifest file is optional.
You may reuse the existing one when packaging.
jar cfm target/Jcmdshell.jar MANIFEST.MF -C target .If your lib/ directory is not next to the JAR, update Class-Path accordingly in your existing MANIFEST.MF.
A fat JAR is created by unpacking dependency JARs and combining their class files with your compiled classes into one runnable JAR.
Do not just place dependency JARs inside your JAR - Java won’t load nested JARs automatically.
# PowerShell
javac -cp "lib/*" -d target (Get-ChildItem -Recurse -Filter *.java src/main/java/xyz/stackpancakes).FullName# *NIX shell
javac -cp "lib/*" -d target $(find src/main/java/xyz/stackpancakes -name "*.java")mkdir fatbuildmkdir -p fatbuildCopy-Item -Recurse target\* fatbuild\cp -R target/* fatbuild/Use
jar xfinside the staging directory to extract the dependency.
Push-Location fatbuild
jar xf ..\lib\jline-3.30.6.jar
Pop-Locationcd fatbuild && jar xf ../lib/jline-3.30.6.jarNow fatbuild/ contains:
xyz/stackpancakes/... # your classes
org/jline/... # dependency classes
META-INF/... # manifests, services, signatures from deps
PowerShell:
Remove-Item fatbuild\META-INF\*.SF -ErrorAction Ignore
Remove-Item fatbuild\META-INF\*.RSA -ErrorAction Ignore
Remove-Item fatbuild\META-INF\*.DSA -ErrorAction IgnoreBatch:
del /Q fatbuild\META-INF\*.SF 2>nul
del /Q fatbuild\META-INF\*.RSA 2>nul
del /Q fatbuild\META-INF\*.DSA 2>nul*NIX:
rm -f fatbuild/META-INF/*.SF fatbuild/META-INF/*.RSA fatbuild/META-INF/*.DSAIf
META-INF/servicescollisions occur across multiple deps, merge or remove those files as needed.
Create MANIFEST.MF with:
Manifest-Version: 1.0
Main-Class: xyz.stackpancakes.Main
(Keep the final blank line.)
jar cfm target/Jcmdshell-fat.jar MANIFEST.MF -C fatbuild .Batch / Powershell:
java --enable-native-access=ALL-UNNAMED -jar target\Jcmdshell-fat.jar*NIX:
java --enable-native-access=ALL-UNNAMED -jar target/Jcmdshell-fat.jarNotes
- Keep your own
META-INF/MANIFEST.MF; do not deleteMETA-INFentirely. - Remove signature files (
*.SF,*.RSA,*.DSA) from unpacked dependencies. - For many dependencies or complex
META-INF/servicesmerges, consider using Maven Shade.
*NIX:
java --enable-native-access=ALL-UNNAMED -cp "target/Jcmdshell.jar:lib/*" xyz.stackpancakes.MainWindows:
java --enable-native-access=ALL-UNNAMED -cp "target/Jcmdshell.jar;lib/*" xyz.stackpancakes.Mainjava --enable-native-access=ALL-UNNAMED -jar target/Jcmdshell-fat.jarJcmdshell/
├─ src/
│ └─ main/java/xyz/stackpancakes/...
├─ lib/ # only needed for manual builds
├─ target/ # Maven outputs .jar here
├─ MANIFEST.MF # used when packaging
└─ README.md
Pull requests and suggestions are welcome.