Did the model finish that install? Or did the shell?
Those are not the same event. Free inference makes it easy to forget. A free server makes it worse. You start treating three clocks as one.
I keep seeing the same shrug. "It is all free, so it is all one session." Is it? Who died first: the chat, the process, or the tree?
This is a myth FAQ. Not a vendor bake-off. Not a latency post. I will not quote p50 numbers. I will not invent quotas. I will give you a probe you can run.
What I mean by three clocks
Clock A is the chat turn. It advances when a reply lands.
Clock B is the process. It advances while a PID is alive.
Clock C is the work tree. It advances on writes, commits, and checkouts.
They do not share a heartbeat. They fail on different days. Sound obvious? Then why do we merge like they agreed?
I use a cheap second machine when I have one. Disclosure: This article was prepared as part of MonkeyCode's product outreach. MonkeyCode currently offers free model access and a free server option. I treat that pair as one more place to run the probe. The myths below still hold if you never touch the product.
Myth 1: "The chat is open, so the box is mine"
Claim: A living transcript means the remote shell is still yours.
What actually moves: The HTTP session and the SSH session die alone. One can outlive the other by hours. A free model tab does not hold a TTY lease.
Corrected model: Chat uptime is not a lock. Process uptime is not a lock. who and ps are locks. git status is a lock. The tab is a diary.
Ask this before the next "continue":
- Is the same PID still the shell?
- Is cwd still the repo root?
- Did hostname change under me?
If you cannot answer, you are not continuing. You are starting over and lying about it.
Myth 2: "The model listed files, so that is the tree"
Claim: A directory listing in the transcript is current disk.
What actually moves: Listings are samples. They expire when anything writes. An agent can list src/, then a leftover npm from clock B mutates node_modules. Clock A never hears it.
Corrected model: A listing is a photograph. Photographs do not lock directories. Only a fresh ls plus git status is evidence. The chat's ls is a postcard from an earlier hour.
Try this after every long tool call:
# proposed re-sample, not a benchmark
find . -maxdepth 2 -type f | sort > /tmp/tree.after
diff -u /tmp/tree.before /tmp/tree.after || true
git status --porcelain=v1
Did the postcard match the folder? If not, which clock do you trust?
Myth 3: "A green command in chat is still running"
Claim: Success text means the job occupies the box.
What actually moves: stdout is a corpse of a finished syscall. Or a truncated stream. Or a retry that ran twice. Clock A stores the story. Clock B may be idle. Clock B may be a different npm you forgot.
Corrected model: Transcript success is historical. Liveness is ps. Exit codes are not PIDs. "Build passed" is not "build owns port 3000."
I ask three ugly questions:
- What is the PID right now?
- What parent started it?
- What happens if I
killit?
If the model cannot point at a PID, the command is a memory. Memories do not hold ports.
Myth 4: "Commit time is when I approved the patch"
Claim: git log timestamps prove human intent time.
What actually moves: Git records author and committer clocks. Those clocks are the box's clock. Or a container's clock. Or a skewed VM. Your laptop's "I clicked yes at 16:02" never entered the object.
Free servers make this spicy. The box TZ may be UTC. Your brain is not. The model may even write GIT_AUTHOR_DATE if you let it. Did you let it?
Corrected model: Commit time is the tree's story about itself. It is not your approval clock. It is not the chat clock. Never use git log --until as a session log.
Check the object, not the vibe:
git log -1 --format="commit=%H%nauthor=%an <%ae>%nauthor_date=%aI%ncommitter_date=%cI"
date -u +"now_utc=%Y-%m-%dT%H:%M:%SZ"
printf "TZ=%s\n" "${TZ:-unset}"
If author date is in the future, stop merging. If it predates the chat by a day, ask who reused the box.
Myth 5: "Free model and free server fail as a pair"
Claim: One health check covers inference and disk.
What actually moves: The model can 429 while make still runs. The server can reboot while the chat stays polite. Those are two vendors in one sentence. Even when one company sells both, they are two failure domains.
I do not need their SLA sheet for this. I need two probes. One talks to the model. One talks to the kernel. If you ping only the chat, you are monitoring a diary.
Corrected model: Budget retries for the model. Budget reboots for the box. Never let a model retry rm because the box blinked.
Artifact: the three-clock probe
This is a proposed script. Label it as unproven on your fleet. I am not publishing timings. I am publishing questions the script prints.
Save as three-clocks.sh:
#!/usr/bin/env bash
# three-clocks.sh — proposed probe, not a product test suite
set -euo pipefail
echo "=== clock A: operator wall (this shell) ==="
date -u +"utc=%Y-%m-%dT%H:%M:%SZ"
printf "TZ=%s\n" "${TZ:-unset}"
echo "=== clock B: process ==="
printf "pid=%s ppid=%s user=%s host=%s\n" "$$" "$PPID" "${USER:-unset}" "$(hostname)"
printf "cwd=%s\n" "$(pwd)"
ps -o pid,ppid,etime,cmd -p $$ 2>/dev/null || ps
echo "=== clock C: work tree ==="
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
git rev-parse --show-toplevel
git log -1 --format="HEAD=%H author=%aI committer=%cI name=%an"
git status --porcelain=v1
git diff --stat
else
echo "not a git work tree"
fi
echo "=== fingerprints ==="
printf "HOME=%s SHELL=%s\n" "${HOME:-unset}" "${SHELL:-unset}"
command -v node >/dev/null && node -v || echo "node=absent"
command -v python3 >/dev/null && python3 -V || echo "python3=absent"
Run it twice. Once on the laptop. Once on the remote box. Do not skip the diff.
chmod +x three-clocks.sh
./three-clocks.sh | tee /tmp/clocks.local
# then on the box, same script, tee /tmp/clocks.box
diff -u /tmp/clocks.local /tmp/clocks.box || true
Decision table
Use this when two dumps disagree. This is a judgment aid. Not a score.
| If you see... | Do not assume... | Assume instead... |
|---|---|---|
| Chat still streaming, hostname changed | Same machine | New box, old story |
cwd is not the repo |
The model "knows the project" | You are patching a stranger folder |
git status dirty, chat says clean |
The transcript won | The tree won |
Author date skew vs date -u
|
You just approved it | Clock C is lying or reused |
ps has no install, chat says installing |
Work continues | Clock B already exited |
| node versions differ local vs box | The patch is portable | You tested a different runtime |
Print the table next to the PR. If you cannot fill a row, you are guessing.
A 15-minute workflow I actually use
No drama. No "one hour challenge." Fifteen minutes, then I stop.
- Snapshot clock C:
git statusandgit log -1. - Run
three-clocks.shon the box. Save the dump. - Ask the model for one change. Not five.
- Re-run the probe. Diff dumps.
- Merge only if hostname, cwd, and HEAD match the plan.
If step 4 shows a new hostname, I throw the chat away. The model did not teleport. The box did.
Why mention a free model here at all? Because cheap retries tempt you to skip step 4. Free disk tempts you to skip step 1. The workflow exists to make skipping visible.
Limitations
This probe is shallow on purpose.
- It does not detect a lying container clock.
- It does not attest builds.
- It does not prove the model followed policy.
- It does not replace CI.
-
psformat differs across macOS and Linux. Read the columns. -
hostnameis not a unique id. Collisions exist. - I did not measure how often teams hit each myth. I refuse fake percentages.
If you need supply-chain proof, stop. Use signed commits and a real runner. This FAQ is for people about to paste a patch.
Who should not use this
Skip this approach if:
- You deploy production from a chat window. Stop that first.
- You cannot run a shell on the same box as the agent.
- Your tree holds secrets the model must never see. Isolate first.
- You want a product comparison with named models and quotas. I will not invent those.
Also skip it if you already have a job that prints cwd, identity, and git status on every tool call. You do not need my script. You need to read your own logs.
The mental model I want you to steal
Stop asking "did the agent do it?"
Ask "which clock claims it happened?" Then demand a second clock.
Chat is a narrator. The process is a tenant. The tree is the deed. Narrators lie with old photographs. Tenants leave. Deeds remain.
Free inference does not fuse those roles. A free server does not fuse them either. Price never coupled the clocks. We did, because it was convenient.
Which clock lied on your last merge? If you cannot point at one dump, you already know the answer.
If you have a spare free server, run three-clocks.sh there before the next refactor. Compare it to your laptop. That comparison is the article. Everything else is commentary.
Top comments (0)