Did your agent just pass on a rented box?
That green check lives on somebody else's filesystem.
It is not the same as local git status.
It is not your pinned CI image either.
These five claims keep showing up in review threads.
They sound reasonable, and they are usually false.
This FAQ is a corrected mental model, not a tour.
Why this FAQ exists
Free remote workspaces make cheap agent loops tempting.
Free model access makes those loops cheap to retry.
Cheap retries create a new failure mode: false confidence.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
MonkeyCode offers free model access and a free server option.
That pairing is why it appears in this workflow.
Those two facts are the only product claims here.
No model names. No quota theater. No fake hardware numbers.
The rest is a check you can run on any unknown box.
The artifact: fingerprint before you trust a pass
Do not argue about "the environment." Measure it.
Treat the snippet below as a proposed harness, not a benchmark.
Save it as env_fingerprint.py.
Run it locally, on the remote box, and in CI.
#!/usr/bin/env python3
"""Proposed harness: compare three environments before you merge."""
from __future__ import annotations
import hashlib
import json
import os
import platform
import shutil
import subprocess
import sys
from pathlib import Path
CHECKS = ("python3", "node", "git", "docker", "pytest", "cargo")
def which_map() -> dict[str, str | None]:
return {name: shutil.which(name) for name in CHECKS}
def git_head() -> str | None:
try:
out = subprocess.check_output(
["git", "rev-parse", "HEAD"],
stderr=subprocess.DEVNULL,
text=True,
)
return out.strip()
except (OSError, subprocess.CalledProcessError):
return None
def tree_digest(root: Path) -> str:
h = hashlib.sha256()
paths = sorted(p for p in root.rglob("*") if p.is_file())
for path in paths:
rel = path.relative_to(root).as_posix()
if rel.startswith(".git/") or "/node_modules/" in f"/{rel}/":
continue
h.update(rel.encode())
h.update(b"\0")
h.update(path.read_bytes())
return h.hexdigest()[:16]
def fingerprint() -> dict:
root = Path.cwd()
return {
"cwd": str(root),
"platform": platform.platform(),
"python": sys.version.split()[0],
"user": os.environ.get("USER") or os.environ.get("USERNAME"),
"home": os.environ.get("HOME"),
"path_hash": hashlib.sha256(
os.environ.get("PATH", "").encode()
).hexdigest()[:12],
"tools": which_map(),
"git_head": git_head(),
"tree16": tree_digest(root),
"has_dotenv": (root / ".env").exists(),
"has_secrets_dir": (root / ".secrets").exists(),
}
if __name__ == "__main__":
label = sys.argv[1] if len(sys.argv) > 1 else "unlabeled"
doc = fingerprint()
doc["label"] = label
print(json.dumps(doc, indent=2, sort_keys=True))
Run it three times. Diff the JSON. Do not skip the diffs.
python3 env_fingerprint.py local > /tmp/fp-local.json
# on the free remote box
python3 env_fingerprint.py remote > /tmp/fp-remote.json
# in CI
python3 env_fingerprint.py ci > /tmp/fp-ci.json
diff -u /tmp/fp-local.json /tmp/fp-remote.json
diff -u /tmp/fp-remote.json /tmp/fp-ci.json
What changed? Paths? Tool versions? A .env that should not exist?
If the fingerprints diverge, a "pass" is not portable.
That is the whole article, compressed into a diff.
Myth 1: "The free server is basically localhost"
Is it the same kernel, PATH, and UID?
Probably not, and you should not guess.
A free remote box is a different computer.
It has a different package set and leftover state.
Your laptop has different leftovers. CI should have none.
Corrected mental model
- Localhost is your laptop, with weekly tool drift.
- The free server is a rented workspace with unknown history.
- CI is a pinned image you actually version in git.
Decision table
| Signal | Local laptop | Free remote box | Pinned CI image |
|---|---|---|---|
| Tool versions | Drift weekly | Unknown at boot | Pinned in config |
| Secrets on disk | Sometimes, sadly | Treat as hostile | Injected, then gone |
| Network egress | Your LAN plus VPN | Provider network | Restricted |
| Persistence | Until you delete it | Do not assume | Ephemeral by design |
| Pass meaning | "It ran here" | "It ran somewhere" | "It ran the contract" |
If a check only exists in one column, do not merge yet.
Ask which machine you can actually describe in an incident.
Myth 2: "If the agent wrote a file, it persisted"
Did the process write to a durable disk?
Or did it write to a tmpfs that dies on reconnect?
Agents talk like filesystems are durable chat history.
Chat logs are not mounts. Mounts are not backups.
A write you cannot re-read is not a write you can ship.
Corrected mental model
- A write is durable only after a new session can read it.
- A write is reviewable only after it lands in git.
- A write is releasable only after CI sees the same blob.
Proposed persistence probe
Label this as unexecuted until you actually run it.
# Proposed: prove persistence across a reconnect
probe="probe-$(date -u +%s)"
printf '%s\n' "$probe" > .agent-probe.txt
sha256sum .agent-probe.txt
# disconnect, reconnect, then:
test -f .agent-probe.txt || {
echo "probe vanished; the pass vanished too" >&2
exit 1
}
sha256sum .agent-probe.txt
git status --porcelain -- .agent-probe.txt
If the file vanished, the pass vanished with it.
Do not argue with a filesystem. Hash it, then commit it.
Myth 3: "It is my workspace, so secrets are fine"
Is the disk yours, or a shared free pool?
Unless the provider publishes a tenancy model, assume hostile disk.
That is the boring default, and it keeps you employed.
API keys in prompts are already gone.
".Temporary" secrets become logs and screenshots.
A .env on a free box is a leak with extra steps.
What not to copy onto a free server
- Production tokens
- Customer data dumps
- Private keys and SSH agents
-
.npmrcfiles with auth tokens - Cloud CLI credentials and cookie jars
Use injected, short-lived tokens if an API call is required.
Revoke them when the session ends. No revoke, no upload.
# Proposed: fail the session if a secret file is present
for f in .env credentials.json .npmrc; do
if [ -f "$f" ]; then
echo "refusing to run: $f in workspace" >&2
exit 2
fi
done
Put that at the top of the agent entrypoint.
Yes, it will annoy you. That is the point.
Myth 4: "A green remote run is a CI signal"
Who defined green? The agent? The model? A flaky script?
A free remote pass is a smoke test at best.
It is not a release gate, and it is not an audit log.
Corrected mental model
- Remote pass means the loop did not crash on that box.
- Local pass means your dirty laptop also survived.
- CI pass means the pinned contract survived.
You need step 3 to merge.
You may use step 1 to decide whether step 2 is worth the time.
You never replace step 3 with a chat screenshot.
# Proposed CI gate. Pin tools your org already trusts.
# Reuse your existing checkout and language-setup actions.
name: contract
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
run: echo "use your org's pinned checkout action"
- name: Fingerprint
run: python3 env_fingerprint.py ci
- name: Contract
run: pytest -q
Notice what is missing from that gate.
There is no "skip if the agent already passed."
There is no pasted model transcript as evidence.
Myth 5: "I can skip local reproduction"
Why would you skip the machine you actually ship from?
Because the free stack already ran the same commands?
Same commands on different fingerprints are different experiments.
You already measured that with env_fingerprint.py.
Feelings about sameness are not a three-way diff.
Corrected mental model
- Reproduction is a three-way diff, not a vibe.
- If local fails and remote passed, believe local first.
- Then ask which dependency you forgot to pin.
Short triage list
- Diff fingerprints. Circle PATH, python, and missing tools.
- Diff
git status --porcelainon both machines. - Re-run the failing command with
set -x. - Only then ask the model what it "thinks" happened.
The model did not see your laptop.
Your laptop is still the environment you ship from.
The free box is a scratch pad until the hashes match.
Who should not use this approach
Skip the free remote box if any item below is true.
- You handle regulated or customer-identifying data
- You cannot revoke tokens on a short timer
- You need bit-for-bit builds for this release
- You cannot run the fingerprint script in CI
- You treat chat output as an audit log
Also skip it if you will not diff environments.
The workflow without the diffs is just vibes with extra JSON.
Limitations
This harness does not prove security.
It does not prove reproducibility of model tokens.
It does not pin OS packages beyond what you add later.
tree_digest skips .git and node_modules on purpose.
That skip can hide the bug you actually care about.
Extend the skip list deliberately, not by accident.
This article does not claim the free server is isolated.
It does not claim persistence, speed, or a particular OS image.
It only uses a cheap box as a place to run the same checks.
If the checks fail there, they fail on any unknown machine.
That is useful. It is not a platform endorsement.
Closing
So, can you use a free remote dev box?
Yes, as a scratch pad with a fingerprint.
No, as a substitute for CI or for your laptop.
Ask the ugly question before you merge.
Did this pass on a machine you can describe?
If you already have free model access and a free server option, run the three-way fingerprint first. Keep the pass. Throw away the myth.
Top comments (0)