Prompt & Done · LOWEFFORT pack

Same prompt, five Claude effort settings: all five passed the same ten checks.

Effort is the setting that decides how hard Claude thinks before and while it works. Low is the cheapest and fastest, max spends without limits. We gave Claude Opus 5.5 one kanban-board prompt at each level, once, and scored every result with ten checks the model never saw. This is the exact prompt, the checks and what we measured on 22 Oct 2026.

1 The prompt (identical for every level)

Make an empty folder, start Claude Code in it, and send:

Build a kanban board as one self-contained file called index.html (plain HTML, CSS and JavaScript; no libraries, no network). It must meet every requirement below, and it should look like a polished product.

1. Three columns titled To Do, Doing and Done. Give the column containers data-testid="col-todo", "col-doing" and "col-done".
2. Each column has a text input (data-testid="input-todo", "input-doing", "input-done"). Pressing Enter adds a card with that text to the column, clears the input, and ignores empty or whitespace-only text. Every card has data-testid="card".
3. Cards can be dragged with the mouse from one column to another (HTML5 drag and drop).
4. Each card has a delete button with data-testid="delete".
5. Double-clicking a card's text lets you edit it; Enter saves the change.
6. Each column header shows a card-count badge: data-testid="count-todo", "count-doing", "count-done".
7. A search box (data-testid="search") hides cards that do not match what you type, as you type.
8. The board is saved to localStorage and is restored after a reload.
9. Doing has a work-in-progress limit of 3: when Doing already holds 3 cards, adding or dropping a fourth is refused, and the Doing column container gets the CSS class "full" while it holds 3.
10. A theme toggle button (data-testid="theme") switches light and dark mode by adding or removing the class "dark" on <body>, and the choice survives a reload.

Write only index.html in the current directory, then stop.

Then open index.html in a browser.

2 How to set the effort level

# in a session
/effort low

# or when you start Claude Code
claude --effort low

Valid levels on Opus 5.5: low, medium, high, xhigh, max. Medium is the default on Opus 5.5 (Claude Code model config, effort docs).

3 What we measured

Claude Code 2.1.308, model claude-opus-5-5, one headless run per level in an empty folder with no plugins, hooks or MCP servers. Cost is what Claude Code reported for the run (API-equivalent list price; our runs used a subscription). Checks: ten Playwright checks, one per requirement, never shown to the model.

EffortTimeAPI-equivalent costOutput tokensHidden checks
Low0:31$0.173,94710 / 10
Medium (default)1:12$0.279,20110 / 10
High1:26$0.3210,93810 / 10
Extra high (xhigh)14:34$3.0199,10610 / 10
Max40:51$7.01263,79910 / 10

The higher levels built more polish (responsive layout, animations, keyboard shortcuts, a progress bar) and tested their own file before finishing. On these ten checks that did not raise the score.

4 The ten hidden checks

One per requirement in the prompt: three columns; Enter adds a card and ignores empty text; drag between columns; delete; double-click to edit; count badges; search filters; localStorage restore after reload; work-in-progress limit of 3 on Doing (typed and dropped); a dark-mode toggle that persists. Run them yourself against any index.html:

pip install playwright && playwright install chromium
python check.py path/to/folder   # prints JSON with passed / total
check.py (the full test)
"""Hidden acceptance test for the kanban prompt. usage: check.py <dir> -> prints JSON {passed, total, results, shot}"""
import sys, json, pathlib
from playwright.sync_api import sync_playwright
d = pathlib.Path(sys.argv[1]).resolve()
html = d / "index.html"
res = {}
def check(name):
    def deco(fn):
        def run(*a, **k):
            try:
                res[name] = bool(fn(*a, **k))
            except Exception as e:
                res[name] = False
        return run
    return deco
if not html.exists():
    print(json.dumps({"passed": 0, "total": 10, "results": {}, "error": "no index.html"})); sys.exit()
with sync_playwright() as p:
    b = p.chromium.launch()
    ctx = b.new_context(viewport={"width": 1280, "height": 800})
    pg = ctx.new_page()
    errs = []
    pg.on("pageerror", lambda e: errs.append(str(e)))
    url = "file://" + str(html)
    pg.goto(url)
    T = lambda t: pg.locator(f'[data-testid="{t}"]')
    def add(col, text):
        T("input-" + col).fill(text); T("input-" + col).press("Enter")
    @check("1 three columns")
    def c1():
        return all(T(c).count() == 1 for c in ("col-todo", "col-doing", "col-done"))
    c1()
    @check("2 enter adds, empty ignored")
    def c2():
        add("todo", "Alpha"); add("todo", "   "); add("todo", "Beta")
        return T("col-todo").locator('[data-testid="card"]').count() == 2 and T("input-todo").input_value() == "" and "Alpha" in T("col-todo").inner_text()
    c2()
    @check("3 drag between columns")
    def c3():
        card = T("col-todo").locator('[data-testid="card"]').first
        card.drag_to(T("col-done"))
        return T("col-done").locator('[data-testid="card"]').count() == 1 and T("col-todo").locator('[data-testid="card"]').count() == 1
    c3()
    @check("6 count badges")
    def c6():
        return T("count-todo").inner_text().strip() == "1" and T("count-done").inner_text().strip() == "1" and T("count-doing").inner_text().strip() == "0"
    c6()
    @check("5 double-click edit")
    def c5():
        card = T("col-todo").locator('[data-testid="card"]').first
        card.get_by_text("Beta").dblclick()
        pg.keyboard.press("ControlOrMeta+A"); pg.keyboard.type("Gamma"); pg.keyboard.press("Enter")
        return "Gamma" in T("col-todo").inner_text() and "Beta" not in T("col-todo").inner_text()
    c5()
    @check("7 search filters")
    def c7():
        T("search").fill("Gamma")
        vis = [pg.locator('[data-testid="card"]').nth(i).is_visible() for i in range(pg.locator('[data-testid="card"]').count())]
        ok = vis.count(True) == 1
        T("search").fill("")
        vis2 = [pg.locator('[data-testid="card"]').nth(i).is_visible() for i in range(pg.locator('[data-testid="card"]').count())]
        return ok and all(vis2)
    c7()
    @check("9 WIP limit of 3")
    def c9():
        for t in ("d1", "d2", "d3"): add("doing", t)
        full = "full" in (T("col-doing").get_attribute("class") or "").split()
        add("doing", "d4")
        n = T("col-doing").locator('[data-testid="card"]').count()
        # dropping a 4th is refused as well
        T("col-todo").locator('[data-testid="card"]').first.drag_to(T("col-doing"))
        n2 = T("col-doing").locator('[data-testid="card"]').count()
        return full and n == 3 and n2 == 3
    c9()
    @check("10 theme toggle")
    def c10a():
        T("theme").click()
        on = "dark" in (pg.evaluate("document.body.className") or "").split()
        T("theme").click()
        off = "dark" not in (pg.evaluate("document.body.className") or "").split()
        T("theme").click()
        return on and off
    c10a()
    # snapshot before reload for 8
    snap = pg.locator('[data-testid="card"]').count()
    pg.reload()
    @check("8 localStorage restore")
    def c8():
        return pg.locator('[data-testid="card"]').count() == snap and snap >= 5
    c8()
    @check("10b theme persists")
    def c10b():
        return "dark" in (pg.evaluate("document.body.className") or "").split()
    c10b()
    @check("4 delete button")
    def c4():
        n = pg.locator('[data-testid="card"]').count()
        pg.locator('[data-testid="card"]').first.locator('[data-testid="delete"]').click()
        return pg.locator('[data-testid="card"]').count() == n - 1
    c4()
    b.close()
# merge 10 + 10b into one requirement
r10 = res.pop("10 theme toggle", False) and res.pop("10b theme persists", False)
res["10 theme toggle + persists"] = r10
print(json.dumps({"passed": sum(res.values()), "total": 10, "results": res, "page_errors": errs}))

5 Honest limits

One prompt, one run per level, a clear single-file spec. Not a claim about hard, open-ended or long-horizon work, where the higher levels are meant to earn their cost, and not a claim about other models. Try low first when the job is clearly specified; step up when the result is wrong, not by default.