An AI pair programmer that lives inside your NetBeans editor — ask, explain, generate, and refactor code without leaving the IDE.
BeanBot is a NetBeans IDE plugin designed to provide integrated AI capabilities through the Agent Client Protocol (ACP). It offers a structured chat interface for technical assistance, including code generation, project analysis, and automated task execution.
![]() |
![]() |
![]() |
See the User Guide for setup, feature details, and usage instructions.
Supported coding harnesses: Oh My Pi, OpenCode, OpenClaw, Pi, Goose, Cursor, Claude, Hermes, Gemini, Devin — pick one during onboarding or later from the help menu.
Token and cost statistics are captured from the ACP traffic itself, not from an external process: the usage updates and per-turn token figures a harness already sends are recorded into an embedded H2 database under the NetBeans user directory (beanbot/usage-stats.mv.db), so they survive restarts and are readable without a harness running. The currency button in the toolbar opens the panel, which breaks the figures down by model and by agent; they are approximate for harnesses that report incomplete usage.
Due to time constraints, testing is primarily done on this configuration. The plugin should work on other versions/operating systems, but your experience may vary.
| Component | Details |
|---|---|
| OS | openSUSE Tumbleweed-Slowroll |
| NetBeans | RELEASE220 |
| Java | JDK 17+ |
| Oh My Pi | 18.1.21 |
| Opencode | 2.0.20 |
| Opencode plugins | @franzmoca/opencode-lombok, true-mem |
| LLMs | Big Pickle; GPT 5.4-mini, GPT 5.4-nano; GLM 5.1, GLM 5.2; DeepSeek V4 Pro, DeepSeek V4 Flash; Kimi K2.5, Kimi K2.6; Mimo V2.5; Qwen3.5, Qwen3.6; Gemma4 |
Note: Qwen models require --think=false if using Ollama, and a "reasoningEffort": "none"
configuration in opencode.json
- Clone the repository:
git clone https://github.com/anandb/nb-complete.git cd nb-complete - Build the package:
mvn package -DskipTests
- The generated NBM will be located in the
./target/nbm/directory. - Install the plugin through the NetBeans Plugin Manager.
The project follows a hexagonal (ports & adapters) architecture integrated into the NetBeans Platform:
model/: ACP-compliant data records (sessions, messages, updates, config options). Zero dependencies on upper layers.contract/: Service interfaces that define ports for session control, process management, and UI callbacks.manager/implements;ui/consumes.manager/: Core orchestration — protocol client (JSON-RPC over stdin/stdout), session state machine, process lifecycle, and SSE strategy dispatch.mcp/: MCP server integration — hosts a local server that registers the IDE tool set (editor context and navigation, filesystem, git/hg, tasks, projects, stash diff) so that the AI client can inspect open tabs and control editor navigation.project/: NetBeans lifecycle hooks (@OnStart/@OnStop), the open-project manager, and the markdown project type.tasks/: todo.txt task repository integration — bugtracking providers, issue cache, task editors.support/: Pure utilities — logging, JSON mapping, text scanning, constants, browser helpers. Zero dependencies on upper layers.ui/: All Swing components — chat window, message bubbles, streaming animation, theming, options panel, stash diff viewer. Depends oncontract/interfaces, plusmodel/data records,support/utilities, and — through theui/platform/bridge only — theproject/layer. Never importsmanager/ormcp/.
Dependencies flow downward only — no upward imports between layers:
┌─────────┐
│ ui/ │ ← presentation (highest)
└────┬────┘
│
┌────▼────┐
│manager/ │ ← business logic
└────┬────┘
│
┌────────┼────────┐
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│ model/ │ │contract│ │support/│ ← data, interfaces, utils (lowest)
└────────┘ └────────┘ └────────┘
┌──────────┐ SSE / JSON-RPC ┌───────────────────┐
│ Sidebar │ ◄──────────────────► │ AcpProtocolClient │
│ (client) │ stdin/stdout │ (transport) │
└──────────┘ └────────┬──────────┘
│
┌────▼──────┐
│ ProcessMgr│
│ (dispatch)│
└────┬──────┘
│
┌────▼──────┐
│SessionMgr │
│ (session) │
└────┬──────┘
│
┌─────────────┼─────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Strategy │ │ Lifecycle│ │ MCP │
│ Registry │ │ Handler │ │ Server │
└──────────┘ └──────────┘ └──────────┘
project/, mcp/, and tasks/ sit outside this five-layer model: project/ is NetBeans
lifecycle wiring, mcp/ is the tool-serving adapter surface, and tasks/ is a self-contained
bugtracking feature. model/, contract/, and support/ import none of them; manager/
reaches mcp/ only from ProcessManager (via McpManager/McpToolAdapter).
All source lives under src/main/java/github/anandb/netbeans/:
| Package | Files | Role |
|---|---|---|
contract/ |
26 | Service interfaces (UI callbacks, session & process control, permission & request handlers, pinned message control) |
manager/ |
25 | Core orchestration, protocol clients, session management, process lifecycle (includes strategy/, file cache, VCS ignore, the usage-stats and session store) |
mcp/ |
42 | MCP server integration (editor, filesystem, VCS, task and project tool providers, tool input records, message servlet) |
model/ |
28 | ACP-compliant data models (session, messages, updates, config options, color tokens, usage records) |
project/ |
12 | NetBeans lifecycle hooks, project manager (includes mdproject/, the markdown project type) |
support/ |
29 | Utilities (logging, JSON mapping, text scanning, constants, browser helpers, pinned message store, shortcut utils) |
tasks/ |
17 | todo.txt task repository integration (bugtracking providers, issue cache, task editors) |
ui/ |
120 | Swing components, platform integration, markdown project UI (chat, bubbles, theming, options, stash diff, file search, send-to-assistant actions) |
For a guided walkthrough mapped to the plugin's execution flow, read files in this order:
project/ACPStartup.java— NetBeans@OnStarthookproject/ACPShutdown.java—@OnStopcleanupsrc/main/resources/github/anandb/netbeans/ui/layer.xml— NetBeans registration (window menu/shortcuts, editor popup, Git toolbar); the Options panel is registered by annotation inui/ACPOptionsPanelController.java
manager/ProcessManager.java— Owns the ACP server subprocess and acts as the central request-dispatch hub; spawn itself is inmanager/ServerProcessLifecycle.startServer(), launching the harness binary the user selected (10 supported)support/BinaryResolver.java— Locates the binary on PATHmanager/AcpProtocolClient.java— JSON-RPC over stdin/stdout, SSE read loop, pending request tracking
manager/SessionManager.java— Session CRUD, state machine, SSE routingmanager/SessionStateMachine.java— Finite-state machine for session lifecyclemodel/Session.java— Session data recordmodel/SessionUpdate.java— SSE notification payload modelmodel/Message.java— Message model (prompts, tool calls, results)
contract/UIHandler.java— Callback interface for renderingmanager/strategy/StrategyRegistry.java— Sole dispatch class: type switch routesSessionUpdate→ extraction logic, eliminating the strategy interface hierarchy
ui/AssistantTopComponent.java— Main chat window (NetBeans TopComponent)ui/ComponentLifecycleHandler.java— Wires lifecycle events → managersui/SessionLifecycleHandler.java— Glue: receives SSE updates, callsStrategyRegistry.handle(), invokes UIui/ChatThreadPanel.java— Thread of message bubbles with streaming animationui/MessageBubble.java— Individual message turn (thought, tool, code segments)ui/MessageSender.java— Send/cancel logic
model/ProcessedMessage.java— The rendered output model consumed by UImcp/McpManager.java— MCP server integration layercontract/RequestHandler.java— Interface for incoming RPC requests from the server
The plugin reads the following system properties and environment variables:
| Property | System | Description |
|---|---|---|
user.dir |
System | Not used. SessionManager deliberately fails fast instead of falling back to the IDE launcher directory (createSession requires an explicit project cwd) |
user.home |
System | Default folder for Markdown Project creation (MdProjectPanelVisual) |
java.io.tmpdir |
System | Temp directory for pasted images (ImagePasteTransferHandler) |
os.name |
System | Detect Windows for binary resolution and platform-specific launching (BinaryResolver, ProcessTerminator, ACPOptionsPanel) |
beanbot.roundedPanels |
System (true) |
Toggle rounded panel corners (RoundedPanel) |
beanbot.fs.write.enabled |
System (true) |
ACP-only: gates the fs/writeTextFile / fs/write_text_file ACP tools (FsWriteSettings). MCP write tools (write_to_file, replace_lines, insert_in_file) are always confined to open projects and unaffected by this property. Set -Dbeanbot.fs.write.enabled=false to stop advertising the ACP write capability and reject every ACP write |
beanbot.color.* |
System (varies) | Override any UI color. Read by model/ColorRegistry (resolution order: system property → UIManager key → built-in light/dark fallback), not by ColorTheme, which only loads colors.json |
nb.dark.theme |
UIManager | Detect dark theme for icon resolution (IconResourceManager) |
ACP_WIRE_LOG |
Env | Path template for the ACP wire-protocol log (WireLogger). The file written is <template-without-extension>_<YYYYMMDD>-<harness>.log in the template's directory, so successive days and harnesses do not share one file |
PATH |
Env | Search path for the harness binary; all 10 supported harness names are probed (BinaryResolver) |
The color properties are declared in colors.json and cover: background, foreground, selection, accent, sunken background, bubble (user/assistant), code, table, header, thinking, tool, permission, and error colors. Most entries define both light and dark variants; the ones resolved straight from a UIManager key or a single fallback (foreground, sunkenBackground, codeBackground, codeForeground, codeSelection) do not.
BeanBot's Tasks repositories are stored as plain todo.txt files, so they are readable and editable with any standard todo.txt tool. Each task is one line; the format builds on the todo.txt spec and adds a small set of BeanBot-specific extensions.
x (B) 2026-08-02 2026-08-01 Fix the bug @urgent @bug +myproject due:2026-09-01 id:t-1a2b3c4d estimate:5 consumed:2 upd:2026-08-02T10:00:00Z
| Position / token | Meaning |
|---|---|
x (optional) |
Marks the task closed. Its absence means open (open is the implicit default — there is no status: token). |
(A)–(Z) |
Priority letter, immediately after x or as the first token when open. Native todo.txt syntax; only one letter. |
YYYY-MM-DD |
Up to two positional dates before the summary: a completion date (only when x is present) followed by the creation date. Date-only. |
| summary | Free text, preserved verbatim on save. |
@word |
A tag (e.g. @urgent). |
+word |
A project (e.g. +myproject). |
due:YYYY-MM-DD |
Due date (standard todo.txt due: extension). |
id:t-XXXXXXXX |
Stable task id. If a line has no id:, BeanBot assigns one in NetBeans format (t- + 8 hex chars), unique within the file. |
estimate:<int> |
Estimated effort in arbitrary user-inferred units. |
consumed:<int> |
Consumed effort in the same units. |
upd:<iso> |
Last-modified timestamp (full ISO-8601), preserving edit time across saves. |
- Tags and projects are stored only as
@/+tokens — there is no redundanttags:/projects:mirror, so a load→save round-trip never duplicates them. estimate/consumedare integers representing arbitrary, user-defined units (BeanBot does not assign them meaning); they are for personal tracking only.- Unknown tokens are tolerated on read: a token that is neither
@/+nor a recognisedkey:valueis absorbed back into the free-text summary, so files edited by other todo.txt tools remain readable. - Lines with no parseable content (blank lines) are skipped. A line without an
id:token is still parsed — a fresh id is generated for it.
| Problem | Solution |
|---|---|
| Plugin can't find the harness | Use the harness chooser to pick an installed harness, copy its install command, or set the path manually under Options > Assistant. Binaries found on PATH are never auto-selected — you always make the choice. |
| Assistant becomes unresponsive | Click Restart Harness in the toolbar. |
| Ctrl + L stops working | Close and reopen the assistant panel from the Window menu. If that doesn't work, restart the IDE. |
| Sidebar doesn't open after install/upgrade | The plugin auto-opens the sidebar on version change. If it doesn't appear, open it from Window > Assistant. |
| Image paste doesn't work with Wayland on Linux | Install the wl-clipboard package (Wayland) or check your clipboard manager. |
| Image paste broken after OpenCode upgrade | Upgrade to OpenCode >= 1.17.17 to resolve the breakage introduced in v1.17.13. |
| Model not appearing after an OpenCode upgrade | Re-select your model via /models. An upgrade that changes the thought_level split resets model selection. |
| Session config payloads restructured after upgrade | Upgrade to BeanBot >= 1.21.1 and OpenCode >= 1.17.17. Re-select your model and review any custom preamble or session settings. |
| Messages disappear from view | This is display-only — the session still has all messages. Click Show All Messages to keep them visible, and use Reload to re-fetch from the server. |
| LLM modified files unexpectedly | Keep your project under version control so you can revert changes you don't want. You can also set OpenCode to 'ask' before editing, and review changes with the Allow Once/Always Allow/Reject permission prompts. |
| Panel goes blank during docking or resizing | Close and reopen the docked panel from Window > Assistant. NetBeans may not repaint correctly after a drag-dock or undock operation. |
- Opencode sometimes doesn't respond when using nested agents.
- The plugin supports only one active session at a time, switching sessions or reloading the conversation while awaiting a response will cancel the current request.
- Permission requests from subagents (delegated agents) aren't always relayed by some harnesses back to the UI. If a subagent makes a tool call that requires permission, the request may hang and eventually time out because you never receive the Accept/Deny prompt. To mitigate this, instruct your primary agent to perform file modifications or commands directly rather than asking it to delegate those tasks to a subagent. The mini-assistant also shows permission prompts — check whether it is visible if the main sidebar doesn't show one.
- A few harnesses like Pi write directly to files; the pi-permission extension can gate some of those actions.
Development follows standard NetBeans Platform patterns. Contributors are expected to maintain consistency with existing styling and logging conventions. New components must be validated against both light and dark IDE themes.
This software is released under the Apache License, Version 2.0. Further details can be found in the LICENSE file.


