Create or maintain a zero-dependency, single-file executable Java script using $ARGUMENTS. Apply all rules below strictly.
Purpose
These are self-contained, single-file Java scripts installed in a PATH directory (e.g., /usr/local/bin) and invoked like any shell command — no project structure, no build tool, no .java extension.
Composition
- Follow
/java-conventions for all generic Java 25 style, syntax, naming, methods, streams, exceptions, and comments
- The rules below specialize
/java-conventions for single-file source-mode scripts; when this skill is silent on a topic, /java-conventions applies
Single-File Constraint
- Everything lives in one file — all logic, records, enums, sealed types, and helper methods
- If the script grows beyond what fits comfortably in a single file, suggest switching to the
java-cli-app skill instead
- No multi-file source-code programs — this skill is strictly for single-file scripts
Build
- Use Java 25 source-file mode — no build tool, no compilation step
- Never use the
.java extension — scripts are executable files with a lowercase filename and a shebang
- Never use
--enable-preview in the shebang — Java 25 is a GA release, all features used here are standard
- The shebang line is always:
#!/usr/bin/env -S java --source 25
- Save with a short, descriptive, lowercase command name (e.g.,
jsonformat, portcheck, sysinfo)
- Never use dashes in filenames (e.g.,
hello-world) — Java source-file mode does not support them. Use camelCase instead (e.g., helloWorld)
- Mark executable:
chmod +x scriptname
- Install by copying or symlinking to a PATH directory:
cp scriptname /usr/local/bin/ or ln -s $(pwd)/scriptname /usr/local/bin/scriptname
Script Structure
A minimal script:
#!/usr/bin/env -S java --source 25
void main(String... args) throws Exception {
// ...
}
Naming Convention
- The script's filename is its application name — use it consistently in all output: version strings, help text, usage lines, and error messages
- Derive the application name dynamically at startup using
MethodHandles.lookup().lookupClass().getName() — in source-file mode, the class name matches the filename, so there is nothing to hardcode or keep in sync
Version Management
- Suggest maintaining a
String version = "YYYY-MM-DD.N"; instance variable (e.g., String version = "2026-02-20.1";)
- On every change, update the date to the current date and increase the last number
- Print the script name and version on startup as the first line of output (e.g.,
IO.println(name + " " + version);)
- Support
-version flag to print the version — only for scripts that accept additional arguments
Main Method Conventions
- Use
void main(String... args) throws Exception — PATH-installed scripts always accept arguments; declaring throws Exception keeps the code clean by avoiding try-catch boilerplate for checked exceptions like IOException
- Parse arguments manually for simple scripts with few flags
- For scripts with multiple options or complex argument handling, use the
/zargs skill to generate an enum-based argument parser — it remains zero-dependency and single-file
Argument Handling
- Scripts with no additional arguments: do not introduce
-help or -version flags — the script should just do its work
- Scripts with additional arguments: support both
-help and -version flags
- Use clear, descriptive error messages for invalid input
- Exit with code 0 on success, non-zero on failure
Script with additional arguments — include -help and -version:
String name = MethodHandles.lookup().lookupClass().getName();
String version = "2026-02-20.1";
void main(String... args) throws Exception {
IO.println(name + " " + version);
if (args.length == 0 || args[0].equals("-help")) {
IO.println("""
Usage: %s <input> [options]
-help Show this help
-version Show version
""".formatted(name));
return;
}
if (args[0].equals("-version")) {
return;
}
// ...
}
Convenience Scripts for an Existing java-cli-app or JAR
When asked for an executable convenience script for a /java-cli-app project or an existing JAR, do not replicate the application's logic in the script. The script stays a single-file source script whose main calls into the JAR's classes. Instead:
- Keep source-file mode and add the JAR to the classpath in the same shebang — both are required so the source file compiles and can resolve the app's classes:
#!/usr/bin/env -S java --source 25 -cp /path/to/app.jar
- This is the one sanctioned exception to the "never add classpath entries to the shebang" rule under Zero Dependencies — it applies only when wrapping an existing app, never for standalone scripts
- Delegate to the existing functionality by calling the app's public API. Only fall back to invoking its
main(String[]) when no other entry point exists — calling main directly re-runs the app's startup banner and argument parsing
- If the existing code is not callable from a single-file launcher (e.g., no accessible entry point, tightly coupled logic), recommend refactoring the
java-cli-app to expose a public API or executable entry point rather than duplicating its behavior in the script
- Never copy or paraphrase the application's logic into the convenience script
Zero Dependencies
- Only use the
java.base module and standard JDK modules
- Never add external JARs or classpath entries to the shebang
- Use
java.net.http.HttpClient for HTTP, javax.crypto for crypto, java.nio.file for file I/O
- If a task genuinely requires external libraries or multiple files, suggest using the
java-cli-app skill with zb instead
Code Style
Generic Java style comes from /java-conventions. The rules below are script-specific specializations.
- Do not create classes or interfaces — use unnamed classes with top-level methods, records, enums, and sealed types only
- No package declaration
- Use
IO.println() for printing (or IO::println as method reference) — never System.out.println() and never System.Logger (scripts use stdout directly)
- For multi-line output, use a single
IO.println with a text block — never multiple IO.println calls for consecutive lines
stdin / stdout / stderr
- Read from stdin when no file argument is given — support piping (e.g.,
cat file | scriptname)
- Write normal output to stdout
- Write errors and diagnostics to stderr using
System.err.println()
- For colored terminal output (status messages, errors, warnings), use the
/zcl skill — it adds ANSI color support with zero dependencies
- Support both piped input and file arguments where applicable
Configuration (Optional)
- For scripts that need external configuration (properties files, environment overrides), use the
/zcfg skill to add zero-dependency configuration loading
- Most scripts should prefer command-line arguments over configuration files — only use
/zcfg when persistent settings are genuinely needed
Companion Libraries
The following zero-dependency libraries can be embedded directly into single-file scripts. They may need to be cloned first:
- zcl — colored terminal output:
git clone https://github.com/AdamBien/zcl
- zargs — enum-based argument parsing pattern: https://github.com/AdamBien/zeeds/blob/main/zargs (no repo to clone — the
/zargs skill generates the code directly)
- zcfg — configuration loading:
git clone https://github.com/AdamBien/zcfg
Installation Guidance
When presenting the finished script, always include installation instructions:
# Make executable
chmod +x scriptname
# Install system-wide (pick one)
sudo cp scriptname /usr/local/bin/
# or symlink for development
sudo ln -s $(pwd)/scriptname /usr/local/bin/scriptname
1---2name: java-cli-script3description: Create zero-dependency, single-file executable Java scripts for system-wide use via PATH. Use when asked to create a single-file Java shell script, system utility, PATH-installed Java tool, or shebang-launched Java program without the .java extension. Triggers on "Java script", "Java utility", "PATH script", "system script", or requests for single-file Java programs installed in /usr/local/bin or similar PATH directories. Not for multi-file Java applications — use java-cli-app for those.4---56Create or maintain a zero-dependency, single-file executable Java script using $ARGUMENTS. Apply all rules below strictly.78## Purpose910These are self-contained, single-file Java scripts installed in a PATH directory (e.g., `/usr/local/bin`) and invoked like any shell command — no project structure, no build tool, no `.java` extension.1112## Composition1314- Follow `/java-conventions` for all generic Java 25 style, syntax, naming, methods, streams, exceptions, and comments15- The rules below specialize `/java-conventions` for single-file source-mode scripts; when this skill is silent on a topic, `/java-conventions` applies1617## Single-File Constraint1819- Everything lives in one file — all logic, records, enums, sealed types, and helper methods20- If the script grows beyond what fits comfortably in a single file, suggest switching to the `java-cli-app` skill instead21- No multi-file source-code programs — this skill is strictly for single-file scripts2223## Build2425- Use Java 25 source-file mode — no build tool, no compilation step26- Never use the `.java` extension — scripts are executable files with a lowercase filename and a shebang27- Never use `--enable-preview` in the shebang — Java 25 is a GA release, all features used here are standard28- The shebang line is always:2930```31#!/usr/bin/env -S java --source 2532```3334- Save with a short, descriptive, lowercase command name (e.g., `jsonformat`, `portcheck`, `sysinfo`)35- Never use dashes in filenames (e.g., `hello-world`) — Java source-file mode does not support them. Use camelCase instead (e.g., `helloWorld`)36- Mark executable: `chmod +x scriptname`37- Install by copying or symlinking to a PATH directory: `cp scriptname /usr/local/bin/` or `ln -s $(pwd)/scriptname /usr/local/bin/scriptname`3839## Script Structure4041A minimal script:4243```44#!/usr/bin/env -S java --source 254546void main(String... args) throws Exception {47 // ...48}49```5051## Naming Convention5253- The script's filename is its application name — use it consistently in all output: version strings, help text, usage lines, and error messages54- Derive the application name dynamically at startup using `MethodHandles.lookup().lookupClass().getName()` — in source-file mode, the class name matches the filename, so there is nothing to hardcode or keep in sync5556## Version Management5758- Suggest maintaining a `String version = "YYYY-MM-DD.N";` instance variable (e.g., `String version = "2026-02-20.1";`)59- On every change, update the date to the current date and increase the last number60- Print the script name and version on startup as the first line of output (e.g., `IO.println(name + " " + version);`)61- Support `-version` flag to print the version — only for scripts that accept additional arguments6263## Main Method Conventions6465- Use `void main(String... args) throws Exception` — PATH-installed scripts always accept arguments; declaring `throws Exception` keeps the code clean by avoiding try-catch boilerplate for checked exceptions like `IOException`66- Parse arguments manually for simple scripts with few flags67- For scripts with multiple options or complex argument handling, use the `/zargs` skill to generate an enum-based argument parser — it remains zero-dependency and single-file6869## Argument Handling7071- Scripts with no additional arguments: do not introduce `-help` or `-version` flags — the script should just do its work72- Scripts with additional arguments: support both `-help` and `-version` flags73- Use clear, descriptive error messages for invalid input74- Exit with code 0 on success, non-zero on failure7576Script with additional arguments — include `-help` and `-version`:7778```79String name = MethodHandles.lookup().lookupClass().getName();80String version = "2026-02-20.1";8182void main(String... args) throws Exception {83 IO.println(name + " " + version);84 if (args.length == 0 || args[0].equals("-help")) {85 IO.println("""86 Usage: %s <input> [options]87 -help Show this help88 -version Show version89 """.formatted(name));90 return;91 }92 if (args[0].equals("-version")) {93 return;94 }95 // ...96}97```9899## Convenience Scripts for an Existing java-cli-app or JAR100101When asked for an executable convenience script for a `/java-cli-app` project or an existing JAR, do not replicate the application's logic in the script. The script stays a single-file source script whose `main` calls into the JAR's classes. Instead:102103- Keep source-file mode and add the JAR to the classpath in the same shebang — both are required so the source file compiles and can resolve the app's classes:104105```106#!/usr/bin/env -S java --source 25 -cp /path/to/app.jar107```108109- This is the one sanctioned exception to the "never add classpath entries to the shebang" rule under [Zero Dependencies](#zero-dependencies) — it applies only when wrapping an existing app, never for standalone scripts110- Delegate to the existing functionality by calling the app's public API. Only fall back to invoking its `main(String[])` when no other entry point exists — calling `main` directly re-runs the app's startup banner and argument parsing111- If the existing code is not callable from a single-file launcher (e.g., no accessible entry point, tightly coupled logic), recommend refactoring the `java-cli-app` to expose a public API or executable entry point rather than duplicating its behavior in the script112- Never copy or paraphrase the application's logic into the convenience script113114## Zero Dependencies115116- Only use the `java.base` module and standard JDK modules117- Never add external JARs or classpath entries to the shebang118- Use `java.net.http.HttpClient` for HTTP, `javax.crypto` for crypto, `java.nio.file` for file I/O119- If a task genuinely requires external libraries or multiple files, suggest using the `java-cli-app` skill with zb instead120121## Code Style122123Generic Java style comes from `/java-conventions`. The rules below are script-specific specializations.124125- Do not create classes or interfaces — use unnamed classes with top-level methods, records, enums, and sealed types only126- No package declaration127- Use `IO.println()` for printing (or `IO::println` as method reference) — never `System.out.println()` and never `System.Logger` (scripts use stdout directly)128- For multi-line output, use a single `IO.println` with a text block — never multiple `IO.println` calls for consecutive lines129130## stdin / stdout / stderr131132- Read from stdin when no file argument is given — support piping (e.g., `cat file | scriptname`)133- Write normal output to stdout134- Write errors and diagnostics to stderr using `System.err.println()`135- For colored terminal output (status messages, errors, warnings), use the `/zcl` skill — it adds ANSI color support with zero dependencies136- Support both piped input and file arguments where applicable137138## Configuration (Optional)139140- For scripts that need external configuration (properties files, environment overrides), use the `/zcfg` skill to add zero-dependency configuration loading141- Most scripts should prefer command-line arguments over configuration files — only use `/zcfg` when persistent settings are genuinely needed142143## Companion Libraries144145The following zero-dependency libraries can be embedded directly into single-file scripts. They may need to be cloned first:146147- **zcl** — colored terminal output: `git clone https://github.com/AdamBien/zcl`148- **zargs** — enum-based argument parsing pattern: https://github.com/AdamBien/zeeds/blob/main/zargs (no repo to clone — the `/zargs` skill generates the code directly)149- **zcfg** — configuration loading: `git clone https://github.com/AdamBien/zcfg`150151## Installation Guidance152153When presenting the finished script, always include installation instructions:154155```156# Make executable157chmod +x scriptname158159# Install system-wide (pick one)160sudo cp scriptname /usr/local/bin/161# or symlink for development162sudo ln -s $(pwd)/scriptname /usr/local/bin/scriptname163```