Command-line tools for Java Backend Coding Technology - formatting, linting, and project management.
JBCT CLI provides:
| Command | Purpose |
|---|---|
jbct format |
Format Java source files to JBCT style |
jbct lint |
Check code for JBCT compliance (37 rules) |
jbct check |
Combined format check + lint |
jbct init |
Create new JBCT-compliant project |
jbct update |
Update AI tools from repository |
jbct upgrade |
Self-update to latest version |
jbct verify-slice |
Validate Aether slice configuration |
curl -fsSL https://raw.githubusercontent.com/siy/jbct-cli/main/install.sh | sh
The installer:
~/.jbct/lib/jbct.jar~/.jbct/bin/jbct~/.jbct/bin to PATH in your shell RC fileCustom install location:
JBCT_HOME=/custom/path sh install.sh
Download jbct.jar from releases and run:
java -jar jbct.jar --help
git clone https://github.com/siy/jbct-cli.git cd jbct-cli mvn package -DskipTests # JAR: jbct-cli/target/jbct.jar
jbct --version
Format Java source files in-place to JBCT style.
jbct format src/main/java
Options:
| Option | Description |
|---|---|
--check |
Report files needing formatting, exit 1 if any found |
--dry-run |
Show what would be formatted without writing |
--verbose |
Show detailed output |
Examples:
# Format all Java files jbct format src/main/java # Check formatting without modifying (for CI) jbct format --check src/main/java # Preview changes without writing jbct format --dry-run src/main/java # Format with verbose output jbct format --verbose src/main/java
Exit codes:
0 - All files formatted or already compliant1 - Files need formatting (with --check)Check code for JBCT compliance using 37 lint rules.
jbct lint src/main/java
Options:
| Option | Description |
|---|---|
--format <text|json|sarif> |
Output format (default: text) |
--fail-on-warning |
Treat warnings as errors |
--verbose |
Show detailed output |
Examples:
# Lint with text output jbct lint src/main/java # Lint with JSON output (for tooling) jbct lint --format json src/main/java # Lint with SARIF output (for GitHub Code Scanning) jbct lint --format sarif src/main/java # Fail on any warning jbct lint --fail-on-warning src/main/java
Exit codes:
0 - All checks passed1 - Lint issues found2 - Internal error (parse failure, etc.)Combined format check and lint (recommended for CI).
jbct check src/main/java
Options:
| Option | Description |
|---|---|
--fail-on-warning |
Treat warnings as errors |
--verbose |
Show detailed output |
Examples:
# Full check (format + lint) jbct check src/main/java # Strict mode (warnings are errors) jbct check --fail-on-warning src/main/java
Exit codes:
0 - All checks passed1 - Format or lint issues found2 - Internal errorCreate a new JBCT-compliant project.
jbct init my-project
Options:
| Option | Description |
|---|---|
--group-id <id> |
Custom Maven group ID |
--slice <name> |
Create Aether slice project |
Examples:
# Create new project in directory jbct init my-project # Initialize current directory jbct init . # With custom group ID jbct init --group-id com.example my-project # Create Aether slice project jbct init --slice my-slice
What it creates:
Standard project:
pom.xmljbct.toml configuration~/.claude/Slice project (--slice):
@Slice annotated interface with factory methodUpdate AI tools from coding-technology repository.
jbct update
Options:
| Option | Description |
|---|---|
--force |
Force update even if current |
--check |
Check only, don’t install |
Examples:
# Update if new version available jbct update # Force update jbct update --force # Check for updates only jbct update --check
Self-update JBCT CLI to the latest version.
jbct upgrade
Options:
| Option | Description |
|---|---|
--check |
Check only, don’t install |
--force |
Force reinstall |
Examples:
# Check and install latest jbct upgrade # Check only jbct upgrade --check # Force reinstall jbct upgrade --force
Validate Aether slice project configuration.
jbct verify-slice
Options:
| Option | Description |
|---|---|
--strict |
Fail on warnings |
Examples:
# Validate current directory jbct verify-slice # Validate specific directory jbct verify-slice my-slice # Strict mode jbct verify-slice --strict
What it checks:
pom.xml or slice.class propertyslice-api.properties (annotation processor not run)| Rule | Severity | Description |
|---|---|---|
JBCT-RET-01 |
ERROR | Business methods must use T, Option, Result, or Promise |
JBCT-RET-02 |
ERROR | No nested wrappers (Promise<Result<T>>, Option<Option<T>>) |
JBCT-RET-03 |
ERROR | Never return null - use Option<T> |
JBCT-RET-04 |
ERROR | Use Unit instead of Void |
JBCT-RET-05 |
WARNING | Avoid always-succeeding Result (return T directly) |
| Rule | Severity | Description |
|---|---|---|
JBCT-VO-01 |
WARNING | Value objects should have factory returning Result<T> |
JBCT-VO-02 |
ERROR | Don’t bypass factory with direct constructor calls |
| Rule | Severity | Description |
|---|---|---|
JBCT-EX-01 |
ERROR | No business exceptions (throw, throws, exception classes) |
JBCT-EX-02 |
ERROR | Don’t use orElseThrow() - use Result/Option |
| Rule | Severity | Description |
|---|---|---|
JBCT-NAM-01 |
WARNING | Factory methods: TypeName.typeName() |
JBCT-NAM-02 |
WARNING | Use Valid prefix, not Validated |
| Rule | Severity | Description |
|---|---|---|
JBCT-LAM-01 |
WARNING | No complex logic in lambdas (if, switch, try-catch) |
JBCT-LAM-02 |
WARNING | No braces in lambdas - extract to methods |
JBCT-LAM-03 |
WARNING | No ternary in lambdas - use filter() or extract |
JBCT-UC-01 |
WARNING | Use case factories should return lambdas, not nested records |
| Rule | Severity | Description |
|---|---|---|
JBCT-PAT-01 |
WARNING | Use functional iteration instead of raw loops |
JBCT-PAT-02 |
WARNING | No Fork-Join inside Sequencer (Result.all inside flatMap) |
JBCT-SEQ-01 |
WARNING | Chain length limit (2-5 steps) |
| Rule | Severity | Description |
|---|---|---|
JBCT-STY-01 |
WARNING | Prefer fluent failure: cause.result() not Result.failure(cause) |
JBCT-STY-02 |
WARNING | Prefer constructor references: X::new not v -> new X(v) |
JBCT-STY-03 |
WARNING | No fully qualified class names in code |
JBCT-STY-04 |
WARNING | Utility class pattern: use sealed interface with unused record |
JBCT-STY-05 |
WARNING | Prefer method references over equivalent lambdas |
JBCT-STY-06 |
WARNING | Import ordering: java → javax → pragmatica → third-party → project |
| Rule | Severity | Description |
|---|---|---|
JBCT-LOG-01 |
WARNING | No conditional logging - let log level handle filtering |
JBCT-LOG-02 |
WARNING | No logger as method parameter - component owns its logger |
| Rule | Severity | Description |
|---|---|---|
JBCT-MIX-01 |
ERROR | No I/O operations in domain packages |
| Rule | Severity | Description |
|---|---|---|
JBCT-STATIC-01 |
WARNING | Prefer static imports for Pragmatica factories |
| Rule | Severity | Description |
|---|---|---|
JBCT-UTIL-01 |
WARNING | Use Pragmatica parsing utilities (Number.parseInt, etc.) |
JBCT-UTIL-02 |
WARNING | Use Verify.Is predicates for validation |
| Rule | Severity | Description |
|---|---|---|
JBCT-NEST-01 |
WARNING | No nested monadic operations in lambdas |
| Rule | Severity | Description |
|---|---|---|
JBCT-ZONE-01 |
WARNING | Step interfaces should use Zone 2 verbs (validate, process, handle) |
JBCT-ZONE-02 |
WARNING | Leaf functions should use Zone 3 verbs (get, fetch, parse) |
JBCT-ZONE-03 |
WARNING | No zone mixing in sequencer chains |
| Rule | Severity | Description |
|---|---|---|
JBCT-ACR-01 |
WARNING | Acronyms should use PascalCase (HttpClient, not HTTPClient) |
| Rule | Severity | Description |
|---|---|---|
JBCT-SEAL-01 |
WARNING | Error interfaces extending Cause should be sealed |
| Rule | Severity | Description |
|---|---|---|
JBCT-SLICE-01 |
ERROR | External slice dependencies must use API interface |
Note: JBCT-SLICE-01 requires slicePackages configuration:
[lint] slicePackages = ["**.usecase.**"]
The JBCT formatter enforces consistent style:
Continuation aligned to receiver:
return ValidRequest.validRequest(request)
.async()
.flatMap(checkEmail::apply)
.flatMap(saveUser::apply);
Multi-line arguments aligned to opening paren:
return Result.all(Email.email(raw.email()), Password.password(raw.password()), ReferralCode.referralCode(raw.referral())) .map(ValidRequest::new);
// 1. org.pragmatica.* import org.pragmatica.lang.Result; import org.pragmatica.lang.Option; // 2. java/javax import java.util.List; // 3. Third-party import com.fasterxml.jackson.annotation.JsonProperty; // 4. Project import com.example.domain.Email; // (blank line) // 5. Static imports (same grouping order) import static org.pragmatica.lang.Result.all;
JBCT uses jbct.toml for configuration:
[format] maxLineLength = 120 indentSize = 4 alignChainedCalls = true [lint] failOnWarning = false businessPackages = ["**.usecase.**", "**.domain.**"] slicePackages = ["**.usecase.**"] # Required for JBCT-SLICE-01 [lint.rules] JBCT-RET-01 = "error" JBCT-STY-01 = "warning" JBCT-LOG-01 = "off"
./jbct.toml (project)~/.jbct/config.toml (user)| Level | Description |
|---|---|
error |
Causes non-zero exit code |
warning |
Reported but doesn’t fail (unless --fail-on-warning) |
off |
Rule disabled |
Use standard Java @SuppressWarnings annotation to suppress JBCT rules:
// Suppress single rule @SuppressWarnings("JBCT-RET-01") public void legacyMethod() { // This method won't trigger JBCT-RET-01 } // Suppress multiple rules @SuppressWarnings({"JBCT-RET-01", "JBCT-LAM-02"}) public void anotherMethod() { // Won't trigger either rule } // Suppress all JBCT rules @SuppressWarnings("all") public class LegacyAdapter { // No JBCT rules checked in this class }
Scope: Suppression applies to the annotated element and its children:
name: JBCT Check
on: [push, pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '25'
distribution: 'temurin'
- name: Install JBCT CLI
run: curl -fsSL https://raw.githubusercontent.com/siy/jbct-cli/main/install.sh | sh
- name: Run JBCT Check
run: jbct check src/main/java
If using the Maven plugin, CI is simpler:
- uses: actions/setup-java@v4
with:
java-version: '25'
distribution: 'temurin'
cache: maven
- run: mvn verify -B
With plugin bound to verify phase, mvn verify runs all checks.
If you find this useful, consider sponsoring.
Apache 2.0