Did you paste a repo into a remote box today? Did you treat that shell like your laptop?
I keep a short FAQ for that moment. It is not about raw model quality. It is about the machine under the prompt.
The box answers in a familiar prompt. Your files sit on its disk now. Git status can look almost honest here.
So which environment did you actually trust then?
Why this FAQ exists
Five claims keep showing up in agent chats. They sound careful. They are usually false.
The prompt looks local. The process is not local. That gap is where bad patches hide.
I do not debate the chat log first. I dump box identity first. Then I let the model touch files.
The five claims
- "The box inherited my PATH."
- "Locale and timezone match my laptop."
- "SSH agent forwarding just works."
- "My
.envis present, or safely gone." - "Unix flags are just Unix flags."
Want a two minute counter-argument? Run the dump on both machines. Diff the reports. Keep secrets out of both files.
Artifact: box identity dump
This script is a proposed check. It is not a published benchmark. Inspect it before you run it.
#!/usr/bin/env bash
# box-identity.sh — proposed environment dump
# Label: unexecuted template. Read it before running.
set -euo pipefail
out="${1:-box-identity.txt}"
{
echo "=== host ==="
uname -a || true
echo "id: $(id)"
echo "pwd: $(pwd)"
echo "home: ${HOME:-}"
echo "shell: ${SHELL:-}"
echo
echo "=== path ==="
printf '%s\n' "${PATH:-}" | tr ':' '\n'
echo
echo "which python3: $(command -v python3 || echo MISSING)"
echo "which git: $(command -v git || echo MISSING)"
echo "which ssh: $(command -v ssh || echo MISSING)"
echo "which sed: $(command -v sed || echo MISSING)"
echo "which date: $(command -v date || echo MISSING)"
python3 -V 2>&1 || true
git --version 2>&1 || true
echo
echo "=== locale and time ==="
echo "date: $(date)"
echo "date -u: $(date -u)"
echo "TZ=${TZ:-unset}"
echo "LANG=${LANG:-unset}"
echo "LC_ALL=${LC_ALL:-unset}"
locale 2>/dev/null || true
echo
echo "=== git ==="
git rev-parse --show-toplevel 2>/dev/null || echo "not a git work tree"
git config --show-origin --get user.name || true
git config --show-origin --get user.email || true
git remote -v || true
git status -sb || true
echo
echo "=== ssh names only ==="
echo "SSH_AUTH_SOCK=${SSH_AUTH_SOCK:-unset}"
echo "SSH_AGENT_PID=${SSH_AGENT_PID:-unset}"
if [[ -d "${HOME}/.ssh" ]]; then
ls -l "${HOME}/.ssh" | awk '{print $1, $3, $4, $9}'
else
echo "no ~/.ssh directory"
fi
echo
echo "=== userland probe ==="
if echo 'a' | sed -E 's/a/b/' >/dev/null 2>&1; then
echo "sed accepts -E"
else
echo "sed rejects -E"
fi
if date --version >/dev/null 2>&1; then
echo "date looks GNU"
else
echo "date does not look GNU"
fi
} >"$out"
echo "wrote $out"
Run it on the laptop. Run it on the remote box. Store both files beside the repo, not in chat.
Notice what the script refuses to print. No key material. No .env values. No token files.
You want names, paths, and versions. You do not want a second leak. Would you paste printenv into a model thread?
FAQ 1: "The box inherited my PATH"
Claim: the agent uses your python3.
Evidence:
-
command -v python3on the laptop -
command -v python3on the box -
python3 -Von both sides
Corrected model: PATH is a process property. It does not ride with git clone. A free server boots its own image. That image has its own interpreter.
Would you debug imports against the wrong binary? I would not. If the model says it ran pytest, ask which file ran.
command -v pytest
python3 -c 'import sys; print(sys.executable); print(sys.version)'
Two paths mean two worlds. Pin one before you trust a green line.
What the chat usually hides
The model quotes python3. Your brain fills in your python. The box never agreed to that mapping.
Virtualenv names can match too. The contents still differ. Same folder name, different wheels.
FAQ 2: "Locale and timezone match my laptop"
Claim: timestamps and sorts will match CI.
Evidence:
-
dateanddate -u -
TZ,LANG,LC_ALL - one fixture that parses a local timestamp
Corrected model: locale is not in your repo. Timezone is not in package.json. A UTC box passes tests your laptop fails. The reverse happens too.
I treat date tests as environment tests. They are not pure functions. Did the agent "fix" flakes by changing locale? That is a hidden dependency, not a fix.
python3 - <<'PY'
import time, locale
print("tzname", time.tzname)
print("locale", locale.getlocale())
PY
Who owns TZ in that process? You, or the image maintainer?
A cheap trap
String sorts change with LC_COLLATE. Snapshot tests then drift. The model "simplifies" the assertion. You ship a locale bug.
Set timezone in the test command. Do not set it in chat memory.
TZ=UTC LANG=C python3 -m pytest tests/test_clock.py
FAQ 3: "SSH just works on the box"
Claim: git push from the agent is you.
Evidence:
SSH_AUTH_SOCK- name-only listing of
~/.ssh git remote -vgit config user.email
Corrected model: a free server is a different principal. It may have no agent. It may have a key you did not mint. It may have nothing, then ask for a paste.
Do not paste a key. Do not enable forwarding because the prompt looked stuck. Who is origin expecting on that socket?
git remote -v
git config --show-origin --get user.email
echo "${SSH_AUTH_SOCK:-unset}"
If the sock is unset, push is not you. If a key file exists, ask who created it.
This is not the committer-name myth. That myth is about user.email. This one is about transport identity. Commits and pushes can lie separately.
Push path I actually use
Draft on the box. Review the diff locally. Authenticated writes stay on my laptop. The box does not need my agent.
FAQ 4: "My .env is here, or safely gone"
Claim: gitignore means the model cannot see secrets. Or the opposite claim: the box loaded local env by magic.
Evidence:
- whether
.envexists on disk - whether process env has names you recognize
- whether the model asked to
catit
Corrected model: gitignore is a git rule. It is not a memory fence. A file on disk is visible. A missing file is not safe. It is only missing.
Print names. Never print values.
python3 - <<'PY'
import os
keys = sorted(os.environ)
needles = ("KEY", "TOKEN", "SECRET", "PASSWORD", "DATABASE_URL")
interesting = [k for k in keys if any(s in k.upper() for s in needles)]
print("interesting names:", interesting)
print("count", len(keys))
PY
I want the list of names. I do not want values in chat. If .env exists, treat it as hostile until you know the source.
Did you copy it? Did a prior session leave it? Did the model write a placeholder that looks real?
Two failure modes
- The file is absent, tests talk to the wrong host.
- The file is present, and now the chat can quote it.
Neither mode is "handled." Both need an explicit choice.
FAQ 5: "sed is sed, date is date"
Claim: a macOS one-liner will work unchanged.
Evidence:
-
sed -Eversussed -r -
date --versionversus BSDdate uname
Corrected model: the box is probably GNU userland. Your laptop might be BSD userland. Models mix both dialects in one patch.
"Works on my machine" becomes "works in the chat." Neither result is CI.
echo 'foo' | sed -E 's/foo/bar/' && echo "sed -E ok" || echo "sed -E failed"
date +%s
If a patch uses sed -i '', which Unix is that? If a patch uses date -d, ask again.
Makefile edition
make recipes copy your muscle memory. They also copy your OS. Pin POSIX-safe flags, or detect the flavor in the recipe.
Decision table
| Myth | Cheap check | If it fails |
|---|---|---|
| PATH followed me | diff command -v python3
|
pin the interpreter in the task |
| Locale followed me | diff date and LANG
|
set TZ in the test command |
| SSH is me | print SSH_AUTH_SOCK only |
do not push from the box |
.env is handled |
list env names, not values | keep secrets off the box |
| Unix flags match | probe sed and date
|
write POSIX or detect OS |
Print the table once per box. Fill it. Reuse it when the image changes. Did any row stay blank?
Where a free model and free server fit
I use this when the task is cheap exploration. A free model can draft the dump script. A free server can run it off my laptop.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
MonkeyCode provides free model access and a free server option. That pairing is convenient. Convenience is the myth engine.
The product does not teleport PATH. It does not inherit my SSH agent. It does not make GNU and BSD agree.
I still dump identity first. Then I let the model touch the tree. If you start a free remote box, pause. Run the dump before the first apply loop.
What this does not prove
This script is not a sandbox audit. It does not measure isolation. It does not prove the model cannot see a mounted secret.
It also does not prove tests are deterministic. It only shows the environment tests will feel. I do not claim timings. I do not claim quotas. I do not claim how long a box lasts.
Those numbers change. Your dump does not. Keep the dump next to the diff.
Who should not use this approach
Skip this if you need a signed builder SBOM. Skip this if policy forbids unknown remote shells. Skip this if the repo cannot leave your workstation.
Skip this if you planned to paste production credentials "for a minute." A free box is the wrong minute. Also skip the "just push from the box" shortcut.
Use your laptop for authenticated git writes. The remote box can still be useful. It should not become your identity.
Corrected mental model
The repo can move. Your environment does not. The prompt can look local. The process is remote.
The model can quote your file. The file still lives on someone else's layout. Ask one question before the first patch: which machine is speaking?
Then ask a second question. Which PATH, locale, and credentials did that machine boot with? Until those answers sit on disk, the chat is not evidence.
Top comments (0)