Does a zero invoice make you a guest?
I keep hearing that answer in code reviews.
It is wrong, and it keeps shipping bugs.
Free models feel like a sandbox with no adult in the room.
A free server feels like a laptop you did not buy.
Neither of those feelings is a real contract.
This FAQ is about five claims I still hear.
Each claim has a check you can run today.
Each check produces a file, not a vibe.
Why this FAQ exists
Agents now write, install, and leave files behind.
Some of those agents sit on a free remote box.
Some of those agents call a free model.
I use MonkeyCode when I want both in one workflow.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
I am not going to name models, quotas, or hardware here.
Those product details still change without much warning.
Your operator duties do not change with them.
So what actually changes when the bill is zero?
Almost nothing about ownership actually changes here.
Almost everything changes in how people excuse sloppy process.
Myth 1: If I did not pay, I am not the operator
The claim
"It is a free box. I am just trying something."
That sentence shows up before a reckless delete.
It also shows up after a leaked token.
Are you a guest, or can you still wreck the tree?
The check
Ask one question before the first prompt.
Who can destroy this working tree from this shell?
id
pwd
git rev-parse --show-toplevel 2>/dev/null || echo "NO_GIT_ROOT"
printenv | awk -F= '{print $1}' | sort > /tmp/env_names.txt
wc -l /tmp/env_names.txt
You are the operator if you can run those commands.
Payment status is not in that output.
Look at the printed uid; that user is the actor.
Corrected mental model
Free is only a price tag, nothing more.
Operator status is a capability on the box.
If you can write the disk, you own the failure.
Myth 2: The free model is a teammate, not a subprocess
The claim
"The model will remember we agreed on main."
"It knows the repo layout from last night."
Did the model clock in as a coworker?
No. It knows the tokens you sent this turn.
The check
Do not ask the model what branch you are on.
Ask the repository, then pin that answer yourself.
git branch --show-current
git rev-parse HEAD
git status --porcelain
Then wrap the agent like any other command.
Label this as a local header, not a vendor CLI.
# Proposed wrapper. Run it. Do not trust memory.
cat > /tmp/session_header.txt <<EOF
cwd: $(pwd)
branch: $(git branch --show-current 2>/dev/null || echo NONE)
head: $(git rev-parse HEAD 2>/dev/null || echo NONE)
user: $(id -un)
host: $(hostname)
started: $(date -u +%Y-%m-%dT%H:%M:%SZ)
EOF
cat /tmp/session_header.txt
Feed that header into the first message.
Do not let the model invent the header.
If the header and git status disagree, stop talking.
Corrected mental model
A model is a function over current context.
A teammate has continuity and later accountability.
Your subprocess has neither unless you add them.
Myth 3: A free server has no working-directory contract
The claim
"It is temporary, so cwd does not matter."
Then the agent writes into $HOME anyway.
Or into last week's clone with the same name.
Where is cwd when nobody paid for the disk?
The check
Create a session directory with a boring unique name.
Refuse to start if the cwd is wrong.
#!/usr/bin/env bash
# session_cwd.sh — proposed local guard, not production code.
set -euo pipefail
ROOT="${SESSION_ROOT:?set SESSION_ROOT to an empty directory}"
STAMP="$(date -u +%Y%m%dT%H%M%SZ)"
SID="${STAMP}-$$"
WORK="${ROOT}/${SID}"
mkdir -p "${WORK}"
cd "${WORK}"
if [[ "$(pwd)" != "${WORK}" ]]; then
echo "cwd contract failed" >&2
exit 2
fi
echo "${SID}" > .session_id
pwd
ls -la
Run it on an empty SESSION_ROOT.
Read .session_id back from disk.
If the agent cannot echo that file, you stop.
Corrected mental model
Temporary does not mean the path is optional.
A free disk still has real absolute paths.
Paths are the contract, not the invoice.
Myth 4: I can skip a session id because nothing is billed
The claim
"We will recognize the run from the chat title."
Chat titles collide after the third retry.
They also lie when two windows share a topic.
If nothing is billed, do runs still need names?
The check
Mint an id before the model speaks at all.
Write it to three places in the same breath.
mkdir -p "$HOME/session_index"
SID="$(date -u +%Y%m%dT%H%M%SZ)-$(openssl rand -hex 4)"
echo "$SID" | tee .session_id "$HOME/session_index/${SID}.txt"
export SESSION_ID="$SID"
echo "SESSION_ID=$SID"
Then run this tiny checker. It is a local helper.
Treat it as an example until you execute it.
# verify_session.py — unexecuted example until you run it.
from pathlib import Path
import os
import sys
sid_file = Path(".session_id")
if not sid_file.is_file():
print("FAIL: missing .session_id")
sys.exit(1)
sid = sid_file.read_text().strip()
env = os.environ.get("SESSION_ID", "")
if env and env != sid:
print(f"FAIL: env {env!r} != file {sid!r}")
sys.exit(2)
print(f"PASS: session {sid}")
If file, env, and chat disagree, you have two sessions.
You just think you have one session.
Billing never told you which history was real.
Corrected mental model
Billing is only an accounting event.
A session is a causal chain on disk.
You still need the chain when the chain is free.
Myth 5: A retry on a free box is the same run
The claim
"Just hit it again. It is free."
The second run is not the first run.
The disk remembers the first attempt.
Is a free retry a time machine?
The check
Before a retry, snapshot three fingerprints.
Do not snapshot feelings. Snapshot paths and hashes.
#!/usr/bin/env bash
# retry_fingerprint.sh — proposed checklist, not a benchmark.
set -euo pipefail
out="${1:-/tmp/retry_fingerprint.txt}"
{
echo "pwd=$(pwd)"
echo "head=$(git rev-parse HEAD 2>/dev/null || echo NONE)"
echo "dirty=$(git status --porcelain | wc -l | tr -d ' ')"
echo "session=$(cat .session_id 2>/dev/null || echo MISSING)"
python3 - <<'PY'
import hashlib, os, pathlib
paths = [".session_id", "requirements.txt", "package-lock.json", "go.sum"]
for p in paths:
path = pathlib.Path(p)
if path.is_file():
digest = hashlib.sha256(path.read_bytes()).hexdigest()[:12]
print(f"hash_{p}={digest}")
else:
print(f"hash_{p}=ABSENT")
print(f"env_count={len(os.environ)}")
PY
} | tee "$out"
Capture before and after. Then diff the files.
./retry_fingerprint.sh /tmp/retry_fingerprint.before
# ...agent runs...
./retry_fingerprint.sh /tmp/retry_fingerprint.after
diff -u /tmp/retry_fingerprint.before /tmp/retry_fingerprint.after || true
If dirty files grew, you did not retry.
You continued a mutated tree under a reused story.
Price did not reset the filesystem for you.
Corrected mental model
Retries are new causal histories on purpose.
Free retries still mutate state on disk.
A zero invoice does not rewind HEAD or cwd.
Artifact: a 20-minute operator loop you can rerun
Here is the whole loop as a procedure.
It is not a latency study. It is not a score.
- Create
SESSION_ROOTas an empty directory. - Run
session_cwd.shand keep the printed id. - Write the git header into
/tmp/session_header.txt. - Export
SESSION_IDfrom.session_id. - Run
verify_session.pyand demandPASS. - Take a fingerprint before the agent starts.
- Take a fingerprint after the agent stops.
- Diff the two files before you retry anything.
Decision table
Paste this table into the PR, not a chat summary.
| Claim you heard | What to measure | Pass looks like | Fail looks like |
|---|---|---|---|
| I am not the operator |
id plus write access |
your uid owns cwd | mystery uid or read-only |
| The model remembers | header versus git status
|
they match | model cites a dead branch |
| cwd does not matter |
pwd versus SESSION_ROOT
|
exact prefix match |
$HOME or an old clone |
| chat title is the id |
.session_id versus env |
one string, three places | two strings, one chat |
| retry equals first run | fingerprint diff | empty diff or a new sid | dirty tree, same sid |
If a row fails, you do not prompt again.
You fix the contract, then you prompt again.
What this does not prove
This does not measure model quality at all.
This does not measure server speed at all.
I am not publishing latency numbers in this FAQ.
This does not make a free box a production host.
It does not replace backups you can restore.
It does not replace secret scanning before push.
Free model access and a free server option are availability claims.
They are not a promise about how long anything lasts.
They are not a hardware spec, and I will not invent one.
If you need guaranteed capacity, stop this pattern.
If you need a compliance boundary, stop this pattern.
If you cannot explain who can rm the tree, stop.
Do not put production secrets on a free server.
Do not let an agent inherit cloud credentials "just to try."
Do not confuse a clean invoice with a clean rollback.
Who should skip this approach
Skip it if you already have locked CI runners.
Skip it if your threat model forbids shared remote shells.
Skip it if you cannot store session files next to code.
This FAQ is for people mixing a free model with a free box.
It is for spikes, canaries, and messy prototypes.
It is not for payroll, hospitals, or anything you cannot rebuild.
Closing
So, if the runtime is free, who is the operator?
You are, if you can change the disk.
The model is not. The invoice is not.
Run the checklist once on an empty directory.
Then tell me which myth died first.
Top comments (1)
Your point about equating free resources with a lack of responsibility resonates deeply. It's crucial for developers to maintain rigorous ownership practices, even when using free models or servers. Implementing those command checks you described can significantly mitigate the risks associated with mismanagement. If you’re looking for further engineering support on enhancing the MonkeyCode workflow, I’d be glad to explore a paid collaboration to contribute to that area. How do you envision scaling these practices across larger teams?