Spec-Driven Development: How to Control AI Agents Like Junie

AI agents like Junie work best with structure, not vague prompts. Learn how spec-driven development — using requirements, plans, and task lists — gives you control while keeping the agent's speed.

Spec-Driven Development: How to Control AI Agents Like Junie

TL;DR

  • AI agents work best with structure — vague prompts produce unpredictable results
  • Break work into three artifacts: requirements.md (what), plan.md (how), and tasks.md (execution checklist)
  • Execute in phases, not all at once — review after each batch of tasks
  • This approach gives you control while letting the agent handle implementation speed

The Big Picture

AI coding agents promise to accelerate development, but there's a gap between promise and practice. Hand an agent like Junie a vague instruction — "refactor this module" or "add tests" — and you'll get unpredictable output. Sometimes brilliant. Often messy. Always hard to review.

The problem isn't the agent. It's the lack of structure.

Spec-driven development solves this by forcing you to think before the agent acts. You start with clear requirements, refine them into a development plan, then break that plan into discrete tasks. The agent executes those tasks in controlled batches while you stay in the loop. No black-box rewrites. No "trust me, I fixed it" commits.

This isn't about micromanaging AI. It's about giving it the scaffolding it needs to be useful. Complex features — the kind that span multiple files, touch legacy code, or require careful sequencing — become manageable when you treat the agent as a fast implementer, not a strategic thinker.

How It Works

The workflow centers on three markdown files that live in your project. Each serves a distinct purpose.

Step 1: Write requirements.md

Start by documenting what needs to happen, not how to do it. This file is your North Star. Keep it high-level: "Add persistence for user preferences" or "Replace legacy authentication module with OAuth2." These are outcomes, not implementation details.

Why write this down? Because agents like Junie can scan your codebase and suggest improvements, but they can't read your mind about priorities. When you define the direction yourself, you set boundaries. The agent figures out how to get there within those constraints.

This file doesn't need to be formal. Bullet points work. The goal is a shared starting point that doesn't vanish after one chat session.

Step 2: Generate plan.md

Once requirements exist, ask Junie to create a development plan. Enable the "Think More" toggle — this forces deeper reasoning and better verification. You're not asking for code yet. You're asking the agent to think through the approach: what's the sequence of work? What are the dependencies? What could go wrong?

The prompt looks like this:

Read the contents of requirements.md and create a detailed development plan 
describing how to implement these requirements. 

The plan should include: 
– A short overview of the goal. 
– The main steps or phases required to achieve it. 
– Any dependencies, risks, or considerations to keep in mind. 

Do not write or modify any code yet. Save the plan as plan.md.

Junie will produce a document outlining strategy, phases, and potential risks. Sometimes it includes small code snippets to illustrate ideas. If you want pure strategy without code, say so explicitly in the prompt.

This file is a checkpoint. Review it. Tweak it. Approve it before moving forward. If the plan misses something critical, fix it now — before any code changes.

Step 3: Create tasks.md

Plans are abstract. Tasks are concrete. Ask Junie to convert plan.md into an enumerated checklist where each item represents a verifiable action. The prompt:

Read the contents of plan.md and generate a detailed, enumerated task list based on it. 

Each task should be clear, actionable, and written in a way that allows it to be marked as completed once done. 

Maintain a logical order of execution. Group the tasks logically into phases. 

Save the result as tasks.md, formatted as a numbered list with checkboxes (for example, - [ ] Implement data repository). 

Do not start implementing any tasks yet—only create the list.

The result is a markdown file with checkboxes, grouped into phases. This becomes your control panel. It's persistent, external to Junie's memory, and easy to track. You can reorder tasks, add new ones, or tell Junie to complete just the next two items and stop.

Granularity matters. "Implement new data repository" is good. "Write a function" is too small. "Refactor everything" is too big. Each task should be specific enough to mark complete, but not so granular it becomes busywork.

Step 4: Execute in phases

Now you're ready to code. The key: don't ask Junie to "do everything in tasks.md" at once. Work in bounded phases. Start with tasks 1-3. Review the changes. Run tests. Then move to the next batch.

A good execution prompt looks like this:

Proceed with the implementation steps for Phase 1 according to the tasks listed in tasks.md.  
Mark the tasks as done [x] upon completion.

This phrasing enforces boundaries. Junie completes the scoped work, updates the checklist, and stops. You review before proceeding. If a task uncovers unexpected complexity, update tasks.md to reflect new sub-tasks before continuing.

This controlled iteration keeps you in the driver's seat. The agent handles speed. You handle direction and quality control.

What This Changes For Developers

Traditional AI agent workflows feel like handing over the steering wheel. You describe a feature, the agent disappears for a while, then returns with a pile of changes. Maybe they work. Maybe they don't. Either way, you're stuck reviewing a diff that spans dozens of files with no clear narrative.

Spec-driven development flips this. You stay involved at every decision point. Requirements force you to clarify what you actually want. The plan surfaces assumptions and risks before code gets written. The task list breaks intimidating features into reviewable chunks.

This matters most for complex work. Refactoring a legacy module? Adding tests to untested code? Migrating to a new architecture? These aren't "write a function" tasks. They require sequencing, context, and judgment. Agents struggle with that unless you provide scaffolding.

The workflow also creates an audit trail. Six weeks from now, when someone asks "why did we implement it this way?", you have requirements.md and plan.md to reference. The decision-making is documented, not buried in chat history.

One more benefit: this approach works across agents. The methodology isn't Junie-specific. Junie's LLM-agnostic architecture means you can swap models without rewriting your workflow. The three-file structure — requirements, plan, tasks — translates to any agent that can read markdown and follow instructions.

Try It Yourself

JetBrains published a complete prompt that generates all three files plus updates to Junie's guidelines in one shot. Paste this into Junie's input, then add your high-level requirements where indicated:

# Spec-Driven Development Prompt 

Transform the provided high-level requirements into a complete set of project planning artifacts for spec-driven development.   

## Instructions: 

You must produce **four files** inside the `docs/` and `.junie/` directories:   

- `docs/requirements.md`   
- `docs/plan.md`   
- `docs/tasks.md`   
- `.junie/guidelines.md`   

Follow the methodology below step by step: 

--- 

### Step 1: Create `docs/requirements.md` 

- Title: **Requirements Document**   
- Introduction: Summarize the application purpose and key functionality.   
- Requirements section:   

  - Use sequential numbering (1, 2, 3, …).   
  - Each requirement must include:   
    - **User Story** in the format:   

      > As a user, I want [goal] so that [benefit/reason]   

    - **Acceptance Criteria** in the format:   

      > WHEN [condition] THEN the system SHALL [expected behavior]   

- Guidelines:   

  - Focus on user goals and benefits.   
  - Make acceptance criteria specific, testable, and precise.   
  - Cover normal flows, edge cases, error handling, persistence, and UI/UX.   
  - Group related requirements logically.   

--- 

### Step 2: Create `docs/plan.md` 

- Analyze `docs/requirements.md`.   
- Develop a **detailed implementation plan**:   
  - Link each plan item explicitly to the corresponding requirements.   
  - Assign priorities (e.g., High, Medium, Low).   
  - Group related plan items logically.   
- Ensure comprehensive coverage of all requirements.   

--- 

### Step 3: Create `docs/tasks.md` 

- Based on the implementation plan in `docs/plan.md`, produce a **detailed enumerated technical task list**:   

  - Each task must have a placeholder `[ ]` to mark completion.   
  - Link each task both to:   
    - the development plan item in `docs/plan.md`   
    - the related requirement(s) in `docs/requirements.md`   
- Group tasks into **development phases**.   
- Organize phases logically (e.g., Setup → Core Features → Advanced Features → Testing & QA).   

--- 

### Step 4: Update `.junie/guidelines.md` 

- Add **concise technical instructions** on how to work with the `docs/tasks.md` checklist.   
- Instructions should include:   
  - Mark tasks as `[x]` when completed.   
  - Keep phases intact but add new tasks if needed.   
  - Ensure every new or modified task stays linked to a requirement and plan item.   
  - Keep formatting consistent with the existing style.   

--- 

## Input: 

[INSERT YOUR HIGH-LEVEL REQUIREMENTS FOR THE APPLICATION YOU WANT TO CREATE]   

## Output: 

1. `docs/requirements.md` – structured requirements document   
2. `docs/plan.md` – implementation plan with priorities and links   
3. `docs/tasks.md` – detailed enumerated task list grouped into phases   
4. `.junie/guidelines.md` – updated concise instructions for working with the task list

This prompt generates the full scaffolding in one pass. From there, execute tasks in phases using the workflow described above.

The Bottom Line

Use this if you're building complex features where sequencing and context matter — refactors, migrations, test coverage for legacy code. Skip it if you're prototyping or writing one-off scripts where speed trumps structure.

The real risk isn't that AI agents are too powerful. It's that they're powerful without guardrails. Spec-driven development gives you those guardrails. You define the destination. The agent handles the drive. You review at every checkpoint. That's how you ship ambitious features without losing control of the codebase.

If you're already using Junie, try this workflow on your next non-trivial task. If you're evaluating agents, this methodology works across tools — it's a pattern, not a product feature. The three-file structure scales from solo projects to team workflows. Start small. One feature. Three files. Controlled execution. See if it changes how you think about working with AI.

Source: Junie