My experience using Junie for the past few months

Junie is one of the best coding agent I've been trying out so far. Very well integrated with IntelliJ, great for Kotlin, and the test first focus makes it quite good at coming out with good results. However, I do miss the capability to only accept part of a solution and it can be very slowwwwww.

My experience using Junie for the past few months
The Junie logo and tagline

I've been a big fan of all things JetBrains for a long time. The company itself, for many reasons but also their high quality products (and languages, but you know that about me already 😝). As a fan, I've jumped on the occasion to be using Junie (JetBrains coding agent) as soon as it came out. This post summarises my experience, in no particular order of features.

NOTE: The examples below are a compilation created over a long period of time. They are illustrations of the issues I've met but aren't meant to be exact examples.

Quick intro

Junie is JetBrains equivalent of Copilot (or Windsurf / Cursor together with the IDE). It is only available inside the IntelliJ based IDEs (Rider, Pycharm, .... included) and is available through an additional "AI" monthly paid fee (10$/month at the time of writing). They have a limited free plan too.

You can install Junie from the Marketplace. Once installed it appears as a window in your IDE

The Junie window inside IntelliJ

Junie has 2 modes at the moment :

  • Code : You ask Junie something, it will most likely write code / create / edit files in your project.
  • Ask : In case you don't want changes, but rather ask a question or chat with the AI, you can switch to Ask mode. Handy if you want to weight choices in your project, or ask about potential issues / optimisations.

I'm very glad they added this mode actually, I tend to use the AI a lot to help me with reasoning and it is very frustrating to have half a dozen files changes only when asking of a refactoring makes sense.

You can also activate the "brave mode" option, which will allow the AI to run commands in your terminal without your explicit permission every time. I was a little worried at the beginning but so far nothing crazy has happened. I'll report the first time Junie decides to $ rm -rf /, that'll sure be fun and I can only blame myself then.

The many AI products, naming and differentiations

I'm a little confused between the different types of AI products IntelliJ is offering at the moment, which are most relevant to me, but also what are their differentiations. I just found out writing this blog that they have a dedicated page for this actually.

To me, it's still really not clear what the difference between Junie and the AI assistant is. It looks like Junie is the AI assistant, but with more bells and whistles? Except Junie is not customisable (models, prompt library, ...), while the assistant is? Then there's also Mellum, the JetBrains LLM. It feels like I have to learn a whole lot of new product names with little differentiation and it's a bit more than I want to have to remember.

The pricing page with features also basically tells you you get everything as part of the subscription anyways, which is good news! (unless you're enterprise, then you're screwed). Oh, and one thing to mention : pretty cool to see a flat price for the agent, when most of the competition mentions token limit pricing instead!

The features table of the JetBrains AI products package

I understand the market is moving very fast and is honestly quite a mess at the moment, but I'd appreciate a "use me if, don't use me if" part that's a bit clearer.

Junie is VERY eager to solve my issues

I like to use my coding agent as if I had a junior pair programmer with me. I usually don't ask it for a complete project / solution, but rather first look at a list of things we need to achieve for a particular outcome, before diving into each piece of it separately. That way seems to be an optimal way to speed up delivery, while keeping an actual control over quality and overall architecture.

In my experience so far, Junie tends to REALLY want to be doing a lot of work and I sometimes have a hard time telling it to only do one thing.

I may ask it to create a single test, and I'll have a complete test class created, the implementation will be refactored and it will also go on and upgrade some of my dependencies while it's at it.

It can be frustrating, because it's not what I asked for, and it will take me time to refuse part of the solution... Here is a concrete example where I ask Junie to create a test for a single class method.

Asking to test a method, only to have my implementation changed and refactored

By the way, this was my method at the time 😅. Yup, it was basically empty.

And this is the summary of what Junie did by the end of its quest. Not only did it create a test, it also decided to create the actual implementation of the method. As I'd tell my junior if they were not an AI : very industrious, but not what I asked for buddy....

I refused Junie's solution, and asked it again. This time being more precise about what I DIDN'T want (modifying the implementation):

This time, the results were as expected. But it took me 2 tries, and my sentence in my request actually was longer.

EDIT : The awesome Marit Van Dijk mentioned the allowlist on Bluesky, which I didn't know about!

Junie can get some basic stuff wrong

This was a bit surprising to me. I've seen Junie get imports wrong for AssertJ for example. To the extent that the code wouldn't compile. (Also, I would have liked it to ask me to add AssertJ as a dependency instead of just decide to start using it 😅). It's quickly and easily fixed, since it will try to build by itself, fail and iterate. But still, I wonder where that comes from.

For smaller libraries, I've also seen Junie struggle to use basic objects. In the below example, it wants to use reflection and complex shenanigans where a simple instantiation just works out of the box. The actual implementation uses val feature = RichtextFacetMention() . It also tries to access fields using getDeclaredField() where accessors are perfectly fine facet.features = mutableListOf(feature).

Junie getting lost with basic POJOs

I'm not exactly sure why this is happening and I honestly also haven't dived very deep into it. I wonder if that isn't because kbsky is both multiplatform as well as Java compatible and there is some confusing generation happening to get that compatibility.

To fix this, I've had to write some of the code myself so the agent can learn from it. It's become pretty good at it now, but it also means that I don't trust the agent with the code as much as I'd like to 😊.

Trust, but verify

Related, but tangential : It happens very often that Junie does some extra things for me that are completely unrelated to the task at hand. It can be changing some formatting, or updating a version, or changing a Gradle option. The changes aren't bad per se, but this also means that I have to be very careful about checking the output of the task when Junie is done. Those changes also can be in places that aren't really suitable for tests, making them harder to spot in any other way than a thorough code review.

Here is an example where Junie decided that checking for null fields wasn't enough. The fields also shouldn't be empty. This isn't a bad change per se, however it wasn't really done at the right moment. At least, it does inform me at the end of the task though so that's that. Not quite welcome if it had slipped, but also not terrible. I'm on the edge on this one, I like the changes but it also makes me feel I can't quite trust the agent. What if those changes had large impact on my clients?

Junie decides that null isn't enough. Fields also shouldn't be empty.
Junie informs me of the change

Junie can be opiniated about the names / locations of my files

I've had a few times where Junie would take my file, take its content and decide to place it somewhere else. It's also explicit about it, telling me my file is now deprecated. Even though the agent may be correct overall (maybe my naming isn't great. Maybe the file should be in another place), I don't quite like that it makes tracking history more difficult in the future. It also makes reviewing the changes harder. As usual, I'd rather have this done in a separate step, not at the same time as functional changes.

Funnily enough, this can even happen mid task, where Junie moves the file around, finds a solution to the problem and moves everything back. I'd love to know more about the reasoning behind this ^^.

Clearly Junie didn't like the name of my file 😊

I really miss the option to refuse part of the solution

At the moment, what I miss THE MOST, BY FAR about Junie compared to other similar agent is the option to accept / refuse part of a solution. When Junie thinks it's done, it will tell you. You can then decide to accept, refuse or tell it to try again.

Junie waiting for a decision

Now, I may be 90% OK with the solution, but want to remove the gradle options that it also added at the same time. I've had a time where it added tests, and also a Jitpack configuration. I mean, thank you, but no?

Cursor is more fine grained in that regard, and will let you individually accept / refuse changes :

Accept / Reject feature in cursor (Screenshot courtosy of datacamp)

When I asked about this on the discord, the official answer was to use the commit window of IntelliJ to do this. This is a valid, but subpar answer imho. It also makes it more difficult for me to check whether the refused changes are breaking the complete task in any way. I have to switch to manual mode for this. There must be a way to do better.

Ask mode responses are great!

The scratch files as an output to the ask mode are great. When you chat with Junie in ask mode, the output is a Markdown file that is placed in your scratches folder. I really like this for several reasons :

  • The output is structured and readable
  • It is easily shareable
  • I can reuse this as input for later tasks.

I haven't tried this yet, but I also think that makes it for a very good start of keeping a log of decisions if they were placed somewhere together with my source code.

A structured answer to a question I asked Junie

Junie is extremely slow in my experience compared to other tools I've used

This is my main gripe with Junie at the moment honestly. Even for simple-ish requests (think, write a simple method to filter a data class ), Junie will take between 3 and 4 minutes to complete. I haven't benchmarked this, but it felt much longer than most other coding agents I've tried.

This is understandable, given how it works. It will first make a plan, verify its plan across many files of the project, create the implementation, make sure the code builds, write tests for the method, run those tests. It usually will discover a couple bugs that way, reiterate and keep looping until it finally succeeds. This is pretty much how I, mere human, would also do it. (This is while using Brave mode by the way).

My issue with this is that during that whole time, I am not actually actively involved in the process. I will be needed soon to verify the implementation because I'm not actually pair programming and seeing the code being written live I cannot be in a "copilot seat". The pilot actually closes the door of the cockpit and reopens it when it thinks it's ready.

My issues with this is that it really disrupts my flow. During that time, I cannot quite start doing something else to keep the context fresh in my head. I also do not want to start checking email / slack because I want to keep in the flow. I haven't found a good way yet to use that time in a way that isn't disrupting. It has made me actually decide to not use Junie for many things several times.

Now that compiling Kotlin is fast again in IntelliJ I wait for Junie instead 😄

When spending 4/5 hours in the IDE, this spinning wheel really started grinding my gears after a while 🫤.

Random 401s when leaving the IDE open too long

Not sure whether others experience this too, but Junie regularly lost contact with its servers and the only way to fix this was to restart IntelliJ completely. I never close my IDE, and rarely restart my computer and after a few days Junie tends to just give me an unknown error that won't go away even when reloading the plugin. Not a huge issue, CMD+Q CMD-Space are only a couple keystrokes but still, it's a mild annoyance.

Random errors at time, forcing me to restart the IDE.

The need for structured Junie guidelines?

There are many prompt libraries out there. I asked on the Junie discord where people were sharing their Junie guidelines. To my surprise, that doesn't really seem to be a thing today, and everyone mentioned they either didn't use any or they were too project specific. However, the first thing that the Junie guide mentions is to create those guidelines.

This makes me wonder whether there is a need for a Junie guidelines library, or at least a place where people can share how they use this file. Because at the moment I feel like I'm underutilising the tool and I could pick up great ideas from others.

In summary, some personal tips :

  • Use a guidelines file to personalize Junie as you want it.
  • Chat about large pieces of work with Junie, and then ask it to do the work piece by piece for better implementation results.
  • Don't ask Junie to just "upgrade" your project because it will be late on versions. Instead, check first and be specific about what you want.
  • Don't hesitate to switch between ask and code modes consciously, for best results.
  • If you find a way to stay actively in the flow while Junie is doing its thing, please let me know.
  • I really hope Junie becomes faster over time, because during long coding days it's sometimes a make or break situation for me, and I'm likely to start using another agent in the future simply because of this.