Mechanism

The vibe coding production review tail is just git log

The hard part of taking a vibe-coded prototype to production is not security or testing in the abstract. It is reconstructing what the agent did, prompt by prompt, so a human can decide what survives. mk0r writes that record as the prototype is being built. Each successful agent turn ends with one git commit whose message is the first line of your prompt. The review tail already exists.

M
Matthew Diakonov
6 min

Direct answer (verified 2026-05-09)

To review a vibe-coded mk0r app for production, open the per-turn git log of the project. Every successful agent turn runs git add -A && git commit -q -m '<your prompt's first line>' inside the sandbox (src/core/e2b.ts line 1773). The commit message is your prompt, sliced to 120 characters (src/app/api/chat/route.ts line 1008). So git log --oneline is the prompt history; git show <sha> is one isolated diff to review. That is the review tail.

Why this is not the default in most builders

The default shape of a vibe-coded artifact is one final blob: a repo at the end of a session, an HTML file streamed to the browser, a deployed preview URL. That shape is great for sharing, terrible for review. A reviewer arriving at the blob has to ask, what did the agent do? Which prompt added the auth call? Which one removed the rate limit? The questions are about the process, but the only surface available is the result.

The fix is to write the process down at the moment it happens. Not as an export step at the end, not as a transcript log next to the repo, but inside the repo itself, so the same tool a reviewer already knows answers the questions. That is what per-turn commits do. Every turn is a diff with a label.

Reviewing a vibe-coded app for production

Reviewer opens the final repo or the live preview and tries to reverse-engineer what happened. The commit log is one squashed commit or 'final-build', the chat transcript is a separate document, mapping prompts to file changes is manual.

  • No prompt-to-diff mapping
  • Bundled changes in one commit
  • Chat transcript decoupled from code
  • Risk surface is an essay, not a list

The five-minute production review session

Concretely, here is what reviewing a mk0r prototype looks like before you graduate it to a real host. None of these steps require leaving the project; the artifact is the project.

1

Open the project repo, not the chat

Every mk0r session has a real /app working tree inside its E2B sandbox with a real git repo. The chat UI is one view of that tree. The git log is another. For a production review, the log is the one you want.

getGitHistory at src/core/e2b.ts line 1909 runs `git log --format='%H|||%s|||%an|||%aI' -n 50` and exposes it via /api/chat/history. Same data, no UI between you and it.

2

Read the commit messages as prompts

Every commit message in a mk0r project is the first line of the prompt that produced the diff, truncated to 120 chars. So `git log --oneline` reads like the chat: 'add a priority field high or normal', 'make the badge teal', 'persist todos to localStorage'.

src/app/api/chat/route.ts line 1008-1011: const msg = prompt.split("\n")[0].trim().slice(0, 120) || "Agent turn". Then commitTurn(sessionKey, msg).

3

Diff each turn in isolation

Because every successful turn is one commit, `git show <sha>` shows you exactly what the agent changed for one prompt. No bundled-up multi-prompt PR. No merged interpretation. The review unit is the turn.

src/core/e2b.ts line 1771-1774: `git add -A`, `git diff --cached --quiet` (skip noop turns), `git commit -q -m '${safeMsg}'`, `git rev-parse HEAD`. Whole tree per turn, one SHA emitted.

4

Find the moment things drifted

Most vibe-coded apps go wrong at one specific turn. With this layout you can usually point at it: scan the messages, spot the prompt where you got greedy ('rewrite all four screens to use the new layout'), open that diff first.

Undo and redo navigate the same history. src/core/e2b.ts line 1855-1866 walks an activeIndex backward through historyStack, calling git checkout <sha> -- . into a new empty commit. Reverting one turn is one click in the chat UI or one command in a terminal.

5

Decide what graduates

After the review, the question is which subset of turns survives. The answer is a real git operation: keep the SHAs you trust, drop the ones you do not. The repo travels with you when the prototype goes to a real host.

Per-turn commits make `git rebase -i`, `git cherry-pick`, and `git revert` first-class review tools instead of post-hoc reconstructions. The history was always going to be the artifact; mk0r just wrote it down at the right granularity.

120 chars

The commit message of every AI turn is the first line of the user prompt, truncated to 120 chars.

src/app/api/chat/route.ts line 1008-1011, src/core/e2b.ts line 1773

What the log actually looks like

A real session run, abbreviated. Each line is a real entry shape from getGitHistory: a SHA, a message, an author, an ISO date. The messages are prompts. The diffs (one per SHA) are what survived that turn.

$ git log --oneline -n 8
8a3f2b1 persist the todo list to localStorage on every change
71c40d9 add a priority field, high or normal, with a small badge
2d9ee54 make the empty state friendlier with one short line
f019aab when I tap a todo, mark it done with a strikethrough
b5c3210 add a button at the bottom that says Add
3e7a66d a todo list with checkboxes
9a14f08 Initial template
$ git show 71c40d9 --stat
71c40d9 add a priority field, high or normal, with a small badge
src/types.ts | 3 ++-
src/lib/seed.ts | 6 ++++--
src/components/Todo.tsx | 12 +++++++++++-
3 files changed, 16 insertions(+), 5 deletions(-)

The exact format string is at src/core/e2b.ts line 1909: git log --format='%H|||%s|||%an|||%aI' -n 50. The chat history pane uses the same data; you can also run the command yourself if you ssh into the VM.

The honest limits of this surface

The per-turn commit log is the most useful production-review artifact a vibe-coded app could give you. It is not a compliance log. Three things to know before you treat it as one.

The author of every commit is the sandbox's default git identity, not the user who typed the prompt. The session itself is authenticated and tied to a user via Firebase, but the in-VM git identity does not carry that through. For solo prototyping that is fine. For a multi-user team review, the prompt history is your attribution layer, not the commit author field.

The commit message is only the first line of the prompt, sliced to 120 characters. A long multi-step instruction (the kind a reviewer would actually want to read in full) gets cropped. The full prompt body lives in the agent's message history, not in the commit. Treat the message as a label, not a record.

The repo lives inside the E2B sandbox, which auto-pauses every hour and recycles after 45 minutes of pool idle time (src/core/e2b.ts line 33 and line 1896). The session is restored from a persisted head SHA in Firestore on the next prompt, so the log is durable across pauses. It is not durable across deletions unless you push it to a remote, which mk0r does not do automatically. If you need a permanent off-system review trail, export the repo before the prototype goes cold.

Want me to walk through your prototype's commit log with you?

Twenty minutes, your project, an honest read on which turns survive the production review and which ones to revert before you ship.

Frequently asked questions

What is the production review tail of a vibe-coded app, in plain words?

It is the list of changes a reviewer has to read through to decide whether the app is safe to ship. In most AI builders that list does not exist as a structured artifact, you get a final repo or a final HTML file and you have to reverse-engineer what the agent did, which prompt produced which behavior, and where the risk crept in. In mk0r the tail is literal: the per-turn git log. Every prompt becomes a commit, every diff is reviewable in isolation, and `git show <sha>` is the unit a reviewer actually wants. That is what 'review tail' means here, the chronological list of agent turns you walk back through before production.

How does mk0r get my prompt into the commit message exactly?

src/app/api/chat/route.ts line 1007 to 1013 is the whole answer. After the agent finishes streaming a turn, the server takes the raw prompt string, splits on newline, takes the first line, trims it, slices it to 120 characters, and falls back to the literal string 'Agent turn' if that produced nothing. Then it calls commitTurn(sessionKey, msg). commitTurn lives in src/core/e2b.ts at line 1759, escapes single quotes in the message, runs `cd /app && git add -A && git commit -q -m '<msg>' && git rev-parse HEAD` inside the VM, and returns the new SHA. The chat stream emits a 'version' event with the sha and message so the UI can show the new history entry, but the commit is real either way.

What if the agent produced no changes on a turn, do I still get a junk commit?

No. The script at src/core/e2b.ts line 1772 runs `git diff --cached --quiet` after `git add -A`. If nothing is staged the script echoes NOCHANGE and exits zero. commitTurn returns null in that case and no version event is emitted. So the review tail is dense, every entry corresponds to an actual diff. This is the right behavior for a review surface, you do not want a turn-by-turn log of every time the agent fetched something or thought out loud.

Can I see the log without opening a terminal?

Yes. The chat panel has a history view backed by /api/chat/history, which calls getGitHistory(sessionKey, 50) at src/core/e2b.ts line 1901. That function runs `git log --format='%H|||%s|||%an|||%aI' -n 50` inside the VM and returns an array of {sha, message, author, createdAt, isActive}. The active turn is the entry whose sha matches activeIndex in the historyStack persisted to Firestore. Click any entry to undo to that point. This is the same data a terminal git log would show, just in the product UI.

What does the review tail not give me?

Three honest gaps. First, the commit author is the VM's default git identity, not your name, so you cannot tell turns apart by user. Second, the commit message is only the first line of your prompt, so a multi-paragraph instruction loses everything past the first newline once truncated to 120 chars. Third, the per-session repo is local to the sandbox; there is no continuous push to a remote, so if you want a durable artifact for an external reviewer you need to deploy the repo somewhere that captures the log. None of these are deal-breakers for a self-review on the way to production. They do mean the review tail is a starting point, not a compliance log.

Is this an official audit log?

It is not framed that way. The intent of commitTurn is iteration-time history, fast undo, and honest blame for which prompt produced which file change. But the artifact you get is exactly what an audit log of a code-generating system would want, an ordered record of inputs and the diffs they produced. If you treat it as the start of a production review rather than a finished compliance trail, it is the most useful thing in the project.

How does this compare to reviewing code from a tool that streams HTML and never shows me a repo?

The streamed-HTML path is the other generation mode in this same product (Quick mode). It is great for a one-shot mobile demo. It does not give you a per-turn diff because there is no repo, just a fresh HTML document each time. For a production review you want VM mode, which is what the commit log applies to. The picking-mode question is in src/core/e2b.ts and the chat route. Quick mode is the right tool when the output is the artifact. VM mode with the per-turn commits is the right tool when the process is the artifact.

mk0r.AI app builder
© 2026 mk0r. All rights reserved.