{"slug": "building-with-mini-part-2-9-shaping-the-vision-with-project", "title": "Building with mini, Part 2/9: Shaping the vision with project", "summary": "Mini, a developer tool for project scaffolding, introduces a 'mini project' command that conducts a critical plan-before-code interview via Claude Code. The interview walks through four stages to shape a project's vision, pushing back on weak ideas and refining design decisions. In a real session, the tool helped a developer choose the decimal module over floats for a calculator project and define error message formats.", "body_md": "In Part 1 we ran `mini init`\n\nand got **pycalc** — a small calculator for the terminal. `init`\n\nasked only four questions, and `.mini/project.md`\n\nis accordingly thin: a name, one line about *what*, *who it's for*, and the constraints (\"Python 3, standard library only\").\n\nThat's enough to start, but not enough to steer. Three things are missing: **how** we'll build it, **what we deliberately won't build**, and **how we'll know it's done**.\n\nThat's exactly what `mini project`\n\nadds.\n\n`mini project`\n\nopens an interactive Claude Code session — but not to write code. It's a **plan-before-code interview**. Claude gets your current `project.md`\n\nas the starting point (it won't ask what the project is about again) and walks you through four stages:\n\n`project.md`\n\nis shown for approval; only then does it get saved.One trait, faithful to the philosophy from Part 0: the interview is instructed to be **critical, not agreeable**. A weak idea doesn't get nodded through — you're told why it's weak.\n\nAnd what the command *doesn't* do: it never touches `.mini/state.json`\n\n. Phase state stays in tested TypeScript; `project`\n\nrewrites one markdown page. The finished document isn't saved by a hallucination either — at the end the agent runs `mini project --apply`\n\n, and the contract goes through the same parser and renderer as `init`\n\n.\n\n```\ncd pycalc\nmini project\n```\n\nMini first prints the exact prompt it will send to Claude (no magic — you see everything) and asks whether to start the session. What follows is from a real session, condensed; the answers are mine.\n\nClaude opened by reflecting the project back and refusing to assume anything:\n\n\"Terminal calculator\" can mean three quite different things, and each leads to a different design.\n\n1. How is it used?One-shot (`pycalc \"2+3*4\"`\n\n→ prints`14`\n\nand exits), an interactive REPL, or both? This is the most important decision — it determines the whole structure. And careful: for the one-shot case people already use`python -c \"print(2+3*4)\"`\n\nor`bc`\n\n. What makes pycalc different, so that it has a reason to exist? That's not nitpicking — it's the question the \"What I'm building\" line has to answer.\n\n2. How much math?Just`+ - * / ( )`\n\nwith precedence? Powers, modulo? Functions like`sqrt`\n\n,`sin`\n\n? Variables? Every extra level means a more complex parser, and variables only make sense in a REPL.\n\n3. How will you evaluate expressions?Fair warning: the tempting shortcut is`eval()`\n\n. It's one line, but it's a security hole (it evaluates arbitrary Python) and you learn nothing from it. Alternatives:`ast.parse`\n\nwith a node whitelist, or your own parser. What's your goal — tohavea tool, or tolearn how to write a parser?\n\nMy answers: one-shot; versus `python -c`\n\nit's less typing and nicer error messages, versus `bc`\n\nnatural syntax and decimals without `scale`\n\nsetup. Just the four operators and parentheses. And the goal is to learn — own tokenizer and recursive descent, no `eval()`\n\n.\n\nClaude then proposed the pipeline (tokenizer → recursive descent parser → evaluation, tokens carrying their position in the input) and pushed back where my framing was lazy:\n\nNumber semantics and division.You yourself list \"decimals without scale setup\" as the advantage over`bc`\n\n. So`1/2`\n\nmust be`0.5`\n\n, not`0`\n\n. I'd propose floats — but floats have the known artifacts (`0.1+0.2`\n\n→`0.30000000000000004`\n\n). The alternative is the`decimal`\n\nmodule (still standard library). For a calculator whose selling point is decimal numbers, I'd seriously consider`decimal`\n\n. Which one?\n\nGood catch — `decimal`\n\nit is. The interview just changed a design decision I would have gotten wrong by default. Two more came out of the same batch: **unary minus** goes in (\"without it the calculator feels broken — but it's a conscious scope extension, so I'm saying it out loud\"), and errors get a defined shape — stderr, non-zero exit code, and a message that points at the problem:\n\n```\nerror: unexpected character '+' at position 2\n2++3\n  ^\n```\n\nThen stage three — the part I've come to value most. First the agreed leave-outs, then the things *Claude* would be tempted to add:\n\nPower ``and modulo`\n\n%`** — tempting, \"just one more rule\". But`\n\n` is right-associative, which is a new class of problem in the parser. **Leave outin v1; once recursive descent is clear to you, it's the ideal v2 exercise.Reading from stdin/pipes(`echo \"2+2\" | pycalc`\n\n) — useful, but it grows the CLI layer.Leave out.Colored output,— the project needs none of it. One positional argument.`argparse`\n\nwith ten flagsLeave out.Packaging (pyproject.toml, pip install)— needless overhead for a learning script.Leave out.\n\nAnd the closing move the prompt demands — \"is there any question that, answered wrong, would send us down the wrong path?\" — earned its place:\n\nWe chose\n\n`decimal`\n\n, but we never saidwhat. The default context gives 28 significant digits:`1/3`\n\nprints`0.3333333333333333333333333333`\n\n. Technically correct, absurd as calculator output — and the fix, \"set your precision\", is exactly the`scale`\n\nfrom`bc`\n\nyou wanted to avoid. I propose: compute at default precision,round the output to 10 places and strip trailing zeros(`6.0`\n\n→`6`\n\n). Trade-off: the output is no longer the bit-exact intermediate value, but for a calculator readability wins.\n\nAfter I approved the draft, Claude saved it itself — through the contract, not by editing the file freehand:\n\n```\nmini project --apply <<'EOF'\nNAME: pycalc\nWHAT: A small command-line calculator: `pycalc \"2+3*4\"` evaluates one expression and exits. Less typing than `python -c`, nicer error messages, and decimal arithmetic that works without bc's scale setup.\nFOR_WHOM: People who want quick arithmetic in the terminal\nCONSTRAINTS: Python 3, standard library only\nAPPROACH:\n- One-shot CLI: single positional argument, result on stdout, errors on stderr with a non-zero exit code.\n- Pipeline: tokenizer → recursive descent parser → evaluation. No eval(); the goal is to learn how to write a parser.\n- Grammar: + - * / with correct precedence, parentheses, unary minus.\n- Numbers via decimal (exact decimal arithmetic: 0.1+0.2 = 0.3); output rounded to 10 places with trailing zeros stripped (6.0 → 6).\n- Tokens carry their position in the input so errors can point at the exact spot (message + caret line).\n- Tests: unittest with a table of cases (expression → expected result or error).\nNON_GOALS:\n- Do not add an interactive REPL mode in this version.\n- Do not add functions (sqrt, sin, …), constants, variables or assignment.\n- Do not use eval() — ever, not even as a temporary shortcut.\n- Do not add ** or % in this version (right-associativity of ** is a v2 exercise).\n- Do not read expressions from stdin/pipes; one positional argument only.\n- Do not add packaging (pyproject.toml, pip install) — run as a plain script.\n- Do not add colors or extra CLI flags.\nSUCCESS:\n- `pycalc \"2+3*4\"` returns 14; precedence and parentheses verified by the unittest case table.\n- `0.1+0.2` → 0.3, `1/2` → 0.5, `-5+3` → -2.\n- Every invalid input (2++3, (2+3, abc, empty, division by zero) exits non-zero with a stderr message showing position and caret — never a traceback.\n- Runs on plain Python 3 with zero dependencies outside the standard library.\nEOF\n[ok] Updated .mini/project.md\n```\n\nThat contract is also the command's second mode: `--apply`\n\nreads stdin, starts no Claude, and just writes the file. Handy when you want to edit `project.md`\n\nfrom a script or by hand without a session.\n\n**One thing to watch:** `--apply`\n\ndoes a *full replace*. Whatever you omit from the contract disappears from the file. The session prompt instructs the agent to keep the existing NAME / FOR_WHOM / CONSTRAINTS — but when you write the contract by hand, that's on you.\n\nNo new file appeared — `project.md`\n\nis still one page, it just steers now. Compare the before and after: `init`\n\ngave us \"A small command-line calculator\"; the interview turned that into a sharpened one-liner, six approach points, seven non-goals and four testable success criteria. The non-goals aren't decoration: mini keeps them in front of every later step, so when an agent in phase 7 feels like \"improving\" the calculator with colored output, the project has it in writing that no, it won't.\n\nAnd the cost side: the whole thing is one interactive session, and you pay for it once. The result is a page that *saves* tokens afterwards — newer versions of mini send warm sessions only a reference (\"read `.mini/project.md`\n\nif you don't already have it in context\") instead of inlining it again and again.\n\nIs the interview worth it for every project? Honestly, no — for a weekend script, `init`\n\nalone is fine. It pays off the moment a project is big enough that an agent will work on it across many sessions without you re-explaining the vision each time.\n\n`project.md`\n\nnow says what, for whom, how, what not, and when it's done. But the interview also left something behind: ideas like the ** operator — rejected for v1, too good to lose. A backlog for things that aren't phases yet is exactly what `mini todo`\n\nis for. Capturing ideas — that's Part 3.\n\n*mini is open source: npm install -g mini-orchestrator, then mini install-commands in your project. Source and docs on *", "url": "https://wpnews.pro/news/building-with-mini-part-2-9-shaping-the-vision-with-project", "canonical_source": "https://dev.to/stkremen/building-with-mini-part-2-shaping-the-vision-with-project-848", "published_at": "2026-06-17 11:00:00+00:00", "updated_at": "2026-06-17 11:21:32.310669+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence", "large-language-models"], "entities": ["Mini", "Claude Code", "pycalc"], "alternates": {"html": "https://wpnews.pro/news/building-with-mini-part-2-9-shaping-the-vision-with-project", "markdown": "https://wpnews.pro/news/building-with-mini-part-2-9-shaping-the-vision-with-project.md", "text": "https://wpnews.pro/news/building-with-mini-part-2-9-shaping-the-vision-with-project.txt", "jsonld": "https://wpnews.pro/news/building-with-mini-part-2-9-shaping-the-vision-with-project.jsonld"}}