JBCT CLI
Command-line tools for Java Backend Coding Technology - formatting, linting, and project management.
Overview
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 |
Installation
Quick Install (Linux/macOS)
curl -fsSL https://raw.githubusercontent.com/siy/jbct-cli/main/install.sh | sh
The installer:
- Verifies Java is installed (JDK 25+ required)
- Downloads latest release from GitHub
- Installs to
~/.jbct/lib/jbct.jar - Creates wrapper script at
~/.jbct/bin/jbct - Adds
~/.jbct/binto PATH in your shell RC file
Custom install location:
JBCT_HOME=/custom/path sh install.sh
Manual Installation
Download jbct.jar from releases and run:
java -jar jbct.jar --help
Build from Source
git clone https://github.com/siy/jbct-cli.git
cd jbct-cli
mvn package -DskipTests
# JAR: jbct-cli/target/jbct.jar
Verify Installation
jbct --version
Commands
format
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)
lint
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.)
check
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 error
init
Create 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:
- JBCT-compliant
pom.xml jbct.tomlconfiguration- AI tools installed to
~/.claude/
Slice project (--slice):
@Sliceannotated interface with factory method- Implementation class
- Sample request/response records
- Unit test
update
Update 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
upgrade
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
verify-slice
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:
- Missing
pom.xmlorslice.classproperty - Missing
slice-api.properties(annotation processor not run) - Missing manifest entries
Lint Rules (37 total)
Return Kinds (5 rules)
| 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) |
Value Objects (2 rules)
| 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 |
Exceptions (2 rules)
| 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 |
Naming (2 rules)
| Rule | Severity | Description |
|---|---|---|
JBCT-NAM-01 |
WARNING | Factory methods: TypeName.typeName() |
JBCT-NAM-02 |
WARNING | Use Valid prefix, not Validated |
Lambda/Composition (4 rules)
| 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 |
Patterns (3 rules)
| 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) |
Style (6 rules)
| 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 |
Logging (2 rules)
| 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 |
Architecture (1 rule)
| Rule | Severity | Description |
|---|---|---|
JBCT-MIX-01 |
ERROR | No I/O operations in domain packages |
Static Imports (1 rule)
| Rule | Severity | Description |
|---|---|---|
JBCT-STATIC-01 |
WARNING | Prefer static imports for Pragmatica factories |
Utilities (2 rules)
| Rule | Severity | Description |
|---|---|---|
JBCT-UTIL-01 |
WARNING | Use Pragmatica parsing utilities (Number.parseInt, etc.) |
JBCT-UTIL-02 |
WARNING | Use Verify.Is predicates for validation |
Nesting (1 rule)
| Rule | Severity | Description |
|---|---|---|
JBCT-NEST-01 |
WARNING | No nested monadic operations in lambdas |
Zones (3 rules)
| 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 |
Acronyms (1 rule)
| Rule | Severity | Description |
|---|---|---|
JBCT-ACR-01 |
WARNING | Acronyms should use PascalCase (HttpClient, not HTTPClient) |
Sealed Types (1 rule)
| Rule | Severity | Description |
|---|---|---|
JBCT-SEAL-01 |
WARNING | Error interfaces extending Cause should be sealed |
Slice Architecture (1 rule)
| Rule | Severity | Description |
|---|---|---|
JBCT-SLICE-01 |
ERROR | External slice dependencies must use API interface |
Note: JBCT-SLICE-01 requires slicePackages configuration:
[lint]
slicePackages = ["**.usecase.**"]
Formatter Style
The JBCT formatter enforces consistent style:
Method Chain Alignment
Continuation aligned to receiver:
return ValidRequest.validRequest(request)
.async()
.flatMap(checkEmail::apply)
.flatMap(saveUser::apply);
Argument Alignment
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);
Import Grouping
// 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;
Other Rules
- Indentation: 4 spaces, no tabs
- Line length: 120 characters max
- Blank lines: One between methods, none after opening brace
Configuration
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"
Priority Chain
- CLI arguments (highest)
./jbct.toml(project)~/.jbct/config.toml(user)- Built-in defaults (lowest)
Rule Severity Levels
| Level | Description |
|---|---|
error |
Causes non-zero exit code |
warning |
Reported but doesn’t fail (unless --fail-on-warning) |
off |
Rule disabled |
Suppressing Rules with @SuppressWarnings
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:
- On class → suppresses for entire class (all methods)
- On method → suppresses for that method only
CI Integration
GitHub Actions
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
With Maven Plugin
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.
Requirements
- Java 25+
- Linux, macOS, or Windows (WSL)
Resources
- AI Tools - Claude Code integration
- Maven Plugin - Build integration
- JBCT Coding Guide - Complete technical reference
- GitHub Repository
Support
If you find this useful, consider sponsoring.
License
Apache 2.0