Learn how to write issues that produce good code: title, description, acceptance criteria, file context, and how to scope tasks so agents succeed on the first attempt.
Write issues that reliably produce good code on the first attempt — the title, description, acceptance criteria, file context, and scope patterns that work.
┌─────────────────────────────────────────────────────┐
│ title One-line summary — imperative voice │
│ description What to build + where + constraints │
│ context Relevant files, existing patterns │
│ acceptance How to know it's done correctly │
│ scope What NOT to change │
└─────────────────────────────────────────────────────┘
All of this lives in the description field of the issue (the title alone is not enough for code tasks).
Weak — the agent will probably miss:
{
"title": "Add user profile endpoint",
"description": "Add an API endpoint for user profiles"
}
Problems: no file path, no response shape, no test requirement, no constraints.
Strong — the agent has everything it needs:
{
"title": "Add GET /api/users/:id/profile endpoint",
"description": "## Task\nAdd a new route handler in `src/routes/users.ts`.\n\n## Endpoint spec\n- Method: GET\n- Path: /api/users/:id/profile\n- Auth: require JWT (use the `requireAuth` middleware already on other routes)\n- Response: `{ id, name, email, createdAt }` from the `users` table\n- 404 if user not found\n\n## Acceptance criteria\n- [ ] Route is registered in `src/app.ts`\n- [ ] Handler is in `src/routes/users.ts` following existing patterns\n- [ ] Test added in `tests/users.test.ts` covering 200 and 404 cases\n- [ ] `npm test` passes\n\n## Do not change\n- Do not modify the users table schema\n- Do not change other existing routes"
}
Use the HTTP method + path for API tasks, or the component + action for UI tasks:
✓ Add GET /api/orders/:id/items endpoint
✓ Refactor UserCard component to use Tailwind classes
✓ Fix bug: pagination resets on filter change in ProductList
✗ Fix the bug
✗ Improve API
Always name the exact files. Agents perform better when they know where to look:
Add a new file `src/services/email.ts` that exports a `sendWelcomeEmail(userId: string)` function.
Update `src/routes/auth.ts` to call `sendWelcomeEmail` after successful registration (line ~45, after `await createUser(...)`).
This is as important as what to build:
## Do not change
- Do not modify `src/db/schema.ts`
- Do not change the existing `POST /api/auth/register` response shape
- Do not add new npm packages
Frame these as things the agent can verify:
## Acceptance criteria
- [ ] `src/services/email.ts` exists and exports `sendWelcomeEmail`
- [ ] `npm test` passes (no new failing tests)
- [ ] TypeScript compiles with no errors (`npx tsc --noEmit`)
- [ ] The function is called in `src/routes/auth.ts`
Tell the agent where to look for existing patterns to follow:
## Context
- See `src/services/sms.ts` for an example of a similar service pattern
- Auth middleware is in `src/middleware/auth.ts`
- Existing email config is in `src/config.ts` under the `email` key
| Task size | Example | Typical duration |
|---|---|---|
| XS | Fix a typo in an error message | < 1 min |
| S | Add a single endpoint with test | 2–5 min |
| M | Add a CRUD resource (4 endpoints + tests) | 5–15 min |
| L | Migrate a module to a new pattern | 15–30 min |
| XL | Add a full feature across multiple files | 30–60 min |
Start with S and M tasks. XL tasks often produce harder-to-review diffs and are more likely to miss acceptance criteria. Break them down.
Bug fix:
## Bug
Describe what is broken and how to reproduce it.
File: `src/...` Line: ~42
## Expected behaviour
What should happen.
## Fix approach
Suggested fix (or leave blank for agent to determine).
## Acceptance criteria
- [ ] The reproduction steps no longer trigger the bug
- [ ] Existing tests still pass
New feature:
## Feature
What to build.
## Files to create/modify
- Create: `src/...`
- Modify: `src/...`
## Spec
Detailed requirements, API shape, or UI behaviour.
## Acceptance criteria
- [ ] ...
- [ ] npm test passes
title or description field?