Skip to main content

Plugin Integration API

DevoxxGenie exposes a lightweight runtime API that other IntelliJ plugins can use to interact with it. This page documents how to detect DevoxxGenie, send prompts programmatically, and create backlog task files that are picked up by the Spec-Driven Development workflow.


Detecting DevoxxGenie at Runtime

Before calling any DevoxxGenie API, verify the plugin is installed and enabled using PluginManagerCore:

import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.extensions.PluginId;

public class DevoxxGenieDetector {
private static final String PLUGIN_ID = "com.devoxx.genie";

public static boolean isAvailable() {
var plugin = PluginManagerCore.getPlugin(PluginId.getId(PLUGIN_ID));
return plugin != null && plugin.isEnabled();
}
}

Always guard integration code with this check so your plugin degrades gracefully when DevoxxGenie is not present.


Sending a Prompt via Reflection

DevoxxGenie exposes ExternalPromptService for receiving prompt text from other plugins. Access it via reflection to avoid a hard compile-time dependency:

import com.intellij.openapi.project.Project;

public class DevoxxGeniePromptSender {

public static void sendPrompt(Project project, String promptText) {
if (!DevoxxGenieDetector.isAvailable()) return;

try {
Class<?> serviceClass = Class.forName(
"com.devoxx.genie.service.ExternalPromptService"
);
Object instance = serviceClass
.getMethod("getInstance", Project.class)
.invoke(null, project);

serviceClass
.getMethod("setPromptText", String.class)
.invoke(instance, promptText);

} catch (Exception e) {
// DevoxxGenie not available or API changed — fail silently
}
}
}

setPromptText(String) populates the DevoxxGenie prompt input field and submits it, triggering a full LLM query with the current conversation context.


Creating Backlog Tasks via Java API

DevoxxGenie exposes ExternalTaskService as a programmatic API for creating backlog tasks. Access it via reflection — no compile-time dependency required:

import com.intellij.openapi.project.Project;
import java.util.List;

public class DevoxxGenieTaskCreator {

public static String createTask(Project project, String title, String description,
String priority, List<String> labels) {
if (!DevoxxGenieDetector.isAvailable()) return null;

try {
Class<?> serviceClass = Class.forName(
"com.devoxx.genie.service.ExternalTaskService"
);
Object instance = serviceClass
.getMethod("getInstance", Project.class)
.invoke(null, project);

return (String) serviceClass
.getMethod("createBacklogTask",
String.class, String.class, String.class, List.class)
.invoke(instance, title, description, priority, labels);

} catch (Exception e) {
// DevoxxGenie not available or API changed — fail silently
return null;
}
}
}

createBacklogTask initialises the backlog directory structure if it does not yet exist, allocates the next available task ID, creates the task file, and returns the ID (e.g. "TASK-5").

Parameters

ParameterTypeDescription
titleStringShort human-readable task title
descriptionStringFull markdown description of the task
priorityString"low", "medium", or "high"
labelsList<String>Free-form tags (e.g. ["bug", "sonarlint"])

When to use this vs direct file writing

Use ExternalTaskService when you need a simple, reliable path with automatic ID management. Use direct file writing when you need richer metadata fields such as source, rule, file, or line that are not exposed by this API.


Creating Backlog Task Files

For integrations that need richer metadata fields (source, rule, file, line, etc.), you can write structured task files directly. These are automatically recognised by the Spec-Driven Development workflow. Files are written to backlog/tasks/ inside the project root.

File Format

Each task is a Markdown file with YAML frontmatter:

---
id: TASK-42
title: Fix NullPointerException in UserService.getUser()
status: todo
priority: high
created: 2026-02-18
source: sonarlint
rule: java:S2259
file: src/main/java/com/example/UserService.java
line: 87
---

## Description

SonarQube rule **java:S2259** (Null pointers should not be dereferenced) was triggered at
`UserService.java:87`. The return value of `userRepository.findById(id)` is not checked for
`null` before being dereferenced.

## Acceptance Criteria

- [ ] Add a null-check or use `Optional` for the return value of `findById`
- [ ] Ensure no `NullPointerException` can occur in the affected code path
- [ ] All existing tests pass after the fix

Frontmatter Fields

FieldRequiredDescription
idYesUnique task identifier (e.g. TASK-42)
titleYesShort human-readable task title
statusYestodo, in-progress, or done
priorityNolow, medium, high, or critical
createdNoISO 8601 date
sourceNoOriginating tool (e.g. sonarlint, spotbugs)
ruleNoTool-specific rule ID
fileNoSource file path relative to project root
lineNoLine number of the finding

Task ID Synchronisation

To avoid ID collisions, scan existing task files before assigning a new ID.

DevoxxGenie stores tasks in three locations:

LocationContent
backlog/tasks/Active tasks
backlog/completed/Completed tasks
backlog/archive/tasks/Archived tasks

Algorithm:

import java.io.*;
import java.nio.file.*;
import java.util.regex.*;

public class TaskIdAllocator {
private static final Pattern ID_PATTERN = Pattern.compile("^id:\\s*TASK-(\\d+)", Pattern.MULTILINE);

public static int nextTaskId(Path projectRoot) throws IOException {
int max = 0;
for (String dir : new String[]{"backlog/tasks", "backlog/completed", "backlog/archive/tasks"}) {
Path folder = projectRoot.resolve(dir);
if (!Files.isDirectory(folder)) continue;
try (var stream = Files.walk(folder, 1)) {
for (Path p : (Iterable<Path>) stream.filter(f -> f.toString().endsWith(".md"))::iterator) {
String content = Files.readString(p);
var matcher = ID_PATTERN.matcher(content);
if (matcher.find()) {
max = Math.max(max, Integer.parseInt(matcher.group(1)));
}
}
}
}
return max + 1;
}
}

Task Filename Convention

Name task files using this pattern to keep them sortable and identifiable:

TASK-{n}-{tool}-{rule}-{file}-l{line}.md

Examples:

TASK-42-sonarlint-java_S2259-UserService-l87.md
TASK-43-spotbugs-NP_NULL_ON_SOME_PATH-OrderProcessor-l124.md

Rules:

  • Replace special characters (:, /, .) with _ or -
  • Keep the filename under ~100 characters
  • The numeric prefix TASK-{n} ensures natural sort order matches creation order

Real-World Integrations

PluginFeaturesSource
SonarLint DevoxxGenieAI fix + backlog task creationGitHub
SpotBugs DevoxxGenieAI fix (prompt-only)GitHub