Jgo
Launcher and dependency manager for Java programs ☕
Install / Use
/learn @apposed/JgoREADME
jgo: painless Java environments and execution
Summary
jgo launches Java applications directly from Maven coordinates—no installation required. Specify a Maven artifact identifier and an optional main class, and jgo resolves dependencies, materializes the environment including the version of Java needed, and runs your program.
# Run Jython REPL (latest version)
jgo org.python:jython-standalone
# Run with specific version
jgo org.python:jython-standalone:2.7.3
Features
- Zero-configuration execution: Automatic Java download and version management thanks to
cjdkintegration - Pure Python dependency resolver: No Maven installation required to resolve dependency graphs
- Reproducible environments:
jgo.tomlproject files with lock files (likepackage.json+package-lock.json) - Three-layer architecture: Independently useful layers for Maven resolution, environment building, and execution
- Powerful Python API: Fine-grained control over dependency resolution and execution
- Intelligent module handling: Full support of the Java module system (JPMS), including intelligent classification of dependencies on module-path or class-path as appropriate
Quick Start
CLI Usage
# Run Jython REPL
jgo org.python:jython-standalone
# Run with arguments
jgo org.python:jython-standalone -- -- script.py --verbose
# Multiple artifacts with main class (use @ separator)
jgo org.scijava:scijava-common+org.scijava:scripting-jython@ScriptREPL
# Force update from remote repos
jgo -u org.python:jython-standalone
# Use specific Java version
jgo --java-version 17 net.imagej:imagej
# Print classpath without running
jgo info classpath org.python:jython-standalone
# Preview commands without executing (--dry-run)
jgo --dry-run run org.scijava:parsington # See java command
jgo --dry-run init org.python:jython-standalone # Preview jgo.toml
Python API
import jgo
# Simple one-liner
jgo.run("org.python:jython-standalone:2.7.3", app_args=["script.py"])
# Build environment without running
env = jgo.build("org.python:jython-standalone")
print(env.classpath) # List of JAR paths
# Resolve dependencies
components = jgo.resolve("org.python:jython-standalone")
for comp in components:
print(f"{comp.groupId}:{comp.artifactId}:{comp.version}")
Project Mode with jgo.toml
Create reproducible environments:
# jgo.toml
[environment]
name = "my-java-app"
[repositories]
scijava.public = "https://maven.scijava.org/content/groups/public"
[dependencies]
coordinates = ["net.imagej:imagej:2.15.0"]
[entrypoints]
default = "main"
main = "net.imagej.Main"
[settings]
cache_dir = ".jgo" # Local environment like .venv
# Run from current directory
jgo sync
# Creates .jgo/ with jars/ and jgo.lock.toml
Installation
<details><summary><strong>Installing jgo with uv</strong></summary>uv tool install jgo
</details>
<details><summary><strong>Installing jgo with pip</strong></summary>
pip install jgo
</details>
<details><summary><strong>Installing jgo with conda</strong></summary>
conda install -c conda-forge jgo
</details>
<details><summary><strong>Installing jgo from source</strong></summary>
git clone https://github.com/apposed/jgo
uv tool install --with-editable jgo jgo
When installed in this fashion, changes to the jgo source code will be immediately reflected when running jgo from the command line.
uv add jgo
or
pixi add jgo
Not sure which to use? Read this.
</details>Examples
| Program | Command |
|-----------------------------:|:------------------------------------------------------------------------------------|
| Jython REPL | jgo org.python:jython-standalone |
| JRuby eval | echo "puts 'Hello Ruby'" \| jgo org.jruby:jruby-complete@jruby.Main |
| Groovy REPL | jgo org.codehaus.groovy:groovy-groovysh+commons-cli:commons-cli:1.3.1@shell.Main |
Note the usage of the + syntax as needed to append elements to the classpath.
If you add
scijava.public = https://maven.scijava.org/content/groups/public
to the
[repositories] section of your settings file
(see the configuration docs),
you can also try:
| Program | Command |
|-----------------------------:|:------------------------------------------------------------------------------------|
| SciJava REPL with JRuby | jgo org.scijava:scijava-common+org.scijava:scripting-jruby@ScriptREPL |
| SciJava REPL with Jython | jgo org.scijava:scijava-common+org.scijava:scripting-jython@ScriptREPL |
| SciJava REPL with Groovy | jgo org.scijava:scijava-common+org.scijava:scripting-groovy@ScriptREPL |
| SciJava REPL with Clojure | jgo org.scijava:scijava-common+org.scijava:scripting-clojure@ScriptREPL |
| SciJava REPL with JavaScript | jgo org.scijava:scijava-common+org.scijava:scripting-javascript@ScriptREPL |
FAQ
- Is it fast?
Endpoints are synthesized in a local cache under
~/.cache/jgo. So invoking the same endpoint a second time is really quick. - What does "no installation" mean?
Classpath elements are hard-linked
into
~/.cache/jgofrom~/.m2/repositoryrather than copied, so the cache folder has a tiny footprint even if you execute lots of different endpoints. - What if an endpoint has a new version?
Pass the
-uflag tojgoto rebuild the endpoint. Note that unlikemvn,jgodoes not check for updates otherwise.
Documentation
Full documentation is available at jgo.apposed.org:
- Getting Started — Installation and quick start
- CLI Reference — All commands and options
- Project Mode — Working with
jgo.toml - Python API — Using jgo from Python code
- Configuration — Repositories, shortcuts, and settings
- Migration Guide — Upgrading from jgo 1.x
- Architecture — The three-layer design
Use help(jgo) in Python for detailed API documentation.
Development
Code style
jgo uses ruff for linting and formatting:
make lint
Testing
# Run all tests
make test
# Run specific test file
bin/test.sh tests/test_maven_basic.py
# Run with coverage
uv run pytest --cov=src/jgo tests/
