Estimate Effort with your coding agent

Your agent already knows your code. These instructions teach it to estimate how much work a Linear issue is, and to hand the number to Ranked. Your code stays with your agent; Ranked never sees it.

  1. 1

    Open your agent in your repository

    Claude Code, Devin, Cursor, Codex or any agent that can read your code and use Linear (for Claude Code: turn on the Linear connector).

  2. 2

    Give it the instructions

    Copy the instructions below into your agent, or save them in your repository and tell it to follow the file. Then say which issues, or a project.

  3. 3

    Check the dry run

    It first shows a table: Effort, risk and the main changes per issue. Nothing is written until you say yes.

  4. 4

    Let it write

    Teams with Linear estimates: it sets the estimate, and Ranked updates the score. Teams without: it comments @Ranked e3 with its reasoning, and Ranked saves the Effort.

What it estimates, and what it doesn't

Code tells how big a change is, so the agent estimates Effort and notes technical risk. Reach, Impact and Confidence are about your users and evidence, so they stay with your team. Effort on its own is fine: the issue shows as incomplete until someone adds the rest.

Not sure your agent is good at it? The instructions include a backtest: it estimates issues you already finished, using the code from before the work, and compares with what the work turned out to be.

The instructions

# Estimate Effort for Linear issues from the codebase

A prompt for your own coding agent (Claude Code, Devin, Cursor, Codex…) that
has your repository and a Linear connection. It estimates the **Effort** of
Linear issues by reading the code, so Ranked can score them with RICE.

What it does **not** do: set Reach, Impact or Confidence. Those are about
users and evidence, not code. The agent can only add a technical-risk note.

---

## How to use

1. Open your agent in the repository the issues are about.
2. Make sure it can read Linear (for Claude Code: the Linear connector or MCP server).
3. Paste: `Follow agents/estimate-effort.md` (or paste this file) and say which
   issues, a project, or "the backtest" (below).
4. It always starts in **dry run**: a table, nothing written. You decide.

## Rules for the agent

- Read each issue fully: title, description, comments, linked issues, images if you can.
- Find the code it touches: search for the screens, functions, data and APIs the
  issue mentions. Open the files. Don't guess from names alone.
- Check what already exists before pricing it in: related fixes or features may already
  be in the code (the issue text can be older than the code). Estimate only what's left.
- For each issue, write down:
  - **Changes**: the files or modules that will change or be added, and roughly how much.
  - **Effort**: one number in the team's unit (ask if unknown; default *ideal person-days*:
    focused work by one person who knows the codebase, including tests and review).
    Use these anchors: 0.5 = a copy or config tweak, or a new entry point to something that
    already exists; 1 = one small, well-understood change; 3 = a feature across a few files;
    5 = several parts (UI + backend + data); 8+ = split it.
    If the team builds with AI coding help, small changes go faster: prefer 0.5 over 1 for
    them. Ask the team, or calibrate with a backtest first.
  - **Technical risk**: low / medium / high, with the one thing most likely to blow up the
    estimate (unknown API, data migration, platform limits, no tests).
  - **Confidence in the estimate**: one sentence. Don't call it RICE Confidence.
- Never change an existing human estimate unless asked. Mention when you disagree.
- Keep it short: 3–5 lines of reasoning per issue.

## Output: dry run (always first)

A table: issue · title · Effort · risk · main changes. Then the reasoning per issue.
Ask before writing anything to Linear.

## Writing to Linear (only after the user says yes)

- **Team uses Linear estimates**: set the issue's estimate to the nearest allowed value
  (Fibonacci 1, 2, 3, 5, 8…; T-shirt XS–XXL; etc.). Ranked recalculates the score
  automatically. Add one comment with the reasoning, starting "Effort estimate (agent):".
- **Team doesn't use estimates** (Ranked shows a typed Effort): comment on the issue
  with the command on the first line and the reasoning below it:

  ```
  @Ranked e3
  Effort estimate (agent): 3 ideal person-days. Changes: … Risk: medium, …
  ```

  Ranked reads only the line with `@Ranked`. A ✅ means it was saved. Effort alone is
  accepted even before Reach, Impact and Confidence are set; the issue shows as
  Incomplete until a person adds them.

## Backtest (to check how good the estimates are)

For finished issues the code already contains the solution, so the estimate must be
made on the code **from before the work**, without seeing what the work was.

**Don't use Linear's `startedAt` / `completedAt` as the cutoff.** Teams often move
issues to "In progress" and "Done" after the work, so those dates can come after the
solution was written.

### 1. Find each cutoff without reading history

For each issue ID, run exactly this; it prints only commit hashes, no messages:

```
git log --reverse --format=%H -i --grep="<ISSUE-ID>" | head -1
```

- The cutoff is the **parent** of that commit: `<hash>^`.
- If nothing is found, use the last commit before the issue's `createdAt`:
  `git rev-list -1 --before="<createdAt>" HEAD`, and mark the issue "cutoff by date".

**Never** run `git log`, `git show`, `git diff` or `git blame` that prints messages or
changes at or after a cutoff, and don't open the issue's branch or PR, until every
estimate is written down (step 3).

### 2. Keep the estimator blind

Whoever collects the issues must not read anything that describes the solution:
- From Linear, take only the title, the description, and comments created **before** the
  cutoff commit's date. Later comments (wrap-ups, "done, here's what changed") leak the answer.
- If you've already seen a solution (a comment, a commit message, a PR), don't estimate
  yourself: hand each issue to a **fresh sub-agent** with only the allowed text and the
  cutoff worktree, and say so in the result.
- Linear shows only the current description. If it may have been edited after the work
  started, note it as a possible leak.

### 3. Estimate each issue at its cutoff

```
git worktree add ../estimate-tmp <cutoff>
```

Estimate using only that worktree and the allowed issue text (step 2). The worktree may
already contain work from issues committed just before: check what's already there, as in
the rules above. Then remove the worktree:
`git worktree remove ../estimate-tmp`.

### 4. Write all estimates down first

Output the table of estimates (issue · Effort · risk · main changes) **before** looking at
any actual work.

### 5. Only then measure the actual size

For each issue, measure the commits that mention its ID:

```
git log -i --grep="<ISSUE-ID>" --shortstat --format="%h"
```

Use files changed and lines added + removed as the actual size, **leaving out translation /
locale files, lockfiles and generated code** (they inflate small changes: one string in 5
languages is 5 files). For example:

```
git log -i --grep="<ISSUE-ID>" --numstat --format="" -- . ':!**/locales/**' ':!**/i18n/**' ':!package-lock.json'
```

(adjust the excluded paths to the repo). Linear's dates aren't reliable (step 1), and
AI-assisted work makes hours misleading anyway. Lines are a stand-in for effort; they miss
design iteration, tuning and device testing, so say so.

### 6. Compare

Output one table: issue · estimated Effort · files changed · lines changed · estimate
rank · actual rank. Then:

- how many issues are in the same order, and the biggest misses with a one-line reason;
- whether anything leaked (e.g. a cutoff by date), so the result is honest.

Write nothing to Linear in a backtest. Save the result as a Markdown file in the repo (e.g.
`docs/effort-backtest-<date>.md`) if the team wants a record.

Don't have Ranked in Linear yet? See how it works.