Plan, Code, Ship: Building My Claude Code + Neovim Workflow
I had my Cursor workflows set up and working well in both environments. At Seis, our head of architect had configured all the rules and complex patterns - a really solid setup that embraced best practices from the beginning. I also had my personal environment where I'd set up my own workflow. Both were working pretty good.
Then Claude Code was released. I started testing it and immediately noticed the agent was way better than Cursor. With Cursor, we needed to set up a lot of rules to make the agent not do things we didn't want, and it wasn't easy to get the agent to stop writing code that didn't follow the patterns we already had in our codebase. Claude Code just... got it. It understood our existing patterns and practices without all that configuration overhead.
What was not only the agent that was effective and efficient, but also the UX of using just the agent - just interacting with the agent, without any other components on the screen, without the folder tree, without terminal, without code even. It was just me and the agent interacting. It was so clean, so smooth.
But I quickly realized something: I still needed to check the code that the agent generates, and I realized I needed a less noisy environment. I wanted that clean terminal interface for the AI interaction, but I also wanted to seamlessly switch to files when needed - just not in the same way Cursor provides.
That was the perfect excuse to switch back to Neovim. I love Neovim. I love the fluency of vim motions, how everything flows when you're really in the zone.
So I started using Claude Code inside a Neovim terminal buffer. It was okay, but the interaction wasn't fluid enough. The integration felt clunky.
That's when I decided to build my own plugin.
I wanted Claude Code to run as a terminal buffer but actually integrate with Neovim properly. And while I was at it, I added my own vibe-coding workflow: a software engineer agent, a product analyst agent, and a code reviewer agent. I also kept some commands for plan, code, and ship.
Let me show you how this all works in practice.
A Typical Development Session
Let me walk you through how this actually works. Say I need to build a new feature - maybe a user authentication system for a side project.
I'm in Neovim working on my codebase. When I need Claude Code, I press <leader>cc
and my plugin toggles open a vertical split with Claude Code running as a terminal buffer. Everything stays integrated - no leaving my Neovim environment.
If I want to send Claude some existing code for context, I visually select it and press <leader>cs
. The selected code goes directly to Claude without me having to copy-paste or switch windows.
The real magic happens when Claude suggests changes to files. I can quickly navigate to those files in my main window, make edits, then jump back to the Claude buffer with normal vim motions. When I need project context, the plugin can send my entire project structure to Claude automatically.
Sessions save automatically, so if I need to stop working and come back tomorrow, I press <leader>cn
to start a new session or just <leader>cc
to continue where I left off.
The plugin handles all the window management - I can configure it as a floating window, horizontal split, new tab, whatever works for my current setup. I often use it alongside nvim-tree for a complete IDE layout.
Custom Agents and Commands in Action
Within this integrated environment, I've built my own set of agents. I have three specialized agents that handle different phases of development:
When I start a new feature, I typically begin with my Product Analyst agent:
Let's use the product analyst agent to gather requirements for a user authentication system
The Product Analyst focuses purely on requirements - no technical bias, just clear user stories and edge cases. It outputs a clean PRD with requirements written as BDD specs and a plan of slices of the feature that I can actually ship incrementally.
You can check the prompt for the agent in the code, but the main focus of this agent is to help me gather requirements and ask the annoying questions to find edge cases and have a good description of every scenario.
The BDD approach came from my manager, who told me about an interview where Ken Beck talked about how agents are like genies. You need to be super explicit with your wishes or something bad could happen. And Ken Beck found that expressing requirements as BDD specs was a good way to work with these "genies."
The output of this interaction - the requirements expressed as BDD specs, slices, and all that context - gets saved into a .ai
folder in markdown format. This file will be used by the Software Engineer agent in the next step.
I want to make a point here about why I save these files. I watched a video that basically said the prompts we write are kind of the new code. Think about it: the code we write gets compiled and transpiled into files that the machine can execute. The code is what defines what we want to do, and we can generate the software multiple times from it because the code is the source of truth.
Prompts are now like the new code. The prompt is what creates the code that will then create the software. But we're treating prompts like some volatile, throwaway stuff. That's wrong. The prompt is becoming the new source code because it defines what we want and generates everything downstream.
That's why I save the files generated by the Product Analyst agent - they're not just outputs, they're the new source code for my features.
Once I have my requirements, I switch to my Software Engineer agent:
Use the software engineer agent to implement the first slice from this PRD
The Software Engineer agent is smart about context. First, it checks if there's already a feature specification in the .ai
folder. If there isn't one, and I didn't provide a file in the initial prompt, it starts asking questions to build the specification of what it needs to write.
But here's what I love about this workflow - the Software Engineer agent doesn't just start coding. It reads the requirements, presents a design approach first, and we iterate on that. "I think we should use JWT tokens here." "What about refresh token rotation?" This design discussion happens before any code gets written.
When we agree on the approach, the agent follows a strict TDD process: writes the test first, makes it fail, writes the code, refactors, and reviews it. This happens in a loop until all the tasks that need to be implemented are done.
I've also enforced that the agent should only write the code we actually need and be verbose and expressive in the code. I don't want obfuscated code from the agent. Basically, because I still think I'll need to fix bugs or change stuff if something happens in production. So the code still needs to be human-friendly.
Before I ship anything, I bring in my Code Reviewer agent:
Use the code reviewer agent to review this implementation
The Code Reviewer agent is basically my "don't fuck up too much" safety net. Look, I'll be honest - sometimes I get lazy checking all the code the Software Engineer agent produces. That's human nature. So I built this agent to catch improvements we can make, things we should clean up, potential issues I might miss.
It catches things like potential security issues, edge cases, code quality concerns, performance improvements, or just general cleanup that would make the code better. It's like having a senior developer do a final review before the code goes out.
And to finalize this flow, I have a command - maybe the only command that doesn't need to be deprecated later - the ship command. I ask an agent to commit, create a good commit message, create a PR, and push to origin. And in the case of this plugin repository, it also releases a new version of it.
In that way, I feel like the entire circle is closed. And it's all about that. It's about shipping things. Ship a lot. Ship often. And this command is what makes that last piece possible.
I also have my original plan
, code
, and ship
commands that work alongside these agents. Right now they coexist, but I'll probably deprecate the commands in favor of the more specialized agents - except for ship, which completes the entire workflow.
The plugin includes a claude install agents
command that installs these agents at either personal or project level, depending on what I need.
Wrapping Up
This is my workflow using AI at the moment. It's probably not the best approach, and it's probably something that works differently for you than what I've described in this post.
But for me, I've found a good balance between using AI assistance and staying in command of my development starship. I get to use a UI that's less visually demanding than Cursor, but it also allows me to stay in control. And I enjoy it more.
Because at the end of the day, enjoying the tools you're using is one of the main ways to enjoy your profession. And to feel that your time is well spent.
The plugin is open source at https://github.com/carlos-rodrigo/claude-code.nvim if you want to try it or adapt it for your own workflow.
How are you handling AI integration in your development setup? I'd love to hear what's working for you.
Follow me for more thoughts on AI-assisted development and building better workflows.