Your AI says it's done.malveon checks if it really is.
malveon reads the code your AI wrote and checks it against your to-do list. Each item gets a plain answer (hooked up, broken, missing, or half done) and the exact line that proves it. It also catches what your AI added without being asked, and what it broke on the way.
curl -fsSL https://get.malveon.com/install.sh | shWindows: irm https://get.malveon.com/install.ps1 | iex. Also on npm, Homebrew, Scoop, and the VS Code and Cursor extension. Free during the beta. No account. Your code stays on your computer.
~/landing-shop $ malveon check --features PLAN.mdFIX THESE FIRST============================================================================== 1. BROKEN — `CancelButton` cancels an order with `DELETE /api/orders/[id]` `CancelButton` exists (src\components\CancelButton.tsx) — but it calls DELETE /api/order/:param (src\components\CancelButton.tsx:5), and no server route handles that (src\app\api\orders\[id]\route.ts:4) 2. new call to nowhere — DELETE /api/order/:param DELETE /api/order/:param is a call added this session, and no route in the project serves it (src\components\CancelButton.tsx:5) 3. HALF BUILT — `OrderNotes` saves a note on an order with `POST /api/notes` POST /api/notes reaches its server route (src\app\api\notes\route.ts:4), but the route never changes any data: it only reads table `notes` (src\app\api\notes\route.ts:6) — and this line expects a change (src\components\OrderNotes.tsx:9)OVERVIEW============================================================================== read from the code ✔ · your build/tests: not run (turn on "exec" in malveon.json, or pass --exec) · your real app: not verified (malveon never runs it) Plan items built & connected 2 CONNECTED · 1 BROKEN · 1 NOT BUILT · 1 HALF BUILT · 1 REWRITE · 1 SKIPPED (2 not ticked yet, don't block) Your prompts vs the code not set up Frontend & backend agree on data 2 MATCH · 0 MISMATCH Backend route conflicts clean UI elements may overlap clean Unplanned code 2 flagged New bugs this session 1 found Unfinished code (TODOs) clean Agent's claims vs reality 0 CONFIRMED · 1 MISMATCH · 6 NOT CLAIMED Build, lint & tests actually ran not run (pass --exec to include)⋮GATE: blocked — a commit gated on this run should not proceed - plan items: 1 BROKEN, 0 NOT BUILT, 1 HALF BUILT, 0 REWRITE THIS LINE - new bugs this session: 1 introduced (something that worked now broken, or a known bug pattern added) - agent's claims vs reality: 1 claim(s) contradicted by what was actually verified
A real malveon report on a small test app, shortened. It opens with what to fix first: a Cancel button that calls an address the server doesn't have, and a note that never actually saves. The overview also flags an Email receipt button nobody asked for. “GATE: blocked” means “don't ship this yet.”
Built after a week of reading Reddit threads from people whose AI said "fully functional" while half the features didn't actually work.
The AI says the Save button is done.You click it. Nothing gets saved.So you check every file yourself. That was the job you gave the AI.
And it isn't only the Save button.
- The second opinion that agrees
- So you ask another AI to check the first one. It reads the same files and gives you another opinion. You still don’t know.
- The thing that used to work
- While fixing one problem, your AI quietly breaks something else. You find out when a user clicks it.
- The extra nobody asked for
- You asked for one thing. The AI also added an Email receipt button and a new address on your server. You find out when you read the changes, if you do.
A straight answer for each one
Each item on your list gets one of six answers. These are the exact words malveon prints, with a real example from a test app.
- BROKENBroken
It’s there, but it won’t work. The button asks the server for something that doesn’t exist.
Your list said
CancelButtoncancels an order withDELETE /api/orders/[id]malveon foundit calls DELETE /api/order/:param (src\components\CancelButton.tsx:5), and no server route handles that
- NOT BUILTMissing
It’s on your list. It isn’t in the code at all.
Your list saidExport all orders as CSV from
GET /api/reports/ordersmalveon foundnothing in the code serves or calls /api/reports/orders
- HALF BUILTHalf done
Part of it is there. A button that leads nowhere, or a Save that never actually saves.
Your list said
OrderNotessaves a note on an order withPOST /api/notesmalveon foundthe route never changes any data: it only reads table
notes(src\app\api\notes\route.ts:6)- REWRITE THIS LINEToo vague
Your list item is too vague to check. Say which page, button, or file you mean.
Your list saidMake orders better
malveon foundnames no URL, file, or code name, and no code clearly matches its words
- CONNECTEDHooked up
It’s built, and the button really reaches the part that does the work and saves it.
Your list said
RefundButtonsends a refund toPOST /api/refunds, which saves it torefundsmalveon foundinserts into table
refunds(src\app\api\refunds\route.ts:6)- SKIPPEDNot a coding task
Something code can’t show, like a color change or a step you do by hand. It says why.
Your list saidButtons use the brand color and a 1.5px stroke icon
malveon founda design or styling change — malveon reads code, it can’t see how the page looks
Every answer points to the exact spot in the code it's based on, so you can check it yourself.
Follow one feature from the button to where it's saved
Clicking a button starts a chain: the page sends a request, code on the server answers it, and something gets saved. malveon follows that chain for every item. If the chain stops before anything is saved, you'll know. Files that merely exist don't count as done.
malveon follows this chain through the code. It never opens your app.
CONNECTED(hooked up: the refund is saved)RefundButton sends a refund to POST /api/refunds, which saves it to refunds
The page
page /orders
Sends
POST /api/refunds
src/
components/ RefundButton.tsx:5 Server
route POST /api/refunds
src/
app/ api/ refunds/ route.ts:4 What gets saved
inserts into table
refundssrc/
app/ api/ refunds/ route.ts:6
HALF BUILT(half done: the note is never saved)OrderNotes saves a note on an order with POST /api/notes
The page
page /orders
Sends
POST /api/notes
src/
components/ OrderNotes.tsx:9 Server
route POST /api/notes
src/
app/ api/ notes/ route.ts:4 What gets saved
changes no data: only reads table
notessrc/
app/ api/ notes/ route.ts:6
Every submission failed. The page looked finished.
On a real app we test with, a form sent its answers under one set of names, and the server expected different ones: challengeId instead of challenge_id. So the server turned away every single submission. The AI said it was done, and nothing looked wrong until someone pressed Submit.
malveon checks that what a page sends matches what the server expects. It caught this in one check and pointed to both lines.
What the form sendssrc/components/challenges/ChallengeDetailClient.tsx
133 const res = await fetch("/api/submissions", {134 method: "POST",135 headers: { "Content-Type": "application/json" },136 body: JSON.stringify({137 challengeId: id,138 githubRepo: submissionData.githubRepo,139 demoUrl: submissionData.demoUrl,140 techStack: selectedTechStack,141 wrongDecision: submissionData.wrongDecision,142 defendedDecision: submissionData.defendedDecision,143 }),144 });
What the server expects (and the error it returns otherwise)src/app/api/submissions/route.ts
47 try {48 const body = await request.json();4950 // Basic validation51 if (!body.challenge_id || !body.wrong_decision || !body.defended_decision) {52 return NextResponse.json({ error: "Missing required fields" }, { status: 400 });53 }
malveon's report, word for word:
fields: CONTRACT MISMATCH — POST /api/submissions (src\components\challenges\ChallengeDetailClient.tsx:133) → route (src\app\api\submissions\route.ts:38): the handler reads challenge_id, wrong_decision, defended_decision from the request body, but the call never sends challenge_id, defended_decision, wrong_decision
What your AI did that you didn't see
malveon compares your code with how it was when you started working, so it can tell what your AI changed along the way.
What it broke
did this session's own changes break something that worked, or add a known bug pattern? NEW CALL TO NOWHERE — DELETE /api/order/:param src\components\CancelButton.tsx:5 DELETE /api/order/:param is a call added this session, and no route in the project serves it
What nobody asked for
did the agent build anything this session neither your plan nor your own prompts asked for? route /api/receipts method: POST evidence: src\app\api\receipts\route.ts:4 call /api/receipts method: POST evidence: src\components\ReceiptButton.tsx:5
It broke something that worked. If a button that reached the server now points at an address that doesn't exist, malveon says so and shows the line. It also flags a few common leftovers: a debugging line left in, a test switched to “only”, or a secret key from a well-known service pasted into the code. That is a short list plus the before-and-after comparison, not a general bug finder.
It added something nobody asked for. malveon lists every new request your page makes, and every new address your server answers, that neither your plan nor your own prompts asked for. Your AI's own summary doesn't count as asking. It sees buttons that talk to your server. A button that only changes how the page looks, like a dark mode switch, is out of its reach. It lists these for you to review and doesn't block your work.
And what it left behind:
- A “done” the code doesn’t back up
- When the note your AI writes as it saves its work says an item is done or working, malveon checks that against the code. If they disagree, it shows you the line.
- Notes to self
- “TODO”, “FIXME” and “not implemented” in lines your AI wrote this session. It reads JavaScript, TypeScript, Python and Go files.
- Two places answering one address
- If two parts of your server claim the same address for the same kind of request, only one of them can run. malveon lists both.
- Layouts that may overlap
- A positioned element with nothing to anchor it, a common cause of pieces overlapping on screen. This is a warning about the code. malveon never looks at your screen.
It checks the code, not the AI's word
- No AI grading AI. malveon reads the code itself, so the same code always gets the same answer, and every answer points to the exact line.
- Your AI can run it too. It gets the same report you would see. When a decision is needed, like running commands on your computer, malveon asks you, not the AI.
- It checks what you asked for in chat. Most requests to an AI never make it into a written plan. After a one-time setup, malveon can check those too.
- It runs your project’s own tests only after you say yes.
- You can set it to stop half-done work from being saved into your project’s history (a “commit”) until it’s fixed.
Your AI agent asked malveon to run this repo’s own commands on your machine:
npm run build (build, in the project root)
These run the repo’s own code: its build scripts, test runner config and test files. Only approve a repo you trust. Allow them for this repo (until its build scripts or malveon.json change)?
When your AI asks to run commands on your computer, this is what you see. Only you can answer it.
Save a file. See what broke.
Using VS Code or Cursor? Add the malveon extension and it checks again a few seconds after you save. Problems show up right next to your code, and clicking one takes you to the exact line.
Malveon: Results
- Plan items
- BROKEN (1)
CancelButtoncancels an order withDELETE /api/orders/[id]- NOT BUILT (1)
- HALF BUILT (1)
- REWRITE THIS LINE (1)
- CONNECTED (2)
- SKIPPED (1)not code tasks: headings, notes, design and manual steps
- Your prompts
- Other checks
- Frontend and backend agree on dataclean
- Backend route conflictsclean
- New bugs this session1
- Unplanned code2
- UI elements may overlapclean
- Unfinished code (TODOs)clean
- Agent's claims vs reality1
Malveon / landing-shop
3 things block a commit
Fix these, then run the check again.
- Read from the code done
- Your build and tests: not run
- Your real app: not verified — malveon never runs it
- plan items: 1 BROKEN, 0 NOT BUILT, 1 HALF BUILT, 0 REWRITE THIS LINE
- new bugs this session: 1 introduced (something that worked now broken, or a known bug pattern added)
- agent’s claims vs reality: 1 claim(s) contradicted by what was actually verified
- 1 BROKEN
- 1 NOT BUILT
- 1 HALF BUILT
- 1 REWRITE THIS LINE
- 2 CONNECTED
- 1 SKIPPED
Plan items
Every line of your plan, checked against the code. From PLAN.md. Change
CancelButton cancels an order with DELETE /api/orders/[id]
CancelButton exists (src\components\CancelButton.tsx) — but it calls DELETE /api/order/:param (src\components\CancelButton.tsx:5), and no server route handles that; the server route for /api/orders/:id exists (src\app\api\orders\[id]\route.ts:4), but no frontend call to it was found (if something outside the app calls it — a health check, webhook, cron job or public API — say so in the line)
src/app/api/orders/[id]/route.ts:4src/components/CancelButton.tsx:5
Set it up once, then keep working
Install
Paste one line into your terminal, or add the extension to VS Code or Cursor.
Show it your list
Point it at the plan or checklist your AI is working from. It remembers it.
Keep working
It checks when you save, when your AI asks it to, or whenever you run it.
malveon never runs your app, never runs your project's own commands until you've said yes, and never sends your code or file names anywhere.
Pick the line for your computer
Not sure which? On a Mac or Linux use the first line, on Windows the second. Copy it into your terminal and press Enter.
- macOS / Linux
- curl -fsSL https://get.malveon.com/install.sh | sh
- Windows
- irm https://get.malveon.com/install.ps1 | iex
- npm
- npm install -g malveon
- Homebrew
- brew tap ladsondavid/malveon https://github.com/LadsonDavid/Malveon && brew install malveon
- Scoop
- scoop bucket add malveon https://github.com/LadsonDavid/Malveon; scoop install malveon
- VS Code / Cursor
- Search “malveon” in Extensions
Every download is checked against the release's checksum list before it's installed, and a file that doesn't match is refused. That list is signed with malveon's release key. Updates always check the signature, and so does the Mac and Linux installer when your computer has OpenSSL 3.
Frequently asked questions
Don't take our word for it
Pick one. It opens with a question about malveon already typed, including what malveon can't do. The AI answers from what it finds online, so it can be wrong or out of date about us too. malveon's own answers never come from an AI. They come from your code.
The question it asks
I use AI coding agents (Claude Code, Cursor, Codex, Antigravity). Explain malveon (malveon.com): what it checks when my agent says a task is done, including anything the agent added that I didn’t ask for and anything it broke along the way, how it proves each verdict, what it can’t check, and how to install it. Use malveon.com and github.com/LadsonDavid/Malveon as sources.
Your AI already says it's done. Find out what's actually finished.
curl -fsSL https://get.malveon.com/install.sh | shWindows: irm https://get.malveon.com/install.ps1 | iex. Also on npm, Homebrew, Scoop, and the VS Code and Cursor extension. Free during the beta. No account. Your code stays on your computer.