This document defines high-value Claude Code skills for the Source Code Portal codebase. These skills automate common development tasks and accelerate feature development.
Last Updated: 2026-01-27 Status: Skills defined, ready for implementation
Skills are specialized capabilities that Claude Code can perform. Each skill below represents a common task that would normally take hours or days but can be automated to take minutes.
Skills are organized into three categories:
- Migration Skills - Spring Boot migration and modernization
- Integration Skills - Adding new external service integrations
- Configuration Skills - Managing repository groups and settings
Purpose: Incrementally migrate components from Undertow to Spring Boot
Status: ✅ Knowledge complete (7/8 tasks done in Phase 2)
What it does:
- Analyzes the component to migrate (controller, service, configuration)
- Determines the appropriate Spring Boot pattern
- Creates Spring Boot equivalent with annotations
- Maintains dual-mode compatibility (Undertow + Spring Boot coexist)
- Adds @Profile("!test") for proper test isolation
- Compiles and verifies the migration
- Documents the changes
Example Usage:
/migrate-to-spring-boot GroupController
What gets created:
- Spring MVC controller with @RestController or @Controller
- Dependency injection with constructor injection
- Request mapping annotations (@GetMapping, @PostMapping)
- Automatic JSON serialization with ResponseEntity
- Model attributes for Thymeleaf templates
- Error handling with @ExceptionHandler
Time Saved: 2-4 hours per controller → 5-10 minutes
Knowledge Source: Tasks 1-7 in PHASE2_PROGRESS.md, TASK5_SUMMARY.md
Purpose: Convert a specific Undertow controller to Spring MVC
Status: ✅ Implemented (2026-01-27)
What it does:
- Reads the existing Undertow controller
- Identifies handler methods and routing
- Creates Spring MVC equivalent:
- @RestController for REST endpoints (automatic JSON)
- @Controller for web pages (Thymeleaf)
- @RequestMapping for routing
- @GetMapping/@PostMapping/@PutMapping/@DeleteMapping
- @RequestParam/@PathVariable for parameters
- ResponseEntity for REST responses
- Model for Thymeleaf attributes
- Handles CORS, error handling, validation
- Maintains dual-mode operation
- Reduces code by 70-80%
Example Usage:
/migrate-controller src/main/java/no/cantara/docsite/controller/GroupController.java
Before (Undertow - 180 lines):
public class GroupController implements HttpHandler {
@Override
public void handleRequest(HttpServerExchange exchange) {
String groupId = exchange.getQueryParameters().get("groupId").getFirst();
JsonObjectBuilder builder = Json.createObjectBuilder();
builder.add("group", groupId);
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/json");
exchange.getResponseSender().send(builder.build().toString());
}
}After (Spring MVC - 40 lines):
@RestController
@RequestMapping("/group")
public class GroupRestController {
@GetMapping("/{groupId}")
public ResponseEntity<Map<String, Object>> getGroup(@PathVariable String groupId) {
Map<String, Object> response = new HashMap<>();
response.put("group", groupId);
return ResponseEntity.ok(response);
}
}Time Saved: 1-3 hours per controller → 5 minutes
Knowledge Source: TASK5_SUMMARY.md, PingRestController.java, HealthRestController.java, DashboardWebController.java
Purpose: Create custom Spring Boot Actuator health indicator
Status: ✅ Implemented (2026-01-27)
What it does:
- Prompts for health indicator name and purpose
- Prompts for health check logic (service to monitor)
- Creates HealthIndicator implementation:
- Component annotation with name
- @Profile("!test") exclusion
- Health check logic
- Status determination (UP/DOWN/DEGRADED)
- Detailed health information
- Error handling with try-catch
- Adds logging
- Compiles and verifies
- Documents the endpoint
Example Usage:
/add-health-indicator jenkins
What gets created:
@Component("jenkins")
@Profile("!test")
public class JenkinsHealthIndicator implements HealthIndicator {
private static final Logger LOG = LoggerFactory.getLogger(JenkinsHealthIndicator.class);
@Override
public Health health() {
try {
// Check Jenkins connectivity
boolean jenkinsUp = checkJenkinsAPI();
if (!jenkinsUp) {
return Health.down()
.withDetail("error", "Jenkins API unreachable")
.build();
}
return Health.up()
.withDetail("jenkinsUrl", jenkinsUrl)
.withDetail("lastSeen", lastSeenTimestamp)
.build();
} catch (Exception e) {
LOG.error("Jenkins health check failed", e);
return Health.down()
.withDetail("error", e.getMessage())
.build();
}
}
}Endpoint Created: /actuator/health/jenkins
Time Saved: 1-2 hours → 5 minutes
Knowledge Source: TASK7_SUMMARY.md, GitHubHealthIndicator.java, CacheHealthIndicator.java, ExecutorHealthIndicator.java
Purpose: Create Spring @Scheduled task to replace custom executor tasks
Status: ✅ Implemented (2026-01-27)
What it does:
- Prompts for task name and purpose
- Prompts for schedule (fixed rate, fixed delay, or cron)
- Prompts for initial delay
- Creates @Service with @Scheduled method:
- @ConditionalOnProperty for feature flag
- @Scheduled annotation with configuration properties
- Dependency injection of required services
- Error handling and logging
- Metrics/health tracking
- Adds configuration properties to application.yml
- Compiles and verifies
- Documents in /actuator/scheduledtasks
Example Usage:
/add-scheduled-task fetch-releases
What gets created:
@Service
@ConditionalOnProperty(name = "scp.scheduled.enabled", havingValue = "true")
@Profile("!test")
public class FetchReleasesScheduledService {
private static final Logger LOG = LoggerFactory.getLogger(FetchReleasesScheduledService.class);
@Scheduled(
fixedRateString = "${scp.scheduled.releases.interval-minutes}",
timeUnit = TimeUnit.MINUTES,
initialDelayString = "${scp.scheduled.releases.initial-delay-minutes:2}"
)
public void fetchReleases() {
LOG.info("Fetching GitHub releases");
try {
// Fetch and cache releases
HealthResource.instance().markScheduledWorkerLastSeen("releases");
} catch (Exception e) {
LOG.error("Failed to fetch releases", e);
}
}
}Configuration added to application.yml:
scp:
scheduled:
releases:
interval-minutes: 60
initial-delay-minutes: 2Time Saved: 1-2 hours → 5 minutes
Knowledge Source: TASK6_SUMMARY.md, JenkinsStatusScheduledService.java, SnykStatusScheduledService.java
Purpose: Set up Spring Cache abstraction with Caffeine for a new cache
Status: 🆕 New skill based on Task 4 learnings
What it does:
- Prompts for cache name and purpose
- Prompts for cache key structure
- Prompts for TTL and max size
- Adds cache name to CacheConfiguration
- Creates @Cacheable service methods
- Creates cache key class if needed
- Adds Micrometer metrics binding
- Compiles and verifies
- Documents cache endpoints
Example Usage:
/configure-spring-cache pullRequests
What gets modified/created:
CacheConfiguration.java (adds cache name):
@Bean
public CaffeineCacheManager cacheManager() {
cacheManager.setCacheNames(
"repositories", "commits", "contents",
"pullRequests" // NEW
);
}PullRequestService.java (new service):
@Service
public class PullRequestService {
@Cacheable(value = "pullRequests", key = "#org + ':' + #repo")
public List<PullRequest> getPullRequests(String org, String repo) {
// Fetch from GitHub API
}
@CacheEvict(value = "pullRequests", key = "#org + ':' + #repo")
public void invalidatePullRequests(String org, String repo) {
// Clear cache
}
}Metrics exposed:
/actuator/metrics/cache.size?tag=cache:pullRequests/actuator/metrics/cache.gets?tag=cache:pullRequests
Time Saved: 1-2 hours → 10 minutes
Knowledge Source: TASK4_SUMMARY.md, CacheConfiguration.java, CacheMetricsConfiguration.java
Purpose: Add new type-safe configuration properties
Status: 🆕 New skill based on Task 3 learnings
What it does:
- Prompts for configuration section name
- Prompts for properties (name, type, default value)
- Adds nested static class to ApplicationProperties.java
- Adds configuration to application.yml
- Adds ConfigurationBridge mapping (for legacy compatibility)
- Validates configuration loads correctly
- Compiles and verifies
Example Usage:
/add-spring-config gitlab
What gets created:
ApplicationProperties.java:
@Configuration
@ConfigurationProperties(prefix = "scp")
public class ApplicationProperties {
private GitLab gitlab = new GitLab();
public static class GitLab {
private String baseUrl = "https://gitlab.com";
private String accessToken;
private int apiVersion = 4;
// Getters and setters
}
}application.yml:
scp:
gitlab:
base-url: ${SCP_GITLAB_BASE_URL:https://gitlab.com}
access-token: ${SCP_GITLAB_ACCESS_TOKEN:}
api-version: 4ConfigurationBridge.java (legacy compatibility):
public String evaluateToString(String key) {
return switch (key) {
case "gitlab.base.url" -> properties.getGitlab().getBaseUrl();
case "gitlab.access.token" -> properties.getGitlab().getAccessToken();
// ...
};
}Time Saved: 30-60 minutes → 5 minutes
Knowledge Source: TASK3_SUMMARY.md, ApplicationProperties.java, ConfigurationBridge.java
Purpose: Safely update an outdated dependency
Status: 📋 Planned (from original skill list)
What it does:
- Identifies dependency in pom.xml
- Searches for changelog/migration guide (GitHub releases, website)
- Analyzes breaking changes
- Updates version in pom.xml
- Scans codebase for affected usage patterns
- Suggests code changes if breaking changes detected
- Compiles and runs affected tests
- Creates commit with migration notes
Example Usage:
/modernize-dependency slf4j
What it does:
- Finds
org.slf4j:slf4j-apiin pom.xml (currently 1.8.0-beta4) - Fetches latest stable version (2.0.9)
- Reads migration guide from SLF4J website
- Identifies breaking changes (none for this upgrade)
- Updates pom.xml
- Compiles project
- Runs tests
- Creates commit: "chore: upgrade SLF4J 1.8.0-beta4 → 2.0.9 (stable)"
Time Saved: 2-4 hours → 10-15 minutes
Value: Critical for updating dependencies safely without breaking the application
Purpose: Add new external service integration (GitLab, CircleCI, SonarQube, etc.)
Status: 📋 Planned (from original skill list)
What it does:
- Prompts for service type:
- SCM provider (GitHub, GitLab, Bitbucket)
- CI/CD service (Jenkins, CircleCI, Travis, GitHub Actions)
- Security service (Snyk, SonarQube, Veracode)
- Badge service (Shields.io, custom)
- Prompts for service details (base URL, API version, auth method)
- Creates integration components:
- Command class extending BaseHystrixCommand (or Resilience4j)
- Domain models with JSON-B annotations
- Fetch task classes
- Cache configuration
- Scheduled fetch service (@Scheduled)
- Health indicator
- Configuration properties
- Link URL generator
- Tests with mock responses
- Updates repository configuration structure
- Compiles and verifies
- Documents the integration
Example Usage:
/add-integration gitlab
What gets created (8-10 files):
- GitLabCommand.java - HTTP client for GitLab API
- GitLabRepository.java - Domain model
- GitLabCommit.java - Domain model
- FetchGitLabRepositories.java - Fetch task
- GitLabScheduledService.java - @Scheduled service
- GitLabHealthIndicator.java - Health check
- ApplicationProperties.GitLab - Configuration
- GitLabLinkBuilder.java - URL generator
- GitLabIntegrationTest.java - Tests
- Updates to config.json schema
Time Saved: 4-6 weeks → 30-60 minutes
Value: Dramatically accelerates adding new service integrations
Purpose: Add webhook support for new SCM provider
Status: 📋 Planned (from original skill list)
What it does:
- Prompts for provider name (GitLab, Bitbucket, etc.)
- Prompts for supported events (push, pull request, release)
- Creates webhook handler components:
- WebhookHandler interface (if not exists)
- Provider-specific webhook handler implementation
- Signature verification (HMAC, JWT, etc.)
- Event payload parsing
- Event-to-task mapping (update cache, trigger fetch)
- Controller endpoint (@PostMapping)
- Tests with sample payloads
- Updates webhook routing configuration
- Adds signature validation configuration
- Compiles and verifies
- Documents webhook setup instructions
Example Usage:
/add-webhook-handler gitlab
What gets created:
GitLabWebhookHandler.java:
@Component
public class GitLabWebhookHandler implements WebhookHandler {
@Override
public String getProvider() {
return "gitlab";
}
@Override
public boolean verifySignature(String payload, String signature, String secret) {
// GitLab signature verification (X-Gitlab-Token)
}
@Override
public void handleEvent(String eventType, String payload) {
switch (eventType) {
case "Push Hook" -> handlePush(payload);
case "Merge Request Hook" -> handleMergeRequest(payload);
case "Release Hook" -> handleRelease(payload);
}
}
}GitLabWebhookController.java:
@RestController
@RequestMapping("/gitlab/webhook")
public class GitLabWebhookController {
@PostMapping
public ResponseEntity<Void> handleWebhook(
@RequestHeader("X-Gitlab-Event") String event,
@RequestHeader("X-Gitlab-Token") String token,
@RequestBody String payload
) {
if (!webhookHandler.verifySignature(payload, token, secret)) {
return ResponseEntity.status(403).build();
}
webhookHandler.handleEvent(event, payload);
return ResponseEntity.ok().build();
}
}Documentation created: GITLAB_WEBHOOK_SETUP.md
Time Saved: 1-2 weeks → 20-30 minutes
Value: Enables multi-provider webhook support for real-time updates
Purpose: Add new repository group configuration
Status: 📋 Planned (from original skill list)
What it does:
- Prompts for group ID (e.g., "whydah", "stingray")
- Prompts for display name (e.g., "Whydah IAM Platform")
- Prompts for description
- Prompts for repository patterns (regex, e.g., "Whydah*", "ConfigService*")
- Prompts for default group repo
- Prompts for external service configurations:
- Jenkins prefix/suffix patterns
- Snyk organization/project patterns
- Custom badge configurations
- Validates regex patterns (compiles them)
- Updates config.json with proper JSON formatting
- Optionally triggers immediate prefetch for new group
- Validates configuration loads correctly
Example Usage:
/add-repository-group stingray
What gets updated:
config.json:
{
"groups": [
{
"groupId": "stingray",
"display-name": "Stingray Monitoring",
"description": "Monitoring and observability tools",
"defaultGroupRepo": "Stingray-Dashboard",
"artifactId": ["Stingray*"],
"jenkins": {
"prefix": "Stingray-"
},
"snyk": {
"organization": "cantara",
"projectPrefix": "stingray-"
}
}
]
}Validation performed:
- Regex patterns compile successfully
- Group ID is unique
- Default group repo exists (optional check)
- JSON is valid
Time Saved: 15-30 minutes → 2-3 minutes
Value: Makes configuration changes trivial, no JSON syntax errors
Based on immediate value and Phase 2 completion:
- ✅
/migrate-controller- Convert Undertow controllers to Spring MVC (Implemented 2026-01-27) - ✅
/add-health-indicator- Create custom health indicators (Implemented 2026-01-27) - ✅
/add-scheduled-task- Create @Scheduled tasks (Implemented 2026-01-27)
/add-repository-group- Frequent configuration changes/configure-spring-cache- New caches for PR, issues, etc./modernize-dependency- Many outdated dependencies
/add-spring-config- New configuration sections as needed/add-integration- Future multi-provider support/add-webhook-handler- Multi-provider webhooks/migrate-to-spring-boot- General migration orchestrator
Each skill should:
- Prompt for required information - Use AskUserQuestion for user input
- Validate inputs - Check patterns compile, files exist, etc.
- Generate code - Create or modify files with proper formatting
- Compile and verify - Run mvn compile to ensure it works
- Create tests - Generate appropriate test cases
- Document - Add comments, README updates
- Report results - Show what was created and where
- Use kebab-case:
/add-health-indicator - Start with verb:
/add-,/migrate-,/configure- - Be specific: Not
/add-component, but/add-health-indicator
Before marking a skill "implemented":
- Test with real use case from codebase
- Verify compilation succeeds
- Verify tests pass
- Verify documentation is clear
- Verify time savings vs manual approach
| Skill | Knowledge Source Files |
|---|---|
/migrate-to-spring-boot |
PHASE2_PROGRESS.md, all TASK*_SUMMARY.md files |
/migrate-controller |
TASK5_SUMMARY.md, PingRestController.java, HealthRestController.java, DashboardWebController.java |
/add-health-indicator |
TASK7_SUMMARY.md, GitHubHealthIndicator.java, CacheHealthIndicator.java, ExecutorHealthIndicator.java |
/add-scheduled-task |
TASK6_SUMMARY.md, JenkinsStatusScheduledService.java, SnykStatusScheduledService.java |
/configure-spring-cache |
TASK4_SUMMARY.md, CacheConfiguration.java, CacheMetricsConfiguration.java |
/add-spring-config |
TASK3_SUMMARY.md, ApplicationProperties.java, ConfigurationBridge.java |
/add-integration |
commands/.java, fetch/.java, domain/jenkins/.java, domain/snyk/.java |
/add-webhook-handler |
controller/GithubWebhookController.java |
/add-repository-group |
domain/config/*.java, config.json |
- ✅ Complete Task 8 (Remove Undertow, finalize Spring Boot) - DONE
- ✅ Implement Tier 1 skills (
/migrate-controller,/add-health-indicator,/add-scheduled-task) - DONE - Test skills with real migration scenarios (as needs arise)
- ✅ Document skill usage in CLAUDE.md - DONE
- Implement Tier 2 skills as needs arise
- Gather feedback on skill effectiveness
Status: ✅ Tier 1 skills implemented and ready to use Last Updated: 2026-01-27 Next Action: Use skills for future development, implement Tier 2 skills as needed