7.2 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
qctl is a multi-module Maven CLI tool for the QRun platform. It provides commands for project scaffolding (qqq), package management (qbit), deployment (qrun), and AI-assisted planning (qstudio).
Build Commands
# Full build with tests
mvn clean verify
# Fast compile (skip tests)
mvn compile -DskipTests
# Checkstyle only
mvn checkstyle:check
# Spotless check/apply
mvn spotless:check
mvn spotless:apply
# Native build (requires GraalVM 21 and -Pnative profile)
JAVA_HOME=/Library/Java/JavaVirtualMachines/graalvm-21.jdk/Contents/Home mvn clean package -DskipTests -Pnative
# Output: qctl-cli/target/qctl
# Test version flag
./qctl-cli/target/qctl --version
Module Structure
qctl/
├── qctl-shared # DTOs, ExitCodes, SPI interfaces, utilities
├── qctl-core # Config, HTTP client, auth, cache, logging, Main entrypoint
├── qctl-qqq # Template scaffolding (init, list) with Velocity
├── qctl-qbit # Package management commands, lockfile handling
├── qctl-qrun # OCI packaging and deployment commands
├── qctl-qstudio # AI planning commands (offline V1)
├── qctl-cli # Aggregator for native image build (has native profile)
├── qctl-integration-tests # E2E and integration tests with fixture templates
├── docs/ # Architecture and design documentation
├── packaging/ # Distribution manifests (Homebrew, Scoop, AUR, Docker)
└── codestyle/ # Checkstyle config and license headers
Architecture
Plugin System: Commands discovered via ServiceLoader<CommandPlugin>. Each module implements CommandPlugin and registers via META-INF/services.
CLI Framework: Picocli with annotation-based commands. Main entrypoint in qctl-core/Main.java.
Template System: Templates fetched from QRun-IO/templates-hub. Apache Velocity for rendering with StringTool helpers ($str.kebab(), $str.pascal(), $str.replace()). Supports computed variables and transforms. Path variables use __VARNAME__ or $VARNAME syntax.
Interactive Commands: All console I/O goes through ConsoleUI class (qctl-qqq/template/ConsoleUI.java). This separates UI from logic.
Version Info: VersionProvider reads from version.properties (Maven-filtered). Shows version, build timestamp, and git commit hash. Uses ${revision} property for CI-friendly versioning.
Native Image: GraalVM 21 with reflection config. Native build is in a Maven profile (-Pnative) in qctl-cli/pom.xml.
Code Style
- 3-space indentation (Checkstyle enforced)
- Braces on new line (
LeftCurly: nl) - Javadoc required on all methods (flowerbox style)
- No star imports
- Import order: javax, java, third-party, static (alphabetical)
Flowerbox Javadoc:
/***************************************************************************
* Brief description.
*
* @param foo description
* @return description
* @since 0.1.0
***************************************************************************/
Key Patterns
Exit Codes (qctl-shared/ExitCodes.java):
- 0=success, 1=generic, 2=usage, 3=network, 4=auth, 5=not found, 6=validation, 7=integrity, 8=conflict, 9=cancelled
Config Paths:
- macOS:
~/Library/Application Support/qctl/qctl.yaml - Linux:
$XDG_CONFIG_HOME/qctl/qctl.yaml - Windows:
%APPDATA%\qctl\qctl.yaml
CI/CD Pipeline
Workflow: .github/workflows/build.yml
Trigger: Push to main/develop, tags v*, PRs
Jobs:
test- Runmvn clean verifybuild-native- Build native images for 5 platforms (only on push, not PRs)release- Create GitHub release with artifacts (only on tags)docker- Build/push multi-arch Docker image to GHCRupdate-homebrew- Push toQRun-IO/homebrew-qctltapupdate-scoop- Create PR for Scoop manifest updateupdate-aur- Create PR for AUR PKGBUILD update
Build Matrix:
| Platform | Runner | Artifact |
|---|---|---|
| Linux x64 | ubuntu-latest | qctl-linux-amd64 |
| Linux ARM64 | ubuntu-24.04-arm | qctl-linux-arm64 |
| macOS Intel | macos-15 | qctl-macos-amd64 |
| macOS ARM | macos-14 | qctl-macos-arm64 |
| Windows x64 | windows-latest | qctl-windows-amd64.exe |
Required Secrets:
HOMEBREW_TAP_TOKEN- PAT with repo scope for homebrew tap
Release Process:
git tag -a v0.0.3 -m "Release v0.0.3"
git push origin v0.0.3
Distribution
| Channel | Location | Update Method |
|---|---|---|
| Homebrew | QRun-IO/homebrew-qctl |
Direct push |
| Scoop | packaging/scoop/qctl.json |
PR to develop |
| AUR | packaging/aur/PKGBUILD |
PR to develop |
| Docker | ghcr.io/qrun-io/qctl |
Direct push |
| GitHub | Releases | Auto-created |
Install:
# Homebrew
brew tap QRun-IO/qctl && brew install qctl
# Docker
docker run ghcr.io/qrun-io/qctl --help
Native Image Notes
- Native profile is in
qctl-cli/pom.xml(activated with-Pnative) - Velocity requires runtime initialization for template parsing
- Jackson records need reflection config in
META-INF/native-image/reflect-config.json - Resources config in
META-INF/native-image/resource-config.json
Testing
Frameworks: JUnit 5 + AssertJ + Mockito
Run Tests:
mvn test # Unit tests only
mvn verify # Unit + integration tests
mvn test -pl qctl-integration-tests # E2E tests only
Test Modules:
- Unit tests in each module's
src/test/java/ - Integration tests in
qctl-integration-tests/
E2E Test Infrastructure (qctl-integration-tests/):
CommandTestHarness- In-process command execution with stdout/stderr captureTestTemplateRegistry- Fixture-based template registry for offline testingTestableConsoleUI- Simulated user input for interactive promptsExitCodeAssertions- Fluent assertions for exit codes
Test Fixtures (src/test/resources/fixtures/templates/):
| Fixture | Purpose |
|---|---|
test-minimal |
Basic template with no prompts |
test-with-prompts |
Template with interactive prompts |
test-full-substitution |
Tests variable replacement in content |
test-computed-vars |
Tests computed variables (packagePath) |
test-transforms |
Tests delete transforms |
test-variable-typo |
Tests "Did you mean?" suggestions |
Path Variable Syntax:
- Use
__VARNAME__in directory names (converted to$VARNAMEat runtime) - Avoids shell/Maven interpretation of
$characters - Example:
template/src/main/java/__packagePath__/App.java
Session Continuity
To continue from last session, see docs/internal/session-state.md for current progress and next steps.
Knowledge base
Reviewed dossier for this repo (commit c7cf55a99e51, branch develop, 2026-07-04):
R:/Git.Local/KofTwentyTwo/second-brain/knowledge/qqq/repos/qctl.md
QQQ platform hub (cross-repo map, v4.0 impact tracking, licensing follow-ups):
R:/Git.Local/KofTwentyTwo/second-brain/knowledge/qqq/qqq-hub.md