jbx.json

jbx.json is the project descriptor for publishing or installing a Java artifact with jbx. Keep it small: put durable artifact metadata here, and keep command-specific experiments on the command line.

JSON Schema: /schemas/jbx-json/v1.json

Minimal descriptor

Use this when you only need local install/serve workflows or when Git metadata can fill in Maven Central metadata later:

{
  "$schema": "https://jbx.telegraphic.dev/schemas/jbx-json/v1.json",
  "main": "HelloTool.java",
  "group": "dev.telegraphic.demo",
  "id": "hello-tool",
  "version": "1.0.0",
  "java": "25",
  "dependencies": ["info.picocli:picocli:4.7.7"],
  "runtimeDependencies": ["org.slf4j:slf4j-nop:2.0.17"]
}

Try it locally before publishing:

jbx publish --file jbx.json --dry-run
jbx publish --file jbx.json --serve 0
jbx install --file jbx.json --destination build/local-m2

Maven Central-ready descriptor

Real publishing needs normal Maven metadata: project URL, license, developer, and SCM. jbx can infer some values from GitHub, but explicit metadata is better for repeatable releases.

{
  "$schema": "https://jbx.telegraphic.dev/schemas/jbx-json/v1.json",
  "main": "dev.telegraphic.demo.HelloTool",
  "group": "dev.telegraphic.demo",
  "id": "hello-tool",
  "version": "1.0.0",
  "name": "Hello Tool",
  "description": "Small CLI published with jbx.",
  "url": "https://github.com/telegraphic-dev/hello-tool",
  "licenses": [
    {
      "name": "Apache-2.0",
      "url": "https://www.apache.org/licenses/LICENSE-2.0.txt"
    }
  ],
  "developers": [
    {
      "name": "Telegraphic",
      "organization": "Telegraphic",
      "organizationUrl": "https://telegraphic.dev"
    }
  ],
  "scm": {
    "connection": "scm:git:https://github.com/telegraphic-dev/hello-tool.git",
    "developerConnection": "scm:git:ssh://git@github.com/telegraphic-dev/hello-tool.git",
    "url": "https://github.com/telegraphic-dev/hello-tool"
  },
  "sources": ["HelloTool.java"],
  "repositories": ["snapshots=https://repo.example.test/maven"]
}

Run a dry run first. Real publishing still needs Central Portal and signing credentials configured in the environment or command options.

jbx publish --file jbx.json --dry-run
jbx publish --file jbx.json --publish

Fields

Real-life patterns

Publish a small CLI with Picocli

{
  "$schema": "https://jbx.telegraphic.dev/schemas/jbx-json/v1.json",
  "main": "CleanImports.java",
  "group": "com.acme.tools",
  "id": "clean-imports",
  "version": "0.3.0",
  "dependencies": ["info.picocli:picocli:4.7.7"]
}
jbx publish --file jbx.json --dry-run

Keep parser/logging providers runtime-only

Use runtimeDependencies for implementation libraries needed when the tool runs but not when callers compile against the artifact:

{
  "$schema": "https://jbx.telegraphic.dev/schemas/jbx-json/v1.json",
  "main": "dev.acme.RewriteTool",
  "group": "dev.acme",
  "id": "rewrite-tool",
  "version": "1.2.0",
  "dependencies": ["org.openrewrite:rewrite-java:8.56.1"],
  "runtimeDependencies": [
    "org.openrewrite:rewrite-java-21:8.56.1",
    "org.slf4j:slf4j-nop:2.0.17"
  ]
}

Pin the published source set

If the repository has helpers, examples, or generated files you do not want in the artifact, set sources explicitly:

{
  "$schema": "https://jbx.telegraphic.dev/schemas/jbx-json/v1.json",
  "main": "App.java",
  "group": "dev.acme",
  "id": "app",
  "version": "1.0.0",
  "sources": [
    "App.java",
    "AppSupport.java"
  ]
}

Publish helper artifacts from GitHub Actions

telegraphic-dev/jbx-utils is a good shape for a real repository: one repo, several small helper artifacts, each with its own descriptor. The jbx-rewrite/jbx.json descriptor keeps shared Maven metadata explicit and only names the source and dependencies for that artifact:

{
  "$schema": "https://jbx.telegraphic.dev/schemas/jbx-json/v1.json",
  "group": "dev.telegraphic.jbx",
  "version": "0.1.0",
  "package": "dev.telegraphic.jbx",
  "url": "https://github.com/telegraphic-dev/jbx-utils",
  "licenses": [
    { "name": "MIT License", "url": "https://opensource.org/licenses/MIT" }
  ],
  "developers": [
    { "name": "Telegraphic", "organizationUrl": "https://github.com/telegraphic-dev" }
  ],
  "scm": {
    "connection": "scm:git:https://github.com/telegraphic-dev/jbx-utils.git",
    "developerConnection": "scm:git:ssh://git@github.com/telegraphic-dev/jbx-utils.git",
    "url": "https://github.com/telegraphic-dev/jbx-utils"
  },
  "java": "21",
  "main": "src/JbxRewrite.java",
  "id": "jbx-rewrite",
  "name": "jbx-rewrite",
  "description": "OpenRewrite runner and recipe-discovery helper used by jbx rewrite",
  "dependencies": [
    "org.openrewrite:rewrite-core:8.56.1",
    "org.openrewrite:rewrite-java:8.56.1"
  ]
}

Use CI to prove the bundle layout before release. jbx-utils runs dry-run publishing without signing for every helper artifact:

name: CI

on:
  pull_request:
  push:
    branches: [main]

permissions:
  contents: read

jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: '25'
      - uses: dtolnay/rust-toolchain@stable
      - name: Install jbx
        run: cargo install --git https://github.com/telegraphic-dev/jbx.git --locked jbx
      - name: Verify publish bundle
        run: scripts/verify-publish-bundle.sh

Then keep real Maven Central uploads in a separate release/manual workflow. The workflow needs these GitHub secrets: CENTRAL_TOKEN_USERNAME, CENTRAL_TOKEN_PASSWORD, GPG_PRIVATE_KEY, GPG_PASSPHRASE, and GPG_KEY_ID.

name: Publish to Maven Central

on:
  release:
    types: [published]
  workflow_dispatch:
    inputs:
      version:
        description: Maven artifact version to publish, e.g. 0.1.0
        required: true

permissions:
  contents: read

jobs:
  publish:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        project: [jbx-check, jbx-graph, jbx-rewrite]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: '25'
      - uses: dtolnay/rust-toolchain@stable
      - name: Install jbx
        run: cargo install --git https://github.com/telegraphic-dev/jbx.git --locked jbx
      - name: Import GPG signing key
        uses: crazy-max/ghaction-import-gpg@v6
        with:
          gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
          passphrase: ${{ secrets.GPG_PASSPHRASE }}
      - name: Publish ${{ matrix.project }}
        env:
          CENTRAL_TOKEN_USERNAME: ${{ secrets.CENTRAL_TOKEN_USERNAME }}
          CENTRAL_TOKEN_PASSWORD: ${{ secrets.CENTRAL_TOKEN_PASSWORD }}
          GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }}
        run: |
          VERSION="${{ github.event.inputs.version }}"
          if [ -z "$VERSION" ]; then
            VERSION="${GITHUB_REF_NAME#v}"
          fi
          jbx publish \
            --publish \
            --file "${{ matrix.project }}/jbx.json" \
            --version "$VERSION" \
            --gpg-key "$GPG_KEY_ID" \
            --output "target/${{ matrix.project }}-central-bundle.zip" \
            --target-dir "target/publish/${{ matrix.project }}" \
            --cache-dir .jbx-cache

Two details matter:

Descriptor and directives

Descriptor fields override or replace matching source directives where both exist:

That keeps a library release reproducible without forcing all metadata into the Java file.

Verification checklist