← all posts
// workflow · junie

.junie/guidelines.md: teaching Junie your house rules

The first time you run Junie on a real project, it guesses. It guesses your test command, guesses your naming conventions, guesses whether the generated client under src/generated is fair game for editing. Some guesses land. The ones that don't cost you a rejected diff and ten minutes of cleanup. Per task, forever, until you write the rules down.

Writing them down is what .junie/guidelines.md is for: a markdown file in your repo that Junie reads before it works. It's JetBrains' member of a genre you already know (CLAUDE.md, AGENTS.md, GEMINI.md), and the genre's rules transfer almost completely. If you've read writing agent context files, treat this as the Junie-specific appendix.

What earns a line

My test for every line in the file: would a capable new hire need this to land an acceptable first PR, and would they struggle to infer it from the code in five minutes? Both yes: it goes in. Otherwise it stays out.

  • Exact commands. How to build, run all tests, run one test. An agent that knows the command doesn't burn half its run rediscovering it.
  • Conventions with teeth. The rules that actually come up in code review: error-handling patterns, module boundaries, test naming, "services never import from the web layer".
  • Do-not-touch zones. Generated code, vendored directories, migration history, the legacy package with its own laws. Agents edit whatever they can see; say what's off the table.
  • Definition of done. Tests pass, linter clean, public API changes come with docs. Junie treats this as exit criteria instead of inventing its own.

In practice that's shorter than it sounds. A useful guidelines file often looks like this:

Build: ./gradlew build
Run one test: ./gradlew test --tests OrderServiceTest
Style: no wildcard imports; DTOs are Kotlin data classes
Never edit build/ or src/generated/ — regenerate instead
Every endpoint change ships with a test in api-tests/
Done = ./gradlew check passes with zero new warnings

What to leave out

  • Anything a tool already enforces. If the formatter or linter fixes it automatically, prose about it is wasted context.
  • Aspirational architecture. The file describes the codebase you have, not the one you wish you had. Agents follow instructions literally and will happily "fix" reality to match your dreams.
  • Volatile details. Ticket numbers, sprint goals, this week's feature flags. Stale instructions are a trap, because the agent follows them with full confidence.
  • Secrets. It's a committed file. Treat it like one.

Short beats complete

Every line is loaded on every task, so the guidelines file spends from the same context budget your actual code needs. And instruction-following degrades as the file bloats. Long files don't get followed better; they get skimmed, by models as by humans. My working limit is one to two screens. The same discipline shows up on the Claude side: CLAUDE.md in practice lands on nearly identical rules, which tells you this is about how agents read, not about any one vendor.

Every convention you don't write down, the agent rediscovers by guessing wrong in a diff you then have to reject.

Version it, evolve it

The file lives inside the repo, and that's the feature, not an implementation detail. It travels with branches, gets reviewed in PRs, and diverges per project, exactly what house rules should do. The maintenance loop is simple: every time Junie repeats a mistake, treat it as a bug report against the file and fix the file, not just the diff. After a month of that, guidelines.md becomes the shortest honest onboarding doc your repo has. New humans read it too.

One calibration warning: guidelines steer, they don't enforce. Junie can still misweigh a rule twenty minutes into a long run, and no sentence in a markdown file reliably stops an agent from touching something it believes needs touching. Anything that must never happen deserves a harder mechanism: CI checks, protected paths, or the approval flow I cover in Junie's leash. Write the file on day one, keep it under two screens, and prune it the way you prune flaky tests: ruthlessly, with the diff history to prove each line earned its place.

#junie#context#workflow