Your AI agent says it's done.malveon reads the code and tells you if it is.
Point it at your plan. Every line comes back CONNECTED, BROKEN, NOT BUILT, or HALF BUILT, with the file and line that proves it. It never asks the agent.
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.
~/landing-shop $ malveon check --features PLAN.mdOVERVIEW============================================================================== 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 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 clean New bugs this session clean 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, 1 NOT BUILT, 1 HALF BUILT, 1 REWRITE THIS LINE - agent's claims vs reality: 1 claim(s) contradicted by what was actually verified
Real output from malveon v0.3.3 on a small demo app. The full report goes on to explain every line.
Built after a week of reading Reddit threads from developers whose agents said "fully functional" while half the routes didn't exist.
The agent says it "wired up" the endpoint.You open the code. Nothing on the other end.So you re-read every file yourself. That was the job you handed off.
One straight answer per line
- BROKEN
Built, but it won’t work. It calls a URL nothing serves, or with a method the server doesn’t accept.
CancelButtoncancels an order withDELETE /api/orders/[id]it calls DELETE /api/order/:param (src\components\CancelButton.tsx:5), and no server route handles that
- NOT BUILT
Your plan names it. Your code doesn’t have it.
Export all orders as CSV from
GET /api/reports/ordersnothing in the code serves or calls /api/reports/orders
- HALF BUILT
Part of it is there. A route nothing calls, a save that never writes, a file nothing uses.
OrderNotessaves a note on an order withPOST /api/notesthe route never changes any data: it only reads table
notes(src\app\api\notes\route.ts:6)- REWRITE THIS LINE
Too vague to check. Name the file, URL, or component it’s about.
Make checkout feel faster
names no URL, file, or code name, and no code clearly matches its words
- CONNECTED
Built, and the screen really reaches its server route or database.
RefundButtonsends a refund toPOST /api/refunds, which saves it torefundsinserts into table
refunds(src\app\api\refunds\route.ts:6)- SKIPPED
Not a code task: a heading, a design note, a manual step. The reason is shown.
Buttons use the brand color and a 1.5px stroke icon
a design or styling change — malveon reads code, it can’t see how the page looks
The examples are from the same demo run. Every answer names the file and line it's based on. Open it and check.
Follow one feature from the button to the database
For every connected line, malveon traces the route through your code: the page, the call, the server route, and what it changes. A save button whose route never writes anything comes back HALF BUILT. The files existing isn't enough.
CONNECTEDRefundButton sends a refund to POST /api/refunds, which saves it to refunds
Screen
page /orders
Call
POST /api/refunds
src/
components/ RefundButton.tsx:5 Server
route POST /api/refunds
src/
app/ api/ refunds/ route.ts:4 Changes
inserts into table
refundssrc/
app/ api/ refunds/ route.ts:6
HALF BUILTOrderNotes saves a note on an order with POST /api/notes
Screen
page /orders
Call
POST /api/notes
src/
components/ OrderNotes.tsx:9 Server
route POST /api/notes
src/
app/ api/ notes/ route.ts:4 Changes
changes no data: only reads table
notessrc/
app/ api/ notes/ route.ts:6
Every submission failed. The page looked finished.
On a Next.js and Supabase app we test against, the challenge form sent challengeId. The server read challenge_id. Every submission came back 400. The agent said done, and nothing complained until someone pressed Submit.
malveon compares what each screen sends with what its route reads. It flagged the mismatch, with both file lines, in one check.
src/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 });
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 }
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
Proof you can open in your editor
- Reads your code, not the agent’s word. The checks don’t call an AI model. malveon looks up every URL, file, and component your plan names.
- Your agent can’t grade its own homework. Run it as an MCP server and Claude Code, Cursor, or Antigravity calls malveon itself. When something needs a decision, malveon asks you in a dialog, never the agent.
- Checks your prompts too, not only the plan doc. Most of what you ask an agent for is typed into chat and never reaches a plan. Turn on prompt checking and each request gets a verdict too.
- Runs your real build and tests when you say so. Add --exec for a real pass or fail. A repo can’t run its own scripts on your machine until you approve them.
- Stops a bad commit. Add it as a pre-commit hook and anything BROKEN, NOT BUILT, or HALF BUILT blocks the commit.
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. Only approve a repo you trust. Allow them for this repo (until its malveon.json changes)?
What you see when an agent asks malveon to run your build. The agent can't answer it for you.
Save a file. See what broke.
The VS Code and Cursor extension checks again a few seconds after you save. Results show in the sidebar, the Problems panel, and the status bar. Click any line to jump to the code.
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)
- Your prompts
- Other checks
- Frontend and backend agree on dataclean
- Backend route conflictsclean
- New bugs this sessionclean
- Agent's claims vs reality1
Malveon / landing-shop
2 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, 1 NOT BUILT, 1 HALF BUILT, 1 REWRITE THIS LINE
- 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
src/app/api/orders/[id]/route.ts:4src/components/CancelButton.tsx:5
Three things can be true. malveon tells you which.
Read from the code
Checked on every run.
Your build and tests
Passed, failed, or not run. Only as real as the run behind it.
Your real app
Never claimed. malveon doesn’t open a browser or start your server, and it won’t pretend it did.
Your agent says "done" about all three at once. malveon reports each one separately.
Set it up once, then keep working
Install
The one-line command, or the VS Code and Cursor extension.
Pick your plan
Choose your plan files once. malveon.json remembers them for you and your agent.
Work as usual
The check runs when you save, when your agent calls it, or when you type malveon check.
However you install things
- 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 release is signed. The installer and malveon update check the signature before anything runs.
Nothing about your project leaves your machine
Your code, file names, plans, and prompts stay local. Each run sends one anonymous event: your OS, CPU type, and whether the result was clean or blocked. Turn it off with --no-telemetry or DO_NOT_TRACK=1. The extension follows VS Code's telemetry setting.
Frequently asked questions
The hosted version is next
The CLI and the editor extension are out. A hosted service, where checks run without a terminal, is being built. Leave your email and we'll tell you when it's ready. That's all we'll use it for.
Your agent already says it's done. Find out which lines actually are.
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.