Inspiration
Java tooling inside Neovim is powerful, but build-workspace tasks still interrupt the editing flow. Creating projects, inspecting dependency drift, changing versions, and managing Maven modules often means leaving Neovim or editing build files manually.
I wanted the cargo new plus cargo add feeling for JVM work without leaving Neovim. That became duke.nvim, but the goal is not to recreate an IDE. It is to give Neovim a focused project and build-model layer beside tools such as nvim-jdtls.
What it does
duke.nvim is a pure Lua plugin for Neovim 0.11 and newer.
It can:
- Create Maven, Gradle, and Spring Boot projects through guided workflows
- Discover Maven and Gradle workspaces without running builds
- Refresh resolved build information explicitly
- Show dependency drift, ownership, and dependency paths
- Build exact, reviewable Maven multi-file upgrade plans
- Apply upgrades with stale-buffer and conflict protection
- Add, upgrade, inspect, and remove Maven dependencies
- Safely create Maven reactor modules
- Navigate Spring configuration files and generated Java sources
Its Project Center separates fast local inspection from explicit build-backed refreshes. Dependency upgrades are session-scoped plans, so users can inspect every affected file before applying changes.
How we built it
I designed the product direction, Java workflow, safety rules, and scope. I used GPT-5.6 through Codex CLI as an engineering collaborator for architecture, implementation, test construction, edge-case investigation, documentation, and release verification.
Codex helped trace behavior across Lua modules, propose safer transaction boundaries, write Plenary tests, run live Maven and Gradle projects, and keep README and vimdoc synchronized. I kept asking whether each feature made Java workspace work safer or merely made the plugin bigger. I reviewed the real workflows, rejected weak assumptions and unnecessary scope, and controlled every release action.
Challenges we ran into
The hardest problem was not generating files. It was changing existing workspaces without corrupting user state.
Build files may be modified in unsaved Neovim buffers. Network requests and pickers may finish after the file changes. Maven values may come from parents, properties, or effective models. Gradle may require a newer runner JVM while still targeting Java 8.
This led to several core rules: re-read files before mutation, distinguish raw ownership from effective values, separate target Java from runner Java, stage generated projects privately, and make every multi-file change explicit and reviewable.
Accomplishments that we're proud of
duke.nvim grew from a project scaffold into a safe Java workspace tool while staying pure Lua and independent of any required UI framework, JDTLS manager, JDK vendor, or plugin ecosystem.
I am especially proud of the Project Center's local-first workspace model and the session-scoped Maven upgrade plans. They make complex build information visible before any file changes, then produce an exact receipt after applying a plan.
What we learned
I learned that useful developer tooling needs more than successful commands. It needs honest models, bounded scope, observable plans, and recovery behavior users can trust.
I also learned to treat the Java target and the JVM running a build as separate choices. That distinction lets Gradle run on a modern JDK while a generated project still targets Java 8 or 11.
What's next for duke.nvim
Next I want to harden the complete Maven, Gradle, Spring, module, dependency, and JDTLS handoff journeys against more real projects. I also want to deepen reactor-wide dependency analysis and raw-versus-effective ownership reporting. Gradle dependency editing will remain read-only until I can prove a mutation model with the same safety guarantees as Maven.
Log in or sign up for Devpost to join the conversation.