Marn is a CLI tool that reads scripts from pom.xml and executes them, similar to how yarn works with package.json.
Cross-platform: Works on Windows, Linux, and macOS!
Download the latest pre-compiled binary for your platform:
| Platform | Download |
|---|---|
| Windows x64 | marn-windows-amd64.exe |
| Linux x64 | marn-linux-amd64 |
| Linux ARM64 | marn-linux-arm64 |
| macOS x64 | marn-darwin-amd64 |
| macOS ARM64 (M1/M2) | marn-darwin-arm64 |
π‘ Tip: You can also browse all releases at github.com/machinastudios/marn/releases
After downloading, install globally:
On Linux/macOS:
# Make executable and install
chmod +x marn-linux-amd64
./marn-linux-amd64 initOn Windows (PowerShell):
.\marn-windows-amd64.exe init- Go 1.21 or higher
- Maven (for running the Maven commands)
On Linux/macOS:
cd marn
chmod +x build.sh
./build.shOn Windows (PowerShell):
cd marn
.\build.ps1This will create binaries in the dist/ directory.
After installation, you can use marn with the following commands:
| Command | Description |
|---|---|
marn init |
Install marn globally (copies binary to PATH) |
marn install |
Install dependencies (mvn dependency:resolve) |
marn link |
Link current project to local Maven repository (~/.m2) |
marn build |
Build the project (mvn clean compile) |
marn test |
Run tests (mvn test) |
marn package |
Package the project (mvn package) |
marn run |
Build and run the JAR |
marn clean |
Clean the project (mvn clean) |
marn watch |
Watch for changes and rebuild |
marn version |
Show version |
marn <script> |
Run custom script from pom.xml |
If you're working on a local dependency (like mshared), use marn link to install it to your local Maven repository:
cd mshared
marn linkThis runs mvn clean install -DskipTests, making the project available to other projects that depend on it.
Define custom scripts in your pom.xml under <properties>:
<properties>
<script.dev>mvn clean compile -DskipTests</script.dev>
<script.lint>mvn checkstyle:check</script.lint>
</properties>Then run them with:
marn dev
marn lintYou can define pre* and post* scripts that run before and after any command (including custom scripts):
<properties>
<script.preBuild>echo "Preparing build..."</script.preBuild>
<script.postBuild>cp ${BUILD_ARTIFACT} dist/</script.postBuild>
<script.dev>mvn clean compile</script.dev>
<script.preDev>echo "Starting dev mode"</script.preDev>
<script.postDev>echo "Dev mode complete"</script.postDev>
</properties>Pre-scripts run before the main command, and post-scripts run after. If a pre-script fails, the main command won't run. If a post-script fails, the program exits with an error.
Marn automatically sets the following environment variables that you can use in your scripts:
Set after marn build and marn run. Contains the absolute path to the most recently compiled JAR file.
Set after marn build, marn package, and marn run. Contains the absolute path to the target/ directory.
You can use environment variables in scripts using ${VAR} or $VAR syntax:
<properties>
<script.postBuild>cp ${BUILD_ARTIFACT} ../deploy/</script.postBuild>
<script.deploy>scp ${BUILD_ARTIFACT} server:/opt/app/</script.deploy>
<script.copyJars>cp ${TARGET_DIR}/*.jar dist/</script.copyJars>
</properties>Marn automatically loads environment variables from a .env file in your project root if it exists:
DATABASE_URL=jdbc:postgresql://localhost:5432/mydb
API_KEY=secret123
PORT=8080Variables in .env won't override existing environment variables. You can use these variables in your scripts:
<properties>
<script.run>java -jar ${BUILD_ARTIFACT} --port=${PORT}</script.run>
</properties>Marn provides Unix-like command aliases on Windows, so you can use the same scripts across all platforms:
cp- Copy files/directories (supports wildcards like*.jar)mv- Move/rename filesrm- Remove filesmkdir- Create directoriestouch- Create files or update timestampscat- Display file contentsgrep- Search text in filesls- List filespwd- Print working directorywhich- Find command location
Example:
<properties>
<script.postBuild>cp ${TARGET_DIR}/*.jar ../deploy/</script.postBuild>
<script.cleanup>rm -rf ${TARGET_DIR}/classes</script.cleanup>
</properties>Configure watch mode in your pom.xml:
<properties>
<watch.dirs>src/main/java src/main/resources</watch.dirs>
<watch.buildCommand>compile</watch.buildCommand>
<watch.skipTests>true</watch.skipTests>
<watch.debounceTime>2</watch.debounceTime>
<watch.postCommand>./marn run</watch.postCommand>
<watch.localDeps>../mshared</watch.localDeps>
</properties>Then run:
marn watchThis will watch for changes in the specified directories and rebuild automatically.
Marn automatically detects SNAPSHOT dependencies that have local sibling directories. When you run marn build, marn test, or marn watch, it will:
- Find dependencies with SNAPSHOT versions
- Check if a sibling directory with the same artifactId exists
- Build those dependencies first before building the main project
You can also manually configure local dependencies in pom.xml:
<properties>
<watch.localDeps>../mshared ../another-dep</watch.localDeps>
</properties>marn/
βββ src/ # Source code
β βββ main.go # Entry point and command handling
β βββ colors.go # Terminal color definitions
β βββ colors_windows.go # Windows-specific color handling
β βββ colors_unix.go # Unix-specific color handling
β βββ commands.go # Main commands (build, test, run, etc.)
β βββ init.go # Global installation command
β βββ pom.go # POM parsing and property extraction
β βββ watch.go # Watch mode implementation
β βββ utils.go # Utility functions
β βββ go.mod # Go module definition
β βββ go.sum # Go dependencies checksum
βββ dist/ # Compiled binaries (generated)
βββ build.sh # Linux/macOS build script
βββ build.ps1 # Windows build script
βββ README.md # Documentation
βββ .github/
βββ workflows/
βββ release.yml # GitHub Actions workflow
The project includes a GitHub Actions workflow that:
- On every push to
main: Validates that the code builds for all platforms - On tag push (
v*): Creates a release with binaries for all platforms
To create a new release:
git tag v1.0.0
git push origin v1.0.0The workflow will automatically:
- Build binaries for Linux, Windows, and macOS (both amd64 and arm64)
- Create a GitHub release with all binaries
- Generate release notes
- Include SHA256 checksums
- Uses PowerShell to run shell commands
- Provides Unix command aliases (
cp,mv,rm, etc.) - Uses
taskkillto kill existing Java processes - Installs to
%USERPROFILE%\bin - Make sure Maven (
mvn.cmd) is in your PATH
- Uses
bash -cto run shell commands - Uses
pkillto kill existing Java processes - Installs to
/usr/local/bin(may require sudo) - Uses
fsnotifyfor file watching (native inotify on Linux)
MIT